Browse Source

merged trac #310: consity ElementPtr as much as possible.

git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2803 e5f2f494-b856-4b98-b285-d166d9295462
JINMEI Tatuya 14 years ago
parent
commit
62b03a0fd2

+ 13 - 17
src/bin/auth/auth_srv.cc

@@ -68,7 +68,7 @@ private:
 public:
 public:
     AuthSrvImpl(const bool use_cache, AbstractXfroutClient& xfrout_client);
     AuthSrvImpl(const bool use_cache, AbstractXfroutClient& xfrout_client);
     ~AuthSrvImpl();
     ~AuthSrvImpl();
-    isc::data::ElementPtr setDbFile(const isc::data::ElementPtr config);
+    isc::data::ConstElementPtr setDbFile(isc::data::ConstElementPtr config);
 
 
     bool processNormalQuery(const IOMessage& io_message, Message& message,
     bool processNormalQuery(const IOMessage& io_message, Message& message,
                             MessageRenderer& response_renderer);
                             MessageRenderer& response_renderer);
@@ -426,7 +426,7 @@ AuthSrvImpl::processNotify(const IOMessage& io_message, Message& message,
     static const string command_template_end = "\"}]}";
     static const string command_template_end = "\"}]}";
 
 
     try {
     try {
-        ElementPtr notify_command = Element::fromJSON(
+        ConstElementPtr notify_command = Element::fromJSON(
                 command_template_start + question->getName().toText() + 
                 command_template_start + question->getName().toText() + 
                 command_template_master + remote_ip_address +
                 command_template_master + remote_ip_address +
                 command_template_rrclass + question->getClass().toText() +
                 command_template_rrclass + question->getClass().toText() +
@@ -434,7 +434,7 @@ AuthSrvImpl::processNotify(const IOMessage& io_message, Message& message,
         const unsigned int seq =
         const unsigned int seq =
             xfrin_session_->group_sendmsg(notify_command, "Zonemgr",
             xfrin_session_->group_sendmsg(notify_command, "Zonemgr",
                                           "*", "*");
                                           "*", "*");
-        ElementPtr env, answer, parsed_answer;
+        ConstElementPtr env, answer, parsed_answer;
         xfrin_session_->group_recvmsg(env, answer, false, seq);
         xfrin_session_->group_recvmsg(env, answer, false, seq);
         int rcode;
         int rcode;
         parsed_answer = parseAnswer(rcode, answer);
         parsed_answer = parseAnswer(rcode, answer);
@@ -459,19 +459,17 @@ AuthSrvImpl::processNotify(const IOMessage& io_message, Message& message,
     return (true);
     return (true);
 }
 }
 
 
-ElementPtr
-AuthSrvImpl::setDbFile(const isc::data::ElementPtr config) {
-    ElementPtr answer = isc::config::createAnswer();
-    ElementPtr final;
+ConstElementPtr
+AuthSrvImpl::setDbFile(ConstElementPtr config) {
+    ConstElementPtr answer = isc::config::createAnswer();
 
 
     if (config && config->contains("database_file")) {
     if (config && config->contains("database_file")) {
         db_file_ = config->get("database_file")->stringValue();
         db_file_ = config->get("database_file")->stringValue();
-        final = config;
     } else if (config_session_ != NULL) {
     } else if (config_session_ != NULL) {
         bool is_default;
         bool is_default;
         string item("database_file");
         string item("database_file");
-        ElementPtr value = config_session_->getValue(is_default, item);
-        final = Element::createMap();
+        ConstElementPtr value = config_session_->getValue(is_default, item);
+        ElementPtr final = Element::createMap();
 
 
         // If the value is the default, and we are running from
         // If the value is the default, and we are running from
         // a specific directory ('from build'), we need to use
         // a specific directory ('from build'), we need to use
@@ -485,6 +483,7 @@ AuthSrvImpl::setDbFile(const isc::data::ElementPtr config) {
                                     "/bind10_zones.sqlite3");
                                     "/bind10_zones.sqlite3");
         }
         }
         final->set(item, value);
         final->set(item, value);
+        config = final;
 
 
         db_file_ = value->stringValue();
         db_file_ = value->stringValue();
     } else {
     } else {
@@ -501,7 +500,7 @@ AuthSrvImpl::setDbFile(const isc::data::ElementPtr config) {
     // fail, while acquiring resources in the RAII manner.  We then perform
     // fail, while acquiring resources in the RAII manner.  We then perform
     // delete and swap operations which should not fail.
     // delete and swap operations which should not fail.
     DataSrcPtr datasrc_ptr(DataSrcPtr(new Sqlite3DataSrc));
     DataSrcPtr datasrc_ptr(DataSrcPtr(new Sqlite3DataSrc));
-    datasrc_ptr->init(final);
+    datasrc_ptr->init(config);
     data_sources_.addDataSrc(datasrc_ptr);
     data_sources_.addDataSrc(datasrc_ptr);
 
 
     // The following code should be exception free.
     // The following code should be exception free.
@@ -513,15 +512,12 @@ AuthSrvImpl::setDbFile(const isc::data::ElementPtr config) {
     return (answer);
     return (answer);
 }
 }
 
 
-ElementPtr
-AuthSrv::updateConfig(isc::data::ElementPtr new_config) {
+ConstElementPtr
+AuthSrv::updateConfig(ConstElementPtr new_config) {
     try {
     try {
         // the ModuleCCSession has already checked if we have
         // the ModuleCCSession has already checked if we have
         // the correct ElementPtr type as specified in our .spec file
         // the correct ElementPtr type as specified in our .spec file
-        ElementPtr answer = isc::config::createAnswer();
-        answer = impl_->setDbFile(new_config);
-
-        return (answer);
+        return (impl_->setDbFile(new_config));
     } catch (const isc::Exception& error) {
     } catch (const isc::Exception& error) {
         if (impl_->verbose_mode_) {
         if (impl_->verbose_mode_) {
             cerr << "[b10-auth] error: " << error.what() << endl;
             cerr << "[b10-auth] error: " << error.what() << endl;

+ 1 - 1
src/bin/auth/auth_srv.h

@@ -69,7 +69,7 @@ public:
                         isc::dns::MessageRenderer& response_renderer);
                         isc::dns::MessageRenderer& response_renderer);
     void setVerbose(bool on);
     void setVerbose(bool on);
     bool getVerbose() const;
     bool getVerbose() const;
-    isc::data::ElementPtr updateConfig(isc::data::ElementPtr config);
+    isc::data::ConstElementPtr updateConfig(isc::data::ConstElementPtr config);
     isc::config::ModuleCCSession* configSession() const;
     isc::config::ModuleCCSession* configSession() const;
     void setConfigSession(isc::config::ModuleCCSession* config_session);
     void setConfigSession(isc::config::ModuleCCSession* config_session);
 
 

+ 6 - 6
src/bin/auth/main.cc

@@ -66,19 +66,19 @@ AuthSrv *auth_server;
 
 
 asio_link::IOService* io_service;
 asio_link::IOService* io_service;
 
 
-ElementPtr
-my_config_handler(ElementPtr new_config) {
+ConstElementPtr
+my_config_handler(ConstElementPtr new_config) {
     return (auth_server->updateConfig(new_config));
     return (auth_server->updateConfig(new_config));
 }
 }
 
 
-ElementPtr
-my_command_handler(const string& command, const ElementPtr args) {
-    ElementPtr answer = createAnswer();
+ConstElementPtr
+my_command_handler(const string& command, ConstElementPtr args) {
+    ConstElementPtr answer = createAnswer();
 
 
     if (command == "print_message") {
     if (command == "print_message") {
         cout << args << endl;
         cout << args << endl;
         /* let's add that message to our answer as well */
         /* let's add that message to our answer as well */
-        answer->get("result")->add(args);
+        answer = createAnswer(0, args);
     } else if (command == "shutdown") {
     } else if (command == "shutdown") {
         io_service->stop();
         io_service->stop();
     }
     }

+ 20 - 17
src/bin/auth/tests/auth_srv_unittest.cc

@@ -85,26 +85,27 @@ private:
         {}
         {}
         virtual void establish(const char* socket_file);
         virtual void establish(const char* socket_file);
         virtual void disconnect();
         virtual void disconnect();
-        virtual int group_sendmsg(ElementPtr msg, string group,
+        virtual int group_sendmsg(ConstElementPtr msg, string group,
                                   string instance, string to);
                                   string instance, string to);
-        virtual bool group_recvmsg(ElementPtr& envelope, ElementPtr& msg,
+        virtual bool group_recvmsg(ConstElementPtr& envelope,
+                                   ConstElementPtr& msg,
                                    bool nonblock, int seq);
                                    bool nonblock, int seq);
         virtual void subscribe(string group, string instance);
         virtual void subscribe(string group, string instance);
         virtual void unsubscribe(string group, string instance);
         virtual void unsubscribe(string group, string instance);
         virtual void startRead(boost::function<void()> read_callback);
         virtual void startRead(boost::function<void()> read_callback);
-        virtual int reply(ElementPtr& envelope, ElementPtr& newmsg);
-        virtual bool hasQueuedMsgs();
+        virtual int reply(ConstElementPtr envelope, ConstElementPtr newmsg);
+        virtual bool hasQueuedMsgs() const;
         virtual void setTimeout(size_t timeout UNUSED_PARAM) {};
         virtual void setTimeout(size_t timeout UNUSED_PARAM) {};
         virtual size_t getTimeout() const { return 0; };
         virtual size_t getTimeout() const { return 0; };
 
 
-        void setMessage(ElementPtr msg) { msg_ = msg; }
+        void setMessage(ConstElementPtr msg) { msg_ = msg; }
         void disableSend() { send_ok_ = false; }
         void disableSend() { send_ok_ = false; }
         void disableReceive() { receive_ok_ = false; }
         void disableReceive() { receive_ok_ = false; }
 
 
-        ElementPtr sent_msg;
+        ConstElementPtr sent_msg;
         string msg_destination;
         string msg_destination;
     private:
     private:
-        ElementPtr msg_;
+        ConstElementPtr msg_;
         bool send_ok_;
         bool send_ok_;
         bool receive_ok_;
         bool receive_ok_;
     };
     };
@@ -174,19 +175,19 @@ AuthSrvTest::MockSession::startRead(
 {}
 {}
 
 
 int
 int
-AuthSrvTest::MockSession::reply(ElementPtr& envelope UNUSED_PARAM,
-                                ElementPtr& newmsg UNUSED_PARAM)
+AuthSrvTest::MockSession::reply(ConstElementPtr envelope UNUSED_PARAM,
+                                ConstElementPtr newmsg UNUSED_PARAM)
 {
 {
     return (-1);
     return (-1);
 }
 }
 
 
 bool
 bool
-AuthSrvTest::MockSession::hasQueuedMsgs() {
+AuthSrvTest::MockSession::hasQueuedMsgs() const {
     return (false);
     return (false);
 }
 }
 
 
 int
 int
-AuthSrvTest::MockSession::group_sendmsg(ElementPtr msg, string group,
+AuthSrvTest::MockSession::group_sendmsg(ConstElementPtr msg, string group,
                                         string instance UNUSED_PARAM,
                                         string instance UNUSED_PARAM,
                                         string to UNUSED_PARAM)
                                         string to UNUSED_PARAM)
 {
 {
@@ -200,8 +201,8 @@ AuthSrvTest::MockSession::group_sendmsg(ElementPtr msg, string group,
 }
 }
 
 
 bool
 bool
-AuthSrvTest::MockSession::group_recvmsg(ElementPtr& envelope UNUSED_PARAM,
-                                        ElementPtr& msg,
+AuthSrvTest::MockSession::group_recvmsg(ConstElementPtr& envelope UNUSED_PARAM,
+                                        ConstElementPtr& msg,
                                         bool nonblock UNUSED_PARAM,
                                         bool nonblock UNUSED_PARAM,
                                         int seq UNUSED_PARAM)
                                         int seq UNUSED_PARAM)
 {
 {
@@ -539,7 +540,8 @@ TEST_F(AuthSrvTest, notify) {
     EXPECT_EQ("Zonemgr", notify_session.msg_destination);
     EXPECT_EQ("Zonemgr", notify_session.msg_destination);
     EXPECT_EQ("notify",
     EXPECT_EQ("notify",
               notify_session.sent_msg->get("command")->get(0)->stringValue());
               notify_session.sent_msg->get("command")->get(0)->stringValue());
-    ElementPtr notify_args = notify_session.sent_msg->get("command")->get(1);
+    ConstElementPtr notify_args =
+        notify_session.sent_msg->get("command")->get(1);
     EXPECT_EQ("example.com.", notify_args->get("zone_name")->stringValue());
     EXPECT_EQ("example.com.", notify_args->get("zone_name")->stringValue());
     EXPECT_EQ(DEFAULT_REMOTE_ADDRESS,
     EXPECT_EQ(DEFAULT_REMOTE_ADDRESS,
               notify_args->get("master")->stringValue());
               notify_args->get("master")->stringValue());
@@ -567,7 +569,8 @@ TEST_F(AuthSrvTest, notifyForCHClass) {
 
 
     // Other conditions should be the same, so simply confirm the RR class is
     // Other conditions should be the same, so simply confirm the RR class is
     // set correctly.
     // set correctly.
-    ElementPtr notify_args = notify_session.sent_msg->get("command")->get(1);
+    ConstElementPtr notify_args =
+        notify_session.sent_msg->get("command")->get(1);
     EXPECT_EQ("CH", notify_args->get("zone_class")->stringValue());
     EXPECT_EQ("CH", notify_args->get("zone_class")->stringValue());
 }
 }
 
 
@@ -695,12 +698,12 @@ void
 updateConfig(AuthSrv* server, const char* const dbfile,
 updateConfig(AuthSrv* server, const char* const dbfile,
              const bool expect_success)
              const bool expect_success)
 {
 {
-    const ElementPtr config_answer =
+    ConstElementPtr config_answer =
         server->updateConfig(Element::fromJSON(dbfile));
         server->updateConfig(Element::fromJSON(dbfile));
     EXPECT_EQ(Element::map, config_answer->getType());
     EXPECT_EQ(Element::map, config_answer->getType());
     EXPECT_TRUE(config_answer->contains("result"));
     EXPECT_TRUE(config_answer->contains("result"));
 
 
-    const ElementPtr result = config_answer->get("result");
+    ConstElementPtr result = config_answer->get("result");
     EXPECT_EQ(Element::list, result->getType());
     EXPECT_EQ(Element::list, result->getType());
     EXPECT_EQ(expect_success ? 0 : 1, result->get(0)->intValue());
     EXPECT_EQ(expect_success ? 0 : 1, result->get(0)->intValue());
 }
 }

+ 112 - 84
src/lib/cc/data.cc

@@ -20,6 +20,7 @@
 
 
 #include <cassert>
 #include <cassert>
 #include <climits>
 #include <climits>
+#include <map>
 #include <cstdio>
 #include <cstdio>
 #include <iostream>
 #include <iostream>
 #include <string>
 #include <string>
@@ -35,21 +36,21 @@ namespace isc {
 namespace data {
 namespace data {
 
 
 std::string
 std::string
-Element::str() {
+Element::str() const {
     std::stringstream ss;
     std::stringstream ss;
     toJSON(ss);
     toJSON(ss);
     return (ss.str());
     return (ss.str());
 }
 }
 
 
 std::string
 std::string
-Element::toWire() {
+Element::toWire() const {
     std::stringstream ss;
     std::stringstream ss;
     toJSON(ss);
     toJSON(ss);
     return (ss.str());
     return (ss.str());
 }
 }
 
 
 void
 void
-Element::toWire(std::ostream& ss) {
+Element::toWire(std::ostream& ss) const {
     toJSON(ss);
     toJSON(ss);
 }
 }
 
 
@@ -81,12 +82,12 @@ Element::getValue(std::string& t UNUSED_PARAM) {
 }
 }
 
 
 bool
 bool
-Element::getValue(std::vector<ElementPtr>& t UNUSED_PARAM) {
+Element::getValue(std::vector<ConstElementPtr>& t UNUSED_PARAM) {
     return (false);
     return (false);
 }
 }
 
 
 bool
 bool
-Element::getValue(std::map<std::string, ElementPtr>& t UNUSED_PARAM) {
+Element::getValue(std::map<std::string, ConstElementPtr>& t UNUSED_PARAM) {
     return (false);
     return (false);
 }
 }
 
 
@@ -111,27 +112,29 @@ Element::setValue(const std::string& v UNUSED_PARAM) {
 }
 }
 
 
 bool
 bool
-Element::setValue(const std::vector<ElementPtr>& v UNUSED_PARAM) {
+Element::setValue(const std::vector<ConstElementPtr>& v UNUSED_PARAM) {
     return (false);
     return (false);
 }
 }
 
 
 bool
 bool
-Element::setValue(const std::map<std::string, ElementPtr>& v UNUSED_PARAM) {
+Element::setValue(const std::map<std::string,
+                  ConstElementPtr>& v UNUSED_PARAM)
+{
     return (false);
     return (false);
 }
 }
 
 
-ElementPtr
-Element::get(const int i UNUSED_PARAM) {
+ConstElementPtr
+Element::get(const int i UNUSED_PARAM) const {
     isc_throw(TypeError, "get(int) called on a non-list Element");
     isc_throw(TypeError, "get(int) called on a non-list Element");
 }
 }
 
 
 void
 void
-Element::set(const size_t i UNUSED_PARAM, ElementPtr element UNUSED_PARAM) {
+Element::set(const size_t i UNUSED_PARAM, ConstElementPtr element UNUSED_PARAM) {
     isc_throw(TypeError, "set(int, element) called on a non-list Element");
     isc_throw(TypeError, "set(int, element) called on a non-list Element");
 }
 }
 
 
 void
 void
-Element::add(ElementPtr element UNUSED_PARAM) {
+Element::add(ConstElementPtr element UNUSED_PARAM) {
     isc_throw(TypeError, "add() called on a non-list Element");
     isc_throw(TypeError, "add() called on a non-list Element");
 }
 }
 
 
@@ -141,18 +144,18 @@ Element::remove(const int i UNUSED_PARAM) {
 }
 }
 
 
 size_t
 size_t
-Element::size() {
+Element::size() const {
     isc_throw(TypeError, "size() called on a non-list Element");
     isc_throw(TypeError, "size() called on a non-list Element");
 }
 }
 
 
-ElementPtr
-Element::get(const std::string& name UNUSED_PARAM) {
+ConstElementPtr
+Element::get(const std::string& name UNUSED_PARAM) const {
     isc_throw(TypeError, "get(string) called on a non-map Element");
     isc_throw(TypeError, "get(string) called on a non-map Element");
 }
 }
 
 
 void
 void
 Element::set(const std::string& name UNUSED_PARAM,
 Element::set(const std::string& name UNUSED_PARAM,
-             ElementPtr element UNUSED_PARAM)
+             ConstElementPtr element UNUSED_PARAM)
 {
 {
     isc_throw(TypeError, "set(name, element) called on a non-map Element");
     isc_throw(TypeError, "set(name, element) called on a non-map Element");
 }
 }
@@ -163,18 +166,18 @@ Element::remove(const std::string& name UNUSED_PARAM) {
 }
 }
 
 
 bool
 bool
-Element::contains(const std::string& name UNUSED_PARAM) {
+Element::contains(const std::string& name UNUSED_PARAM) const {
     isc_throw(TypeError, "contains(string) called on a non-map Element");
     isc_throw(TypeError, "contains(string) called on a non-map Element");
 }
 }
 
 
-ElementPtr
-Element::find(const std::string& identifier UNUSED_PARAM) {
+ConstElementPtr
+Element::find(const std::string& identifier UNUSED_PARAM) const {
     isc_throw(TypeError, "find(string) called on a non-map Element");
     isc_throw(TypeError, "find(string) called on a non-map Element");
 }
 }
 
 
 bool
 bool
 Element::find(const std::string& identifier UNUSED_PARAM,
 Element::find(const std::string& identifier UNUSED_PARAM,
-              ElementPtr& t UNUSED_PARAM)
+              ConstElementPtr t UNUSED_PARAM) const
 {
 {
     return (false);
     return (false);
 }
 }
@@ -189,12 +192,18 @@ throwJSONError(const std::string& error, const std::string& file, int line, int
 }
 }
 }
 }
 
 
-std::ostream& operator <<(std::ostream &out, const isc::data::ElementPtr& e) {
-    return (out << e->str());
+std::ostream&
+operator<<(std::ostream &out, const Element& e) {
+    return (out << e.str());
 }
 }
 
 
-bool operator==(const isc::data::ElementPtr a, const isc::data::ElementPtr b) {
-    return (a->equals(b));
+bool
+operator==(const Element& a, const Element& b) {
+    return (a.equals(b));
+}
+
+bool operator!=(const Element& a, const Element& b) {
+    return (!a.equals(b));
 };
 };
 
 
 //
 //
@@ -428,7 +437,7 @@ from_stringstream_list(std::istream &in, const std::string& file, int& line, int
 {
 {
     char c = 0;
     char c = 0;
     ElementPtr list = Element::createList();
     ElementPtr list = Element::createList();
-    ElementPtr cur_list_element;
+    ConstElementPtr cur_list_element;
 
 
     skip_chars(in, " \t\n", line, pos);
     skip_chars(in, " \t\n", line, pos);
     while (c != EOF && c != ']') {
     while (c != EOF && c != ']') {
@@ -462,7 +471,7 @@ from_stringstream_map(std::istream &in, const std::string& file, int& line,
             in.get();
             in.get();
             pos++;
             pos++;
 
 
-            ElementPtr value = Element::fromJSON(in, file, line, pos);
+            ConstElementPtr value = Element::fromJSON(in, file, line, pos);
             map->set(key, value);
             map->set(key, value);
             
             
             skip_to(in, file, line, pos, ",}", " \t\n");
             skip_to(in, file, line, pos, ",}", " \t\n");
@@ -614,20 +623,17 @@ Element::fromJSON(const std::string &in) {
 // to JSON format
 // to JSON format
 
 
 void
 void
-IntElement::toJSON(std::ostream& ss)
-{
+IntElement::toJSON(std::ostream& ss) const {
     ss << intValue();
     ss << intValue();
 }
 }
 
 
 void
 void
-DoubleElement::toJSON(std::ostream& ss)
-{
+DoubleElement::toJSON(std::ostream& ss) const {
     ss << doubleValue();
     ss << doubleValue();
 }
 }
 
 
 void
 void
-BoolElement::toJSON(std::ostream& ss)
-{
+BoolElement::toJSON(std::ostream& ss) const {
     if (boolValue()) {
     if (boolValue()) {
         ss << "true";
         ss << "true";
     } else {
     } else {
@@ -636,26 +642,23 @@ BoolElement::toJSON(std::ostream& ss)
 }
 }
 
 
 void
 void
-NullElement::toJSON(std::ostream& ss)
-{
+NullElement::toJSON(std::ostream& ss) const {
     ss << "null";
     ss << "null";
 }
 }
 
 
 void
 void
-StringElement::toJSON(std::ostream& ss)
-{
+StringElement::toJSON(std::ostream& ss) const {
     ss << "\"";
     ss << "\"";
     ss << stringValue();
     ss << stringValue();
     ss << "\"";
     ss << "\"";
 }
 }
 
 
 void
 void
-ListElement::toJSON(std::ostream& ss)
-{
+ListElement::toJSON(std::ostream& ss) const {
     ss << "[ ";
     ss << "[ ";
 
 
-    const std::vector<ElementPtr>& v = listValue();
-    for (std::vector<ElementPtr>::const_iterator it = v.begin();
+    const std::vector<ConstElementPtr>& v = listValue();
+    for (std::vector<ConstElementPtr>::const_iterator it = v.begin();
          it != v.end(); ++it) {
          it != v.end(); ++it) {
         if (it != v.begin()) {
         if (it != v.begin()) {
             ss << ", ";
             ss << ", ";
@@ -666,12 +669,11 @@ ListElement::toJSON(std::ostream& ss)
 }
 }
 
 
 void
 void
-MapElement::toJSON(std::ostream& ss)
-{
+MapElement::toJSON(std::ostream& ss) const {
     ss << "{ ";
     ss << "{ ";
 
 
-    const std::map<std::string, ElementPtr>& m = mapValue();
-    for (std::map<std::string, ElementPtr>::const_iterator it = m.begin();
+    const std::map<std::string, ConstElementPtr>& m = mapValue();
+    for (std::map<std::string, ConstElementPtr>::const_iterator it = m.begin();
          it != m.end(); ++it) {
          it != m.end(); ++it) {
         if (it != m.begin()) {
         if (it != m.begin()) {
             ss << ", ";
             ss << ", ";
@@ -690,13 +692,13 @@ MapElement::toJSON(std::ostream& ss)
 // we're looking for) is not a MapElement
 // we're looking for) is not a MapElement
 // returns 0 if it could simply not be found
 // returns 0 if it could simply not be found
 // should that also be an exception?
 // should that also be an exception?
-ElementPtr
-MapElement::find(const std::string& id) {
+ConstElementPtr
+MapElement::find(const std::string& id) const {
     const size_t sep = id.find('/');
     const size_t sep = id.find('/');
     if (sep == std::string::npos) {
     if (sep == std::string::npos) {
         return (get(id));
         return (get(id));
     } else {
     } else {
-        ElementPtr ce = get(id.substr(0, sep));
+        ConstElementPtr ce = get(id.substr(0, sep));
         if (ce) {
         if (ce) {
             // ignore trailing slash
             // ignore trailing slash
             if  (sep + 1 != id.size()) {
             if  (sep + 1 != id.size()) {
@@ -735,14 +737,14 @@ Element::fromWire(std::stringstream& in, int length) {
 }
 }
 
 
 void
 void
-MapElement::set(const std::string& key, ElementPtr value) {
+MapElement::set(const std::string& key, ConstElementPtr value) {
     m[key] = value;
     m[key] = value;
 }
 }
 
 
 bool
 bool
-MapElement::find(const std::string& id, ElementPtr& t) {
+MapElement::find(const std::string& id, ConstElementPtr t) const {
     try {
     try {
-        ElementPtr p = find(id);
+        ConstElementPtr p = find(id);
         if (p) {
         if (p) {
             t = p;
             t = p;
             return (true);
             return (true);
@@ -754,43 +756,43 @@ MapElement::find(const std::string& id, ElementPtr& t) {
 }
 }
 
 
 bool
 bool
-IntElement::equals(ElementPtr other) {
-    return (other->getType() == Element::integer) &&
-           (i == other->intValue());
+IntElement::equals(const Element& other) const {
+    return (other.getType() == Element::integer) &&
+           (i == other.intValue());
 }
 }
 
 
 bool
 bool
-DoubleElement::equals(ElementPtr other) {
-    return (other->getType() == Element::real) &&
-           (d == other->doubleValue());
+DoubleElement::equals(const Element& other) const {
+    return (other.getType() == Element::real) &&
+           (d == other.doubleValue());
 }
 }
 
 
 bool
 bool
-BoolElement::equals(ElementPtr other) {
-    return (other->getType() == Element::boolean) &&
-           (b == other->boolValue());
+BoolElement::equals(const Element& other) const {
+    return (other.getType() == Element::boolean) &&
+           (b == other.boolValue());
 }
 }
 
 
 bool
 bool
-NullElement::equals(ElementPtr other) {
-    return (other->getType() == Element::null);
+NullElement::equals(const Element& other) const {
+    return (other.getType() == Element::null);
 }
 }
 
 
 bool
 bool
-StringElement::equals(ElementPtr other) {
-    return (other->getType() == Element::string) &&
-           (s == other->stringValue());
+StringElement::equals(const Element& other) const {
+    return (other.getType() == Element::string) &&
+           (s == other.stringValue());
 }
 }
 
 
 bool
 bool
-ListElement::equals(ElementPtr other) {
-    if (other->getType() == Element::list) {
+ListElement::equals(const Element& other) const {
+    if (other.getType() == Element::list) {
         const int s = size();
         const int s = size();
-        if (s != other->size()) {
+        if (s != other.size()) {
             return (false);
             return (false);
         }
         }
         for (int i = 0; i < s; ++i) {
         for (int i = 0; i < s; ++i) {
-            if (!get(i)->equals(other->get(i))) {
+            if (!get(i)->equals(*other.get(i))) {
                 return (false);
                 return (false);
             }
             }
         }
         }
@@ -801,13 +803,14 @@ ListElement::equals(ElementPtr other) {
 }
 }
 
 
 bool
 bool
-MapElement::equals(ElementPtr other) {
-    if (other->getType() == Element::map) {
-        std::map<std::string, ElementPtr> m = mapValue();
-        for (std::map<std::string, ElementPtr>::const_iterator it = m.begin();
+MapElement::equals(const Element& other) const {
+    if (other.getType() == Element::map) {
+        const std::map<std::string, ConstElementPtr>& m = mapValue();
+        for (std::map<std::string, ConstElementPtr>::const_iterator it =
+                 m.begin();
              it != m.end() ; ++it) {
              it != m.end() ; ++it) {
-            if (other->contains((*it).first)) {
-                if (!get((*it).first)->equals(other->get((*it).first))) {
+            if (other.contains((*it).first)) {
+                if (!get((*it).first)->equals(*other.get((*it).first))) {
                     return (false);
                     return (false);
                 }
                 }
             } else {
             } else {
@@ -819,9 +822,10 @@ MapElement::equals(ElementPtr other) {
         // compare those elements; if one of them is missing we
         // compare those elements; if one of them is missing we
         // differ (and if it's not missing the loop above has checked
         // differ (and if it's not missing the loop above has checked
         // it)
         // it)
-        m = other->mapValue();
-        for (std::map<std::string, ElementPtr>::const_iterator it = m.begin();
-             it != m.end() ; ++it) {
+        std::map<std::string, ConstElementPtr>::const_iterator it;
+        for (it = other.mapValue().begin();
+             it != other.mapValue().end();
+             ++it) {
             if (!contains((*it).first)) {
             if (!contains((*it).first)) {
                 return (false);
                 return (false);
             }
             }
@@ -833,12 +837,12 @@ MapElement::equals(ElementPtr other) {
 }
 }
 
 
 bool
 bool
-isNull(ElementPtr p) {
+isNull(ConstElementPtr p) {
     return (!p);
     return (!p);
 }
 }
 
 
 void
 void
-removeIdentical(ElementPtr a, const ElementPtr b) {
+removeIdentical(ElementPtr a, ConstElementPtr b) {
     if (!b) {
     if (!b) {
         return;
         return;
     }
     }
@@ -846,26 +850,50 @@ removeIdentical(ElementPtr a, const ElementPtr b) {
         isc_throw(TypeError, "Non-map Elements passed to removeIdentical");
         isc_throw(TypeError, "Non-map Elements passed to removeIdentical");
     }
     }
 
 
-    std::map<std::string, ElementPtr> m = a->mapValue();
-    for (std::map<std::string, ElementPtr>::const_iterator it = m.begin();
+    const std::map<std::string, ConstElementPtr>& m = a->mapValue();
+    for (std::map<std::string, ConstElementPtr>::const_iterator it = m.begin();
          it != m.end() ; ++it) {
          it != m.end() ; ++it) {
         if (b->contains((*it).first)) {
         if (b->contains((*it).first)) {
-            if (a->get((*it).first)->equals(b->get((*it).first))) {
+            if (a->get((*it).first)->equals(*b->get((*it).first))) {
                 a->remove((*it).first);
                 a->remove((*it).first);
             }
             }
         }
         }
     }
     }
 }
 }
 
 
+ConstElementPtr
+removeIdentical(ConstElementPtr a, ConstElementPtr b) {
+    ElementPtr result = Element::createMap();
+
+    if (!b) {
+        return (result);
+    }
+    
+    if (a->getType() != Element::map || b->getType() != Element::map) {
+        isc_throw(TypeError, "Non-map Elements passed to removeIdentical");
+    }
+
+    const std::map<std::string, ConstElementPtr>& m = a->mapValue();
+    for (std::map<std::string, ConstElementPtr>::const_iterator it = m.begin();
+         it != m.end() ; ++it) {
+        if (!b->contains((*it).first) ||
+            !a->get((*it).first)->equals(*b->get((*it).first))) {
+            result->set((*it).first, (*it).second);
+        }
+    }
+
+    return (result);
+}
+
 void
 void
-merge(ElementPtr element, const ElementPtr other) {
+merge(ElementPtr element, ConstElementPtr other) {
     if (element->getType() != Element::map ||
     if (element->getType() != Element::map ||
         other->getType() != Element::map) {
         other->getType() != Element::map) {
         isc_throw(TypeError, "merge arguments not MapElements");
         isc_throw(TypeError, "merge arguments not MapElements");
     }
     }
     
     
-    std::map<std::string, ElementPtr> m = other->mapValue();
-    for (std::map<std::string, ElementPtr>::const_iterator it = m.begin();
+    std::map<std::string, ConstElementPtr> m = other->mapValue();
+    for (std::map<std::string, ConstElementPtr>::const_iterator it = m.begin();
          it != m.end() ; ++it) {
          it != m.end() ; ++it) {
         if ((*it).second && (*it).second->getType() != Element::null) {
         if ((*it).second && (*it).second->getType() != Element::null) {
             element->set((*it).first, (*it).second);
             element->set((*it).first, (*it).second);

+ 106 - 68
src/lib/cc/data.h

@@ -29,6 +29,7 @@ namespace isc { namespace data {
 class Element;
 class Element;
 // todo: describe the rationale behind ElementPtr?
 // todo: describe the rationale behind ElementPtr?
 typedef boost::shared_ptr<Element> ElementPtr;
 typedef boost::shared_ptr<Element> ElementPtr;
+typedef boost::shared_ptr<const Element> ConstElementPtr;
 
 
 ///
 ///
 /// \brief A standard Data module exception that is thrown if a function
 /// \brief A standard Data module exception that is thrown if a function
@@ -90,7 +91,7 @@ public:
     virtual ~Element() {};
     virtual ~Element() {};
 
 
     /// \return the type of this element
     /// \return the type of this element
-    int getType() { return (type); }
+    int getType() const { return (type); }
 
 
     /// Returns a string representing the Element and all its
     /// Returns a string representing the Element and all its
     /// child elements; note that this is different from stringValue(),
     /// child elements; note that this is different from stringValue(),
@@ -99,24 +100,24 @@ public:
     /// The resulting string will contain the Element in JSON format.
     /// The resulting string will contain the Element in JSON format.
     ///
     ///
     /// \return std::string containing the string representation
     /// \return std::string containing the string representation
-    std::string str();
+    std::string str() const;
 
 
     /// Returns the wireformat for the Element and all its child
     /// Returns the wireformat for the Element and all its child
     /// elements.
     /// elements.
     ///
     ///
     /// \return std::string containing the element in wire format
     /// \return std::string containing the element in wire format
-    std::string toWire();
-    void toWire(std::ostream& out);
+    std::string toWire() const;
+    void toWire(std::ostream& out) const;
 
 
     /// \name pure virtuals, every derived class must implement these
     /// \name pure virtuals, every derived class must implement these
 
 
     /// \returns true if the other ElementPtr has the same type and
     /// \returns true if the other ElementPtr has the same type and
     ///          value
     ///          value
-    virtual bool equals(ElementPtr other) = 0;
+    virtual bool equals(const Element& other) const = 0;
     
     
     /// Converts the Element to JSON format and appends it to
     /// Converts the Element to JSON format and appends it to
     /// the given stringstream.
     /// the given stringstream.
-    virtual void toJSON(std::ostream& ss) = 0;
+    virtual void toJSON(std::ostream& ss) const = 0;
 
 
     /// \name Type-specific getters
     /// \name Type-specific getters
     ///
     ///
@@ -126,12 +127,22 @@ public:
     /// If you want an exception-safe getter method, use
     /// If you want an exception-safe getter method, use
     /// getValue() below
     /// getValue() below
     //@{
     //@{
-    virtual long int intValue() { isc_throw(TypeError, "intValue() called on non-integer Element"); };
-    virtual double doubleValue() { isc_throw(TypeError, "doubleValue() called on non-double Element"); };
-    virtual bool boolValue() { isc_throw(TypeError, "boolValue() called on non-Bool Element"); };
-    virtual std::string stringValue() { isc_throw(TypeError, "stringValue() called on non-string Element"); };
-    virtual const std::vector<boost::shared_ptr<Element> >& listValue() { isc_throw(TypeError, "listValue() called on non-list Element"); }; // replace with real exception or empty vector?
-    virtual const std::map<std::string, boost::shared_ptr<Element> >& mapValue() { isc_throw(TypeError, "mapValue() called on non-map Element"); }; // replace with real exception or empty map?
+    virtual long int intValue() const
+    { isc_throw(TypeError, "intValue() called on non-integer Element"); };
+    virtual double doubleValue() const
+    { isc_throw(TypeError, "doubleValue() called on non-double Element"); };
+    virtual bool boolValue() const
+    { isc_throw(TypeError, "boolValue() called on non-Bool Element"); };
+    virtual std::string stringValue() const
+    { isc_throw(TypeError, "stringValue() called on non-string Element"); };
+    virtual const std::vector<ConstElementPtr>& listValue() const {
+        // replace with real exception or empty vector?
+        isc_throw(TypeError, "listValue() called on non-list Element");
+    };
+    virtual const std::map<std::string, ConstElementPtr>& mapValue() const {
+        // replace with real exception or empty map?
+        isc_throw(TypeError, "mapValue() called on non-map Element");
+    };
     //@}
     //@}
 
 
     /// \name Exception-safe getters
     /// \name Exception-safe getters
@@ -147,8 +158,8 @@ public:
     virtual bool getValue(double& t);
     virtual bool getValue(double& t);
     virtual bool getValue(bool& t);
     virtual bool getValue(bool& t);
     virtual bool getValue(std::string& t);
     virtual bool getValue(std::string& t);
-    virtual bool getValue(std::vector<ElementPtr>& t);
-    virtual bool getValue(std::map<std::string, ElementPtr>& t);
+    virtual bool getValue(std::vector<ConstElementPtr>& t);
+    virtual bool getValue(std::map<std::string, ConstElementPtr>& t);
     //@}
     //@}
 
 
     ///
     ///
@@ -163,8 +174,8 @@ public:
     virtual bool setValue(const double v);
     virtual bool setValue(const double v);
     virtual bool setValue(const bool t);
     virtual bool setValue(const bool t);
     virtual bool setValue(const std::string& v);
     virtual bool setValue(const std::string& v);
-    virtual bool setValue(const std::vector<ElementPtr>& v);
-    virtual bool setValue(const std::map<std::string, ElementPtr>& v);
+    virtual bool setValue(const std::vector<ConstElementPtr>& v);
+    virtual bool setValue(const std::map<std::string, ConstElementPtr>& v);
     //@}
     //@}
 
 
 
 
@@ -179,17 +190,17 @@ public:
     /// Returns the ElementPtr at the given index. If the index is out
     /// Returns the ElementPtr at the given index. If the index is out
     /// of bounds, this function throws an std::out_of_range exception.
     /// of bounds, this function throws an std::out_of_range exception.
     /// \param i The position of the ElementPtr to return
     /// \param i The position of the ElementPtr to return
-    virtual ElementPtr get(const int i);
+    virtual ConstElementPtr get(const int i) const;
 
 
     /// Sets the ElementPtr at the given index. If the index is out
     /// Sets the ElementPtr at the given index. If the index is out
     /// of bounds, this function throws an std::out_of_range exception.
     /// of bounds, this function throws an std::out_of_range exception.
     /// \param i The position of the ElementPtr to set
     /// \param i The position of the ElementPtr to set
     /// \param element The ElementPtr to set at the position
     /// \param element The ElementPtr to set at the position
-    virtual void set(const size_t i, ElementPtr element);
+    virtual void set(const size_t i, ConstElementPtr element);
 
 
     /// Adds an ElementPtr to the list
     /// Adds an ElementPtr to the list
     /// \param element The ElementPtr to add
     /// \param element The ElementPtr to add
-    virtual void add(ElementPtr element);
+    virtual void add(ConstElementPtr element);
 
 
     /// Removes the element at the given position. If the index is out
     /// Removes the element at the given position. If the index is out
     /// of nothing happens.
     /// of nothing happens.
@@ -197,7 +208,7 @@ public:
     virtual void remove(const int i);
     virtual void remove(const int i);
 
 
     /// Returns the number of elements in the list.
     /// Returns the number of elements in the list.
-    virtual size_t size();
+    virtual size_t size() const;
     //@}
     //@}
 
 
     
     
@@ -209,11 +220,11 @@ public:
     /// Returns the ElementPtr at the given key
     /// Returns the ElementPtr at the given key
     /// \param name The key of the Element to return
     /// \param name The key of the Element to return
     /// \return The ElementPtr at the given key
     /// \return The ElementPtr at the given key
-    virtual ElementPtr get(const std::string& name);
+    virtual ConstElementPtr get(const std::string& name) const;
 
 
     /// Sets the ElementPtr at the given key
     /// Sets the ElementPtr at the given key
     /// \param name The key of the Element to set
     /// \param name The key of the Element to set
-    virtual void set(const std::string& name, ElementPtr element);
+    virtual void set(const std::string& name, ConstElementPtr element);
 
 
     /// Remove the ElementPtr at the given key
     /// Remove the ElementPtr at the given key
     /// \param name The key of the Element to remove
     /// \param name The key of the Element to remove
@@ -222,7 +233,7 @@ public:
     /// Checks if there is data at the given key
     /// Checks if there is data at the given key
     /// \param name The key of the Element to remove
     /// \param name The key of the Element to remove
     /// \return true if there is data at the key, false if not.
     /// \return true if there is data at the key, false if not.
-    virtual bool contains(const std::string& name);
+    virtual bool contains(const std::string& name) const;
 
 
     /// Recursively finds any data at the given identifier. The
     /// Recursively finds any data at the given identifier. The
     /// identifier is a /-separated list of names of nested maps, with
     /// identifier is a /-separated list of names of nested maps, with
@@ -237,13 +248,13 @@ public:
     /// \return The ElementPtr at the given identifier. Returns a
     /// \return The ElementPtr at the given identifier. Returns a
     /// null ElementPtr if it is not found, which can be checked with
     /// null ElementPtr if it is not found, which can be checked with
     /// Element::is_null(ElementPtr e).
     /// Element::is_null(ElementPtr e).
-    virtual ElementPtr find(const std::string& identifier);
+    virtual ConstElementPtr find(const std::string& identifier) const;
 
 
     /// See \c Element::find()
     /// See \c Element::find()
     /// \param identifier The identifier of the element to find
     /// \param identifier The identifier of the element to find
     /// \param t Reference to store the resulting ElementPtr, if found.
     /// \param t Reference to store the resulting ElementPtr, if found.
     /// \return true if the element was found, false if not.
     /// \return true if the element was found, false if not.
-    virtual bool find(const std::string& identifier, ElementPtr& t);
+    virtual bool find(const std::string& identifier, ConstElementPtr t) const;
     //@}
     //@}
 
 
 
 
@@ -365,13 +376,13 @@ class IntElement : public Element {
 
 
 public:
 public:
     IntElement(long int v) : Element(integer), i(v) { }
     IntElement(long int v) : Element(integer), i(v) { }
-    long int intValue() { return (i); }
+    long int intValue() const { return (i); }
     using Element::getValue;
     using Element::getValue;
     bool getValue(long int& t) { t = i; return (true); }
     bool getValue(long int& t) { t = i; return (true); }
     using Element::setValue;
     using Element::setValue;
     bool setValue(const long int v) { i = v; return (true); }
     bool setValue(const long int v) { i = v; return (true); }
-    void toJSON(std::ostream& ss);
-    bool equals(ElementPtr other);
+    void toJSON(std::ostream& ss) const;
+    bool equals(const Element& other) const;
 };
 };
 
 
 class DoubleElement : public Element {
 class DoubleElement : public Element {
@@ -379,13 +390,13 @@ class DoubleElement : public Element {
 
 
 public:
 public:
     DoubleElement(double v) : Element(real), d(v) {};
     DoubleElement(double v) : Element(real), d(v) {};
-    double doubleValue() { return (d); }
+    double doubleValue() const { return (d); }
     using Element::getValue;
     using Element::getValue;
     bool getValue(double& t) { t = d; return (true); }
     bool getValue(double& t) { t = d; return (true); }
     using Element::setValue;
     using Element::setValue;
     bool setValue(const double v) { d = v; return (true); }
     bool setValue(const double v) { d = v; return (true); }
-    void toJSON(std::ostream& ss);
-    bool equals(ElementPtr other);
+    void toJSON(std::ostream& ss) const;
+    bool equals(const Element& other) const;
 };
 };
 
 
 class BoolElement : public Element {
 class BoolElement : public Element {
@@ -393,20 +404,20 @@ class BoolElement : public Element {
 
 
 public:
 public:
     BoolElement(const bool v) : Element(boolean), b(v) {};
     BoolElement(const bool v) : Element(boolean), b(v) {};
-    bool boolValue() { return (b); }
+    bool boolValue() const { return (b); }
     using Element::getValue;
     using Element::getValue;
     bool getValue(bool& t) { t = b; return (true); }
     bool getValue(bool& t) { t = b; return (true); }
     using Element::setValue;
     using Element::setValue;
     bool setValue(const bool v) { b = v; return (true); }
     bool setValue(const bool v) { b = v; return (true); }
-    void toJSON(std::ostream& ss);
-    bool equals(ElementPtr other);
+    void toJSON(std::ostream& ss) const;
+    bool equals(const Element& other) const;
 };
 };
 
 
 class NullElement : public Element {
 class NullElement : public Element {
 public:
 public:
     NullElement() : Element(null) {};
     NullElement() : Element(null) {};
-    void toJSON(std::ostream& ss);
-    bool equals(ElementPtr other);
+    void toJSON(std::ostream& ss) const;
+    bool equals(const Element& other) const;
 };
 };
 
 
 class StringElement : public Element {
 class StringElement : public Element {
@@ -414,77 +425,97 @@ class StringElement : public Element {
 
 
 public:
 public:
     StringElement(std::string v) : Element(string), s(v) {};
     StringElement(std::string v) : Element(string), s(v) {};
-    std::string stringValue() { return (s); }
+    std::string stringValue() const { return (s); }
     using Element::getValue;
     using Element::getValue;
     bool getValue(std::string& t) { t = s; return (true); }
     bool getValue(std::string& t) { t = s; return (true); }
     using Element::setValue;
     using Element::setValue;
     bool setValue(const std::string& v) { s = v; return (true); }
     bool setValue(const std::string& v) { s = v; return (true); }
-    void toJSON(std::ostream& ss);
-    bool equals(ElementPtr other);
+    void toJSON(std::ostream& ss) const;
+    bool equals(const Element& other) const;
 };
 };
 
 
 class ListElement : public Element {
 class ListElement : public Element {
-    std::vector<ElementPtr> l;
+    std::vector<ConstElementPtr> l;
 
 
 public:
 public:
-    ListElement() : Element(list), l(std::vector<ElementPtr>()) {};
-    const std::vector<ElementPtr>& listValue() { return (l); }
+    ListElement() : Element(list) {}
+    const std::vector<ConstElementPtr>& listValue() const { return (l); }
     using Element::getValue;
     using Element::getValue;
-    bool getValue(std::vector<ElementPtr>& t) { t = l; return (true); }
+    bool getValue(std::vector<ConstElementPtr>& t) {
+        t = l;
+        return (true);
+    }
     using Element::setValue;
     using Element::setValue;
-    bool setValue(const std::vector<ElementPtr>& v) { l = v; return (true); }
+    bool setValue(const std::vector<ConstElementPtr>& v) {
+        l = v;
+        return (true);
+    }
     using Element::get;
     using Element::get;
-    ElementPtr get(int i) { return (l.at(i)); }
+    ConstElementPtr get(int i) const { return (l.at(i)); }
     using Element::set;
     using Element::set;
-    void set(size_t i, ElementPtr e) { if (i <= l.size()) {l[i] = e;} else { throw std::out_of_range("vector::_M_range_check"); } };
-    void add(ElementPtr e) { l.push_back(e); };
+    void set(size_t i, ConstElementPtr e) {
+        l.at(i) = e;
+    }
+    void add(ConstElementPtr e) { l.push_back(e); };
     using Element::remove;
     using Element::remove;
     void remove(int i) { l.erase(l.begin() + i); };
     void remove(int i) { l.erase(l.begin() + i); };
-    void toJSON(std::ostream& ss);
-    size_t size() { return (l.size()); }
-    bool equals(ElementPtr other);
+    void toJSON(std::ostream& ss) const;
+    size_t size() const { return (l.size()); }
+    bool equals(const Element& other) const;
 };
 };
 
 
 class MapElement : public Element {
 class MapElement : public Element {
-    std::map<std::string, ElementPtr> m;
+    std::map<std::string, ConstElementPtr> m;
 
 
 public:
 public:
-    MapElement() : Element(map), m(std::map<std::string, ElementPtr>()) {};
+    MapElement() : Element(map) {}
     // TODO: should we have direct iterators instead of exposing the std::map here?
     // TODO: should we have direct iterators instead of exposing the std::map here?
-    const std::map<std::string, ElementPtr>& mapValue() { return (m); }
+    const std::map<std::string, ConstElementPtr>& mapValue() const {
+        return (m);
+    }
     using Element::getValue;
     using Element::getValue;
-    bool getValue(std::map<std::string, ElementPtr>& t) { t = m; return (true); }
+    bool getValue(std::map<std::string, ConstElementPtr>& t) {
+        t = m;
+        return (true);
+    }
     using Element::setValue;
     using Element::setValue;
-    bool setValue(std::map<std::string, ElementPtr>& v) { m = v; return (true); }
+    bool setValue(std::map<std::string, ConstElementPtr>& v) {
+        m = v;
+        return (true);
+    }
     using Element::get;
     using Element::get;
-    ElementPtr get(const std::string& s) { if (contains(s)) { return (m[s]); } else { return (ElementPtr());} }
+    ConstElementPtr get(const std::string& s) const {
+        return (contains(s) ? m.find(s)->second : ElementPtr());
+    };
     using Element::set;
     using Element::set;
-    void set(const std::string& key, ElementPtr value);
+    void set(const std::string& key, ConstElementPtr value);
     using Element::remove;
     using Element::remove;
     void remove(const std::string& s) { m.erase(s); }
     void remove(const std::string& s) { m.erase(s); }
-    bool contains(const std::string& s) { return (m.find(s) != m.end()); }
-    void toJSON(std::ostream& ss);
+    bool contains(const std::string& s) const {
+        return (m.find(s) != m.end());
+    }
+    void toJSON(std::ostream& ss) const;
     
     
     // we should name the two finds better...
     // we should name the two finds better...
     // find the element at id; raises TypeError if one of the
     // find the element at id; raises TypeError if one of the
     // elements at path except the one we're looking for is not a
     // elements at path except the one we're looking for is not a
     // mapelement.
     // mapelement.
     // returns an empty element if the item could not be found
     // returns an empty element if the item could not be found
-    ElementPtr find(const std::string& id);
+    ConstElementPtr find(const std::string& id) const;
 
 
     // find the Element at 'id', and store the element pointer in t
     // find the Element at 'id', and store the element pointer in t
     // returns true if found, or false if not found (either because
     // returns true if found, or false if not found (either because
     // it doesnt exist or one of the elements in the path is not
     // it doesnt exist or one of the elements in the path is not
     // a MapElement)
     // a MapElement)
-    bool find(const std::string& id, ElementPtr& t);
+    bool find(const std::string& id, ConstElementPtr t) const;
 
 
-    bool equals(ElementPtr other);
+    bool equals(const Element& other) const;
 };
 };
 
 
 /// Checks whether the given ElementPtr is a NULL pointer
 /// Checks whether the given ElementPtr is a NULL pointer
 /// \param p The ElementPtr to check
 /// \param p The ElementPtr to check
 /// \return true if it is NULL, false if not.
 /// \return true if it is NULL, false if not.
-bool isNull(ElementPtr p);
+bool isNull(ConstElementPtr p);
 
 
 ///
 ///
 /// \brief Remove all values from the first ElementPtr that are
 /// \brief Remove all values from the first ElementPtr that are
@@ -493,7 +524,14 @@ bool isNull(ElementPtr p);
 /// only contains new and changed values (for ModuleCCSession and
 /// only contains new and changed values (for ModuleCCSession and
 /// configuration update handlers)
 /// configuration update handlers)
 /// Raises a TypeError if a or b are not MapElements
 /// Raises a TypeError if a or b are not MapElements
-void removeIdentical(ElementPtr a, const ElementPtr b);
+void removeIdentical(ElementPtr a, ConstElementPtr b);
+
+/// \brief Create a new ElementPtr from the first ElementPtr, removing all
+/// values that are equal in the second. Both ElementPtrs MUST be MapElements.
+/// The returned ElementPtr will be 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
+ConstElementPtr removeIdentical(ConstElementPtr a, ConstElementPtr b);
 
 
 /// \brief Merges the data from other into element.
 /// \brief Merges the data from other into element.
 /// (on the first level). Both elements must be
 /// (on the first level). Both elements must be
@@ -507,7 +545,7 @@ void removeIdentical(ElementPtr a, const ElementPtr b);
 /// configuration data (which would then result in reverting back
 /// configuration data (which would then result in reverting back
 /// to the default).
 /// to the default).
 /// Raises a TypeError if either ElementPtr is not a MapElement
 /// Raises a TypeError if either ElementPtr is not a MapElement
-void merge(ElementPtr element, const ElementPtr other);
+void merge(ElementPtr element, ConstElementPtr other);
 
 
 ///
 ///
 /// \brief Insert the Element as a string into stream.
 /// \brief Insert the Element as a string into stream.
@@ -524,11 +562,11 @@ void merge(ElementPtr element, const ElementPtr other);
 /// \param e The \c ElementPtr object to insert.
 /// \param e The \c ElementPtr object to insert.
 /// \return A reference to the same \c std::ostream object referenced by
 /// \return A reference to the same \c std::ostream object referenced by
 /// parameter \c os after the insertion operation.
 /// parameter \c os after the insertion operation.
-std::ostream& operator <<(std::ostream &out, const isc::data::ElementPtr& e);
+std::ostream& operator<<(std::ostream& out, const Element& e);
 
 
-bool operator==(const isc::data::ElementPtr a, const isc::data::ElementPtr b);
+bool operator==(const Element& a, const Element& b);
+bool operator!=(const Element& a, const Element& b);
 } }
 } }
-
 #endif // _ISC_DATA_H
 #endif // _ISC_DATA_H
 
 
 // Local Variables: 
 // Local Variables: 

+ 18 - 16
src/lib/cc/session.cc

@@ -296,11 +296,11 @@ Session::establish(const char* socket_file) {
     //
     //
     // send a request for our local name, and wait for a response
     // send a request for our local name, and wait for a response
     //
     //
-    ElementPtr get_lname_msg =
+    ConstElementPtr get_lname_msg =
         Element::fromJSON("{ \"type\": \"getlname\" }");
         Element::fromJSON("{ \"type\": \"getlname\" }");
     sendmsg(get_lname_msg);
     sendmsg(get_lname_msg);
 
 
-    ElementPtr routing, msg;
+    ConstElementPtr routing, msg;
     recvmsg(routing, msg, false);
     recvmsg(routing, msg, false);
 
 
     impl_->lname_ = msg->get("lname")->stringValue();
     impl_->lname_ = msg->get("lname")->stringValue();
@@ -314,7 +314,7 @@ Session::establish(const char* socket_file) {
 // prefix.
 // prefix.
 //
 //
 void
 void
-Session::sendmsg(ElementPtr& msg) {
+Session::sendmsg(ConstElementPtr msg) {
     std::string header_wire = msg->toWire();
     std::string header_wire = msg->toWire();
     unsigned int length = 2 + header_wire.length();
     unsigned int length = 2 + header_wire.length();
     unsigned int length_net = htonl(length);
     unsigned int length_net = htonl(length);
@@ -327,7 +327,7 @@ Session::sendmsg(ElementPtr& msg) {
 }
 }
 
 
 void
 void
-Session::sendmsg(ElementPtr& env, ElementPtr& msg) {
+Session::sendmsg(ConstElementPtr env, ConstElementPtr msg) {
     std::string header_wire = env->toWire();
     std::string header_wire = env->toWire();
     std::string body_wire = msg->toWire();
     std::string body_wire = msg->toWire();
     unsigned int length = 2 + header_wire.length() + body_wire.length();
     unsigned int length = 2 + header_wire.length() + body_wire.length();
@@ -342,18 +342,18 @@ Session::sendmsg(ElementPtr& env, ElementPtr& msg) {
 }
 }
 
 
 bool
 bool
-Session::recvmsg(ElementPtr& msg, bool nonblock, int seq) {
-    ElementPtr l_env;
+Session::recvmsg(ConstElementPtr& msg, bool nonblock, int seq) {
+    ConstElementPtr l_env;
     return (recvmsg(l_env, msg, nonblock, seq));
     return (recvmsg(l_env, msg, nonblock, seq));
 }
 }
 
 
 bool
 bool
-Session::recvmsg(ElementPtr& env, ElementPtr& msg,
-                 bool nonblock, int seq) {
+Session::recvmsg(ConstElementPtr& env, ConstElementPtr& msg,
+                 bool nonblock, int seq)
+{
     size_t length = impl_->readDataLength();
     size_t length = impl_->readDataLength();
-    ElementPtr l_env, l_msg;
     if (hasQueuedMsgs()) {
     if (hasQueuedMsgs()) {
-        ElementPtr q_el;
+        ConstElementPtr q_el;
         for (int i = 0; i < impl_->queue_->size(); i++) {
         for (int i = 0; i < impl_->queue_->size(); i++) {
             q_el = impl_->queue_->get(i);
             q_el = impl_->queue_->get(i);
             if (( seq == -1 &&
             if (( seq == -1 &&
@@ -390,11 +390,13 @@ Session::recvmsg(ElementPtr& env, ElementPtr& msg,
                                         length - header_length);
                                         length - header_length);
     std::stringstream header_wire_stream;
     std::stringstream header_wire_stream;
     header_wire_stream << header_wire;
     header_wire_stream << header_wire;
-    l_env = Element::fromWire(header_wire_stream, header_length);
+    ConstElementPtr l_env =
+        Element::fromWire(header_wire_stream, header_length);
     
     
     std::stringstream body_wire_stream;
     std::stringstream body_wire_stream;
     body_wire_stream << body_wire;
     body_wire_stream << body_wire;
-    l_msg = Element::fromWire(body_wire_stream, length - header_length);
+    ConstElementPtr l_msg =
+        Element::fromWire(body_wire_stream, length - header_length);
     if ((seq == -1 &&
     if ((seq == -1 &&
          !l_env->contains("reply")
          !l_env->contains("reply")
         ) || (
         ) || (
@@ -438,7 +440,7 @@ Session::unsubscribe(std::string group, std::string instance) {
 }
 }
 
 
 int
 int
-Session::group_sendmsg(ElementPtr msg, std::string group,
+Session::group_sendmsg(ConstElementPtr msg, std::string group,
                        std::string instance, std::string to)
                        std::string instance, std::string to)
 {
 {
     ElementPtr env = Element::createMap();
     ElementPtr env = Element::createMap();
@@ -457,14 +459,14 @@ Session::group_sendmsg(ElementPtr msg, std::string group,
 }
 }
 
 
 bool
 bool
-Session::group_recvmsg(ElementPtr& envelope, ElementPtr& msg,
+Session::group_recvmsg(ConstElementPtr& envelope, ConstElementPtr& msg,
                        bool nonblock, int seq)
                        bool nonblock, int seq)
 {
 {
     return (recvmsg(envelope, msg, nonblock, seq));
     return (recvmsg(envelope, msg, nonblock, seq));
 }
 }
 
 
 int
 int
-Session::reply(ElementPtr& envelope, ElementPtr& newmsg) {
+Session::reply(ConstElementPtr envelope, ConstElementPtr newmsg) {
     ElementPtr env = Element::createMap();
     ElementPtr env = Element::createMap();
     long int nseq = ++impl_->sequence_;
     long int nseq = ++impl_->sequence_;
     
     
@@ -482,7 +484,7 @@ Session::reply(ElementPtr& envelope, ElementPtr& newmsg) {
 }
 }
 
 
 bool
 bool
-Session::hasQueuedMsgs() {
+Session::hasQueuedMsgs() const {
     return (impl_->queue_->size() > 0);
     return (impl_->queue_->size() > 0);
 }
 }
 
 

+ 18 - 18
src/lib/cc/session.h

@@ -81,12 +81,12 @@ namespace isc {
             //@}
             //@}
             virtual void establish(const char* socket_file) = 0;
             virtual void establish(const char* socket_file) = 0;
             virtual void disconnect() = 0;
             virtual void disconnect() = 0;
-            virtual int group_sendmsg(isc::data::ElementPtr msg,
+            virtual int group_sendmsg(isc::data::ConstElementPtr msg,
                                       std::string group,
                                       std::string group,
                                       std::string instance = "*",
                                       std::string instance = "*",
                                       std::string to = "*") = 0;
                                       std::string to = "*") = 0;
-            virtual bool group_recvmsg(isc::data::ElementPtr& envelope,
-                                       isc::data::ElementPtr& msg,
+            virtual bool group_recvmsg(isc::data::ConstElementPtr& envelope,
+                                       isc::data::ConstElementPtr& msg,
                                        bool nonblock = true,
                                        bool nonblock = true,
                                        int seq = -1) = 0;
                                        int seq = -1) = 0;
             virtual void subscribe(std::string group,
             virtual void subscribe(std::string group,
@@ -94,9 +94,9 @@ namespace isc {
             virtual void unsubscribe(std::string group,
             virtual void unsubscribe(std::string group,
                              std::string instance = "*") = 0;
                              std::string instance = "*") = 0;
             virtual void startRead(boost::function<void()> read_callback) = 0;
             virtual void startRead(boost::function<void()> read_callback) = 0;
-            virtual int reply(isc::data::ElementPtr& envelope,
-                               isc::data::ElementPtr& newmsg) = 0;
-            virtual bool hasQueuedMsgs() = 0;
+            virtual int reply(isc::data::ConstElementPtr envelope,
+                               isc::data::ConstElementPtr newmsg) = 0;
+            virtual bool hasQueuedMsgs() const = 0;
 
 
             /// \brief Sets the default timeout for blocking reads
             /// \brief Sets the default timeout for blocking reads
             ///        in this session to the given number of milliseconds
             ///        in this session to the given number of milliseconds
@@ -130,28 +130,28 @@ namespace isc {
                                    std::string instance = "*");
                                    std::string instance = "*");
             virtual void unsubscribe(std::string group,
             virtual void unsubscribe(std::string group,
                              std::string instance = "*");
                              std::string instance = "*");
-            virtual int group_sendmsg(isc::data::ElementPtr msg,
+            virtual int group_sendmsg(isc::data::ConstElementPtr msg,
                                       std::string group,
                                       std::string group,
                                       std::string instance = "*",
                                       std::string instance = "*",
                                       std::string to = "*");
                                       std::string to = "*");
-            virtual bool group_recvmsg(isc::data::ElementPtr& envelope,
-                                       isc::data::ElementPtr& msg,
+            virtual bool group_recvmsg(isc::data::ConstElementPtr& envelope,
+                                       isc::data::ConstElementPtr& msg,
                                        bool nonblock = true,
                                        bool nonblock = true,
                                        int seq = -1);
                                        int seq = -1);
-            virtual int reply(isc::data::ElementPtr& envelope,
-                              isc::data::ElementPtr& newmsg);
-            virtual bool hasQueuedMsgs();
+            virtual int reply(isc::data::ConstElementPtr envelope,
+                              isc::data::ConstElementPtr newmsg);
+            virtual bool hasQueuedMsgs() const;
             virtual void setTimeout(size_t milliseconds);
             virtual void setTimeout(size_t milliseconds);
             virtual size_t getTimeout() const;
             virtual size_t getTimeout() const;
     private:
     private:
-            void sendmsg(isc::data::ElementPtr& msg);
-            void sendmsg(isc::data::ElementPtr& env,
-                         isc::data::ElementPtr& msg);
-            bool recvmsg(isc::data::ElementPtr& msg,
+            void sendmsg(isc::data::ConstElementPtr msg);
+            void sendmsg(isc::data::ConstElementPtr env,
+                         isc::data::ConstElementPtr msg);
+            bool recvmsg(isc::data::ConstElementPtr& msg,
                          bool nonblock = true,
                          bool nonblock = true,
                          int seq = -1);
                          int seq = -1);
-            bool recvmsg(isc::data::ElementPtr& env,
-                         isc::data::ElementPtr& msg,
+            bool recvmsg(isc::data::ConstElementPtr& env,
+                         isc::data::ConstElementPtr& msg,
                          bool nonblock = true,
                          bool nonblock = true,
                          int seq = -1);
                          int seq = -1);
         };
         };

+ 141 - 92
src/lib/cc/tests/data_unittests.cc

@@ -29,6 +29,7 @@ using std::setfill;
 using std::setw;
 using std::setw;
 using std::string;
 using std::string;
 
 
+namespace {
 TEST(Element, type) {
 TEST(Element, type) {
     // this tests checks whether the getType() function returns the
     // this tests checks whether the getType() function returns the
     // correct type
     // correct type
@@ -73,7 +74,7 @@ TEST(Element, from_and_to_json) {
     // a set of inputs that are the same when converted to json and
     // a set of inputs that are the same when converted to json and
     // back to a string (tests for inputs that have equivalent, but
     // back to a string (tests for inputs that have equivalent, but
     // different string representations when converted back are below)
     // different string representations when converted back are below)
-    ElementPtr el;
+    ConstElementPtr el;
     std::vector<std::string> sv;
     std::vector<std::string> sv;
 
 
     sv.push_back("12");
     sv.push_back("12");
@@ -92,25 +93,25 @@ TEST(Element, from_and_to_json) {
     sv.push_back("-1.234");
     sv.push_back("-1.234");
     sv.push_back("-123.456");
     sv.push_back("-123.456");
     
     
-    BOOST_FOREACH(std::string s, sv) {
+    BOOST_FOREACH(const std::string& s, sv) {
         // test << operator, which uses Element::str()
         // test << operator, which uses Element::str()
         std::ostringstream stream;
         std::ostringstream stream;
         el = Element::fromJSON(s);
         el = Element::fromJSON(s);
-        stream << el;
-        EXPECT_EQ(stream.str(), s);
+        stream << *el;
+        EXPECT_EQ(s, stream.str());
 
 
         // test toWire(ostream), which should also be the same now
         // test toWire(ostream), which should also be the same now
         std::ostringstream wire_stream;
         std::ostringstream wire_stream;
         el->toWire(wire_stream);
         el->toWire(wire_stream);
-        EXPECT_EQ(wire_stream.str(), s);
+        EXPECT_EQ(s, wire_stream.str());
     }
     }
 
 
     // some parse errors
     // some parse errors
     try {
     try {
         Element::fromJSON("{1}");
         Element::fromJSON("{1}");
-    } catch (isc::data::JSONError pe) {
+    } catch (const isc::data::JSONError& pe) {
         std::string s = std::string(pe.what());
         std::string s = std::string(pe.what());
-        EXPECT_EQ(s, "String expected in <string>:1:3");
+        EXPECT_EQ("String expected in <string>:1:3", s);
     }
     }
     
     
     sv.clear();
     sv.clear();
@@ -169,9 +170,8 @@ TEST(Element, create_and_value_throws) {
     double d;
     double d;
     bool b;
     bool b;
     std::string s("asdf");
     std::string s("asdf");
-    std::vector<ElementPtr> v;
-    std::map<std::string, ElementPtr> m;
-    
+    std::vector<ConstElementPtr> v;
+    std::map<std::string, ConstElementPtr> m;
 
 
     el = Element::create(1);
     el = Element::create(1);
     EXPECT_NO_THROW(el->intValue());
     EXPECT_NO_THROW(el->intValue());
@@ -204,7 +204,7 @@ TEST(Element, create_and_value_throws) {
     EXPECT_THROW(el->set("foo", el), TypeError);
     EXPECT_THROW(el->set("foo", el), TypeError);
     EXPECT_THROW(el->remove("foo"), TypeError);
     EXPECT_THROW(el->remove("foo"), TypeError);
     EXPECT_THROW(el->contains("foo"), TypeError);
     EXPECT_THROW(el->contains("foo"), TypeError);
-    ElementPtr tmp;
+    ConstElementPtr tmp;
     EXPECT_FALSE(el->find("foo", tmp));
     EXPECT_FALSE(el->find("foo", tmp));
     
     
 
 
@@ -322,13 +322,19 @@ TEST(Element, ListElement) {
     EXPECT_ANY_THROW(el->get(3));
     EXPECT_ANY_THROW(el->get(3));
 
 
     el->add(Element::create(32));
     el->add(Element::create(32));
-    EXPECT_EQ(el->get(2)->intValue(), 32);
+    EXPECT_EQ(32, el->get(2)->intValue());
+
+    // boundary condition tests for set()
+    el->set(2, Element::create(0)); // update the last entry of the list
+    EXPECT_EQ(0, el->get(2)->intValue());
+    // attempt of set beyond the range of list should trigger an exception.
+    EXPECT_ANY_THROW(el->set(3, Element::create(0)));
 }
 }
 
 
 TEST(Element, MapElement) {
 TEST(Element, MapElement) {
     // this function checks the specific functions for ListElements
     // this function checks the specific functions for ListElements
     ElementPtr el = Element::fromJSON("{ \"name\": \"foo\", \"value1\": \"bar\", \"value2\": { \"number\": 42 } }");
     ElementPtr el = Element::fromJSON("{ \"name\": \"foo\", \"value1\": \"bar\", \"value2\": { \"number\": 42 } }");
-    ElementPtr el2;
+    ConstElementPtr el2;
     
     
     EXPECT_EQ(el->get("name")->stringValue(), "foo");
     EXPECT_EQ(el->get("name")->stringValue(), "foo");
     EXPECT_EQ(el->get("value2")->getType(), Element::map);
     EXPECT_EQ(el->get("value2")->getType(), Element::map);
@@ -376,7 +382,6 @@ TEST(Element, MapElement) {
 
 
 TEST(Element, to_and_from_wire) {
 TEST(Element, to_and_from_wire) {
     // Wire format is now plain JSON.
     // Wire format is now plain JSON.
-    ElementPtr el;
     EXPECT_EQ("1", Element::create(1)->toWire());
     EXPECT_EQ("1", Element::create(1)->toWire());
     EXPECT_EQ("1.1", Element::create(1.1)->toWire());
     EXPECT_EQ("1.1", Element::create(1.1)->toWire());
     EXPECT_EQ("true", Element::create(true)->toWire());
     EXPECT_EQ("true", Element::create(true)->toWire());
@@ -398,124 +403,167 @@ TEST(Element, to_and_from_wire) {
     EXPECT_THROW(Element::fromJSON("[ 1, 2, }"), isc::data::JSONError);
     EXPECT_THROW(Element::fromJSON("[ 1, 2, }"), isc::data::JSONError);
 }
 }
 
 
-static ElementPtr
+ConstElementPtr
 efs(const std::string& str) {
 efs(const std::string& str) {
     return (Element::fromJSON(str));
     return (Element::fromJSON(str));
 }
 }
 
 
 TEST(Element, equals) {
 TEST(Element, equals) {
-    // why does EXPECT_EQ not work?
-    EXPECT_EQ(efs("1"), efs("1"));
-    EXPECT_NE(efs("1"), efs("2"));
-    EXPECT_NE(efs("1"), efs("\"1\""));
-    EXPECT_NE(efs("1"), efs("[]"));
-    EXPECT_NE(efs("1"), efs("True"));
-    EXPECT_NE(efs("1"), efs("{}"));
-
-    EXPECT_EQ(efs("1.1"), efs("1.1"));
-    EXPECT_NE(efs("1.0"), efs("1"));
-    EXPECT_NE(efs("1.1"), efs("\"1\""));
-    EXPECT_NE(efs("1.1"), efs("[]"));
-    EXPECT_NE(efs("1.1"), efs("True"));
-    EXPECT_NE(efs("1.1"), efs("{}"));
-
-    EXPECT_EQ(efs("True"), efs("True"));
-    EXPECT_NE(efs("True"), efs("False"));
-    EXPECT_NE(efs("True"), efs("1"));
-    EXPECT_NE(efs("True"), efs("\"1\""));
-    EXPECT_NE(efs("True"), efs("[]"));
-    EXPECT_NE(efs("True"), efs("{}"));
-
-    EXPECT_EQ(efs("\"foo\""), efs("\"foo\""));
-    EXPECT_NE(efs("\"foo\""), efs("\"bar\""));
-    EXPECT_NE(efs("\"foo\""), efs("1"));
-    EXPECT_NE(efs("\"foo\""), efs("\"1\""));
-    EXPECT_NE(efs("\"foo\""), efs("True"));
-    EXPECT_NE(efs("\"foo\""), efs("[]"));
-    EXPECT_NE(efs("\"foo\""), efs("{}"));
-
-    EXPECT_EQ(efs("[]"), efs("[]"));
-    EXPECT_EQ(efs("[ 1, 2, 3 ]"), efs("[ 1, 2, 3 ]"));
-    EXPECT_EQ(efs("[ \"a\", [ True, 1], 2.2 ]"), efs("[ \"a\", [ True, 1], 2.2 ]"));
-    EXPECT_NE(efs("[ \"a\", [ True, 1], 2.2 ]"), efs("[ \"a\", [ True, 2], 2.2 ]"));
-    EXPECT_NE(efs("[]"), efs("[1]"));
-    EXPECT_NE(efs("[]"), efs("1"));
-    EXPECT_NE(efs("[]"), efs("\"1\""));
-    EXPECT_NE(efs("[]"), efs("{}"));
-
-    EXPECT_EQ(efs("{}"), efs("{}"));
-    EXPECT_EQ(efs("{ \"foo\": \"bar\" }"), efs("{ \"foo\": \"bar\" }"));
-    EXPECT_EQ(efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }"), efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }"));
-    EXPECT_NE(efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }"), efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar2\" } }"));
-    EXPECT_NE(efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }"), efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\", 1 ], \"item3\": { \"foo\": \"bar\" } }"));
-    EXPECT_NE(efs("{ \"foo\": \"bar\" }"), efs("1"));
-    EXPECT_NE(efs("{ \"foo\": \"bar\" }"), efs("\"1\""));
-    EXPECT_NE(efs("{ \"foo\": \"bar\" }"), efs("[]"));
-    EXPECT_NE(efs("{ \"foo\": \"bar\" }"), efs("{}"));
-    EXPECT_NE(efs("{ \"foo\": \"bar\" }"), efs("{ \"something\": \"different\" }"));
-
-    EXPECT_EQ(efs("null"), Element::create());
+    EXPECT_EQ(*efs("1"), *efs("1"));
+    EXPECT_NE(*efs("1"), *efs("2"));
+    EXPECT_NE(*efs("1"), *efs("\"1\""));
+    EXPECT_NE(*efs("1"), *efs("[]"));
+    EXPECT_NE(*efs("1"), *efs("True"));
+    EXPECT_NE(*efs("1"), *efs("{}"));
+
+    EXPECT_EQ(*efs("1.1"), *efs("1.1"));
+    EXPECT_NE(*efs("1.0"), *efs("1"));
+    EXPECT_NE(*efs("1.1"), *efs("\"1\""));
+    EXPECT_NE(*efs("1.1"), *efs("[]"));
+    EXPECT_NE(*efs("1.1"), *efs("True"));
+    EXPECT_NE(*efs("1.1"), *efs("{}"));
+
+    EXPECT_EQ(*efs("True"), *efs("True"));
+    EXPECT_NE(*efs("True"), *efs("False"));
+    EXPECT_NE(*efs("True"), *efs("1"));
+    EXPECT_NE(*efs("True"), *efs("\"1\""));
+    EXPECT_NE(*efs("True"), *efs("[]"));
+    EXPECT_NE(*efs("True"), *efs("{}"));
+
+    EXPECT_EQ(*efs("\"foo\""), *efs("\"foo\""));
+    EXPECT_NE(*efs("\"foo\""), *efs("\"bar\""));
+    EXPECT_NE(*efs("\"foo\""), *efs("1"));
+    EXPECT_NE(*efs("\"foo\""), *efs("\"1\""));
+    EXPECT_NE(*efs("\"foo\""), *efs("True"));
+    EXPECT_NE(*efs("\"foo\""), *efs("[]"));
+    EXPECT_NE(*efs("\"foo\""), *efs("{}"));
+
+    EXPECT_EQ(*efs("[]"), *efs("[]"));
+    EXPECT_EQ(*efs("[ 1, 2, 3 ]"), *efs("[ 1, 2, 3 ]"));
+    EXPECT_EQ(*efs("[ \"a\", [ True, 1], 2.2 ]"), *efs("[ \"a\", [ True, 1], 2.2 ]"));
+    EXPECT_NE(*efs("[ \"a\", [ True, 1], 2.2 ]"), *efs("[ \"a\", [ True, 2], 2.2 ]"));
+    EXPECT_NE(*efs("[]"), *efs("[1]"));
+    EXPECT_NE(*efs("[]"), *efs("1"));
+    EXPECT_NE(*efs("[]"), *efs("\"1\""));
+    EXPECT_NE(*efs("[]"), *efs("{}"));
+
+    EXPECT_EQ(*efs("{}"), *efs("{}"));
+    EXPECT_EQ(*efs("{ \"foo\": \"bar\" }"), *efs("{ \"foo\": \"bar\" }"));
+    EXPECT_EQ(*efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }"), *efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }"));
+    EXPECT_NE(*efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }"), *efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar2\" } }"));
+    EXPECT_NE(*efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }"), *efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\", 1 ], \"item3\": { \"foo\": \"bar\" } }"));
+    EXPECT_NE(*efs("{ \"foo\": \"bar\" }"), *efs("1"));
+    EXPECT_NE(*efs("{ \"foo\": \"bar\" }"), *efs("\"1\""));
+    EXPECT_NE(*efs("{ \"foo\": \"bar\" }"), *efs("[]"));
+    EXPECT_NE(*efs("{ \"foo\": \"bar\" }"), *efs("{}"));
+    EXPECT_NE(*efs("{ \"foo\": \"bar\" }"), *efs("{ \"something\": \"different\" }"));
+
+    EXPECT_EQ(*efs("null"), *Element::create());
 }
 }
 
 
 TEST(Element, removeIdentical) {
 TEST(Element, removeIdentical) {
     ElementPtr a = Element::createMap();
     ElementPtr a = Element::createMap();
-    ElementPtr b = Element::createMap();
-    ElementPtr c = Element::createMap();
+    ConstElementPtr b = Element::createMap();
+    ConstElementPtr c = Element::createMap();
     removeIdentical(a, b);
     removeIdentical(a, b);
-    EXPECT_EQ(a, c);
+    EXPECT_EQ(*a, *c);
 
 
     a = Element::fromJSON("{ \"a\": 1 }");
     a = Element::fromJSON("{ \"a\": 1 }");
     b = Element::fromJSON("{ \"a\": 1 }");
     b = Element::fromJSON("{ \"a\": 1 }");
     c = Element::createMap();
     c = Element::createMap();
     removeIdentical(a, b);
     removeIdentical(a, b);
-    EXPECT_EQ(a, c);
+    EXPECT_EQ(*a, *c);
 
 
     a = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
     a = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
     b = Element::createMap();
     b = Element::createMap();
     c = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
     c = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
     removeIdentical(a, b);
     removeIdentical(a, b);
-    EXPECT_EQ(a, c);
+    EXPECT_EQ(*a, *c);
 
 
     a = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
     a = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
     b = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
     b = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
     c = Element::createMap();
     c = Element::createMap();
     removeIdentical(a, b);
     removeIdentical(a, b);
-    EXPECT_EQ(a, c);
+    EXPECT_EQ(*a, *c);
 
 
     a = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
     a = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
     b = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 3 ] }");
     b = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 3 ] }");
     c = Element::fromJSON("{ \"b\": [ 1, 2 ] }");
     c = Element::fromJSON("{ \"b\": [ 1, 2 ] }");
     removeIdentical(a, b);
     removeIdentical(a, b);
-    EXPECT_EQ(a, c);
+    EXPECT_EQ(*a, *c);
 
 
     a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     b = Element::createMap();
     b = Element::createMap();
     c = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     c = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     removeIdentical(a, b);
     removeIdentical(a, b);
-    EXPECT_EQ(a, c);
+    EXPECT_EQ(*a, *c);
 
 
     a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     b = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     b = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     c = Element::createMap();
     c = Element::createMap();
     removeIdentical(a, b);
     removeIdentical(a, b);
-    EXPECT_EQ(a, c);
+    EXPECT_EQ(*a, *c);
 
 
     a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     b = Element::fromJSON("{ \"a\": { \"b\": \"d\" } }");
     b = Element::fromJSON("{ \"a\": { \"b\": \"d\" } }");
     c = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     c = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     removeIdentical(a, b);
     removeIdentical(a, b);
-    EXPECT_EQ(a, c);
+    EXPECT_EQ(*a, *c);
 
 
     EXPECT_THROW(removeIdentical(Element::create(1), Element::create(2)), TypeError);
     EXPECT_THROW(removeIdentical(Element::create(1), Element::create(2)), TypeError);
 }
 }
 
 
-TEST(Element, merge)
-{
+TEST(Element, constRemoveIdentical) {
+    ConstElementPtr a = Element::createMap();
+    ConstElementPtr b = Element::createMap();
+    ConstElementPtr c = Element::createMap();
+    EXPECT_EQ(*removeIdentical(a, b), *c);
+
+    a = Element::fromJSON("{ \"a\": 1 }");
+    b = Element::fromJSON("{ \"a\": 1 }");
+    c = Element::createMap();
+    EXPECT_EQ(*removeIdentical(a, b), *c);
+
+    a = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
+    b = Element::createMap();
+    c = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
+    EXPECT_EQ(*removeIdentical(a, b), *c);
+
+    a = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
+    b = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
+    c = Element::createMap();
+    EXPECT_EQ(*removeIdentical(a, b), *c);
+
+    a = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
+    b = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 3 ] }");
+    c = Element::fromJSON("{ \"b\": [ 1, 2 ] }");
+    EXPECT_EQ(*removeIdentical(a, b), *c);
+
+    a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
+    b = Element::createMap();
+    c = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
+    EXPECT_EQ(*removeIdentical(a, b), *c);
+
+    a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
+    b = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
+    c = Element::createMap();
+    EXPECT_EQ(*removeIdentical(a, b), *c);
+
+    a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
+    b = Element::fromJSON("{ \"a\": { \"b\": \"d\" } }");
+    c = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
+    EXPECT_EQ(*removeIdentical(a, b), *c);
+
+    EXPECT_THROW(removeIdentical(Element::create(1), Element::create(2)),
+                 TypeError);
+}
+
+TEST(Element, merge) {
     ElementPtr a = Element::createMap();
     ElementPtr a = Element::createMap();
     ElementPtr b = Element::createMap();
     ElementPtr b = Element::createMap();
-    ElementPtr c = Element::createMap();
+    ConstElementPtr c = Element::createMap();
     merge(a, b);
     merge(a, b);
-    EXPECT_EQ(a, c);
+    EXPECT_EQ(*a, *c);
 
 
     a = Element::fromJSON("1");
     a = Element::fromJSON("1");
     b = Element::createMap();
     b = Element::createMap();
@@ -525,73 +573,74 @@ TEST(Element, merge)
     b = Element::fromJSON("{ \"a\": 1 }");
     b = Element::fromJSON("{ \"a\": 1 }");
     c = Element::fromJSON("{ \"a\": 1 }");
     c = Element::fromJSON("{ \"a\": 1 }");
     merge(a, b);
     merge(a, b);
-    EXPECT_EQ(a, c);
+    EXPECT_EQ(*a, *c);
 
 
     a = Element::createMap();
     a = Element::createMap();
     b = Element::fromJSON("{ \"a\": 1 }");
     b = Element::fromJSON("{ \"a\": 1 }");
     c = Element::fromJSON("{ \"a\": 1 }");
     c = Element::fromJSON("{ \"a\": 1 }");
     merge(b, a);
     merge(b, a);
-    EXPECT_EQ(b, c);
+    EXPECT_EQ(*b, *c);
 
 
     a = Element::fromJSON("{ \"a\": 1 }");
     a = Element::fromJSON("{ \"a\": 1 }");
     b = Element::fromJSON("{ \"a\": 2 }");
     b = Element::fromJSON("{ \"a\": 2 }");
     c = Element::fromJSON("{ \"a\": 2 }");
     c = Element::fromJSON("{ \"a\": 2 }");
     merge(a, b);
     merge(a, b);
-    EXPECT_EQ(a, c);
+    EXPECT_EQ(*a, *c);
 
 
     a = Element::fromJSON("{ \"a\": 1 }");
     a = Element::fromJSON("{ \"a\": 1 }");
     b = Element::fromJSON("{ \"a\": 2 }");
     b = Element::fromJSON("{ \"a\": 2 }");
     c = Element::fromJSON("{ \"a\": 1 }");
     c = Element::fromJSON("{ \"a\": 1 }");
     merge(b, a);
     merge(b, a);
-    EXPECT_EQ(b, c);
+    EXPECT_EQ(*b, *c);
 
 
     a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     b = Element::fromJSON("{ \"a\": { \"b\": \"d\" } }");
     b = Element::fromJSON("{ \"a\": { \"b\": \"d\" } }");
     c = Element::fromJSON("{ \"a\": { \"b\": \"d\" } }");
     c = Element::fromJSON("{ \"a\": { \"b\": \"d\" } }");
     merge(a, b);
     merge(a, b);
-    EXPECT_EQ(a, c);
+    EXPECT_EQ(*a, *c);
 
 
     a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     b = Element::fromJSON("{ \"a\": { \"b\": \"d\" } }");
     b = Element::fromJSON("{ \"a\": { \"b\": \"d\" } }");
     c = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     c = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     merge(b, a);
     merge(b, a);
-    EXPECT_EQ(b, c);
+    EXPECT_EQ(*b, *c);
 
 
     a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     b = Element::fromJSON("{ \"a\": null }");
     b = Element::fromJSON("{ \"a\": null }");
     c = Element::fromJSON("{  }");
     c = Element::fromJSON("{  }");
     merge(a, b);
     merge(a, b);
-    EXPECT_EQ(a, c);
+    EXPECT_EQ(*a, *c);
 
 
     a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     b = Element::fromJSON("{ \"a\": null }");
     b = Element::fromJSON("{ \"a\": null }");
     c = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     c = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
     merge(b, a);
     merge(b, a);
-    EXPECT_EQ(b, c);
+    EXPECT_EQ(*b, *c);
     
     
     // And some tests with multiple values
     // And some tests with multiple values
     a = Element::fromJSON("{ \"a\": 1, \"b\": true, \"c\": null }");
     a = Element::fromJSON("{ \"a\": 1, \"b\": true, \"c\": null }");
     b = Element::fromJSON("{ \"a\": 1, \"b\": null, \"c\": \"a string\" }");
     b = Element::fromJSON("{ \"a\": 1, \"b\": null, \"c\": \"a string\" }");
     c = Element::fromJSON("{ \"a\": 1, \"c\": \"a string\" }");
     c = Element::fromJSON("{ \"a\": 1, \"c\": \"a string\" }");
     merge(a, b);
     merge(a, b);
-    EXPECT_EQ(a, c);
+    EXPECT_EQ(*a, *c);
 
 
     a = Element::fromJSON("{ \"a\": 1, \"b\": true, \"c\": null }");
     a = Element::fromJSON("{ \"a\": 1, \"b\": true, \"c\": null }");
     b = Element::fromJSON("{ \"a\": 1, \"b\": null, \"c\": \"a string\" }");
     b = Element::fromJSON("{ \"a\": 1, \"b\": null, \"c\": \"a string\" }");
     c = Element::fromJSON("{ \"a\": 1, \"b\": true }");
     c = Element::fromJSON("{ \"a\": 1, \"b\": true }");
     merge(b, a);
     merge(b, a);
-    EXPECT_EQ(b, c);
+    EXPECT_EQ(*b, *c);
 
 
     a = Element::fromJSON("{ \"a\": 1, \"b\": 2, \"c\": 3 }");
     a = Element::fromJSON("{ \"a\": 1, \"b\": 2, \"c\": 3 }");
     b = Element::fromJSON("{ \"a\": 3, \"b\": 2, \"c\": 1 }");
     b = Element::fromJSON("{ \"a\": 3, \"b\": 2, \"c\": 1 }");
     c = Element::fromJSON("{ \"a\": 3, \"b\": 2, \"c\": 1 }");
     c = Element::fromJSON("{ \"a\": 3, \"b\": 2, \"c\": 1 }");
     merge(a, b);
     merge(a, b);
-    EXPECT_EQ(a, c);
+    EXPECT_EQ(*a, *c);
 
 
     a = Element::fromJSON("{ \"a\": 1, \"b\": 2, \"c\": 3 }");
     a = Element::fromJSON("{ \"a\": 1, \"b\": 2, \"c\": 3 }");
     b = Element::fromJSON("{ \"a\": 3, \"b\": 2, \"c\": 1 }");
     b = Element::fromJSON("{ \"a\": 3, \"b\": 2, \"c\": 1 }");
     c = Element::fromJSON("{ \"a\": 1, \"b\": 2, \"c\": 3 }");
     c = Element::fromJSON("{ \"a\": 1, \"b\": 2, \"c\": 3 }");
     merge(b, a);
     merge(b, a);
-    EXPECT_EQ(b, c);
+    EXPECT_EQ(*b, *c);
 
 
 }
 }
+}

+ 2 - 2
src/lib/cc/tests/session_unittests.cc

@@ -140,7 +140,7 @@ public:
     // If this message is { "command": "stop" } it'll tell the
     // If this message is { "command": "stop" } it'll tell the
     // io_service it is done. Otherwise it'll re-register this handler
     // io_service it is done. Otherwise it'll re-register this handler
     void someHandler() {
     void someHandler() {
-        isc::data::ElementPtr env, msg;
+        isc::data::ConstElementPtr env, msg;
         sess.group_recvmsg(env, msg, false, -1);
         sess.group_recvmsg(env, msg, false, -1);
 
 
         sess.group_recvmsg(env, msg, false, -1);
         sess.group_recvmsg(env, msg, false, -1);
@@ -188,7 +188,7 @@ TEST_F(SessionTest, connect_ok_connection_reset) {
     // Close the session again, so the next recv() should throw
     // Close the session again, so the next recv() should throw
     sess.disconnect();
     sess.disconnect();
 
 
-    isc::data::ElementPtr env, msg;
+    isc::data::ConstElementPtr env, msg;
     EXPECT_THROW(sess.group_recvmsg(env, msg, false, -1), SessionError);
     EXPECT_THROW(sess.group_recvmsg(env, msg, false, -1), SessionError);
 }
 }
 
 

+ 68 - 57
src/lib/config/ccsession.cc

@@ -52,41 +52,47 @@ namespace isc {
 namespace config {
 namespace config {
 
 
 /// Creates a standard config/command protocol answer message
 /// Creates a standard config/command protocol answer message
-ElementPtr
+ConstElementPtr
 createAnswer() {
 createAnswer() {
     ElementPtr answer = Element::fromJSON("{\"result\": [] }");
     ElementPtr answer = Element::fromJSON("{\"result\": [] }");
-    ElementPtr answer_content = answer->get("result");
+    ElementPtr answer_content = Element::createList();
     answer_content->add(Element::create(0));
     answer_content->add(Element::create(0));
+    answer->set("result", answer_content);
+
     return (answer);
     return (answer);
 }
 }
 
 
-ElementPtr
-createAnswer(const int rcode, const ElementPtr arg) {
+ConstElementPtr
+createAnswer(const int rcode, ConstElementPtr arg) {
     if (rcode != 0 && (!arg || arg->getType() != Element::string)) {
     if (rcode != 0 && (!arg || arg->getType() != Element::string)) {
         isc_throw(CCSessionError, "Bad or no argument for rcode != 0");
         isc_throw(CCSessionError, "Bad or no argument for rcode != 0");
     }
     }
     ElementPtr answer = Element::fromJSON("{\"result\": [] }");
     ElementPtr answer = Element::fromJSON("{\"result\": [] }");
-    ElementPtr answer_content = answer->get("result");
+    ElementPtr answer_content = Element::createList();
     answer_content->add(Element::create(rcode));
     answer_content->add(Element::create(rcode));
     answer_content->add(arg);
     answer_content->add(arg);
+    answer->set("result", answer_content);
+
     return (answer);
     return (answer);
 }
 }
 
 
-ElementPtr
+ConstElementPtr
 createAnswer(const int rcode, const std::string& arg) {
 createAnswer(const int rcode, const std::string& arg) {
     ElementPtr answer = Element::fromJSON("{\"result\": [] }");
     ElementPtr answer = Element::fromJSON("{\"result\": [] }");
-    ElementPtr answer_content = answer->get("result");
+    ElementPtr answer_content = Element::createList();
     answer_content->add(Element::create(rcode));
     answer_content->add(Element::create(rcode));
     answer_content->add(Element::create(arg));
     answer_content->add(Element::create(arg));
+    answer->set("result", answer_content);
+
     return (answer);
     return (answer);
 }
 }
 
 
-ElementPtr
-parseAnswer(int &rcode, const ElementPtr msg) {
+ConstElementPtr
+parseAnswer(int &rcode, ConstElementPtr msg) {
     if (msg &&
     if (msg &&
         msg->getType() == Element::map &&
         msg->getType() == Element::map &&
         msg->contains("result")) {
         msg->contains("result")) {
-        ElementPtr result = msg->get("result");
+        ConstElementPtr result = msg->get("result");
         if (result->getType() != Element::list) {
         if (result->getType() != Element::list) {
             isc_throw(CCSessionError, "Result element in answer message is not a list");
             isc_throw(CCSessionError, "Result element in answer message is not a list");
         } else if (result->get(0)->getType() != Element::integer) {
         } else if (result->get(0)->getType() != Element::integer) {
@@ -111,13 +117,13 @@ parseAnswer(int &rcode, const ElementPtr msg) {
     }
     }
 }
 }
 
 
-ElementPtr
+ConstElementPtr
 createCommand(const std::string& command) {
 createCommand(const std::string& command) {
     return (createCommand(command, ElementPtr()));
     return (createCommand(command, ElementPtr()));
 }
 }
 
 
-ElementPtr
-createCommand(const std::string& command, ElementPtr arg) {
+ConstElementPtr
+createCommand(const std::string& command, ConstElementPtr arg) {
     ElementPtr cmd = Element::createMap();
     ElementPtr cmd = Element::createMap();
     ElementPtr cmd_parts = Element::createList();
     ElementPtr cmd_parts = Element::createList();
     cmd_parts->add(Element::create(command));
     cmd_parts->add(Element::create(command));
@@ -130,13 +136,12 @@ createCommand(const std::string& command, ElementPtr arg) {
 
 
 /// Returns "" and empty ElementPtr() if this does not
 /// Returns "" and empty ElementPtr() if this does not
 /// look like a command
 /// look like a command
-const std::string
-parseCommand(ElementPtr& arg, const ElementPtr command)
-{
+std::string
+parseCommand(ConstElementPtr& arg, ConstElementPtr command) {
     if (command &&
     if (command &&
         command->getType() == Element::map &&
         command->getType() == Element::map &&
         command->contains("command")) {
         command->contains("command")) {
-        ElementPtr cmd = command->get("command");
+        ConstElementPtr cmd = command->get("command");
         if (cmd->getType() == Element::list &&
         if (cmd->getType() == Element::list &&
             cmd->size() > 0 &&
             cmd->size() > 0 &&
             cmd->get(0)->getType() == Element::string) {
             cmd->get(0)->getType() == Element::string) {
@@ -192,9 +197,10 @@ ModuleCCSession::startCheck() {
 ModuleCCSession::ModuleCCSession(
 ModuleCCSession::ModuleCCSession(
     const std::string& spec_file_name,
     const std::string& spec_file_name,
     isc::cc::AbstractSession& session,
     isc::cc::AbstractSession& session,
-    isc::data::ElementPtr(*config_handler)(isc::data::ElementPtr new_config),
-    isc::data::ElementPtr(*command_handler)(
-        const std::string& command, const isc::data::ElementPtr args)
+    isc::data::ConstElementPtr(*config_handler)(
+        isc::data::ConstElementPtr new_config),
+    isc::data::ConstElementPtr(*command_handler)(
+        const std::string& command, isc::data::ConstElementPtr args)
     ) :
     ) :
     session_(session)
     session_(session)
 {
 {
@@ -205,18 +211,20 @@ ModuleCCSession::ModuleCCSession(
     config_handler_ = config_handler;
     config_handler_ = config_handler;
     command_handler_ = command_handler;
     command_handler_ = command_handler;
 
 
-    ElementPtr answer, env;
-
     session_.establish(NULL);
     session_.establish(NULL);
     session_.subscribe(module_name_, "*");
     session_.subscribe(module_name_, "*");
     //session_.subscribe("Boss", "*");
     //session_.subscribe("Boss", "*");
     //session_.subscribe("statistics", "*");
     //session_.subscribe("statistics", "*");
     // send the data specification
     // send the data specification
-    ElementPtr spec_msg = createCommand("module_spec", module_specification_.getFullSpec());
+
+    ConstElementPtr spec_msg = createCommand("module_spec",
+                                             module_specification_.getFullSpec());
     unsigned int seq = session_.group_sendmsg(spec_msg, "ConfigManager");
     unsigned int seq = session_.group_sendmsg(spec_msg, "ConfigManager");
+
+    ConstElementPtr answer, env;
     session_.group_recvmsg(env, answer, false, seq);
     session_.group_recvmsg(env, answer, false, seq);
     int rcode;
     int rcode;
-    ElementPtr err = parseAnswer(rcode, answer);
+    ConstElementPtr err = parseAnswer(rcode, answer);
     if (rcode != 0) {
     if (rcode != 0) {
         std::cerr << "[" << module_name_ << "] Error in specification: " << answer << std::endl;
         std::cerr << "[" << module_name_ << "] Error in specification: " << answer << std::endl;
     }
     }
@@ -224,10 +232,10 @@ ModuleCCSession::ModuleCCSession(
     setLocalConfig(Element::fromJSON("{}"));
     setLocalConfig(Element::fromJSON("{}"));
     // get any stored configuration from the manager
     // get any stored configuration from the manager
     if (config_handler_) {
     if (config_handler_) {
-        ElementPtr cmd = Element::fromJSON("{ \"command\": [\"get_config\", {\"module_name\":\"" + module_name_ + "\"} ] }");
+        ConstElementPtr cmd = Element::fromJSON("{ \"command\": [\"get_config\", {\"module_name\":\"" + module_name_ + "\"} ] }");
         seq = session_.group_sendmsg(cmd, "ConfigManager");
         seq = session_.group_sendmsg(cmd, "ConfigManager");
         session_.group_recvmsg(env, answer, false, seq);
         session_.group_recvmsg(env, answer, false, seq);
-        ElementPtr new_config = parseAnswer(rcode, answer);
+        ConstElementPtr new_config = parseAnswer(rcode, answer);
         if (rcode == 0) {
         if (rcode == 0) {
             handleConfigUpdate(new_config);
             handleConfigUpdate(new_config);
         } else {
         } else {
@@ -242,30 +250,30 @@ ModuleCCSession::ModuleCCSession(
 /// Validates the new config values, if they are correct,
 /// Validates the new config values, if they are correct,
 /// call the config handler with the values that have changed
 /// call the config handler with the values that have changed
 /// If that results in success, store the new config
 /// If that results in success, store the new config
-ElementPtr
-ModuleCCSession::handleConfigUpdate(ElementPtr new_config)
-{
-    ElementPtr answer;
+ConstElementPtr
+ModuleCCSession::handleConfigUpdate(ConstElementPtr new_config) {
+    ConstElementPtr answer;
     ElementPtr errors = Element::createList();
     ElementPtr errors = Element::createList();
     if (!config_handler_) {
     if (!config_handler_) {
         answer = createAnswer(1, module_name_ + " does not have a config handler");
         answer = createAnswer(1, module_name_ + " does not have a config handler");
-    } else if (!module_specification_.validate_config(new_config, false, errors)) {
+    } else if (!module_specification_.validate_config(new_config, false,
+                                                      errors)) {
         std::stringstream ss;
         std::stringstream ss;
         ss << "Error in config validation: ";
         ss << "Error in config validation: ";
-        BOOST_FOREACH(ElementPtr error, errors->listValue()) {
+        BOOST_FOREACH(ConstElementPtr error, errors->listValue()) {
             ss << error->stringValue();
             ss << error->stringValue();
         }
         }
         answer = createAnswer(2, ss.str());
         answer = createAnswer(2, ss.str());
     } else {
     } else {
         // remove the values that have not changed
         // remove the values that have not changed
-        isc::data::removeIdentical(new_config, getLocalConfig());
+        ConstElementPtr diff = removeIdentical(new_config, getLocalConfig());
         // handle config update
         // handle config update
-        answer = config_handler_(new_config);
+        answer = config_handler_(diff);
         int rcode;
         int rcode;
         parseAnswer(rcode, answer);
         parseAnswer(rcode, answer);
         if (rcode == 0) {
         if (rcode == 0) {
             ElementPtr local_config = getLocalConfig();
             ElementPtr local_config = getLocalConfig();
-            isc::data::merge(local_config, new_config);
+            isc::data::merge(local_config, diff);
             setLocalConfig(local_config);
             setLocalConfig(local_config);
         }
         }
     }
     }
@@ -273,15 +281,13 @@ ModuleCCSession::handleConfigUpdate(ElementPtr new_config)
 }
 }
 
 
 bool
 bool
-ModuleCCSession::hasQueuedMsgs()
-{
+ModuleCCSession::hasQueuedMsgs() const {
     return (session_.hasQueuedMsgs());
     return (session_.hasQueuedMsgs());
 }
 }
 
 
 int
 int
-ModuleCCSession::checkCommand()
-{
-    ElementPtr cmd, routing, data;
+ModuleCCSession::checkCommand() {
+    ConstElementPtr cmd, routing, data;
     if (session_.group_recvmsg(routing, data, true)) {
     if (session_.group_recvmsg(routing, data, true)) {
         
         
         /* ignore result messages (in case we're out of sync, to prevent
         /* ignore result messages (in case we're out of sync, to prevent
@@ -289,8 +295,8 @@ ModuleCCSession::checkCommand()
         if (data->getType() != Element::map || data->contains("result")) {
         if (data->getType() != Element::map || data->contains("result")) {
             return (0);
             return (0);
         }
         }
-        ElementPtr arg;
-        ElementPtr answer;
+        ConstElementPtr arg;
+        ConstElementPtr answer;
         try {
         try {
             std::string cmd_str = parseCommand(arg, data);
             std::string cmd_str = parseCommand(arg, data);
             std::string target_module = routing->get("group")->stringValue();
             std::string target_module = routing->get("group")->stringValue();
@@ -313,7 +319,7 @@ ModuleCCSession::checkCommand()
                     }
                     }
                 }
                 }
             }
             }
-        } catch (CCSessionError re) {
+        } catch (const CCSessionError& re) {
             // TODO: Once we have logging and timeouts, we should not
             // TODO: Once we have logging and timeouts, we should not
             // answer here (potential interference)
             // answer here (potential interference)
             answer = createAnswer(1, re.what());
             answer = createAnswer(1, re.what());
@@ -335,15 +341,17 @@ ModuleCCSession::addRemoteConfig(const std::string& spec_file_name)
     session_.subscribe(module_name);
     session_.subscribe(module_name);
 
 
     // Get the current configuration values for that module
     // Get the current configuration values for that module
-    ElementPtr cmd = Element::fromJSON("{ \"command\": [\"get_config\", {\"module_name\":\"" + module_name + "\"} ] }");
-    ElementPtr env, answer;
-    int rcode;
-    
+    ConstElementPtr cmd = Element::fromJSON("{ \"command\": [\"get_config\", {\"module_name\":\"" + module_name + "\"} ] }");
     unsigned int seq = session_.group_sendmsg(cmd, "ConfigManager");
     unsigned int seq = session_.group_sendmsg(cmd, "ConfigManager");
+
+    ConstElementPtr env, answer;
     session_.group_recvmsg(env, answer, false, seq);
     session_.group_recvmsg(env, answer, false, seq);
-    ElementPtr new_config = parseAnswer(rcode, answer);
-    if (rcode == 0) {
-        rmod_config.setLocalConfig(new_config);
+    int rcode;
+    ConstElementPtr new_config = parseAnswer(rcode, answer);
+    if (rcode == 0 && new_config) {
+        ElementPtr local_config = rmod_config.getLocalConfig();
+        isc::data::merge(local_config, new_config);
+        rmod_config.setLocalConfig(local_config);
     } else {
     } else {
         isc_throw(CCSessionError, "Error getting config for " + module_name + ": " + answer->str());
         isc_throw(CCSessionError, "Error getting config for " + module_name + ": " + answer->str());
     }
     }
@@ -365,21 +373,24 @@ ModuleCCSession::removeRemoteConfig(const std::string& module_name)
     }
     }
 }
 }
 
 
-ElementPtr
-ModuleCCSession::getRemoteConfigValue(const std::string& module_name, const std::string& identifier)
+ConstElementPtr
+ModuleCCSession::getRemoteConfigValue(const std::string& module_name,
+                                      const std::string& identifier) const
 {
 {
-    std::map<std::string, ConfigData>::iterator it;
+    std::map<std::string, ConfigData>::const_iterator it =
+        remote_module_configs_.find(module_name);
 
 
-    it = remote_module_configs_.find(module_name);
     if (it != remote_module_configs_.end()) {
     if (it != remote_module_configs_.end()) {
-        return (remote_module_configs_[module_name].getValue(identifier));
+        return ((*it).second.getValue(identifier));
     } else {
     } else {
-        isc_throw(CCSessionError, "Remote module " + module_name + " not found.");
+        isc_throw(CCSessionError,
+                  "Remote module " + module_name + " not found.");
     }
     }
 }
 }
 
 
 void
 void
-ModuleCCSession::updateRemoteConfig(const std::string& module_name, ElementPtr new_config)
+ModuleCCSession::updateRemoteConfig(const std::string& module_name,
+                                    ConstElementPtr new_config)
 {
 {
     std::map<std::string, ConfigData>::iterator it;
     std::map<std::string, ConfigData>::iterator it;
 
 

+ 33 - 20
src/lib/config/ccsession.h

@@ -31,7 +31,7 @@ namespace config {
 /// \brief Creates a standard config/command level success answer message
 /// \brief Creates a standard config/command level success answer message
 ///        (i.e. of the form { "result": [ 0 ] }
 ///        (i.e. of the form { "result": [ 0 ] }
 /// \return Standard command/config success answer message
 /// \return Standard command/config success answer message
-ElementPtr createAnswer();
+ConstElementPtr createAnswer();
 
 
 ///
 ///
 /// \brief Creates a standard config/command level answer message
 /// \brief Creates a standard config/command level answer message
@@ -43,7 +43,7 @@ ElementPtr createAnswer();
 ///            Element type. For rcode == 1, this argument is mandatory,
 ///            Element type. For rcode == 1, this argument is mandatory,
 ///            and must be a StringElement containing an error description
 ///            and must be a StringElement containing an error description
 /// \return Standard command/config answer message
 /// \return Standard command/config answer message
-ElementPtr createAnswer(const int rcode, const ElementPtr arg);
+ConstElementPtr createAnswer(const int rcode, ConstElementPtr arg);
 
 
 ///
 ///
 /// \brief Creates a standard config/command level answer message
 /// \brief Creates a standard config/command level answer message
@@ -52,7 +52,7 @@ ElementPtr createAnswer(const int rcode, const ElementPtr arg);
 /// \param rcode The return code (0 for success)
 /// \param rcode The return code (0 for success)
 /// \param arg A string to put into the StringElement argument
 /// \param arg A string to put into the StringElement argument
 /// \return Standard command/config answer message
 /// \return Standard command/config answer message
-ElementPtr createAnswer(const int rcode, const std::string& arg);
+ConstElementPtr createAnswer(const int rcode, const std::string& arg);
 
 
 ///
 ///
 /// Parses a standard config/command level answer message
 /// Parses a standard config/command level answer message
@@ -63,8 +63,7 @@ ElementPtr createAnswer(const int rcode, const std::string& arg);
 /// \return The optional argument in the message, or an empty ElementPtr
 /// \return The optional argument in the message, or an empty ElementPtr
 ///         if there was no argument. If rcode != 0, this contains a
 ///         if there was no argument. If rcode != 0, this contains a
 ///         StringElement with the error description.
 ///         StringElement with the error description.
-ElementPtr parseAnswer(int &rcode, const ElementPtr msg);
-
+ConstElementPtr parseAnswer(int &rcode, ConstElementPtr msg);
 
 
 ///
 ///
 /// \brief Creates a standard config/command command message with no
 /// \brief Creates a standard config/command command message with no
@@ -72,7 +71,7 @@ ElementPtr parseAnswer(int &rcode, const ElementPtr msg);
 /// 
 /// 
 /// \param command The command string
 /// \param command The command string
 /// \return The created message
 /// \return The created message
-ElementPtr createCommand(const std::string& command);
+ConstElementPtr createCommand(const std::string& command);
 
 
 ///
 ///
 /// \brief Creates a standard config/command command message with the
 /// \brief Creates a standard config/command command message with the
@@ -82,7 +81,7 @@ ElementPtr createCommand(const std::string& command);
 /// \param arg The optional argument for the command. This can be of 
 /// \param arg The optional argument for the command. This can be of 
 ///        any Element type, but it should conform to the .spec file.
 ///        any Element type, but it should conform to the .spec file.
 /// \return The created message
 /// \return The created message
-ElementPtr createCommand(const std::string& command, ElementPtr arg);
+ConstElementPtr createCommand(const std::string& command, ConstElementPtr arg);
 
 
 ///
 ///
 /// \brief Parses the given command into a string containing the actual
 /// \brief Parses the given command into a string containing the actual
@@ -93,7 +92,7 @@ ElementPtr createCommand(const std::string& command, ElementPtr arg);
 /// \param command The command message containing the command (as made
 /// \param command The command message containing the command (as made
 ///        by createCommand()
 ///        by createCommand()
 /// \return The command string
 /// \return The command string
-const std::string parseCommand(ElementPtr& arg, const ElementPtr command);
+std::string parseCommand(ConstElementPtr& arg, ConstElementPtr command);
 
 
 
 
 ///
 ///
@@ -133,11 +132,11 @@ public:
      */
      */
     ModuleCCSession(const std::string& spec_file_name,
     ModuleCCSession(const std::string& spec_file_name,
                     isc::cc::AbstractSession& session,
                     isc::cc::AbstractSession& session,
-                    isc::data::ElementPtr(*config_handler)(
-                        isc::data::ElementPtr new_config) = NULL,
-                    isc::data::ElementPtr(*command_handler)(
+                    isc::data::ConstElementPtr(*config_handler)(
+                        isc::data::ConstElementPtr new_config) = NULL,
+                    isc::data::ConstElementPtr(*command_handler)(
                         const std::string& command,
                         const std::string& command,
-                        const isc::data::ElementPtr args) = NULL
+                        isc::data::ConstElementPtr args) = NULL
                     );
                     );
 
 
     /**
     /**
@@ -148,7 +147,7 @@ public:
      * 
      * 
      * @return true if there are unhandled queued messages
      * @return true if there are unhandled queued messages
      */
      */
-    bool hasQueuedMsgs();
+    bool hasQueuedMsgs() const;
 
 
     /**
     /**
      * Check if there is a command or config change on the command
      * Check if there is a command or config change on the command
@@ -167,7 +166,11 @@ public:
      * 100000 zones, where the whole list is passed every time a single
      * 100000 zones, where the whole list is passed every time a single
      * thing changes)
      * thing changes)
      */
      */
-    void setConfigHandler(isc::data::ElementPtr(*config_handler)(isc::data::ElementPtr new_config)) { config_handler_ = config_handler; };
+    void setConfigHandler(isc::data::ConstElementPtr(*config_handler)(
+                              isc::data::ConstElementPtr new_config))
+    {
+        config_handler_ = config_handler;
+    }
 
 
     /**
     /**
      * Set a command handler; the function that is passed takes an
      * Set a command handler; the function that is passed takes an
@@ -179,7 +182,12 @@ public:
      *
      *
      * This protocol is very likely to change.
      * This protocol is very likely to change.
      */
      */
-    void setCommandHandler(isc::data::ElementPtr(*command_handler)(const std::string& command, const isc::data::ElementPtr args)) { command_handler_ = command_handler; };
+    void setCommandHandler(isc::data::ConstElementPtr(*command_handler)(
+                               const std::string& command,
+                               isc::data::ConstElementPtr args))
+    {
+        command_handler_ = command_handler;
+    }
 
 
     /**
     /**
      * Gives access to the configuration values of a different module
      * Gives access to the configuration values of a different module
@@ -217,7 +225,8 @@ public:
      * \param identifier The identifier of the config value
      * \param identifier The identifier of the config value
      * \return The configuration setting at the given identifier
      * \return The configuration setting at the given identifier
      */
      */
-    ElementPtr getRemoteConfigValue(const std::string& module_name, const std::string& identifier);
+    ConstElementPtr getRemoteConfigValue(const std::string& module_name,
+                                         const std::string& identifier) const;
     
     
 private:
 private:
     ModuleSpec readModuleSpecification(const std::string& filename);
     ModuleSpec readModuleSpecification(const std::string& filename);
@@ -226,13 +235,17 @@ private:
     std::string module_name_;
     std::string module_name_;
     isc::cc::AbstractSession& session_;
     isc::cc::AbstractSession& session_;
     ModuleSpec module_specification_;
     ModuleSpec module_specification_;
-    ElementPtr handleConfigUpdate(ElementPtr new_config);
+    ConstElementPtr handleConfigUpdate(ConstElementPtr new_config);
 
 
-    isc::data::ElementPtr(*config_handler_)(isc::data::ElementPtr new_config);
-    isc::data::ElementPtr(*command_handler_)(const std::string& command, const isc::data::ElementPtr args);
+    isc::data::ConstElementPtr(*config_handler_)(
+        isc::data::ConstElementPtr new_config);
+    isc::data::ConstElementPtr(*command_handler_)(
+        const std::string& command,
+        isc::data::ConstElementPtr args);
 
 
     std::map<std::string, ConfigData> remote_module_configs_;
     std::map<std::string, ConfigData> remote_module_configs_;
-    void updateRemoteConfig(const std::string& module_name, ElementPtr new_config);
+    void updateRemoteConfig(const std::string& module_name,
+                            ConstElementPtr new_config);
 };
 };
 
 
 }
 }

+ 28 - 26
src/lib/config/config_data.cc

@@ -36,15 +36,14 @@ namespace config {
 // If it is a map, we search through the list contained in its
 // If it is a map, we search through the list contained in its
 // 'map_item_spec' value. This code assumes the data has been
 // 'map_item_spec' value. This code assumes the data has been
 // validated and conforms to the specification.
 // validated and conforms to the specification.
-static ElementPtr
-find_spec_part(ElementPtr spec, const std::string& identifier)
-{
+static ConstElementPtr
+find_spec_part(ConstElementPtr spec, const std::string& identifier) {
     //std::cout << "[XX] find_spec_part for " << identifier << std::endl;
     //std::cout << "[XX] find_spec_part for " << identifier << std::endl;
     if (!spec) {
     if (!spec) {
         isc_throw(DataNotFoundError, "Empty specification");
         isc_throw(DataNotFoundError, "Empty specification");
     }
     }
     //std::cout << "in: " << std::endl << spec << std::endl;
     //std::cout << "in: " << std::endl << spec << std::endl;
-    ElementPtr spec_part = spec;
+    ConstElementPtr spec_part = spec;
     if (identifier == "") {
     if (identifier == "") {
         isc_throw(DataNotFoundError, "Empty identifier");
         isc_throw(DataNotFoundError, "Empty identifier");
     }
     }
@@ -55,7 +54,7 @@ find_spec_part(ElementPtr spec, const std::string& identifier)
         //std::cout << "[XX] id part: " << part << std::endl;
         //std::cout << "[XX] id part: " << part << std::endl;
         if (spec_part->getType() == Element::list) {
         if (spec_part->getType() == Element::list) {
             bool found = false;
             bool found = false;
-            BOOST_FOREACH(ElementPtr list_el, spec_part->listValue()) {
+            BOOST_FOREACH(ConstElementPtr list_el, spec_part->listValue()) {
                 if (list_el->getType() == Element::map &&
                 if (list_el->getType() == Element::map &&
                     list_el->contains("item_name") &&
                     list_el->contains("item_name") &&
                     list_el->get("item_name")->stringValue() == part) {
                     list_el->get("item_name")->stringValue() == part) {
@@ -73,7 +72,7 @@ find_spec_part(ElementPtr spec, const std::string& identifier)
     if (id != "" && id != "/") {
     if (id != "" && id != "/") {
         if (spec_part->getType() == Element::list) {
         if (spec_part->getType() == Element::list) {
             bool found = false;
             bool found = false;
-            BOOST_FOREACH(ElementPtr list_el, spec_part->listValue()) {
+            BOOST_FOREACH(ConstElementPtr list_el, spec_part->listValue()) {
                 if (list_el->getType() == Element::map &&
                 if (list_el->getType() == Element::map &&
                     list_el->contains("item_name") &&
                     list_el->contains("item_name") &&
                     list_el->get("item_name")->stringValue() == id) {
                     list_el->get("item_name")->stringValue() == id) {
@@ -87,7 +86,8 @@ find_spec_part(ElementPtr spec, const std::string& identifier)
         } else if (spec_part->getType() == Element::map) {
         } else if (spec_part->getType() == Element::map) {
             if (spec_part->contains("map_item_spec")) {
             if (spec_part->contains("map_item_spec")) {
                 bool found = false;
                 bool found = false;
-                BOOST_FOREACH(ElementPtr list_el, spec_part->get("map_item_spec")->listValue()) {
+                BOOST_FOREACH(ConstElementPtr list_el,
+                              spec_part->get("map_item_spec")->listValue()) {
                     if (list_el->getType() == Element::map &&
                     if (list_el->getType() == Element::map &&
                         list_el->contains("item_name") &&
                         list_el->contains("item_name") &&
                         list_el->get("item_name")->stringValue() == id) {
                         list_el->get("item_name")->stringValue() == id) {
@@ -113,10 +113,11 @@ find_spec_part(ElementPtr spec, const std::string& identifier)
 // Result must be a ListElement
 // Result must be a ListElement
 //
 //
 static void
 static void
-spec_name_list(ElementPtr result, ElementPtr spec_part, std::string prefix, bool recurse = false)
+spec_name_list(ElementPtr result, ConstElementPtr spec_part,
+               const std::string& prefix, bool recurse = false)
 {
 {
     if (spec_part->getType() == Element::list) {
     if (spec_part->getType() == Element::list) {
-        BOOST_FOREACH(ElementPtr list_el, spec_part->listValue()) {
+        BOOST_FOREACH(ConstElementPtr list_el, spec_part->listValue()) {
             if (list_el->getType() == Element::map &&
             if (list_el->getType() == Element::map &&
                 list_el->contains("item_name")) {
                 list_el->contains("item_name")) {
                 std::string new_prefix = prefix;
                 std::string new_prefix = prefix;
@@ -136,26 +137,29 @@ spec_name_list(ElementPtr result, ElementPtr spec_part, std::string prefix, bool
                 }
                 }
             }
             }
         }
         }
-    } else if (spec_part->getType() == Element::map && spec_part->contains("map_item_spec")) {
-        spec_name_list(result, spec_part->get("map_item_spec"), prefix, recurse);
+    } else if (spec_part->getType() == Element::map &&
+               spec_part->contains("map_item_spec")) {
+        spec_name_list(result, spec_part->get("map_item_spec"), prefix,
+                       recurse);
     }
     }
 }
 }
 
 
-ElementPtr
-ConfigData::getValue(const std::string& identifier) {
+ConstElementPtr
+ConfigData::getValue(const std::string& identifier) const {
     // 'fake' is set, but dropped by this function and
     // 'fake' is set, but dropped by this function and
     // serves no further purpose.
     // serves no further purpose.
     bool fake;
     bool fake;
     return (getValue(fake, identifier));
     return (getValue(fake, identifier));
 }
 }
 
 
-ElementPtr
-ConfigData::getValue(bool& is_default, const std::string& identifier) {
-    ElementPtr value = _config->find(identifier);
+ConstElementPtr
+ConfigData::getValue(bool& is_default, const std::string& identifier) const {
+    ConstElementPtr value = _config->find(identifier);
     if (value) {
     if (value) {
         is_default = false;
         is_default = false;
     } else {
     } else {
-        ElementPtr spec_part = find_spec_part(_module_spec.getConfigSpec(), identifier);
+        ConstElementPtr spec_part =
+            find_spec_part(_module_spec.getConfigSpec(), identifier);
         if (spec_part->contains("item_default")) {
         if (spec_part->contains("item_default")) {
             value = spec_part->get("item_default");
             value = spec_part->get("item_default");
             is_default = true;
             is_default = true;
@@ -170,11 +174,10 @@ ConfigData::getValue(bool& is_default, const std::string& identifier) {
 /// Returns an ElementPtr pointing to a ListElement containing
 /// Returns an ElementPtr pointing to a ListElement containing
 /// StringElements with the names of the options at the given
 /// StringElements with the names of the options at the given
 /// identifier. If recurse is true, maps will be expanded as well
 /// identifier. If recurse is true, maps will be expanded as well
-ElementPtr
-ConfigData::getItemList(const std::string& identifier, bool recurse)
-{
+ConstElementPtr
+ConfigData::getItemList(const std::string& identifier, bool recurse) const {
     ElementPtr result = Element::createList();
     ElementPtr result = Element::createList();
-    ElementPtr spec_part = getModuleSpec().getConfigSpec();
+    ConstElementPtr spec_part = getModuleSpec().getConfigSpec();
     if (identifier != "" && identifier != "/") {
     if (identifier != "" && identifier != "/") {
         spec_part = find_spec_part(spec_part, identifier);
         spec_part = find_spec_part(spec_part, identifier);
     }
     }
@@ -184,12 +187,11 @@ ConfigData::getItemList(const std::string& identifier, bool recurse)
 
 
 /// Returns an ElementPtr containing a MapElement with identifier->value
 /// Returns an ElementPtr containing a MapElement with identifier->value
 /// pairs.
 /// pairs.
-ElementPtr
-ConfigData::getFullConfig()
-{
+ConstElementPtr
+ConfigData::getFullConfig() const {
     ElementPtr result = Element::createMap();
     ElementPtr result = Element::createMap();
-    ElementPtr items = getItemList("", true);
-    BOOST_FOREACH(ElementPtr item, items->listValue()) {
+    ConstElementPtr items = getItemList("", true);
+    BOOST_FOREACH(ConstElementPtr item, items->listValue()) {
         result->set(item->stringValue(), getValue(item->stringValue()));
         result->set(item->stringValue(), getValue(item->stringValue()));
     }
     }
     return (result);
     return (result);

+ 11 - 5
src/lib/config/config_data.h

@@ -55,7 +55,7 @@ public:
     /// Raises a DataNotFoundError if the identifier is bad.
     /// Raises a DataNotFoundError if the identifier is bad.
     /// \param identifier The identifier pointing to the configuration
     /// \param identifier The identifier pointing to the configuration
     ///        value that is to be returned
     ///        value that is to be returned
-    ElementPtr getValue(const std::string& identifier);
+    ConstElementPtr getValue(const std::string& identifier) const;
 
 
     /// Returns the value currently set for the given identifier
     /// Returns the value currently set for the given identifier
     /// If no value is set, the default value (as specified by the
     /// If no value is set, the default value (as specified by the
@@ -67,10 +67,11 @@ public:
     ///                   false otherwise
     ///                   false otherwise
     /// \param identifier The identifier pointing to the configuration
     /// \param identifier The identifier pointing to the configuration
     ///        value that is to be returned
     ///        value that is to be returned
-    ElementPtr getValue(bool &is_default, const std::string& identifier);
+    ConstElementPtr getValue(bool& is_default,
+                             const std::string& identifier) const;
 
 
     /// Returns the ModuleSpec associated with this ConfigData object
     /// Returns the ModuleSpec associated with this ConfigData object
-    const ModuleSpec getModuleSpec() { return (_module_spec); }
+    const ModuleSpec& getModuleSpec() const { return (_module_spec); }
 
 
     /// Set the ModuleSpec associated with this ConfigData object
     /// Set the ModuleSpec associated with this ConfigData object
     void setModuleSpec(ModuleSpec module_spec) { _module_spec = module_spec; };
     void setModuleSpec(ModuleSpec module_spec) { _module_spec = module_spec; };
@@ -96,14 +97,15 @@ public:
     ///         StringElements that specify the identifiers at the given
     ///         StringElements that specify the identifiers at the given
     ///         location (or all possible identifiers if identifier==""
     ///         location (or all possible identifiers if identifier==""
     ///         and recurse==false)
     ///         and recurse==false)
-    ElementPtr getItemList(const std::string& identifier = "", bool recurse = false);
+    ConstElementPtr getItemList(const std::string& identifier = "",
+                                bool recurse = false) const;
 
 
     /// Returns all current configuration settings (both non-default and default).
     /// Returns all current configuration settings (both non-default and default).
     /// \return An ElementPtr pointing to a MapElement containing
     /// \return An ElementPtr pointing to a MapElement containing
     ///         string->value elements, where the string is the
     ///         string->value elements, where the string is the
     ///         full identifier of the configuration option and the
     ///         full identifier of the configuration option and the
     ///         value is an ElementPtr with the value.
     ///         value is an ElementPtr with the value.
-    ElementPtr getFullConfig();
+    ConstElementPtr getFullConfig() const;
 
 
 private:
 private:
     ElementPtr _config;
     ElementPtr _config;
@@ -113,3 +115,7 @@ private:
 }
 }
 }
 }
 #endif
 #endif
+
+// Local Variables: 
+// mode: c++
+// End: 

+ 51 - 42
src/lib/config/module_spec.cc

@@ -24,15 +24,16 @@
 
 
 // todo: add more context to thrown ModuleSpecErrors?
 // todo: add more context to thrown ModuleSpecErrors?
 
 
-namespace isc {
-namespace config {
+using namespace isc::config;
 
 
+namespace {
 //
 //
-// static functions
+// Private functions
 //
 //
 
 
-static void
-check_leaf_item(const ElementPtr& spec, const std::string& name, Element::types type, bool mandatory)
+void
+check_leaf_item(ConstElementPtr spec, const std::string& name,
+                Element::types type, bool mandatory)
 {
 {
     if (spec->contains(name)) {
     if (spec->contains(name)) {
         if (spec->get(name)->getType() == type) {
         if (spec->get(name)->getType() == type) {
@@ -48,10 +49,10 @@ check_leaf_item(const ElementPtr& spec, const std::string& name, Element::types
     }
     }
 }
 }
 
 
-static void check_config_item_list(const ElementPtr& spec);
+void check_config_item_list(ConstElementPtr spec);
 
 
-static void
-check_config_item(const ElementPtr& spec) {
+void
+check_config_item(ConstElementPtr spec) {
     check_leaf_item(spec, "item_name", Element::string, true);
     check_leaf_item(spec, "item_name", Element::string, true);
     check_leaf_item(spec, "item_type", Element::string, true);
     check_leaf_item(spec, "item_type", Element::string, true);
     check_leaf_item(spec, "item_optional", Element::boolean, true);
     check_leaf_item(spec, "item_optional", Element::boolean, true);
@@ -72,35 +73,35 @@ check_config_item(const ElementPtr& spec) {
     }
     }
 }
 }
 
 
-static void
-check_config_item_list(const ElementPtr& spec) {
+void
+check_config_item_list(ConstElementPtr spec) {
     if (spec->getType() != Element::list) {
     if (spec->getType() != Element::list) {
         throw ModuleSpecError("config_data is not a list of elements");
         throw ModuleSpecError("config_data is not a list of elements");
     }
     }
-    BOOST_FOREACH(ElementPtr item, spec->listValue()) {
+    BOOST_FOREACH(ConstElementPtr item, spec->listValue()) {
         check_config_item(item);
         check_config_item(item);
     }
     }
 }
 }
 
 
-static void
-check_command(const ElementPtr& spec) {
+void
+check_command(ConstElementPtr spec) {
     check_leaf_item(spec, "command_name", Element::string, true);
     check_leaf_item(spec, "command_name", Element::string, true);
     check_leaf_item(spec, "command_args", Element::list, true);
     check_leaf_item(spec, "command_args", Element::list, true);
     check_config_item_list(spec->get("command_args"));
     check_config_item_list(spec->get("command_args"));
 }
 }
 
 
-static void
-check_command_list(const ElementPtr& spec) {
+void
+check_command_list(ConstElementPtr spec) {
     if (spec->getType() != Element::list) {
     if (spec->getType() != Element::list) {
         throw ModuleSpecError("commands is not a list of elements");
         throw ModuleSpecError("commands is not a list of elements");
     }
     }
-    BOOST_FOREACH(ElementPtr item, spec->listValue()) {
+    BOOST_FOREACH(ConstElementPtr item, spec->listValue()) {
         check_command(item);
         check_command(item);
     }
     }
 }
 }
 
 
-static void
-check_data_specification(const ElementPtr& spec) {
+void
+check_data_specification(ConstElementPtr spec) {
     check_leaf_item(spec, "module_name", Element::string, true);
     check_leaf_item(spec, "module_name", Element::string, true);
     check_leaf_item(spec, "module_description", Element::string, false);
     check_leaf_item(spec, "module_description", Element::string, false);
     // config_data is not mandatory; module could just define
     // config_data is not mandatory; module could just define
@@ -115,21 +116,23 @@ check_data_specification(const ElementPtr& spec) {
 
 
 // checks whether the given element is a valid module specification
 // checks whether the given element is a valid module specification
 // throws a ModuleSpecError if the specification is bad
 // throws a ModuleSpecError if the specification is bad
-static void
-check_module_specification(const ElementPtr& def)
-{
+void
+check_module_specification(ConstElementPtr def) {
     try {
     try {
         check_data_specification(def);
         check_data_specification(def);
     } catch (TypeError te) {
     } catch (TypeError te) {
         throw ModuleSpecError(te.what());
         throw ModuleSpecError(te.what());
     }
     }
 }
 }
+}
 
 
+namespace isc {
+namespace config {
 //
 //
 // Public functions
 // Public functions
 //
 //
 
 
-ModuleSpec::ModuleSpec(ElementPtr module_spec_element,
+ModuleSpec::ModuleSpec(ConstElementPtr module_spec_element,
                        const bool check)
                        const bool check)
                        throw(ModuleSpecError)
                        throw(ModuleSpecError)
                        
                        
@@ -140,7 +143,7 @@ ModuleSpec::ModuleSpec(ElementPtr module_spec_element,
     }
     }
 }
 }
 
 
-const ElementPtr
+ConstElementPtr
 ModuleSpec::getCommandsSpec() const {
 ModuleSpec::getCommandsSpec() const {
     if (module_specification->contains("commands")) {
     if (module_specification->contains("commands")) {
         return (module_specification->get("commands"));
         return (module_specification->get("commands"));
@@ -149,7 +152,7 @@ ModuleSpec::getCommandsSpec() const {
     }
     }
 }
 }
 
 
-const ElementPtr
+ConstElementPtr
 ModuleSpec::getConfigSpec() const {
 ModuleSpec::getConfigSpec() const {
     if (module_specification->contains("config_data")) {
     if (module_specification->contains("config_data")) {
         return (module_specification->get("config_data"));
         return (module_specification->get("config_data"));
@@ -173,16 +176,16 @@ ModuleSpec::getModuleDescription() const {
 }
 }
 
 
 bool
 bool
-ModuleSpec::validate_config(const ElementPtr data, const bool full) {
-    ElementPtr spec = module_specification->find("config_data");
+ModuleSpec::validate_config(ConstElementPtr data, const bool full) const {
+    ConstElementPtr spec = module_specification->find("config_data");
     return (validate_spec_list(spec, data, full, ElementPtr()));
     return (validate_spec_list(spec, data, full, ElementPtr()));
 }
 }
 
 
 bool
 bool
-ModuleSpec::validate_config(const ElementPtr data, const bool full,
-                            ElementPtr errors)
+ModuleSpec::validate_config(ConstElementPtr data, const bool full,
+                            ElementPtr errors) const
 {
 {
-    ElementPtr spec = module_specification->find("config_data");
+    ConstElementPtr spec = module_specification->find("config_data");
     return (validate_spec_list(spec, data, full, errors));
     return (validate_spec_list(spec, data, full, errors));
 }
 }
 
 
@@ -199,7 +202,7 @@ moduleSpecFromFile(const std::string& file_name, const bool check)
         throw ModuleSpecError(errs.str());
         throw ModuleSpecError(errs.str());
     }
     }
 
 
-    ElementPtr module_spec_element = Element::fromJSON(file, file_name);
+    ConstElementPtr module_spec_element = Element::fromJSON(file, file_name);
     if (module_spec_element->contains("module_spec")) {
     if (module_spec_element->contains("module_spec")) {
         return (ModuleSpec(module_spec_element->get("module_spec"), check));
         return (ModuleSpec(module_spec_element->get("module_spec"), check));
     } else {
     } else {
@@ -211,7 +214,7 @@ ModuleSpec
 moduleSpecFromFile(std::ifstream& in, const bool check)
 moduleSpecFromFile(std::ifstream& in, const bool check)
                    throw(JSONError, ModuleSpecError)
                    throw(JSONError, ModuleSpecError)
 {
 {
-    ElementPtr module_spec_element = Element::fromJSON(in);
+    ConstElementPtr module_spec_element = Element::fromJSON(in);
     if (module_spec_element->contains("module_spec")) {
     if (module_spec_element->contains("module_spec")) {
         return (ModuleSpec(module_spec_element->get("module_spec"), check));
         return (ModuleSpec(module_spec_element->get("module_spec"), check));
     } else {
     } else {
@@ -220,6 +223,7 @@ moduleSpecFromFile(std::ifstream& in, const bool check)
 }
 }
 
 
 
 
+namespace {
 //
 //
 // private functions
 // private functions
 //
 //
@@ -227,9 +231,8 @@ moduleSpecFromFile(std::ifstream& in, const bool check)
 //
 //
 // helper functions for validation
 // helper functions for validation
 //
 //
-static bool
-check_type(ElementPtr spec, ElementPtr element)
-{
+bool
+check_type(ConstElementPtr spec, ConstElementPtr element) {
     std::string cur_item_type;
     std::string cur_item_type;
     cur_item_type = spec->get("item_type")->stringValue();
     cur_item_type = spec->get("item_type")->stringValue();
     if (cur_item_type == "any") {
     if (cur_item_type == "any") {
@@ -257,9 +260,12 @@ check_type(ElementPtr spec, ElementPtr element)
     }
     }
     return (false);
     return (false);
 }
 }
+}
 
 
 bool
 bool
-ModuleSpec::validate_item(const ElementPtr spec, const ElementPtr data, const bool full, ElementPtr errors) {
+ModuleSpec::validate_item(ConstElementPtr spec, ConstElementPtr data,
+                          const bool full, ElementPtr errors) const
+{
     if (!check_type(spec, data)) {
     if (!check_type(spec, data)) {
         // we should do some proper error feedback here
         // we should do some proper error feedback here
         // std::cout << "type mismatch; not " << spec->get("item_type") << ": " << data << std::endl;
         // std::cout << "type mismatch; not " << spec->get("item_type") << ": " << data << std::endl;
@@ -270,8 +276,8 @@ ModuleSpec::validate_item(const ElementPtr spec, const ElementPtr data, const bo
         return (false);
         return (false);
     }
     }
     if (data->getType() == Element::list) {
     if (data->getType() == Element::list) {
-        ElementPtr list_spec = spec->get("list_item_spec");
-        BOOST_FOREACH(ElementPtr list_el, data->listValue()) {
+        ConstElementPtr list_spec = spec->get("list_item_spec");
+        BOOST_FOREACH(ConstElementPtr list_el, data->listValue()) {
             if (!check_type(list_spec, list_el)) {
             if (!check_type(list_spec, list_el)) {
                 if (errors) {
                 if (errors) {
                     errors->add(Element::create("Type mismatch"));
                     errors->add(Element::create("Type mismatch"));
@@ -295,10 +301,12 @@ ModuleSpec::validate_item(const ElementPtr spec, const ElementPtr data, const bo
 
 
 // spec is a map with item_name etc, data is a map
 // spec is a map with item_name etc, data is a map
 bool
 bool
-ModuleSpec::validate_spec(const ElementPtr spec, const ElementPtr data, const bool full, ElementPtr errors) {
+ModuleSpec::validate_spec(ConstElementPtr spec, ConstElementPtr data,
+                          const bool full, ElementPtr errors) const
+{
     std::string item_name = spec->get("item_name")->stringValue();
     std::string item_name = spec->get("item_name")->stringValue();
     bool optional = spec->get("item_optional")->boolValue();
     bool optional = spec->get("item_optional")->boolValue();
-    ElementPtr data_el;
+    ConstElementPtr data_el;
     data_el = data->get(item_name);
     data_el = data->get(item_name);
     
     
     if (data_el) {
     if (data_el) {
@@ -318,10 +326,11 @@ ModuleSpec::validate_spec(const ElementPtr spec, const ElementPtr data, const bo
 
 
 // spec is a list of maps, data is a map
 // spec is a list of maps, data is a map
 bool
 bool
-ModuleSpec::validate_spec_list(const ElementPtr spec, const ElementPtr data, const bool full, ElementPtr errors) {
-    ElementPtr cur_data_el;
+ModuleSpec::validate_spec_list(ConstElementPtr spec, ConstElementPtr data,
+                               const bool full, ElementPtr errors) const
+{
     std::string cur_item_name;
     std::string cur_item_name;
-    BOOST_FOREACH(ElementPtr cur_spec_el, spec->listValue()) {
+    BOOST_FOREACH(ConstElementPtr cur_spec_el, spec->listValue()) {
         if (!validate_spec(cur_spec_el, data, full, errors)) {
         if (!validate_spec(cur_spec_el, data, full, errors)) {
             return (false);
             return (false);
         }
         }

+ 22 - 13
src/lib/config/module_spec.h

@@ -51,28 +51,28 @@ namespace isc { namespace config {
     ///
     ///
     class ModuleSpec {
     class ModuleSpec {
     public:
     public:
-        explicit ModuleSpec() {};
+        ModuleSpec() {};
         /// Create a \c ModuleSpec instance with the given data as
         /// Create a \c ModuleSpec instance with the given data as
         /// the specification
         /// the specification
         /// \param e The Element containing the data specification
         /// \param e The Element containing the data specification
-        explicit ModuleSpec(ElementPtr e, const bool check = true)
-                            throw(ModuleSpecError);
+        explicit ModuleSpec(ConstElementPtr e, const bool check = true)
+            throw(ModuleSpecError);
 
 
         /// Returns the commands part of the specification as an
         /// Returns the commands part of the specification as an
         /// ElementPtr, returns an empty ElementPtr if there is none
         /// ElementPtr, returns an empty ElementPtr if there is none
         /// \return ElementPtr Shared pointer to the commands
         /// \return ElementPtr Shared pointer to the commands
         ///                    part of the specification
         ///                    part of the specification
-        const ElementPtr getCommandsSpec() const;
+        ConstElementPtr getCommandsSpec() const;
 
 
         /// Returns the configuration part of the specification as an
         /// Returns the configuration part of the specification as an
         /// ElementPtr
         /// ElementPtr
         /// \return ElementPtr Shared pointer to the configuration
         /// \return ElementPtr Shared pointer to the configuration
         ///                    part of the specification
         ///                    part of the specification
-        const ElementPtr getConfigSpec() const;
+        ConstElementPtr getConfigSpec() const;
 
 
         /// Returns the full module specification as an ElementPtr
         /// Returns the full module specification as an ElementPtr
         /// \return ElementPtr Shared pointer to the specification
         /// \return ElementPtr Shared pointer to the specification
-        const ElementPtr getFullSpec() const { return (module_specification); }
+        ConstElementPtr getFullSpec() const { return module_specification; }
 
 
         /// Returns the module name as specified by the specification
         /// Returns the module name as specified by the specification
         const std::string getModuleName() const;
         const std::string getModuleName() const;
@@ -87,17 +87,22 @@ namespace isc { namespace config {
         /// \param data The base \c Element of the data to check
         /// \param data The base \c Element of the data to check
         /// \return true if the data conforms to the specification,
         /// \return true if the data conforms to the specification,
         /// false otherwise.
         /// false otherwise.
-        bool validate_config(const ElementPtr data, const bool full = false);
+        bool validate_config(ConstElementPtr data,
+                             const bool full = false) const;
 
 
         /// errors must be of type ListElement
         /// errors must be of type ListElement
-        bool validate_config(const ElementPtr data, const bool full, ElementPtr errors);
+        bool validate_config(ConstElementPtr data, const bool full,
+                             ElementPtr errors) const;
 
 
     private:
     private:
-        bool validate_item(const ElementPtr spec, const ElementPtr data, const bool full, ElementPtr errors);
-        bool validate_spec(const ElementPtr spec, const ElementPtr data, const bool full, ElementPtr errors);
-        bool validate_spec_list(const ElementPtr spec, const ElementPtr data, const bool full, ElementPtr errors);
-
-        ElementPtr module_specification;
+        bool validate_item(ConstElementPtr spec, ConstElementPtr data,
+                           const bool full, ElementPtr errors) const;
+        bool validate_spec(ConstElementPtr spec, ConstElementPtr data,
+                           const bool full, ElementPtr errors) const;
+        bool validate_spec_list(ConstElementPtr spec, ConstElementPtr data,
+                                const bool full, ElementPtr errors) const;
+
+        ConstElementPtr module_specification;
     };
     };
 
 
     /// Creates a \c ModuleSpec instance from the contents
     /// Creates a \c ModuleSpec instance from the contents
@@ -126,3 +131,7 @@ namespace isc { namespace config {
 } }
 } }
 
 
 #endif // _DATA_DEF_H
 #endif // _DATA_DEF_H
+
+// Local Variables: 
+// mode: c++
+// End: 

File diff suppressed because it is too large
+ 16 - 16
src/lib/config/tests/ccsession_unittests.cc


+ 25 - 46
src/lib/config/tests/fake_session.cc

@@ -40,12 +40,12 @@ using namespace isc::data;
 
 
 // ok i want these in cc/data 
 // ok i want these in cc/data 
 bool
 bool
-listContains(ElementPtr list, ElementPtr el) {
+listContains(ConstElementPtr list, ConstElementPtr el) {
     if (!list) {
     if (!list) {
         return (false);
         return (false);
     }
     }
-    BOOST_FOREACH(ElementPtr l_el, list->listValue()) {
-        if (l_el == el) {
+    BOOST_FOREACH(ConstElementPtr l_el, list->listValue()) {
+        if (*l_el == *el) {
             return (true);
             return (true);
         }
         }
     }
     }
@@ -53,10 +53,10 @@ listContains(ElementPtr list, ElementPtr el) {
 }
 }
 
 
 void
 void
-listRemove(ElementPtr list, ElementPtr el) {
+listRemove(ElementPtr list, ConstElementPtr el) {
     int i = -1;
     int i = -1;
-    BOOST_FOREACH(ElementPtr s_el, list->listValue()) {
-        if (el == s_el) {
+    BOOST_FOREACH(ConstElementPtr s_el, list->listValue()) {
+        if (*el == *s_el) {
             i = 0;
             i = 0;
         }
         }
         i++;
         i++;
@@ -82,11 +82,6 @@ FakeSession::FakeSession(isc::data::ElementPtr initial_messages,
 FakeSession::~FakeSession() {
 FakeSession::~FakeSession() {
 }
 }
 
 
-bool
-FakeSession::connect() {
-    return (true);
-}
-
 void
 void
 FakeSession::disconnect() {
 FakeSession::disconnect() {
 }
 }
@@ -99,25 +94,8 @@ void
 FakeSession::establish(const char* socket_file) {
 FakeSession::establish(const char* socket_file) {
 }
 }
 
 
-//
-// Convert to wire format and send this on the TCP stream with its length prefix
-//
-void
-FakeSession::sendmsg(ElementPtr& msg) {
-    //cout << "[XX] client sends message: " << msg << endl;
-    // err, to where?
-    addMessage(msg, "*", "*");
-}
-
-void
-FakeSession::sendmsg(ElementPtr& env, ElementPtr& msg) {
-    //cout << "[XX] client sends message: " << msg << endl;
-    //cout << "[XX] env: " << env << endl;
-    addMessage(msg, env->get("group")->stringValue(), env->get("to")->stringValue());
-}
-
 bool
 bool
-FakeSession::recvmsg(ElementPtr& msg, bool nonblock UNUSED_PARAM,
+FakeSession::recvmsg(ConstElementPtr& msg, bool nonblock UNUSED_PARAM,
                      int seq UNUSED_PARAM)
                      int seq UNUSED_PARAM)
 {
 {
     //cout << "[XX] client asks for message " << endl;
     //cout << "[XX] client asks for message " << endl;
@@ -133,7 +111,7 @@ FakeSession::recvmsg(ElementPtr& msg, bool nonblock UNUSED_PARAM,
 }
 }
 
 
 bool
 bool
-FakeSession::recvmsg(ElementPtr& env, ElementPtr& msg,
+FakeSession::recvmsg(ConstElementPtr& env, ConstElementPtr& msg,
                      bool nonblock UNUSED_PARAM,
                      bool nonblock UNUSED_PARAM,
                      int seq UNUSED_PARAM)
                      int seq UNUSED_PARAM)
 {
 {
@@ -147,12 +125,13 @@ FakeSession::recvmsg(ElementPtr& env, ElementPtr& msg,
         messages_->remove(0);
         messages_->remove(0);
         return (true);
         return (true);
     } else if (msg_queue_) {
     } else if (msg_queue_) {
-        BOOST_FOREACH(ElementPtr c_m, msg_queue_->listValue()) {
-            ElementPtr to_remove = ElementPtr();
+        BOOST_FOREACH(ConstElementPtr c_m, msg_queue_->listValue()) {
+            ConstElementPtr to_remove = ElementPtr();
             if (haveSubscription(c_m->get(0), c_m->get(1))) {
             if (haveSubscription(c_m->get(0), c_m->get(1))) {
-                env = Element::createMap();
-                env->set("group", c_m->get(0));
-                env->set("to", c_m->get(1));
+                ElementPtr new_env = Element::createMap();
+                new_env->set("group", c_m->get(0));
+                new_env->set("to", c_m->get(1));
+                env = new_env;
                 msg = c_m->get(2);
                 msg = c_m->get(2);
                 to_remove = c_m;
                 to_remove = c_m;
             }
             }
@@ -192,7 +171,7 @@ FakeSession::unsubscribe(std::string group, std::string instance) {
 }
 }
 
 
 int
 int
-FakeSession::group_sendmsg(ElementPtr msg, std::string group,
+FakeSession::group_sendmsg(ConstElementPtr msg, std::string group,
                            std::string to, std::string instance UNUSED_PARAM)
                            std::string to, std::string instance UNUSED_PARAM)
 {
 {
     //cout << "[XX] client sends message: " << msg << endl;
     //cout << "[XX] client sends message: " << msg << endl;
@@ -202,28 +181,29 @@ FakeSession::group_sendmsg(ElementPtr msg, std::string group,
 }
 }
 
 
 bool
 bool
-FakeSession::group_recvmsg(ElementPtr& envelope, ElementPtr& msg,
+FakeSession::group_recvmsg(ConstElementPtr& envelope, ConstElementPtr& msg,
                            bool nonblock, int seq)
                            bool nonblock, int seq)
 {
 {
     return (recvmsg(envelope, msg, nonblock, seq));
     return (recvmsg(envelope, msg, nonblock, seq));
 }
 }
 
 
 int
 int
-FakeSession::reply(ElementPtr& envelope, ElementPtr& newmsg) {
+FakeSession::reply(ConstElementPtr envelope, ConstElementPtr newmsg) {
     //cout << "[XX] client sends reply: " << newmsg << endl;
     //cout << "[XX] client sends reply: " << newmsg << endl;
     //cout << "[XX] env: " << envelope << endl;
     //cout << "[XX] env: " << envelope << endl;
-    addMessage(newmsg, envelope->get("group")->stringValue(), envelope->get("to")->stringValue());
+    addMessage(newmsg, envelope->get("group")->stringValue(),
+               envelope->get("to")->stringValue());
     return (1);
     return (1);
 }
 }
 
 
 bool
 bool
-FakeSession::hasQueuedMsgs() {
+FakeSession::hasQueuedMsgs() const {
     return (false);
     return (false);
 }
 }
 
 
-ElementPtr
-FakeSession::getFirstMessage(std::string& group, std::string& to) {
-    ElementPtr el;
+ConstElementPtr
+FakeSession::getFirstMessage(std::string& group, std::string& to) const {
+    ConstElementPtr el;
     if (msg_queue_ && msg_queue_->size() > 0) {
     if (msg_queue_ && msg_queue_->size() > 0) {
         el = msg_queue_->get(0);
         el = msg_queue_->get(0);
         msg_queue_->remove(0);
         msg_queue_->remove(0);
@@ -238,7 +218,7 @@ FakeSession::getFirstMessage(std::string& group, std::string& to) {
 }
 }
 
 
 void
 void
-FakeSession::addMessage(ElementPtr msg, const std::string& group,
+FakeSession::addMessage(ConstElementPtr msg, const std::string& group,
                         const std::string& to)
                         const std::string& to)
 {
 {
     ElementPtr m_el = Element::createList();
     ElementPtr m_el = Element::createList();
@@ -270,8 +250,7 @@ FakeSession::haveSubscription(const std::string& group,
 }
 }
 
 
 bool
 bool
-FakeSession::haveSubscription(const ElementPtr group,
-                              const ElementPtr instance)
+FakeSession::haveSubscription(ConstElementPtr group, ConstElementPtr instance)
 {
 {
     return (haveSubscription(group->stringValue(), instance->stringValue()));
     return (haveSubscription(group->stringValue(), instance->stringValue()));
 }
 }

+ 19 - 21
src/lib/config/tests/fake_session.h

@@ -47,40 +47,32 @@ public:
     virtual void startRead(boost::function<void()> read_callback);
     virtual void startRead(boost::function<void()> read_callback);
 
 
     virtual void establish(const char* socket_file = NULL);
     virtual void establish(const char* socket_file = NULL);
-    bool connect();
     virtual void disconnect();
     virtual void disconnect();
-    void sendmsg(isc::data::ElementPtr& msg);
-    void sendmsg(isc::data::ElementPtr& env,
-                 isc::data::ElementPtr& msg);
-    bool recvmsg(isc::data::ElementPtr& msg,
-                 bool nonblock = true, int seq = -1);
-    bool recvmsg(isc::data::ElementPtr& env,
-                 isc::data::ElementPtr& msg,
-                 bool nonblock = true, int seq = -1);
     virtual void subscribe(std::string group,
     virtual void subscribe(std::string group,
                            std::string instance = "*");
                            std::string instance = "*");
     virtual void unsubscribe(std::string group,
     virtual void unsubscribe(std::string group,
                              std::string instance = "*");
                              std::string instance = "*");
-    virtual int group_sendmsg(isc::data::ElementPtr msg,
+    virtual int group_sendmsg(isc::data::ConstElementPtr msg,
                               std::string group,
                               std::string group,
                               std::string instance = "*",
                               std::string instance = "*",
                               std::string to = "*");
                               std::string to = "*");
-    virtual bool group_recvmsg(isc::data::ElementPtr& envelope,
-                               isc::data::ElementPtr& msg,
+    virtual bool group_recvmsg(isc::data::ConstElementPtr& envelope,
+                               isc::data::ConstElementPtr& msg,
                                bool nonblock = true,
                                bool nonblock = true,
                                int seq = -1);
                                int seq = -1);
-    virtual int reply(isc::data::ElementPtr& envelope,
-                      isc::data::ElementPtr& newmsg);
-    virtual bool hasQueuedMsgs();
-    virtual void setTimeout(size_t milliseconds) {};
-    virtual size_t getTimeout() const { return 0; };
-    isc::data::ElementPtr getFirstMessage(std::string& group, std::string& to);
-    void addMessage(isc::data::ElementPtr, const std::string& group,
+    virtual int reply(isc::data::ConstElementPtr envelope,
+                      isc::data::ConstElementPtr newmsg);
+    virtual bool hasQueuedMsgs() const;
+    virtual void setTimeout(size_t milliseconds) {}
+    virtual size_t getTimeout() const { return (0); }
+    isc::data::ConstElementPtr getFirstMessage(std::string& group,
+                                               std::string& to) const;
+    void addMessage(isc::data::ConstElementPtr, const std::string& group,
                     const std::string& to);
                     const std::string& to);
     bool haveSubscription(const std::string& group,
     bool haveSubscription(const std::string& group,
                           const std::string& instance);
                           const std::string& instance);
-    bool haveSubscription(const isc::data::ElementPtr group,
-                          const isc::data::ElementPtr instance);
+    bool haveSubscription(const isc::data::ConstElementPtr group,
+                          const isc::data::ConstElementPtr instance);
 
 
     // For the convenience of tests, we share these internal members
     // For the convenience of tests, we share these internal members
     // with the tester.  The test code may insert update and check,
     // with the tester.  The test code may insert update and check,
@@ -90,6 +82,12 @@ public:
     isc::data::ElementPtr getMsgQueue() { return (msg_queue_); }
     isc::data::ElementPtr getMsgQueue() { return (msg_queue_); }
 
 
 private:
 private:
+    bool recvmsg(isc::data::ConstElementPtr& msg,
+                 bool nonblock = true, int seq = -1);
+    bool recvmsg(isc::data::ConstElementPtr& env,
+                 isc::data::ConstElementPtr& msg,
+                 bool nonblock = true, int seq = -1);
+
     const isc::data::ElementPtr messages_;
     const isc::data::ElementPtr messages_;
     isc::data::ElementPtr subscriptions_;
     isc::data::ElementPtr subscriptions_;
     isc::data::ElementPtr msg_queue_;
     isc::data::ElementPtr msg_queue_;

+ 5 - 4
src/lib/config/tests/module_spec_unittests.cc

@@ -134,23 +134,24 @@ TEST(ModuleSpec, SpecfileCommands)
 }
 }
 
 
 bool
 bool
-data_test(ModuleSpec dd, const std::string& data_file_name) {
+data_test(const ModuleSpec& dd, const std::string& data_file_name) {
     std::ifstream data_file;
     std::ifstream data_file;
 
 
     data_file.open(specfile(data_file_name).c_str());
     data_file.open(specfile(data_file_name).c_str());
-    ElementPtr data = Element::fromJSON(data_file, data_file_name);
+    ConstElementPtr data = Element::fromJSON(data_file, data_file_name);
     data_file.close();
     data_file.close();
 
 
     return (dd.validate_config(data));
     return (dd.validate_config(data));
 }
 }
 
 
 bool
 bool
-data_test_with_errors(ModuleSpec dd, const std::string& data_file_name, ElementPtr errors)
+data_test_with_errors(const ModuleSpec& dd, const std::string& data_file_name,
+                      ElementPtr errors)
 {
 {
     std::ifstream data_file;
     std::ifstream data_file;
 
 
     data_file.open(specfile(data_file_name).c_str());
     data_file.open(specfile(data_file_name).c_str());
-    ElementPtr data = Element::fromJSON(data_file, data_file_name);
+    ConstElementPtr data = Element::fromJSON(data_file, data_file_name);
     data_file.close();
     data_file.close();
 
 
     return (dd.validate_config(data, true, errors));
     return (dd.validate_config(data, true, errors));

+ 1 - 1
src/lib/datasrc/data_source.cc

@@ -1245,7 +1245,7 @@ Nsec3Param::getHash(const Name& name) const {
 // installed files we define the methods here.
 // installed files we define the methods here.
 //
 //
 DataSrc::Result
 DataSrc::Result
-DataSrc::init(const isc::data::ElementPtr config UNUSED_PARAM) {
+DataSrc::init(isc::data::ConstElementPtr config UNUSED_PARAM) {
     return (NOT_IMPLEMENTED);
     return (NOT_IMPLEMENTED);
 }
 }
 
 

+ 2 - 2
src/lib/datasrc/data_source.h

@@ -115,7 +115,7 @@ public:
     // Optional 'low-level' methods.  These will have stub implementations
     // Optional 'low-level' methods.  These will have stub implementations
     // in the general DataSrc class but MAY be overwritten by subclasses
     // in the general DataSrc class but MAY be overwritten by subclasses
     virtual Result init() = 0;
     virtual Result init() = 0;
-    virtual Result init(const isc::data::ElementPtr config) = 0;
+    virtual Result init(isc::data::ConstElementPtr config) = 0;
     virtual Result close() = 0;
     virtual Result close() = 0;
 
 
     // Mandatory 'low-level' methods: These will NOT be implemented by
     // Mandatory 'low-level' methods: These will NOT be implemented by
@@ -187,7 +187,7 @@ public:
     void setClass(const isc::dns::RRClass& c) { rrclass = c; }
     void setClass(const isc::dns::RRClass& c) { rrclass = c; }
 
 
     Result init() { return (NOT_IMPLEMENTED); }
     Result init() { return (NOT_IMPLEMENTED); }
-    Result init(const isc::data::ElementPtr config);
+    Result init(isc::data::ConstElementPtr config);
     Result close() { return (NOT_IMPLEMENTED); }
     Result close() { return (NOT_IMPLEMENTED); }
 
 
     virtual Result findRRset(const isc::dns::Name& qname,
     virtual Result findRRset(const isc::dns::Name& qname,

+ 1 - 1
src/lib/datasrc/sqlite3_datasrc.cc

@@ -558,7 +558,7 @@ Sqlite3DataSrc::~Sqlite3DataSrc() {
 }
 }
 
 
 DataSrc::Result
 DataSrc::Result
-Sqlite3DataSrc::init(const isc::data::ElementPtr config) {
+Sqlite3DataSrc::init(isc::data::ConstElementPtr config) {
     if (config && config->contains("database_file")) {
     if (config && config->contains("database_file")) {
         open(config->get("database_file")->stringValue());
         open(config->get("database_file")->stringValue());
     } else {
     } else {

+ 1 - 1
src/lib/datasrc/sqlite3_datasrc.h

@@ -95,7 +95,7 @@ public:
                              isc::dns::RRsetList& target) const;
                              isc::dns::RRsetList& target) const;
 
 
     Result init() { return (init(isc::data::ElementPtr())); }
     Result init() { return (init(isc::data::ElementPtr())); }
-    Result init(const isc::data::ElementPtr config);
+    Result init(const isc::data::ConstElementPtr config);
     Result close();
     Result close();
 
 
 private:
 private:

+ 1 - 1
src/lib/datasrc/static_datasrc.cc

@@ -260,7 +260,7 @@ StaticDataSrc::init() {
 // Static data source is "configuration less", so the \c config parameter
 // Static data source is "configuration less", so the \c config parameter
 // is intentionally ignored.
 // is intentionally ignored.
 DataSrc::Result
 DataSrc::Result
-StaticDataSrc::init(const isc::data::ElementPtr config UNUSED_PARAM) {
+StaticDataSrc::init(isc::data::ConstElementPtr config UNUSED_PARAM) {
     return (init());
     return (init());
 }
 }
 
 

+ 1 - 1
src/lib/datasrc/static_datasrc.h

@@ -81,7 +81,7 @@ public:
                             isc::dns::RRsetList& target) const;
                             isc::dns::RRsetList& target) const;
 
 
     Result init();
     Result init();
-    Result init(const isc::data::ElementPtr config);
+    Result init(isc::data::ConstElementPtr config);
     Result close();
     Result close();
 private:
 private:
     StaticDataSrcImpl* impl_;
     StaticDataSrcImpl* impl_;

+ 1 - 1
src/lib/datasrc/tests/datasrc_unittest.cc

@@ -49,7 +49,7 @@ using namespace isc::datasrc;
 using namespace isc::data;
 using namespace isc::data;
 
 
 namespace {
 namespace {
-const ElementPtr SQLITE_DBFILE_EXAMPLE = Element::fromJSON(
+ConstElementPtr SQLITE_DBFILE_EXAMPLE = Element::fromJSON(
     "{ \"database_file\": \"" TEST_DATA_DIR "/example.org.sqlite3\"}");
     "{ \"database_file\": \"" TEST_DATA_DIR "/example.org.sqlite3\"}");
 
 
 class DataSrcTest : public ::testing::Test {
 class DataSrcTest : public ::testing::Test {

+ 6 - 6
src/lib/datasrc/tests/sqlite3_unittest.cc

@@ -43,22 +43,22 @@ using namespace isc::datasrc;
 using namespace isc::data;
 using namespace isc::data;
 
 
 namespace {
 namespace {
-ElementPtr SQLITE_DBFILE_EXAMPLE = Element::fromJSON(
+ConstElementPtr SQLITE_DBFILE_EXAMPLE = Element::fromJSON(
     "{ \"database_file\": \"" TEST_DATA_DIR "/test.sqlite3\"}");
     "{ \"database_file\": \"" TEST_DATA_DIR "/test.sqlite3\"}");
-ElementPtr SQLITE_DBFILE_EXAMPLE2 = Element::fromJSON(
+ConstElementPtr SQLITE_DBFILE_EXAMPLE2 = Element::fromJSON(
     "{ \"database_file\": \"" TEST_DATA_DIR "/example2.com.sqlite3\"}");
     "{ \"database_file\": \"" TEST_DATA_DIR "/example2.com.sqlite3\"}");
-ElementPtr SQLITE_DBFILE_EXAMPLE_ROOT = Element::fromJSON(
+ConstElementPtr SQLITE_DBFILE_EXAMPLE_ROOT = Element::fromJSON(
     "{ \"database_file\": \"" TEST_DATA_DIR "/test-root.sqlite3\"}");
     "{ \"database_file\": \"" TEST_DATA_DIR "/test-root.sqlite3\"}");
-ElementPtr SQLITE_DBFILE_BROKENDB = Element::fromJSON(
+ConstElementPtr SQLITE_DBFILE_BROKENDB = Element::fromJSON(
     "{ \"database_file\": \"" TEST_DATA_DIR "/brokendb.sqlite3\"}");
     "{ \"database_file\": \"" TEST_DATA_DIR "/brokendb.sqlite3\"}");
-ElementPtr SQLITE_DBFILE_MEMORY = Element::fromJSON(
+ConstElementPtr SQLITE_DBFILE_MEMORY = Element::fromJSON(
     "{ \"database_file\": \":memory:\"}");
     "{ \"database_file\": \":memory:\"}");
 
 
 // The following file must be non existent and must be non"creatable";
 // The following file must be non existent and must be non"creatable";
 // the sqlite3 library will try to create a new DB file if it doesn't exist,
 // the sqlite3 library will try to create a new DB file if it doesn't exist,
 // so to test a failure case the create operation should also fail.
 // so to test a failure case the create operation should also fail.
 // The "nodir", a non existent directory, is inserted for this purpose.
 // The "nodir", a non existent directory, is inserted for this purpose.
-ElementPtr SQLITE_DBFILE_NOTEXIST = Element::fromJSON(
+ConstElementPtr SQLITE_DBFILE_NOTEXIST = Element::fromJSON(
     "{ \"database_file\": \"" TEST_DATA_DIR "/nodir/notexist\"}");
     "{ \"database_file\": \"" TEST_DATA_DIR "/nodir/notexist\"}");
 
 
 const string sigdata_common(" 20100322084538 20100220084538 "
 const string sigdata_common(" 20100322084538 20100220084538 "

+ 1 - 2
src/lib/datasrc/tests/test_datasrc.cc

@@ -307,8 +307,7 @@ vector<Zone> zones;
 }
 }
 
 
 DataSrc::Result
 DataSrc::Result
-TestDataSrc::init(const isc::data::ElementPtr config UNUSED_PARAM)
-{
+TestDataSrc::init(isc::data::ConstElementPtr config UNUSED_PARAM) {
     return (init());
     return (init());
 }
 }
 
 

+ 1 - 1
src/lib/datasrc/tests/test_datasrc.h

@@ -85,7 +85,7 @@ public:
                              isc::dns::RRsetList& target) const;
                              isc::dns::RRsetList& target) const;
 
 
     Result init();
     Result init();
-    Result init(const isc::data::ElementPtr config);
+    Result init(isc::data::ConstElementPtr config);
     Result close() { return (SUCCESS); }
     Result close() { return (SUCCESS); }
 
 
 private:
 private: