BIND 10 master, updated. dd0f73adac540774a6cb2c99faece4d6c4b90353 Merge branch 'trac2281'

BIND 10 source code commits bind10-changes at lists.isc.org
Thu Feb 14 10:03:48 UTC 2013


The branch, master has been updated
       via  dd0f73adac540774a6cb2c99faece4d6c4b90353 (commit)
       via  67940bdbff79a551466de411f4ed3126a254888e (commit)
       via  8e33f9e96aa79b1f99828c063cab84328ce3f248 (commit)
       via  d404649f95abf23268f91c31b30d52b06e5a3df3 (commit)
       via  cfd00e940391d98c71f3cb026558d66f291a59e0 (commit)
       via  d7f14ea88e8cc0f3e7f08b4ee6c4647ff2908279 (commit)
       via  6a06b311fb9efe408fa6bf6dc2fe37a5ffcf2154 (commit)
       via  11633f6c60336ff1ba648e09b51db064252e034c (commit)
       via  899432b47a8460c65ae0211b0bee1f9296bfa433 (commit)
       via  c30f889cf94e021413599a1bd2f193b887824ba3 (commit)
       via  3a9d8e2406929a87eaefc22953dde380c4a9ebc8 (commit)
       via  fbaab5fd3c4fc983889b194a96310a0239b040d5 (commit)
       via  60a9f3a768ebd546c8aeff70d84b769dc95836ca (commit)
      from  d6f24ba6266d3ed630a3fbbe2b4b8ef2cf501343 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit dd0f73adac540774a6cb2c99faece4d6c4b90353
Merge: d6f24ba 67940bd
Author: Mukund Sivaraman <muks at isc.org>
Date:   Thu Feb 14 15:20:07 2013 +0530

    Merge branch 'trac2281'
    
    Conflicts:
    	src/lib/datasrc/memory/memory_messages.mes
    	src/lib/datasrc/memory_datasrc.cc

-----------------------------------------------------------------------

Summary of changes:
 src/bin/auth/auth_config.cc                        |    2 -
 src/bin/auth/tests/auth_srv_unittest.cc            |    1 -
 src/bin/auth/tests/command_unittest.cc             |    2 -
 src/bin/auth/tests/config_unittest.cc              |    1 -
 src/bin/auth/tests/query_unittest.cc               |  101 +-
 src/lib/datasrc/Makefile.am                        |   14 +-
 src/lib/datasrc/datasrc_messages.mes               |  171 --
 src/lib/datasrc/factory.cc                         |    1 -
 src/lib/datasrc/memory/memory_messages.mes         |  104 +-
 src/lib/datasrc/memory/zone_finder.cc              |   36 +-
 src/lib/datasrc/memory_datasrc.cc                  | 2045 ------------------
 src/lib/datasrc/memory_datasrc.h                   |  366 ----
 src/lib/datasrc/memory_datasrc_link.cc             |  277 ---
 src/lib/datasrc/rbnode_rrset.h                     |  230 --
 src/lib/datasrc/rbtree.h                           | 1993 -----------------
 src/lib/datasrc/static_datasrc.h                   |   50 +
 src/lib/datasrc/static_datasrc_link.cc             |   22 +-
 src/lib/datasrc/tests/Makefile.am                  |    5 +-
 src/lib/datasrc/tests/factory_unittest.cc          |   81 +-
 src/lib/datasrc/tests/memory_datasrc_unittest.cc   | 2246 --------------------
 src/lib/datasrc/tests/rbnode_rrset_unittest.cc     |  276 ---
 src/lib/datasrc/tests/rbtree_unittest.cc           | 1074 ----------
 src/lib/datasrc/tests/testdata/static-bad.zone     |    3 +
 src/lib/datasrc/tests/testdata/static.zone         |    3 +-
 src/lib/datasrc/tests/zonetable_unittest.cc        |  128 --
 src/lib/datasrc/zonetable.cc                       |  160 --
 src/lib/datasrc/zonetable.h                        |  160 --
 src/lib/python/isc/datasrc/tests/Makefile.am       |    1 +
 src/lib/python/isc/datasrc/tests/datasrc_test.py   |   26 +-
 .../python/isc/datasrc/tests/testdata/static.zone  |    3 +
 .../python/isc/datasrc/tests/zone_loader_test.py   |   14 +-
 31 files changed, 292 insertions(+), 9304 deletions(-)
 delete mode 100644 src/lib/datasrc/memory_datasrc.cc
 delete mode 100644 src/lib/datasrc/memory_datasrc.h
 delete mode 100644 src/lib/datasrc/memory_datasrc_link.cc
 delete mode 100644 src/lib/datasrc/rbnode_rrset.h
 delete mode 100644 src/lib/datasrc/rbtree.h
 create mode 100644 src/lib/datasrc/static_datasrc.h
 delete mode 100644 src/lib/datasrc/tests/memory_datasrc_unittest.cc
 delete mode 100644 src/lib/datasrc/tests/rbnode_rrset_unittest.cc
 delete mode 100644 src/lib/datasrc/tests/rbtree_unittest.cc
 create mode 100644 src/lib/datasrc/tests/testdata/static-bad.zone
 delete mode 100644 src/lib/datasrc/tests/zonetable_unittest.cc
 delete mode 100644 src/lib/datasrc/zonetable.cc
 delete mode 100644 src/lib/datasrc/zonetable.h
 create mode 100644 src/lib/python/isc/datasrc/tests/testdata/static.zone

-----------------------------------------------------------------------
diff --git a/src/bin/auth/auth_config.cc b/src/bin/auth/auth_config.cc
index de8325b..58526da 100644
--- a/src/bin/auth/auth_config.cc
+++ b/src/bin/auth/auth_config.cc
@@ -17,8 +17,6 @@
 
 #include <cc/data.h>
 
-#include <datasrc/memory_datasrc.h>
-#include <datasrc/zonetable.h>
 #include <datasrc/factory.h>
 
 #include <auth/auth_srv.h>
diff --git a/src/bin/auth/tests/auth_srv_unittest.cc b/src/bin/auth/tests/auth_srv_unittest.cc
index 826d1b8..f58d0e0 100644
--- a/src/bin/auth/tests/auth_srv_unittest.cc
+++ b/src/bin/auth/tests/auth_srv_unittest.cc
@@ -29,7 +29,6 @@
 #include <server_common/portconfig.h>
 #include <server_common/keyring.h>
 
-#include <datasrc/memory_datasrc.h>
 #include <datasrc/client_list.h>
 #include <auth/auth_srv.h>
 #include <auth/command.h>
diff --git a/src/bin/auth/tests/command_unittest.cc b/src/bin/auth/tests/command_unittest.cc
index be90d73..180cd2c 100644
--- a/src/bin/auth/tests/command_unittest.cc
+++ b/src/bin/auth/tests/command_unittest.cc
@@ -29,8 +29,6 @@
 
 #include <config/ccsession.h>
 
-#include <datasrc/memory_datasrc.h>
-
 #include <asiolink/asiolink.h>
 
 #include <util/unittests/mock_socketsession.h>
diff --git a/src/bin/auth/tests/config_unittest.cc b/src/bin/auth/tests/config_unittest.cc
index 05c6cce..0d6cbf8 100644
--- a/src/bin/auth/tests/config_unittest.cc
+++ b/src/bin/auth/tests/config_unittest.cc
@@ -22,7 +22,6 @@
 #include <cc/data.h>
 
 #include <datasrc/data_source.h>
-#include <datasrc/memory_datasrc.h>
 
 #include <xfr/xfrout_client.h>
 
diff --git a/src/bin/auth/tests/query_unittest.cc b/src/bin/auth/tests/query_unittest.cc
index b017e70..9bf1358 100644
--- a/src/bin/auth/tests/query_unittest.cc
+++ b/src/bin/auth/tests/query_unittest.cc
@@ -30,7 +30,7 @@
 #include <dns/rrtype.h>
 #include <dns/rdataclass.h>
 
-#include <datasrc/memory_datasrc.h>
+#include <datasrc/client.h>
 #include <datasrc/client_list.h>
 
 #include <auth/query.h>
@@ -831,6 +831,68 @@ createDataSrcClientList(DataSrcType type, DataSourceClient& client) {
     }
 }
 
+class MockClient : public DataSourceClient {
+public:
+    virtual FindResult findZone(const isc::dns::Name& origin) const {
+        const Name r_origin(origin.reverse());
+        std::map<Name, ZoneFinderPtr>::const_iterator it =
+            zone_finders_.lower_bound(r_origin);
+
+        if (it != zone_finders_.end()) {
+            const NameComparisonResult result =
+                origin.compare((it->first).reverse());
+            if (result.getRelation() == NameComparisonResult::EQUAL) {
+                return (FindResult(result::SUCCESS, it->second));
+            } else if (result.getRelation() == NameComparisonResult::SUBDOMAIN) {
+                return (FindResult(result::PARTIALMATCH, it->second));
+            }
+        }
+
+        // If it is at the beginning of the map, then the name was not
+        // found (we have already handled the element the iterator
+        // points to).
+        if (it == zone_finders_.begin()) {
+            return (FindResult(result::NOTFOUND, ZoneFinderPtr()));
+        }
+
+        // Check if the previous element is a partial match.
+        --it;
+        const NameComparisonResult result =
+            origin.compare((it->first).reverse());
+        if (result.getRelation() == NameComparisonResult::SUBDOMAIN) {
+            return (FindResult(result::PARTIALMATCH, it->second));
+        }
+
+        return (FindResult(result::NOTFOUND, ZoneFinderPtr()));
+    }
+
+    virtual ZoneUpdaterPtr getUpdater(const isc::dns::Name&, bool, bool) const {
+        isc_throw(isc::NotImplemented,
+                  "Updater isn't supported in the MockClient");
+    }
+
+    virtual std::pair<ZoneJournalReader::Result, ZoneJournalReaderPtr>
+    getJournalReader(const isc::dns::Name&, uint32_t, uint32_t) const {
+        isc_throw(isc::NotImplemented,
+                  "Journaling isn't supported in the MockClient");
+    }
+
+    result::Result addZone(ZoneFinderPtr finder) {
+        // Use the reverse of the name as the key, so we can quickly
+        // find partial matches in the map.
+        zone_finders_[finder->getOrigin().reverse()] = finder;
+        return (result::SUCCESS);
+    }
+
+private:
+    // Note that because we no longer have the old RBTree, and the new
+    // in-memory DomainTree is not useful as it returns const nodes, we
+    // use a std::map instead. In this map, the key is a name stored in
+    // reverse order of labels to aid in finding partial matches
+    // quickly.
+    std::map<Name, ZoneFinderPtr> zone_finders_;
+};
+
 class QueryTest : public ::testing::TestWithParam<DataSrcType> {
 protected:
     QueryTest() :
@@ -856,7 +918,7 @@ protected:
         response.setOpcode(Opcode::QUERY());
         // create and add a matching zone.
         mock_finder = new MockZoneFinder();
-        memory_client.addZone(ZoneFinderPtr(mock_finder));
+        mock_client.addZone(ZoneFinderPtr(mock_finder));
     }
 
     virtual void SetUp() {
@@ -870,7 +932,7 @@ protected:
         // doesn't happen for derived test class.  This also ensures the
         // data source clients are configured after setting NSEC3 hash in case
         // there's dependency.
-        list_ = createDataSrcClientList(GetParam(), memory_client);
+        list_ = createDataSrcClientList(GetParam(), mock_client);
     }
 
     virtual void TearDown() {
@@ -996,11 +1058,7 @@ private:
 
 protected:
     MockZoneFinder* mock_finder;
-    // We use InMemoryClient here. We could have some kind of mock client
-    // here, but historically, the Query supported only InMemoryClient
-    // (originally named MemoryDataSrc) and was tested with it, so we keep
-    // it like this for now.
-    InMemoryClient memory_client;
+    MockClient mock_client;
 
     boost::shared_ptr<ClientList> list_;
     const Name qname;
@@ -1040,7 +1098,7 @@ class QueryTestForMockOnly : public QueryTest {
 protected:
     // Override SetUp() to avoid parameterized setup
     virtual void SetUp() {
-        list_ = createDataSrcClientList(MOCK, memory_client);
+        list_ = createDataSrcClientList(MOCK, mock_client);
     }
 };
 
@@ -1084,8 +1142,8 @@ responseCheck(Message& response, const isc::dns::Rcode& rcode,
 TEST_P(QueryTest, noZone) {
     // There's no zone in the memory datasource.  So the response should have
     // REFUSED.
-    InMemoryClient empty_memory_client;
-    SingletonList empty_list(empty_memory_client);
+    MockClient empty_mock_client;
+    SingletonList empty_list(empty_mock_client);
     EXPECT_NO_THROW(query.process(empty_list, qname, qtype,
                                   response));
     EXPECT_EQ(Rcode::REFUSED(), response.getRcode());
@@ -2258,8 +2316,8 @@ TEST_F(QueryTestForMockOnly, dsAboveDelegation) {
     // simple addition.  For now we test it for mock only.
 
     // Pretending to have authority for the child zone, too.
-    memory_client.addZone(ZoneFinderPtr(new AlternateZoneFinder(
-                                            Name("delegation.example.com"))));
+    mock_client.addZone(ZoneFinderPtr(new AlternateZoneFinder(
+                                           Name("delegation.example.com"))));
 
     // The following will succeed only if the search goes to the parent
     // zone, not the child one we added above.
@@ -2281,8 +2339,8 @@ TEST_P(QueryTest, dsAboveDelegationNoData) {
     // Similar to the previous case, but the query is for an unsigned zone
     // (which doesn't have a DS at the parent).  The response should be a
     // "no data" error.  The query should still be handled at the parent.
-    memory_client.addZone(ZoneFinderPtr(
-                              new AlternateZoneFinder(
+    mock_client.addZone(ZoneFinderPtr(
+                             new AlternateZoneFinder(
                                   Name("unsigned-delegation.example.com"))));
 
     // The following will succeed only if the search goes to the parent
@@ -2366,8 +2424,8 @@ TEST_F(QueryTestForMockOnly, dsAtGrandParentAndChild) {
 
     // Pretending to have authority for the child zone, too.
     const Name childname("grand.delegation.example.com");
-    memory_client.addZone(ZoneFinderPtr(
-                              new AlternateZoneFinder(childname)));
+    mock_client.addZone(ZoneFinderPtr(
+                             new AlternateZoneFinder(childname)));
     query.process(*list_, childname, RRType::DS(), response, true);
     // Note that RR TTL of SOA and its RRSIG are set to SOA MINTTL, 0
     responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 4, 0, NULL,
@@ -2388,8 +2446,8 @@ TEST_F(QueryTestForMockOnly, dsAtRoot) {
     // won't be simple addition.  For now we test it for mock only.
 
     // Pretend to be a root server.
-    memory_client.addZone(ZoneFinderPtr(
-                              new AlternateZoneFinder(Name::ROOT_NAME())));
+    mock_client.addZone(ZoneFinderPtr(
+                             new AlternateZoneFinder(Name::ROOT_NAME())));
     query.process(*list_, Name::ROOT_NAME(), RRType::DS(), response,
                   true);
     // Note that RR TTL of SOA and its RRSIG are set to SOA MINTTL, 0
@@ -2408,9 +2466,8 @@ TEST_F(QueryTestForMockOnly, dsAtRootWithDS) {
     // We could setup the additional zone for other data sources, but it
     // won't be simple addition.  For now we test it for mock only.
 
-    memory_client.addZone(ZoneFinderPtr(
-                              new AlternateZoneFinder(Name::ROOT_NAME(),
-                                                      true)));
+    mock_client.addZone(ZoneFinderPtr(
+                             new AlternateZoneFinder(Name::ROOT_NAME(), true)));
     query.process(*list_, Name::ROOT_NAME(), RRType::DS(), response,
                   true);
     responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 2, 0,
diff --git a/src/lib/datasrc/Makefile.am b/src/lib/datasrc/Makefile.am
index 1a5776f..be79557 100644
--- a/src/lib/datasrc/Makefile.am
+++ b/src/lib/datasrc/Makefile.am
@@ -24,10 +24,7 @@ CLEANFILES += static.zone
 
 lib_LTLIBRARIES = libb10-datasrc.la
 libb10_datasrc_la_SOURCES = data_source.h
-libb10_datasrc_la_SOURCES += rbnode_rrset.h
-libb10_datasrc_la_SOURCES += rbtree.h
 libb10_datasrc_la_SOURCES += exceptions.h
-libb10_datasrc_la_SOURCES += zonetable.h zonetable.cc
 libb10_datasrc_la_SOURCES += zone.h zone_finder.h zone_finder.cc
 libb10_datasrc_la_SOURCES += zone_finder_context.cc
 libb10_datasrc_la_SOURCES += zone_iterator.h
@@ -37,7 +34,6 @@ libb10_datasrc_la_SOURCES += client.h client.cc
 libb10_datasrc_la_SOURCES += database.h database.cc
 libb10_datasrc_la_SOURCES += factory.h factory.cc
 libb10_datasrc_la_SOURCES += client_list.h client_list.cc
-libb10_datasrc_la_SOURCES += memory_datasrc.h memory_datasrc.cc
 libb10_datasrc_la_SOURCES += master_loader_callbacks.h
 libb10_datasrc_la_SOURCES += master_loader_callbacks.cc
 libb10_datasrc_la_SOURCES += rrset_collection_base.h rrset_collection_base.cc
@@ -45,7 +41,7 @@ libb10_datasrc_la_SOURCES += zone_loader.h zone_loader.cc
 nodist_libb10_datasrc_la_SOURCES = datasrc_messages.h datasrc_messages.cc
 libb10_datasrc_la_LDFLAGS = -no-undefined -version-info 1:0:1
 
-pkglib_LTLIBRARIES =  sqlite3_ds.la memory_ds.la static_ds.la
+pkglib_LTLIBRARIES = sqlite3_ds.la static_ds.la
 
 sqlite3_ds_la_SOURCES = sqlite3_accessor.h sqlite3_accessor.cc
 sqlite3_ds_la_SOURCES += sqlite3_accessor_link.cc
@@ -55,12 +51,8 @@ sqlite3_ds_la_LIBADD = $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
 sqlite3_ds_la_LIBADD += libb10-datasrc.la
 sqlite3_ds_la_LIBADD += $(SQLITE_LIBS)
 
-memory_ds_la_SOURCES = memory_datasrc_link.cc
-memory_ds_la_LDFLAGS = -module -avoid-version
-memory_ds_la_LIBADD = $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
-memory_ds_la_LIBADD += libb10-datasrc.la
-
 static_ds_la_SOURCES = static_datasrc_link.cc
+static_ds_la_SOURCES += static_datasrc.h
 static_ds_la_LDFLAGS = -module -avoid-version
 static_ds_la_LIBADD = $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
 static_ds_la_LIBADD += libb10-datasrc.la
@@ -69,7 +61,7 @@ libb10_datasrc_la_LIBADD = $(top_builddir)/src/lib/exceptions/libb10-exceptions.
 libb10_datasrc_la_LIBADD += $(top_builddir)/src/lib/dns/libb10-dns++.la
 libb10_datasrc_la_LIBADD += $(top_builddir)/src/lib/log/libb10-log.la
 libb10_datasrc_la_LIBADD += $(top_builddir)/src/lib/cc/libb10-cc.la
-libb10_datasrc_la_LIBADD += $(builddir)/memory/libdatasrc_memory.la
+libb10_datasrc_la_LIBADD += $(top_builddir)/src/lib/datasrc/memory/libdatasrc_memory.la
 libb10_datasrc_la_LIBADD += $(SQLITE_LIBS)
 
 BUILT_SOURCES = datasrc_config.h datasrc_messages.h datasrc_messages.cc
diff --git a/src/lib/datasrc/datasrc_messages.mes b/src/lib/datasrc/datasrc_messages.mes
index 5311203..2235df8 100644
--- a/src/lib/datasrc/datasrc_messages.mes
+++ b/src/lib/datasrc/datasrc_messages.mes
@@ -350,177 +350,6 @@ There's something suspicious in the master file. This is a warning only.
 It may be a problem or it may be harmless, but it should be checked.
 This problem does not stop the zone from being loaded.
 
-% DATASRC_MEM_ADD_RRSET adding RRset '%1/%2' into zone '%3'
-Debug information. An RRset is being added to the in-memory data source.
-
-% DATASRC_MEM_ADD_WILDCARD adding wildcards for '%1'
-This is a debug message issued during the processing of a wildcard
-name. The internal domain name tree is scanned and some nodes are
-specially marked to allow the wildcard lookup to succeed.
-
-% DATASRC_MEM_ADD_ZONE adding zone '%1/%2'
-Debug information. A zone is being added into the in-memory data source.
-
-% DATASRC_MEM_ANY_SUCCESS ANY query for '%1' successful
-Debug information. The domain was found and an ANY type query is being answered
-by providing everything found inside the domain.
-
-% DATASRC_MEM_CNAME CNAME at the domain '%1'
-Debug information. The requested domain is an alias to a different domain,
-returning the CNAME instead.
-
-% DATASRC_MEM_CNAME_COEXIST can't add data to CNAME in domain '%1'
-This is the same problem as in MEM_CNAME_TO_NONEMPTY, but it happened the
-other way around -- adding some other data to CNAME.
-
-% DATASRC_MEM_CNAME_TO_NONEMPTY can't add CNAME to domain with other data in '%1'
-Someone or something tried to add a CNAME into a domain that already contains
-some other data. But the protocol forbids coexistence of CNAME with anything
-(RFC 1034, section 3.6.2). This indicates a problem with provided data.
-
-% DATASRC_MEM_CREATE creating zone '%1' in '%2' class
-Debug information. A representation of a zone for the in-memory data source is
-being created.
-
-% DATASRC_MEM_DELEG_FOUND delegation found at '%1'
-Debug information. A delegation point was found above the requested record.
-
-% DATASRC_MEM_DESTROY destroying zone '%1' in '%2' class
-Debug information. A zone from in-memory data source is being destroyed.
-
-% DATASRC_MEM_DNAME_ENCOUNTERED encountered a DNAME
-Debug information. While searching for the requested domain, a DNAME was
-encountered on the way.  This may lead to redirection to a different domain and
-stop the search.
-
-% DATASRC_MEM_DNAME_FOUND DNAME found at '%1'
-Debug information. A DNAME was found instead of the requested information.
-
-% DATASRC_MEM_DNAME_NS DNAME and NS can't coexist in non-apex domain '%1'
-A request was made for DNAME and NS records to be put into the same
-domain which is not the apex (the top of the zone). This is forbidden
-by RFC 2672 (section 3) and indicates a problem with provided data.
-
-% DATASRC_MEM_DOMAIN_EMPTY requested domain '%1' is empty
-Debug information. The requested domain exists in the tree of domains, but
-it is empty. Therefore it doesn't contain the requested resource type.
-
-% DATASRC_MEM_DUP_RRSET duplicate RRset '%1/%2'
-An RRset is being inserted into in-memory data source for a second time.  The
-original version must be removed first. Note that loading master files where an
-RRset is split into multiple locations is not supported yet.
-
-% DATASRC_MEM_EXACT_DELEGATION delegation at the exact domain '%1'
-Debug information. There's a NS record at the requested domain. This means
-this zone is not authoritative for the requested domain, but a delegation
-should be followed. The requested domain is an apex of some zone.
-
-% DATASRC_MEM_FIND find '%1/%2'
-Debug information. A search for the requested RRset is being started.
-
-% DATASRC_MEM_FINDNSEC3 finding NSEC3 for %1, mode %2
-Debug information. A search in an in-memory data source for NSEC3 that
-matches or covers the given name is being started.
-
-% DATASRC_MEM_FINDNSEC3_COVER found a covering NSEC3 for %1: %2
-Debug information. An NSEC3 that covers the given name is found and
-being returned.  The found NSEC3 RRset is also displayed.
-
-% DATASRC_MEM_FINDNSEC3_MATCH found a matching NSEC3 for %1 at label count %2: %3
-Debug information. An NSEC3 that matches (a possibly superdomain of)
-the given name is found and being returned.  When the shown label
-count is smaller than that of the given name, the matching NSEC3 is
-for a superdomain of the given name (see DATASRC_MEM_FINDNSEC3_TRYHASH).
-The found NSEC3 RRset is also displayed.
-
-% DATASRC_MEM_FINDNSEC3_TRYHASH looking for NSEC3 for %1 at label count %2 (hash %3)
-Debug information. In an attempt of finding an NSEC3 for the give name,
-(a possibly superdomain of) the name is hashed and searched for in the
-NSEC3 name space.  When the shown label count is smaller than that of the
-shown name, the search tries the superdomain name that share the shown
-(higher) label count of the shown name (e.g., for
-www.example.com. with shown label count of 3, example.com. is being
-tried).
-
-% DATASRC_MEM_FIND_TYPE_AT_ORIGIN origin query for type %1 in in-memory zone %2/%3 successful
-Debug information.  A specific type RRset is requested at a zone origin
-of an in-memory zone and it is found.
-
-% DATASRC_MEM_FIND_ZONE looking for zone '%1'
-Debug information. A zone object for this zone is being searched for in the
-in-memory data source.
-
-% DATASRC_MEM_LOAD loading zone '%1' from file '%2'
-Debug information. The content of master file is being loaded into the memory.
-
-% DATASRC_MEM_NOT_FOUND requested domain '%1' not found
-Debug information. The requested domain does not exist.
-
-% DATASRC_MEM_NO_NSEC3PARAM NSEC3PARAM is missing for NSEC3-signed zone %1/%2
-The in-memory data source has loaded a zone signed with NSEC3 RRs,
-but it doesn't have a NSEC3PARAM RR at the zone origin.  It's likely that
-the zone is somehow broken, but this RR is not necessarily needed for
-handling lookups with NSEC3 in this data source, so it accepts the given
-content of the zone.  Nevertheless the administrator should look into
-the integrity of the zone data.
-
-% DATASRC_MEM_NS_ENCOUNTERED encountered a NS
-Debug information. While searching for the requested domain, a NS was
-encountered on the way (a delegation). This may lead to stop of the search.
-
-% DATASRC_MEM_NXRRSET no such type '%1' at '%2'
-Debug information. The domain exists, but it doesn't hold any record of the
-requested type.
-
-% DATASRC_MEM_OUT_OF_ZONE domain '%1' doesn't belong to zone '%2'
-It was attempted to add the domain into a zone that shouldn't have it
-(eg. the domain is not subdomain of the zone origin). This indicates a
-problem with provided data.
-
-% DATASRC_MEM_RENAME renaming RRset from '%1' to '%2'
-Debug information. A RRset is being generated from a different RRset (most
-probably a wildcard). So it must be renamed to whatever the user asked for. In
-fact, it's impossible to rename RRsets with our libraries, so a new one is
-created and all resource records are copied over.
-
-% DATASRC_MEM_SINGLETON trying to add multiple RRs for domain '%1' and type '%2'
-Some resource types are singletons -- only one is allowed in a domain
-(for example CNAME or SOA). This indicates a problem with provided data.
-
-% DATASRC_MEM_SUCCESS query for '%1/%2' successful
-Debug information. The requested record was found.
-
-% DATASRC_MEM_SUPER_STOP stopped as '%1' is superdomain of a zone node, meaning it's empty
-Debug information. The search stopped because the requested domain was
-detected to be a superdomain of some existing node of zone (while there
-was no exact match).  This means that the domain is an empty nonterminal,
-therefore it is treated  as NXRRSET case (eg. the domain exists, but it
-doesn't have the requested record type).
-
-% DATASRC_MEM_SWAP swapping contents of two zone representations ('%1' and '%2')
-Debug information. The contents of two in-memory zones are being exchanged.
-This is usual practice to do some manipulation in exception-safe manner -- the
-new data are prepared in a different zone object and when it works, they are
-swapped. The old one contains the new data and the other one can be safely
-destroyed.
-
-% DATASRC_MEM_WILDCARD_CANCEL wildcard match canceled for '%1'
-Debug information. A domain above wildcard was reached, but there's something
-below the requested domain. Therefore the wildcard doesn't apply here.  This
-behaviour is specified by RFC 1034, section 4.3.3.
-
-% DATASRC_MEM_WILDCARD_DNAME DNAME record in wildcard domain '%1'
-The software refuses to load DNAME records into a wildcard domain.  It isn't
-explicitly forbidden, but the protocol is ambiguous about how this should
-behave and BIND 9 refuses that as well. Please describe your intention using
-different tools.
-
-% DATASRC_MEM_WILDCARD_NS NS record in wildcard domain '%1'
-The software refuses to load NS records into a wildcard domain.  It isn't
-explicitly forbidden, but the protocol is ambiguous about how this should
-behave and BIND 9 refuses that as well. Please describe your intention using
-different tools.
-
 % DATASRC_META_ADD adding a data source into meta data source
 This is a debug message issued during startup or reconfiguration.
 Another data source is being added into the meta data source.
diff --git a/src/lib/datasrc/factory.cc b/src/lib/datasrc/factory.cc
index 82b4df9..33338db 100644
--- a/src/lib/datasrc/factory.cc
+++ b/src/lib/datasrc/factory.cc
@@ -17,7 +17,6 @@
 #include "data_source.h"
 #include "database.h"
 #include "sqlite3_accessor.h"
-#include "memory_datasrc.h"
 
 #include "datasrc_config.h"
 
diff --git a/src/lib/datasrc/memory/memory_messages.mes b/src/lib/datasrc/memory/memory_messages.mes
index 991bb19..f8d5328 100644
--- a/src/lib/datasrc/memory/memory_messages.mes
+++ b/src/lib/datasrc/memory/memory_messages.mes
@@ -23,19 +23,6 @@ It isn't explicitly forbidden, but no sane zone wouldn have such names
 for NSEC3.  BIND 9 also refuses NSEC3 at wildcard, so this behavior is
 compatible with BIND 9.
 
-% DATASRC_MEMORY_CHECK_ERROR post-load check of zone %1/%2 failed: %3
-The zone was loaded into the data source successfully, but the content fails
-basic sanity checks. See the message if you want to know what exactly is wrong
-with the data. The data can not be used and previous version, if any, will be
-preserved.
-
-% DATASRC_MEMORY_CHECK_WARNING %1/%2: %3
-The zone was loaded into the data source successfully, but there's some problem
-with the content. The problem does not stop the new version from being used
-(though there may be other problems that do, see DATASRC_MEMORY_CHECK_ERROR),
-but it should still be checked and fixed. See the message to know what exactly
-is wrong with the data.
-
 % DATASRC_MEMORY_MEM_ADD_RRSET adding RRset '%1/%2' into zone '%3'
 Debug information. An RRset is being added to the in-memory data source.
 
@@ -101,3 +88,94 @@ The software refuses to load NS records into a wildcard domain.  It isn't
 explicitly forbidden, but the protocol is ambiguous about how this should
 behave and BIND 9 refuses that as well. Please describe your intention using
 different tools.
+
+% DATASRC_MEMORY_CHECK_ERROR post-load check of zone %1/%2 failed: %3
+The zone was loaded into the data source successfully, but the content fails
+basic sanity checks. See the message if you want to know what exactly is wrong
+with the data. The data can not be used and previous version, if any, will be
+preserved.
+
+% DATASRC_MEMORY_CHECK_WARNING %1/%2: %3
+The zone was loaded into the data source successfully, but there's some problem
+with the content. The problem does not stop the new version from being used
+(though there may be other problems that do, see DATASRC_MEMORY_CHECK_ERROR),
+but it should still be checked and fixed. See the message to know what exactly
+is wrong with the data.
+
+% DATASRC_MEMORY_DNAME_ENCOUNTERED encountered a DNAME
+Debug information. While searching for the requested domain, a DNAME was
+encountered on the way.  This may lead to redirection to a different domain and
+stop the search.
+
+% DATASRC_MEMORY_NS_ENCOUNTERED encountered a NS
+Debug information. While searching for the requested domain, a NS was
+encountered on the way (a delegation). This may lead to stop of the search.
+
+% DATASRC_MEMORY_DNAME_FOUND DNAME found at '%1'
+Debug information. A DNAME was found instead of the requested information.
+
+% DATASRC_MEMORY_DELEG_FOUND delegation found at '%1'
+Debug information. A delegation point was found above the requested record.
+
+% DATASRC_MEMORY_SUPER_STOP stopped as '%1' is superdomain of a zone node, meaning it's empty
+Debug information. The search stopped because the requested domain was
+detected to be a superdomain of some existing node of zone (while there
+was no exact match).  This means that the domain is an empty nonterminal,
+therefore it is treated  as NXRRSET case (eg. the domain exists, but it
+doesn't have the requested record type).
+
+% DATASRC_MEMORY_WILDCARD_CANCEL wildcard match canceled for '%1'
+Debug information. A domain above wildcard was reached, but there's something
+below the requested domain. Therefore the wildcard doesn't apply here.  This
+behaviour is specified by RFC 1034, section 4.3.3.
+
+% DATASRC_MEMORY_NOT_FOUND requested domain '%1' not found
+Debug information. The requested domain does not exist.
+
+% DATASRC_MEMORY_FIND_TYPE_AT_ORIGIN origin query for type %1 in in-memory zone %2/%3 successful
+Debug information.  A specific type RRset is requested at a zone origin
+of an in-memory zone and it is found.
+
+% DATASRC_MEMORY_DOMAIN_EMPTY requested domain '%1' is empty
+Debug information. The requested domain exists in the tree of domains, but
+it is empty. Therefore it doesn't contain the requested resource type.
+
+% DATASRC_MEMORY_EXACT_DELEGATION delegation at the exact domain '%1'
+Debug information. There's a NS record at the requested domain. This means
+this zone is not authoritative for the requested domain, but a delegation
+should be followed. The requested domain is an apex of some zone.
+
+% DATASRC_MEMORY_ANY_SUCCESS ANY query for '%1' successful
+Debug information. The domain was found and an ANY type query is being answered
+by providing everything found inside the domain.
+
+% DATASRC_MEMORY_SUCCESS query for '%1/%2' successful
+Debug information. The requested record was found.
+
+% DATASRC_MEMORY_CNAME CNAME at the domain '%1'
+Debug information. The requested domain is an alias to a different domain,
+returning the CNAME instead.
+
+% DATASRC_MEMORY_FINDNSEC3 finding NSEC3 for %1, mode %2
+Debug information. A search in an in-memory data source for NSEC3 that
+matches or covers the given name is being started.
+
+% DATASRC_MEMORY_FINDNSEC3_COVER found a covering NSEC3 for %1: %2
+Debug information. An NSEC3 that covers the given name is found and
+being returned.  The found NSEC3 RRset is also displayed.
+
+% DATASRC_MEMORY_FINDNSEC3_MATCH found a matching NSEC3 for %1 at label count %2: %3
+Debug information. An NSEC3 that matches (a possibly superdomain of)
+the given name is found and being returned.  When the shown label
+count is smaller than that of the given name, the matching NSEC3 is
+for a superdomain of the given name (see DATASRC_MEMORY_FINDNSEC3_TRYHASH).
+The found NSEC3 RRset is also displayed.
+
+% DATASRC_MEMORY_FINDNSEC3_TRYHASH looking for NSEC3 for %1 at label count %2 (hash %3)
+Debug information. In an attempt of finding an NSEC3 for the give name,
+(a possibly superdomain of) the name is hashed and searched for in the
+NSEC3 name space.  When the shown label count is smaller than that of the
+shown name, the search tries the superdomain name that share the shown
+(higher) label count of the shown name (e.g., for
+www.example.com. with shown label count of 3, example.com. is being
+tried).
diff --git a/src/lib/datasrc/memory/zone_finder.cc b/src/lib/datasrc/memory/zone_finder.cc
index e70cbe3..5acc5be 100644
--- a/src/lib/datasrc/memory/zone_finder.cc
+++ b/src/lib/datasrc/memory/zone_finder.cc
@@ -26,7 +26,7 @@
 #include <dns/rrttl.h>
 #include <dns/nsec3hash.h>
 
-#include <datasrc/logger.h>
+#include <datasrc/memory/logger.h>
 
 #include <util/buffer.h>
 
@@ -168,7 +168,7 @@ bool cutCallback(const ZoneNode& node, FindState* state) {
                                                  RRType::DNAME());
 
     if (found_dname != NULL) {
-        LOG_DEBUG(logger, DBG_TRACE_DETAILED, DATASRC_MEM_DNAME_ENCOUNTERED);
+        LOG_DEBUG(logger, DBG_TRACE_DETAILED, DATASRC_MEMORY_DNAME_ENCOUNTERED);
         state->dname_node_ = &node;
         state->rdataset_ = found_dname;
         return (true);
@@ -183,7 +183,7 @@ bool cutCallback(const ZoneNode& node, FindState* state) {
             return (false);
         }
 
-        LOG_DEBUG(logger, DBG_TRACE_DETAILED, DATASRC_MEM_NS_ENCOUNTERED);
+        LOG_DEBUG(logger, DBG_TRACE_DETAILED, DATASRC_MEMORY_NS_ENCOUNTERED);
 
         // BIND 9 checks if this node is not the origin.  That's probably
         // because it can support multiple versions for dynamic updates
@@ -483,13 +483,13 @@ FindNodeResult findNode(const ZoneData& zone_data,
     } else if (result == ZoneTree::PARTIALMATCH) {
         assert(node != NULL);
         if (state.dname_node_ != NULL) { // DNAME
-            LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEM_DNAME_FOUND).
+            LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEMORY_DNAME_FOUND).
                 arg(state.dname_node_->getName());
             return (FindNodeResult(ZoneFinder::DNAME, state.dname_node_,
                                    state.rdataset_));
         }
         if (state.zonecut_node_ != NULL) { // DELEGATION due to NS
-            LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEM_DELEG_FOUND).
+            LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEMORY_DELEG_FOUND).
                 arg(state.zonecut_node_->getName());
             return (FindNodeResult(ZoneFinder::DELEGATION,
                                    state.zonecut_node_,
@@ -498,7 +498,7 @@ FindNodeResult findNode(const ZoneData& zone_data,
         if (node_path.getLastComparisonResult().getRelation() ==
             NameComparisonResult::SUPERDOMAIN) { // empty node, so NXRRSET
             LOG_DEBUG(logger, DBG_TRACE_DATA,
-                      DATASRC_MEM_SUPER_STOP).arg(name_labels);
+                      DATASRC_MEMORY_SUPER_STOP).arg(name_labels);
             ConstNodeRRset nsec_rrset = getClosestNSEC(zone_data, node_path,
                                                        options);
             return (FindNodeResult(ZoneFinder::NXRRSET, nsec_rrset.first,
@@ -516,7 +516,7 @@ FindNodeResult findNode(const ZoneData& zone_data,
                 // baz.foo.wild.example. The common ancestor, foo.wild.example,
                 // should cancel wildcard.  Treat it as NXDOMAIN.
                 LOG_DEBUG(logger, DBG_TRACE_DATA,
-                          DATASRC_MEM_WILDCARD_CANCEL).arg(name_labels);
+                          DATASRC_MEMORY_WILDCARD_CANCEL).arg(name_labels);
                 ConstNodeRRset nsec_rrset = getClosestNSEC(zone_data,
                                                            node_path,
                                                            options);
@@ -546,7 +546,7 @@ FindNodeResult findNode(const ZoneData& zone_data,
                         FindNodeResult::FIND_WILDCARD | zonecut_flag));
         }
 
-        LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEM_NOT_FOUND).
+        LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEMORY_NOT_FOUND).
             arg(name_labels);
         ConstNodeRRset nsec_rrset = getClosestNSEC(zone_data, node_path,
                                                    options);
@@ -785,7 +785,7 @@ InMemoryZoneFinder::findAtOrigin(const isc::dns::RRType& type,
     const RdataSet* const found = RdataSet::find(node->getData(), type);
 
     if (found != NULL) {
-        LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEM_FIND_TYPE_AT_ORIGIN).
+        LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEMORY_FIND_TYPE_AT_ORIGIN).
             arg(type).arg(getOrigin()).arg(rrclass_);
         return (ZoneFinderContextPtr(
                     new Context(*this, options, rrclass_,
@@ -831,7 +831,7 @@ InMemoryZoneFinder::findInternal(const isc::dns::Name& name,
     // If there is an exact match but the node is empty, it's equivalent
     // to NXRRSET.
     if (node->isEmpty()) {
-        LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEM_DOMAIN_EMPTY).
+        LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEMORY_DOMAIN_EMPTY).
             arg(name);
         ConstNodeRRset nsec_rrset = getClosestNSEC(zone_data_, node_path,
                                                    options);
@@ -854,7 +854,7 @@ InMemoryZoneFinder::findInternal(const isc::dns::Name& name,
         found = RdataSet::find(node->getData(), RRType::NS());
         if (found != NULL) {
             LOG_DEBUG(logger, DBG_TRACE_DATA,
-                      DATASRC_MEM_EXACT_DELEGATION).arg(name);
+                      DATASRC_MEMORY_EXACT_DELEGATION).arg(name);
             return (createFindResult(rrclass_, zone_data_, DELEGATION,
                                      node, found, options, wild, &name));
         }
@@ -870,7 +870,7 @@ InMemoryZoneFinder::findInternal(const isc::dns::Name& name,
                                                   wild ? &name : NULL));
             cur_rds = cur_rds->getNext();
         }
-        LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEM_ANY_SUCCESS).
+        LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEMORY_ANY_SUCCESS).
             arg(name);
         return (createFindResult(rrclass_, zone_data_, SUCCESS, node, NULL,
                                  options, wild, &name));
@@ -879,7 +879,7 @@ InMemoryZoneFinder::findInternal(const isc::dns::Name& name,
     found = RdataSet::find(node->getData(), type);
     if (found != NULL) {
         // Good, it is here
-        LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEM_SUCCESS).arg(name).
+        LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEMORY_SUCCESS).arg(name).
             arg(type);
         return (createFindResult(rrclass_, zone_data_, SUCCESS, node, found,
                                  options, wild, &name));
@@ -888,7 +888,7 @@ InMemoryZoneFinder::findInternal(const isc::dns::Name& name,
         found = RdataSet::find(node->getData(), RRType::CNAME());
         if (found != NULL) {
 
-            LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEM_CNAME).arg(name);
+            LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEMORY_CNAME).arg(name);
             return (createFindResult(rrclass_, zone_data_, CNAME, node, found,
                                      options, wild, &name));
         }
@@ -905,7 +905,7 @@ InMemoryZoneFinder::findInternal(const isc::dns::Name& name,
 
 isc::datasrc::ZoneFinder::FindNSEC3Result
 InMemoryZoneFinder::findNSEC3(const isc::dns::Name& name, bool recursive) {
-    LOG_DEBUG(logger, DBG_TRACE_BASIC, DATASRC_MEM_FINDNSEC3).arg(name).
+    LOG_DEBUG(logger, DBG_TRACE_BASIC, DATASRC_MEMORY_FINDNSEC3).arg(name).
         arg(recursive ? "recursive" : "non-recursive");
 
     uint8_t labels_buf[LabelSequence::MAX_SERIALIZED_LENGTH];
@@ -972,7 +972,7 @@ InMemoryZoneFinder::findNSEC3(const isc::dns::Name& name, bool recursive) {
                              name : name.split(qlabels - labels, labels));
         const std::string hlabel = hash->calculate(hname);
 
-        LOG_DEBUG(logger, DBG_TRACE_BASIC, DATASRC_MEM_FINDNSEC3_TRYHASH).
+        LOG_DEBUG(logger, DBG_TRACE_BASIC, DATASRC_MEMORY_FINDNSEC3_TRYHASH).
             arg(name).arg(labels).arg(hlabel);
 
         node = NULL;
@@ -995,7 +995,7 @@ InMemoryZoneFinder::findNSEC3(const isc::dns::Name& name, bool recursive) {
             }
 
             LOG_DEBUG(logger, DBG_TRACE_BASIC,
-                      DATASRC_MEM_FINDNSEC3_MATCH).arg(name).arg(labels).
+                      DATASRC_MEMORY_FINDNSEC3_MATCH).arg(name).arg(labels).
                 arg(*closest);
 
             return (FindNSEC3Result(true, labels, closest, next));
@@ -1014,7 +1014,7 @@ InMemoryZoneFinder::findNSEC3(const isc::dns::Name& name, bool recursive) {
                     closest = createNSEC3RRset(covering_node, getClass());
 
                     LOG_DEBUG(logger, DBG_TRACE_BASIC,
-                              DATASRC_MEM_FINDNSEC3_COVER).
+                              DATASRC_MEMORY_FINDNSEC3_COVER).
                         arg(name).arg(*closest);
                 }
 
diff --git a/src/lib/datasrc/memory_datasrc.cc b/src/lib/datasrc/memory_datasrc.cc
deleted file mode 100644
index 3081759..0000000
--- a/src/lib/datasrc/memory_datasrc.cc
+++ /dev/null
@@ -1,2045 +0,0 @@
-// Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#include <exceptions/exceptions.h>
-
-#include <util/memory_segment_local.h>
-
-#include <dns/name.h>
-#include <dns/nsec3hash.h>
-#include <dns/rdataclass.h>
-#include <dns/rrclass.h>
-#include <dns/masterload.h>
-
-#include <datasrc/memory_datasrc.h>
-#include <datasrc/rbtree.h>
-#include <datasrc/rbnode_rrset.h>
-#include <datasrc/logger.h>
-#include <datasrc/zone_iterator.h>
-#include <datasrc/data_source.h>
-#include <datasrc/factory.h>
-#include <datasrc/zone_finder.h>
-
-#include <boost/function.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/scoped_ptr.hpp>
-#include <boost/bind.hpp>
-#include <boost/foreach.hpp>
-
-#include <algorithm>
-#include <map>
-#include <utility>
-#include <cctype>
-#include <cassert>
-
-using namespace std;
-using namespace isc::dns;
-using namespace isc::dns::rdata;
-using boost::scoped_ptr;
-
-namespace isc {
-namespace datasrc {
-
-using namespace internal;
-
-namespace {
-// Some type aliases
-
-// A functor type used for loading.
-typedef boost::function<void(ConstRRsetPtr)> LoadCallback;
-
-// RRset specified for this implementation
-typedef boost::shared_ptr<internal::RBNodeRRset> RBNodeRRsetPtr;
-typedef boost::shared_ptr<const internal::RBNodeRRset> ConstRBNodeRRsetPtr;
-
-/*
- * Each domain consists of some RRsets. They will be looked up by the
- * RRType.
- *
- * The use of map is questionable with regard to performance - there'll
- * be usually only few RRsets in the domain, so the log n benefit isn't
- * much and a vector/array might be faster due to its simplicity and
- * continuous memory location. But this is unlikely to be a performance
- * critical place and map has better interface for the lookups, so we use
- * that.
- */
-typedef map<RRType, ConstRBNodeRRsetPtr> Domain;
-typedef Domain::value_type DomainPair;
-typedef boost::shared_ptr<Domain> DomainPtr;
-// The tree stores domains
-typedef RBTree<Domain> DomainTree;
-typedef RBNode<Domain> DomainNode;
-
-// In the following dedicated namespace we define a few application-specific
-// RBNode flags.  We use a separate namespace so we can consolidate the
-// definition in a single place, which would hopefully reduce the risk of
-// collisions.
-// (Note: it's within an unnamed namespace, so effectively private.)
-namespace domain_flag {
-// This flag indicates the node is at a "wildcard level" (in short, it means
-// one of the node's immediate child is a wildcard).  See addWildcards()
-// for more details.
-const DomainNode::Flags WILD = DomainNode::FLAG_USER1;
-
-// This flag is used for additional record shortcut.  If a node has this
-// flag, it's under a zone cut for a delegation to a child zone.
-// Note: for a statically built zone this information is stable, but if we
-// change the implementation to be dynamically modifiable, it may not be
-// realistic to keep this flag update for all affected nodes, and we may
-// have to reconsider the mechanism.
-const DomainNode::Flags GLUE = DomainNode::FLAG_USER2;
-
-// This flag indicates the node is generated as a result of wildcard
-// expansion.  In this implementation, this flag can be set only in
-// the separate auxiliary tree of ZoneData (see the structure description).
-const DomainNode::Flags WILD_EXPANDED = DomainNode::FLAG_USER3;
-};
-
-// Separate storage for NSEC3 RRs (and their RRSIGs).  It's an STL map
-// from string to the NSEC3 RRset.  The map key is the first label
-// (upper cased) of the owner name of the corresponding NSEC3 (i.e., map
-// value).  We can use  the standard string comparison (if the comparison
-// target is also upper cased) due to the nature of NSEC3 owner names.
-//
-// Note: We maintain the RRsets in the form of RBNodeRRset even if they are
-// not stored in the RB tree.  The reason is because comparison can be
-// more efficient if we make sure all RRsets returned from this module are
-// of the same type.
-typedef map<string, ConstRBNodeRRsetPtr> NSEC3Map;
-typedef NSEC3Map::value_type NSEC3Pair;
-
-// Actual zone data: Essentially a set of zone's RRs.  This is defined as
-// a separate structure so that it'll be replaceable on reload.
-struct ZoneData {
-    // Note: this code is not entirely exception safe; domains_storage_ could
-    // leak if the constructor throws.  But since it's an intermediate version
-    // toward a full revision and the actual risk of leak should be very small
-    // in practice, we leave it open for now.
-    ZoneData(const Name& origin) :
-        domains_storage_(DomainTree::create(local_mem_sgmt_, true)),
-        domains_(*domains_storage_),
-        aux_wild_domains_(NULL),
-        origin_data_(NULL),
-        nsec_signed_(false)
-    {
-        // We create the node for origin (it needs to exist anyway in future)
-        domains_.insert(local_mem_sgmt_, origin, &origin_data_);
-        DomainPtr origin_domain(new Domain);
-        origin_data_->setData(origin_domain);
-    }
-
-    ~ZoneData() {
-        DomainTree::destroy(local_mem_sgmt_, domains_storage_);
-        if (aux_wild_domains_ != NULL) {
-            DomainTree::destroy(local_mem_sgmt_, aux_wild_domains_);
-        }
-
-        // The assert may be too harsh, but we assume we'll discard (rewrite)
-        // this code soon enough.  Until then this would be a good way to
-        // detect any memory leak.  Also, at that point we shouldn't use
-        // a single separate memory segment for each zone tree; normally
-        // zone data for multiple zones will be managed in a single segment.
-        assert(local_mem_sgmt_.allMemoryDeallocated());
-    }
-
-    // Memory segment to allocate/deallocate memory for the tree and the nodes.
-    // (This will eventually have to be abstract; for now we hardcode the
-    // specific derived segment class).
-    util::MemorySegmentLocal local_mem_sgmt_;
-
-    // The main data (name + RRsets).  We use domains_ as a reference to
-    // domains_storage_ so we don't have to update the rest of the code;
-    // it will eventually have to be revised substantially, at which point
-    // we should clean this up, too.
-    DomainTree* domains_storage_;
-    DomainTree& domains_;
-
-    // An auxiliary tree for wildcard expanded data used in additional data
-    // processing.  It contains names like "ns.wild.example" in the following
-    // example:
-    // child.wild.example. NS ns.wild.example.
-    // *.wild.example IN AAAA 2001:db8::1234
-    // (and there's no exact ns.wild.example. in the zone).  This tree contains
-    // such names with a copy of the RRsets of the matching wildcard name
-    // with its owner name expanded, e.g.:
-    // ns.wild.example. IN AAAA 2001:db8::1234
-    // In theory, this tree could have many such wildcard-expandable names,
-    // each of which has a copy of the original list of RRsets.  In practice,
-    // however, it should be very rare that names for additional section
-    // processing are subject to wildcard expansion, so in most cases this tree
-    // should be even empty, and even if it has content it should be very
-    // small.
-private:
-    DomainTree* aux_wild_domains_;
-public:
-    DomainTree& getAuxWildDomains() {
-        if (aux_wild_domains_ == NULL) {
-            aux_wild_domains_ = DomainTree::create(local_mem_sgmt_);
-        }
-        return (*aux_wild_domains_);
-    }
-
-    // Shortcut to the origin node, which should always exist
-    DomainNode* origin_data_;
-
-    // The optional NSEC3 related data
-    struct NSEC3Data {
-        NSEC3Data(const generic::NSEC3PARAM& nsec3param) :
-            hash_(NSEC3Hash::create(nsec3param))
-        {}
-        NSEC3Data(const generic::NSEC3& nsec3) :
-            hash_(NSEC3Hash::create(nsec3))
-        {}
-        NSEC3Map map_;    // Actual NSEC3 RRs
-        const scoped_ptr<NSEC3Hash> hash_; // hash parameter/calculator
-    };
-    scoped_ptr<NSEC3Data> nsec3_data_; // non NULL only when it's NSEC3 signed
-    bool nsec_signed_; // True if there's at least one NSEC record
-
-    // This templated structure encapsulates the find result of findNode()
-    // method (also templated) below.
-    // The template parameter is expected to be either 'const DomainNode' or
-    // 'DomainNode' (to avoid misuse the template definition itself is kept
-    // private - we only expose expected typedefs).  The former is expected
-    // to be used for lookups, and the latter is expected to be used for
-    // constructing the zone.
-private:
-    template <typename NodeType>
-    struct FindNodeResultBase {
-        // Bitwise flags to represent supplemental information of the
-        // search result:
-        // Search resulted in a wildcard match.
-        static const unsigned int FIND_WILDCARD = 1;
-        // Search encountered a zone cut due to NS but continued to look for
-        // a glue.
-        static const unsigned int FIND_ZONECUT = 2;
-
-        FindNodeResultBase(ZoneFinder::Result code_param,
-                           NodeType* node_param,
-                           ConstRBNodeRRsetPtr rrset_param,
-                           unsigned int flags_param = 0) :
-            code(code_param), node(node_param), rrset(rrset_param),
-            flags(flags_param)
-        {}
-        const ZoneFinder::Result code;
-        NodeType* const node;
-        ConstRBNodeRRsetPtr const rrset;
-        const unsigned int flags;
-    };
-public:
-    typedef FindNodeResultBase<const DomainNode> FindNodeResult;
-    typedef FindNodeResultBase<DomainNode> FindMutableNodeResult;
-
-    // Identify the RBTree node that best matches the given name.
-    // See implementation notes below.
-    //
-    // The caller should pass an empty node_path, and it will contain the
-    // search context (all ancestor nodes that the underlying RBTree search
-    // traverses, and how the search stops) for possible later use at the
-    // caller side.
-    template <typename ResultType>
-    ResultType findNode(const Name& name,
-                        RBTreeNodeChain<Domain>& node_path,
-                        ZoneFinder::FindOptions options) const;
-
-    // A helper method for NSEC-signed zones.  It searches the zone for
-    // the "closest" NSEC corresponding to the search context stored in
-    // node_path (it should contain sufficient information to identify the
-    // previous name of the query name in the zone).  In some cases the
-    // immediate closest name may not have NSEC (when it's under a zone cut
-    // for glue records, or even when the zone is partly broken), so this
-    // method continues the search until it finds a name that has NSEC,
-    // and returns the one found first.  Due to the prerequisite (see below),
-    // it should always succeed.
-    //
-    // node_path must store valid search context (in practice, it's expected
-    // to be set by findNode()); otherwise the underlying RBTree implementation
-    // throws.
-    //
-    // If the zone is not considered NSEC-signed or DNSSEC records were not
-    // required in the original search context (specified in options), this
-    // method doesn't bother to find NSEC, and simply returns NULL.  So, by
-    // definition of "NSEC-signed", when it really tries to find an NSEC it
-    // should succeed; there should be one at least at the zone origin.
-    ConstRBNodeRRsetPtr
-    getClosestNSEC(RBTreeNodeChain<Domain>& node_path,
-                   ZoneFinder::FindOptions options) const;
-};
-
-ConstRBNodeRRsetPtr
-ZoneData::getClosestNSEC(RBTreeNodeChain<Domain>& node_path,
-                         ZoneFinder::FindOptions options) const
-{
-    if (!nsec_signed_ || (options & ZoneFinder::FIND_DNSSEC) == 0) {
-        return (ConstRBNodeRRsetPtr());
-    }
-
-    const DomainNode* prev_node;
-    while ((prev_node = domains_.previousNode(node_path)) != NULL) {
-        if (!prev_node->isEmpty()) {
-            const Domain::const_iterator found =
-                prev_node->getData()->find(RRType::NSEC());
-            if (found != prev_node->getData()->end()) {
-                return (found->second);
-            }
-        }
-    }
-    // This must be impossible and should be an internal bug.
-    // See the description at the method declaration.
-    assert(false);
-    // Even though there is an assert here, strict compilers
-    // will still need some return value.
-    return (ConstRBNodeRRsetPtr());
-}
-
-/// Maintain intermediate data specific to the search context used in
-/// \c find().
-///
-/// It will be passed to \c cutCallback() (see below) and record a possible
-/// zone cut node and related RRset (normally NS or DNAME).
-struct FindState {
-    FindState(bool glue_ok) :
-        zonecut_node_(NULL),
-        dname_node_(NULL),
-        glue_ok_(glue_ok)
-    {}
-
-    // These will be set to a domain node of the highest delegation point,
-    // if any.  In fact, we could use a single variable instead of both.
-    // But then we would need to distinquish these two cases by something
-    // else and it seemed little more confusing when this was written.
-    const DomainNode* zonecut_node_;
-    const DomainNode* dname_node_;
-
-    // Delegation RRset (NS or DNAME), if found.
-    ConstRBNodeRRsetPtr rrset_;
-
-    // Whether to continue search below a delegation point.
-    // Set at construction time.
-    const bool glue_ok_;
-};
-
-// A callback called from possible zone cut nodes and nodes with DNAME.
-// This will be passed from findNode() to \c RBTree::find().
-bool cutCallback(const DomainNode& node, FindState* state) {
-    // We need to look for DNAME first, there's allowed case where
-    // DNAME and NS coexist in the apex. DNAME is the one to notice,
-    // the NS is authoritative, not delegation (corner case explicitly
-    // allowed by section 3 of 2672)
-    const Domain::const_iterator found_dname(node.getData()->find(
-                                                 RRType::DNAME()));
-    if (found_dname != node.getData()->end()) {
-        LOG_DEBUG(logger, DBG_TRACE_DETAILED, DATASRC_MEM_DNAME_ENCOUNTERED);
-        state->dname_node_ = &node;
-        state->rrset_ = found_dname->second;
-        // No more processing below the DNAME (RFC 2672, section 3
-        // forbids anything to exist below it, so there's no need
-        // to actually search for it). This is strictly speaking
-        // a different way than described in 4.1 of that RFC,
-        // but because of the assumption in section 3, it has the
-        // same behaviour.
-        return (true);
-    }
-
-    // Look for NS
-    const Domain::const_iterator found_ns(node.getData()->find(RRType::NS()));
-    if (found_ns != node.getData()->end()) {
-        // We perform callback check only for the highest zone cut in the
-        // rare case of nested zone cuts.
-        if (state->zonecut_node_ != NULL) {
-            return (false);
-        }
-
-        LOG_DEBUG(logger, DBG_TRACE_DETAILED, DATASRC_MEM_NS_ENCOUNTERED);
-
-        // BIND 9 checks if this node is not the origin.  That's probably
-        // because it can support multiple versions for dynamic updates
-        // and IXFR, and it's possible that the callback is called at
-        // the apex and the DNAME doesn't exist for a particular version.
-        // It cannot happen for us (at least for now), so we don't do
-        // that check.
-        state->zonecut_node_ = &node;
-        state->rrset_ = found_ns->second;
-
-        // Unless glue is allowed the search stops here, so we return
-        // false; otherwise return true to continue the search.
-        return (!state->glue_ok_);
-    }
-
-    // This case should not happen because we enable callback only
-    // when we add an RR searched for above.
-    assert(0);
-    // This is here to avoid warning (therefore compilation error)
-    // in case assert is turned off. Otherwise we could get "Control
-    // reached end of non-void function".
-    return (false);
-}
-
-// Implementation notes: this method identifies an RBT node that best matches
-// the give name in terms of DNS query handling.  In many cases,
-// DomainTree::find() will result in EXACTMATCH or PARTIALMATCH (note that
-// the given name is generally expected to be contained in the zone, so
-// even if it doesn't exist, it should at least match the zone origin).
-// If it finds an exact match, that's obviously the best one.  The partial
-// match case is more complicated.
-//
-// We first need to consider the case where search hits a delegation point,
-// either due to NS or DNAME.  They are indicated as either dname_node_ or
-// zonecut_node_ being non NULL.  Usually at most one of them will be
-// something else than NULL (it might happen both are NULL, in which case we
-// consider it NOT FOUND). There's one corner case when both might be
-// something else than NULL and it is in case there's a DNAME under a zone
-// cut and we search in glue OK mode ‒ in that case we don't stop on the
-// domain with NS and ignore it for the answer, but it gets set anyway. Then
-// we find the DNAME and we need to act by it, therefore we first check for
-// DNAME and then for NS. In all other cases it doesn't matter, as at least
-// one of them is NULL.
-//
-// Next, we need to check if the RBTree search stopped at a node for a
-// subdomain of the search name (so the comparison result that stopped the
-// search is "SUPERDOMAIN"), it means the stopping node is an empty
-// non-terminal node.  In this case the search name is considered to exist
-// but no data should be found there.
-//
-// If none of above is the case, we then consider whether there's a matching
-// wildcard.  DomainTree::find() records the node if it encounters a
-// "wildcarding" node, i.e., the immediate ancestor of a wildcard name
-// (e.g., wild.example.com for *.wild.example.com), and returns it if it
-// doesn't find any node that better matches the query name.  In this case
-// we'll check if there's indeed a wildcard below the wildcarding node.
-//
-// Note, first, that the wildcard is checked after the empty
-// non-terminal domain case above, because if that one triggers, it
-// means we should not match according to 4.3.3 of RFC 1034 (the query
-// name is known to exist).
-//
-// Before we try to find a wildcard, we should check whether there's
-// an existing node that would cancel the wildcard match.  If
-// DomainTree::find() stopped at a node which has a common ancestor
-// with the query name, it might mean we are comparing with a
-// non-wildcard node. In that case, we check which part is common. If
-// we have something in common that lives below the node we got (the
-// one above *), then we should cancel the match according to section
-// 4.3.3 of RFC 1034 (as the name between the wildcard domain and the
-// query name is known to exist).
-//
-// If there's no node below the wildcarding node that shares a common ancestor
-// of the query name, we can conclude the wildcard is the best match.
-// We'll then identify the wildcard node via an incremental search.  Note that
-// there's no possibility that the query name is at an empty non terminal
-// node below the wildcarding node at this stage; that case should have been
-// caught above.
-//
-// If none of the above succeeds, we conclude the name doesn't exist in
-// the zone.
-template <typename ResultType>
-ResultType
-ZoneData::findNode(const Name& name, RBTreeNodeChain<Domain>& node_path,
-                   ZoneFinder::FindOptions options) const
-{
-    DomainNode* node = NULL;
-    FindState state((options & ZoneFinder::FIND_GLUE_OK) != 0);
-
-    const DomainTree::Result result =
-        domains_.find(LabelSequence(name), &node, node_path,
-                      cutCallback, &state);
-    const unsigned int zonecut_flag =
-        (state.zonecut_node_ != NULL) ? FindNodeResult::FIND_ZONECUT : 0;
-    if (result == DomainTree::EXACTMATCH) {
-        return (ResultType(ZoneFinder::SUCCESS, node, state.rrset_,
-                           zonecut_flag));
-    } else if (result == DomainTree::PARTIALMATCH) {
-        assert(node != NULL);
-        if (state.dname_node_ != NULL) { // DNAME
-            LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEM_DNAME_FOUND).
-                arg(state.rrset_->getName());
-            return (ResultType(ZoneFinder::DNAME, NULL, state.rrset_));
-        }
-        if (state.zonecut_node_ != NULL) { // DELEGATION due to NS
-            LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEM_DELEG_FOUND).
-                arg(state.rrset_->getName());
-            return (ResultType(ZoneFinder::DELEGATION, NULL, state.rrset_));
-        }
-        if (node_path.getLastComparisonResult().getRelation() ==
-            NameComparisonResult::SUPERDOMAIN) { // empty node, so NXRRSET
-            LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEM_SUPER_STOP).arg(name);
-            return (ResultType(ZoneFinder::NXRRSET, node,
-                               getClosestNSEC(node_path, options)));
-        }
-        if (node->getFlag(domain_flag::WILD) && // maybe a wildcard, check only
-            (options & ZoneFinder::NO_WILDCARD) == 0) { // if not disabled.
-            if (node_path.getLastComparisonResult().getRelation() ==
-                NameComparisonResult::COMMONANCESTOR) {
-                // This means, e.g., we have *.wild.example and
-                // bar.foo.wild.example and are looking for
-                // baz.foo.wild.example. The common ancestor, foo.wild.example,
-                // should cancel wildcard.  Treat it as NXDOMAIN.
-                LOG_DEBUG(logger, DBG_TRACE_DATA,
-                          DATASRC_MEM_WILDCARD_CANCEL).arg(name);
-                return (ResultType(ZoneFinder::NXDOMAIN, NULL,
-                                   getClosestNSEC(node_path, options)));
-            }
-            // Now the wildcard should be the best match.
-            const Name wildcard(Name("*").concatenate(
-                                    node_path.getAbsoluteName()));
-
-            // Clear the node_path so that we don't keep incorrect (NSEC)
-            // context
-            node_path.clear();
-            DomainTree::Result result(domains_.find(wildcard, &node,
-                                                    node_path));
-            // Otherwise, why would the domain_flag::WILD be there if
-            // there was no wildcard under it?
-            assert(result == DomainTree::EXACTMATCH);
-            return (ResultType(ZoneFinder::SUCCESS, node, state.rrset_,
-                               FindNodeResult::FIND_WILDCARD |
-                               zonecut_flag));
-        }
-        // Nothing really matched.
-        LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEM_NOT_FOUND).arg(name);
-        return (ResultType(ZoneFinder::NXDOMAIN, node,
-                           getClosestNSEC(node_path, options)));
-    } else {
-        // If the name is neither an exact or partial match, it is
-        // out of bailiwick, which is considered an error.
-        isc_throw(OutOfZone, name.toText() << " not in " <<
-                             origin_data_->getName());
-    }
-}
-} // unnamed namespace
-
-namespace internal {
-
-/// \brief An encapsulation type for a pointer of an additional node
-/// associated with an \c RBNodeRRset object.
-///
-/// Currently this is defined as a structure only so that it can declared
-/// in rbnode_rrset.h; this is essentially a pointer to \c DomainNode.
-/// In future, however, this structure may have other attributes.
-struct AdditionalNodeInfo {
-    explicit AdditionalNodeInfo(DomainNode* node) : node_(node) {}
-    DomainNode* node_;
-};
-
-//
-// RBNodeRRset details
-//
-struct RBNodeRRsetImpl {
-public:
-    RBNodeRRsetImpl(const ConstRRsetPtr& rrset) : rrset_(rrset)
-    {}
-
-    ConstRRsetPtr rrset_;     ///< Underlying RRset
-    scoped_ptr<vector<AdditionalNodeInfo> > additionals_;
-};
-
-RBNodeRRset::RBNodeRRset(const ConstRRsetPtr& rrset) :
-    impl_(new RBNodeRRsetImpl(rrset))
-{
-}
-
-RBNodeRRset::~RBNodeRRset() {
-    delete impl_;
-}
-
-unsigned int
-RBNodeRRset::getRdataCount() const {
-    return (impl_->rrset_->getRdataCount());
-}
-
-const Name&
-RBNodeRRset::getName() const {
-    return (impl_->rrset_->getName());
-}
-
-const RRClass&
-RBNodeRRset::getClass() const {
-    return (impl_->rrset_->getClass());
-}
-
-const RRType&
-RBNodeRRset::getType() const {
-    return (impl_->rrset_->getType());
-}
-
-const RRTTL&
-RBNodeRRset::getTTL() const {
-    return (impl_->rrset_->getTTL());
-}
-
-void
-RBNodeRRset::setName(const Name&) {
-    isc_throw(isc::NotImplemented, "RBNodeRRset::setName() not supported");
-}
-
-void
-RBNodeRRset::setTTL(const RRTTL&) {
-    isc_throw(isc::NotImplemented, "RBNodeRRset::setTTL() not supported");
-}
-
-string
-RBNodeRRset::toText() const {
-    return (impl_->rrset_->toText());
-}
-
-unsigned int
-RBNodeRRset::toWire(AbstractMessageRenderer& renderer) const {
-    return (impl_->rrset_->toWire(renderer));
-}
-
-unsigned int
-RBNodeRRset::toWire(isc::util::OutputBuffer& buffer) const {
-    return (impl_->rrset_->toWire(buffer));
-}
-
-void
-RBNodeRRset::addRdata(ConstRdataPtr) {
-    isc_throw(isc::NotImplemented, "RBNodeRRset::addRdata() not supported");
-}
-
-void
-RBNodeRRset::addRdata(const Rdata&) {
-    isc_throw(isc::NotImplemented, "RBNodeRRset::addRdata() not supported");
-}
-
-RdataIteratorPtr
-RBNodeRRset::getRdataIterator() const {
-    return (impl_->rrset_->getRdataIterator());
-}
-
-RRsetPtr
-RBNodeRRset::getRRsig() const {
-    return (impl_->rrset_->getRRsig());
-}
-
-unsigned int
-RBNodeRRset::getRRsigDataCount() const {
-    return (impl_->rrset_->getRRsigDataCount());
-}
-
-void
-RBNodeRRset::addRRsig(const ConstRdataPtr& rdata) {
-    AbstractRRset* p = const_cast<AbstractRRset*>(impl_->rrset_.get());
-    p->addRRsig(rdata);
-}
-
-void
-RBNodeRRset::addRRsig(const RdataPtr& rdata) {
-    AbstractRRset* p = const_cast<AbstractRRset*>(impl_->rrset_.get());
-    p->addRRsig(rdata);
-}
-
-void
-RBNodeRRset::addRRsig(const AbstractRRset& sigs) {
-    AbstractRRset* p = const_cast<AbstractRRset*>(impl_->rrset_.get());
-    p->addRRsig(sigs);
-}
-
-void
-RBNodeRRset::addRRsig(const ConstRRsetPtr& sigs) {
-    AbstractRRset* p = const_cast<AbstractRRset*>(impl_->rrset_.get());
-    p->addRRsig(sigs);
-}
-
-void
-RBNodeRRset::addRRsig(const RRsetPtr& sigs) {
-    AbstractRRset* p = const_cast<AbstractRRset*>(impl_->rrset_.get());
-    p->addRRsig(sigs);
-}
-
-void
-RBNodeRRset::removeRRsig() {
-    AbstractRRset* p = const_cast<AbstractRRset*>(impl_->rrset_.get());
-    p->removeRRsig();
-}
-
-ConstRRsetPtr
-RBNodeRRset::getUnderlyingRRset() const {
-    return (impl_->rrset_);
-}
-
-void
-RBNodeRRset::addAdditionalNode(const AdditionalNodeInfo& additional) {
-    // Lazy initialization
-    if (!impl_->additionals_) {
-        impl_->additionals_.reset(new vector<AdditionalNodeInfo>);
-    }
-    impl_->additionals_->push_back(additional);
-}
-
-const vector<AdditionalNodeInfo>*
-RBNodeRRset::getAdditionalNodes() const {
-    return (impl_->additionals_.get());
-}
-
-void
-RBNodeRRset::copyAdditionalNodes(RBNodeRRset& dst) const {
-    if (impl_->additionals_) {
-        dst.impl_->additionals_.reset(
-            new vector<AdditionalNodeInfo>(impl_->additionals_->begin(),
-                                           impl_->additionals_->end()));
-    }
-}
-
-} // end of internal
-
-namespace {
-/*
- * Prepares a rrset to be return as a result.
- *
- * If rename is false, it returns the one provided. If it is true, it
- * creates a new rrset with the same data but with provided name.
- * In addition, if DNSSEC records are required by the original caller of
- * find(), it also creates expanded RRSIG based on the RRSIG of the
- * wildcard RRset.
- * It is designed for wildcard case, where we create the rrsets
- * dynamically.
- */
-ConstRBNodeRRsetPtr
-prepareRRset(const Name& name, const ConstRBNodeRRsetPtr& rrset, bool rename,
-             ZoneFinder::FindOptions options)
-{
-    if (rename) {
-        LOG_DEBUG(logger, DBG_TRACE_DETAILED, DATASRC_MEM_RENAME).
-            arg(rrset->getName()).arg(name);
-        RRsetPtr result_base(new RRset(name, rrset->getClass(),
-                                       rrset->getType(), rrset->getTTL()));
-        for (RdataIteratorPtr i(rrset->getRdataIterator()); !i->isLast();
-             i->next()) {
-            result_base->addRdata(i->getCurrent());
-        }
-        if ((options & ZoneFinder::FIND_DNSSEC) != 0) {
-            ConstRRsetPtr sig_rrset = rrset->getRRsig();
-            if (sig_rrset) {
-                RRsetPtr result_sig(new RRset(name, sig_rrset->getClass(),
-                                              RRType::RRSIG(),
-                                              sig_rrset->getTTL()));
-                for (RdataIteratorPtr i(sig_rrset->getRdataIterator());
-                     !i->isLast();
-                     i->next())
-                {
-                    result_sig->addRdata(i->getCurrent());
-                }
-                result_base->addRRsig(result_sig);
-            }
-        }
-        RBNodeRRsetPtr result(new RBNodeRRset(result_base));
-        rrset->copyAdditionalNodes(*result);
-        return (result);
-    } else {
-        ConstRRsetPtr sig_rrset = rrset->getRRsig();
-        if (sig_rrset &&
-            ((options & ZoneFinder::FIND_DNSSEC) == 0)) {
-            RRsetPtr result_base(new RRset(name, rrset->getClass(),
-                                           rrset->getType(),
-                                           rrset->getTTL()));
-            for (RdataIteratorPtr i(rrset->getRdataIterator());
-                 !i->isLast();
-                 i->next()) {
-                result_base->addRdata(i->getCurrent());
-            }
-
-            RBNodeRRsetPtr result(new RBNodeRRset(result_base));
-            rrset->copyAdditionalNodes(*result);
-            return (result);
-        } else {
-            return (rrset);
-        }
-    }
-}
-
-// Specialized version of ZoneFinder::ResultContext, which specifically
-// holds rrset in the form of RBNodeRRset.
-struct RBNodeResultContext {
-    /// \brief Constructor
-    ///
-    /// The first three parameters correspond to those of
-    /// ZoneFinder::ResultContext.  If node is non NULL, it specifies the
-    /// found RBNode in the search.
-    RBNodeResultContext(ZoneFinder::Result code_param,
-                        ConstRBNodeRRsetPtr rrset_param,
-                        ZoneFinder::FindResultFlags flags_param,
-                        const DomainNode* node) :
-        code(code_param), rrset(rrset_param), flags(flags_param),
-        found_node(node)
-    {}
-
-    const ZoneFinder::Result code;
-    const ConstRBNodeRRsetPtr rrset;
-    const ZoneFinder::FindResultFlags flags;
-    const DomainNode* const found_node;
-};
-}
-
-// cppcheck-suppress noConstructor
-class InMemoryZoneFinder::Context : public ZoneFinder::Context {
-public:
-    /// \brief Constructor.
-    ///
-    /// Note that we don't have a specific constructor for the findAll() case.
-    /// For (successful) type ANY query, found_node points to the
-    /// corresponding RB node, which is recorded within this specialized
-    /// context.
-    Context(ZoneFinder& finder, ZoneFinder::FindOptions options,
-            const RBNodeResultContext& result) :
-        ZoneFinder::Context(options,
-                            ResultContext(result.code, result.rrset,
-                                          result.flags)),
-        finder_(finder), rrset_(result.rrset), found_node_(result.found_node)
-    {}
-
-protected:
-    virtual ZoneFinder* getFinder() { return (&finder_); }
-
-    virtual const std::vector<isc::dns::ConstRRsetPtr>* getAllRRsets() const {
-        return (NULL);
-    }
-
-    virtual void getAdditionalImpl(const vector<RRType>& requested_types,
-                                   vector<ConstRRsetPtr>& result)
-    {
-        if (!rrset_) {
-            // In this case this context should encapsulate the result of
-            // findAll() and found_node_ should point to a valid answer node.
-            if (found_node_ == NULL || found_node_->isEmpty()) {
-                isc_throw(isc::Unexpected,
-                          "Invalid call to in-memory getAdditional: caller's "
-                          "bug or broken zone");
-            }
-            BOOST_FOREACH(const DomainPair& dom_it, *found_node_->getData()) {
-                getAdditionalForRRset(*dom_it.second, requested_types,
-                                      result, options_);
-            }
-        } else {
-            getAdditionalForRRset(*rrset_, requested_types, result, options_);
-        }
-    }
-
-private:
-    // Retrieve additional RRsets for a given RRset associated in the context.
-    // The process is straightforward: it examines the link to
-    // AdditionalNodeInfo vector (if set), and find RRsets of the requested
-    // type for each node.
-    static void getAdditionalForRRset(const RBNodeRRset& rrset,
-                                      const vector<RRType>& requested_types,
-                                      vector<ConstRRsetPtr>& result,
-                                      ZoneFinder::FindOptions options)
-    {
-        const vector<AdditionalNodeInfo>* additionals_ =
-            rrset.getAdditionalNodes();
-        if (additionals_ == NULL) {
-            return;
-        }
-        const bool glue_ok = (rrset.getType() == RRType::NS());
-        BOOST_FOREACH(const AdditionalNodeInfo& additional, *additionals_) {
-            assert(additional.node_ != NULL);
-            if (additional.node_->isEmpty()) {
-                continue;
-            }
-            if (!glue_ok && additional.node_->getFlag(domain_flag::GLUE)) {
-                continue;
-            }
-            const bool wild_expanded =
-                additional.node_->getFlag(domain_flag::WILD_EXPANDED);
-            BOOST_FOREACH(const RRType& rrtype, requested_types) {
-                Domain::const_iterator found =
-                    additional.node_->getData()->find(rrtype);
-                if (found != additional.node_->getData()->end()) {
-                    // If the additional node was generated as a result of
-                    // wildcard expansion, we return the underlying RRset,
-                    // in case the caller has the same RRset but as a result
-                    // of normal find() and needs to know they are of the same
-                    // kind; otherwise we simply use the stored RBNodeRRset.
-                    ConstRRsetPtr rp;
-                    if (wild_expanded) {
-                        rp = found->second->getUnderlyingRRset();
-                    } else {
-                        rp = found->second;
-                    }
-                    result.push_back(ZoneFinder::stripRRsigs(rp, options));
-                }
-            }
-        }
-    }
-
-    ZoneFinder& finder_;
-    const ConstRBNodeRRsetPtr rrset_;
-    const DomainNode* const found_node_;
-};
-
-// Private data and hidden methods of InMemoryZoneFinder
-struct InMemoryZoneFinder::InMemoryZoneFinderImpl {
-    // Constructor
-    InMemoryZoneFinderImpl(const RRClass& zone_class, const Name& origin) :
-        zone_class_(zone_class), origin_(origin),
-        zone_data_(new ZoneData(origin_))
-    {}
-
-    // Information about the zone
-    RRClass zone_class_;
-    Name origin_;
-    string file_name_;
-
-    // The actual zone data
-    scoped_ptr<ZoneData> zone_data_;
-
-    // Common process for zone load.
-    // rrset_installer is a functor that takes another functor as an argument,
-    // and expected to call the latter for each RRset of the zone.  How the
-    // sequence of the RRsets is generated depends on the internal
-    // details  of the loader: either from a textual master file or from
-    // another data source.
-    // filename is the file name of the master file or empty if the zone is
-    // loaded from another data source.
-    void load(const string& filename,
-              boost::function<void(LoadCallback)> rrset_installer);
-
-    // Add the necessary magic for any wildcard contained in 'name'
-    // (including itself) to be found in the zone.
-    //
-    // In order for wildcard matching to work correctly in find(),
-    // we must ensure that a node for the wildcarding level exists in the
-    // backend RBTree.
-    // E.g. if the wildcard name is "*.sub.example." then we must ensure
-    // that "sub.example." exists and is marked as a wildcard level.
-    // Note: the "wildcarding level" is for the parent name of the wildcard
-    // name (such as "sub.example.").
-    //
-    // We also perform the same trick for empty wild card names possibly
-    // contained in 'name' (e.g., '*.foo.example' in 'bar.*.foo.example').
-    void addWildcards(util::MemorySegment& mem_sgmt, DomainTree& domains,
-                      const Name& name)
-    {
-        Name wname(name);
-        const unsigned int labels(wname.getLabelCount());
-        const unsigned int origin_labels(origin_.getLabelCount());
-        for (unsigned int l = labels;
-             l > origin_labels;
-             --l, wname = wname.split(1)) {
-            if (wname.isWildcard()) {
-                LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEM_ADD_WILDCARD).
-                    arg(name);
-                // Ensure a separate level exists for the "wildcarding" name,
-                // and mark the node as "wild".
-                DomainNode* node;
-                DomainTree::Result result(domains.insert(mem_sgmt,
-                                                         wname.split(1),
-                                                         &node));
-                assert(result == DomainTree::SUCCESS ||
-                       result == DomainTree::ALREADYEXISTS);
-                node->setFlag(domain_flag::WILD);
-
-                // Ensure a separate level exists for the wildcard name.
-                // Note: for 'name' itself we do this later anyway, but the
-                // overhead should be marginal because wildcard names should
-                // be rare.
-                result = domains.insert(mem_sgmt, wname, &node);
-                assert(result == DomainTree::SUCCESS ||
-                       result == DomainTree::ALREADYEXISTS);
-            }
-        }
-    }
-
-    // A helper predicate used in contextCheck() to check if a given domain
-    // name has a RRset of type different than NSEC.
-    static bool isNotNSEC(const DomainPair& element) {
-        return (element.second->getType() != RRType::NSEC());
-    }
-
-    /*
-     * Does some checks in context of the data that are already in the zone.
-     * Currently checks for forbidden combinations of RRsets in the same
-     * domain (CNAME+anything, DNAME+NS).
-     *
-     * If such condition is found, it throws AddError.
-     */
-    void contextCheck(const AbstractRRset& rrset, const Domain& domain) const {
-        // Ensure CNAME and other type of RR don't coexist for the same
-        // owner name except with NSEC, which is the only RR that can coexist
-        // with CNAME (and also RRSIG, which is handled separately)
-        if (rrset.getType() == RRType::CNAME()) {
-            if (find_if(domain.begin(), domain.end(), isNotNSEC)
-                != domain.end()) {
-                LOG_ERROR(logger, DATASRC_MEM_CNAME_TO_NONEMPTY).
-                    arg(rrset.getName());
-                isc_throw(AddError, "CNAME can't be added with other data for "
-                          << rrset.getName());
-            }
-        } else if (rrset.getType() != RRType::NSEC() &&
-                   domain.find(RRType::CNAME()) != domain.end()) {
-            LOG_ERROR(logger, DATASRC_MEM_CNAME_COEXIST).arg(rrset.getName());
-            isc_throw(AddError, "CNAME and " << rrset.getType() <<
-                      " can't coexist for " << rrset.getName());
-        }
-
-        /*
-         * Similar with DNAME, but it must not coexist only with NS and only in
-         * non-apex domains.
-         * RFC 2672 section 3 mentions that it is implied from it and RFC 2181
-         */
-        if (rrset.getName() != origin_ &&
-            // Adding DNAME, NS already there
-            ((rrset.getType() == RRType::DNAME() &&
-            domain.find(RRType::NS()) != domain.end()) ||
-            // Adding NS, DNAME already there
-            (rrset.getType() == RRType::NS() &&
-            domain.find(RRType::DNAME()) != domain.end())))
-        {
-            LOG_ERROR(logger, DATASRC_MEM_DNAME_NS).arg(rrset.getName());
-            isc_throw(AddError, "DNAME can't coexist with NS in non-apex "
-                "domain " << rrset.getName());
-        }
-    }
-
-    // Validate rrset before adding it to the zone.  If something is wrong
-    // it throws an exception.  It doesn't modify the zone, and provides
-    // the strong exception guarantee.
-    void addValidation(const ConstRRsetPtr rrset) {
-        if (!rrset) {
-            isc_throw(NullRRset, "The rrset provided is NULL");
-        }
-        if (rrset->getRdataCount() == 0) {
-            isc_throw(AddError, "The rrset provided is empty: " <<
-                      rrset->getName() << "/" << rrset->getType());
-        }
-        // Check for singleton RRs. It should probably handled at a different
-        // layer in future.
-        if ((rrset->getType() == RRType::CNAME() ||
-            rrset->getType() == RRType::DNAME()) &&
-            rrset->getRdataCount() > 1)
-        {
-            // XXX: this is not only for CNAME or DNAME. We should generalize
-            // this code for all other "singleton RR types" (such as SOA) in a
-            // separate task.
-            LOG_ERROR(logger, DATASRC_MEM_SINGLETON).arg(rrset->getName()).
-                arg(rrset->getType());
-            isc_throw(AddError, "multiple RRs of singleton type for "
-                      << rrset->getName());
-        }
-        // NSEC3/NSEC3PARAM is not a "singleton" per protocol, but this
-        // implementation requests it be so at the moment.
-        if ((rrset->getType() == RRType::NSEC3() ||
-             rrset->getType() == RRType::NSEC3PARAM()) &&
-            rrset->getRdataCount() > 1) {
-            isc_throw(AddError, "Multiple NSEC3/NSEC3PARAM RDATA is given for "
-                      << rrset->getName() << " which isn't supported");
-        }
-
-        NameComparisonResult compare(origin_.compare(rrset->getName()));
-        if (compare.getRelation() != NameComparisonResult::SUPERDOMAIN &&
-            compare.getRelation() != NameComparisonResult::EQUAL)
-        {
-            LOG_ERROR(logger, DATASRC_MEM_OUT_OF_ZONE).arg(rrset->getName()).
-                arg(origin_);
-            isc_throw(OutOfZone, "The name " << rrset->getName() <<
-                " is not contained in zone " << origin_);
-        }
-
-        // Some RR types do not really work well with a wildcard.
-        // Even though the protocol specifically doesn't completely ban such
-        // usage, we refuse to load a zone containing such RR in order to
-        // keep the lookup logic simpler and more predictable.
-        // See RFC4592 and (for DNAME) draft-ietf-dnsext-rfc2672bis-dname
-        // for more technical background.  Note also that BIND 9 refuses
-        // NS at a wildcard, so in that sense we simply provide compatible
-        // behavior.
-        if (rrset->getName().isWildcard()) {
-            if (rrset->getType() == RRType::NS()) {
-                LOG_ERROR(logger, DATASRC_MEM_WILDCARD_NS).
-                    arg(rrset->getName());
-                isc_throw(AddError, "Invalid NS owner name (wildcard): " <<
-                          rrset->getName());
-            }
-            if (rrset->getType() == RRType::DNAME()) {
-                LOG_ERROR(logger, DATASRC_MEM_WILDCARD_DNAME).
-                    arg(rrset->getName());
-                isc_throw(AddError, "Invalid DNAME owner name (wildcard): " <<
-                          rrset->getName());
-            }
-        }
-
-        // Owner names of NSEC3 have special format as defined in RFC5155,
-        // and cannot be a wildcard name or must be one label longer than
-        // the zone origin.  While the RFC doesn't prohibit other forms of
-        // names, no sane zone would have such names for NSEC3.
-        // BIND 9 also refuses NSEC3 at wildcard.
-        if (rrset->getType() == RRType::NSEC3() &&
-            (rrset->getName().isWildcard() ||
-             rrset->getName().getLabelCount() !=
-             origin_.getLabelCount() + 1)) {
-            LOG_ERROR(logger, DATASRC_BAD_NSEC3_NAME).
-                arg(rrset->getName());
-            isc_throw(AddError, "Invalid NSEC3 owner name: " <<
-                      rrset->getName());
-        }
-    }
-
-    result::Result addRRsig(const ConstRRsetPtr sig_rrset, ZoneData& zone_data)
-    {
-        // Check consistency of the type covered.
-        // We know the RRset isn't empty, so the following check is safe.
-        RdataIteratorPtr rit = sig_rrset->getRdataIterator();
-        const RRType covered = dynamic_cast<const generic::RRSIG&>(
-            rit->getCurrent()).typeCovered();
-        for (rit->next(); !rit->isLast(); rit->next()) {
-            if (dynamic_cast<const generic::RRSIG&>(
-                    rit->getCurrent()).typeCovered() != covered) {
-                isc_throw(AddError, "RRSIG contains mixed covered types: "
-                          << sig_rrset->toText());
-            }
-        }
-
-        // Find the RRset to be covered; if not found, treat it as an error
-        // for now.
-        ConstRRsetPtr covered_rrset;
-        if (covered != RRType::NSEC3()) {
-            DomainNode* node = NULL;
-            if (zone_data.domains_.find(sig_rrset->getName(), &node) !=
-                DomainTree::EXACTMATCH || node == NULL || !node->getData()) {
-                isc_throw(AddError,
-                          "RRSIG is being added, but no RR to be covered: "
-                          << sig_rrset->getName());
-            }
-            const Domain::const_iterator it = node->getData()->find(covered);
-            if (it != node->getData()->end()) {
-                covered_rrset = it->second;
-            }
-        } else {
-            // In case of NSEC3 if something is found it must be NSEC3 RRset
-            // under the assumption of our current implementation.
-            if (zone_data.nsec3_data_) {
-                // Convert the first label to upper-cased text.  Note that
-                // for a valid NSEC3 RR the label should only consist of
-                // positive 8-bit char values, so using toupper(int) should be
-                // safe (if it's a bogus label for NSEC3 the zone won't work
-                // anyway).  Also note the '::' below: g++'s STL implementation
-                // seems to require it to toupper to make this compile.
-                string fst_label =
-                    sig_rrset->getName().split(0, 1).toText(true);
-                transform(fst_label.begin(), fst_label.end(),
-                          fst_label.begin(), ::toupper);
-
-                NSEC3Map::const_iterator found =
-                    zone_data.nsec3_data_->map_.find(fst_label);
-                if (found != zone_data.nsec3_data_->map_.end()) {
-                    covered_rrset = found->second;
-                    assert(covered_rrset->getType() == covered);
-                }
-            }
-        }
-        if (!covered_rrset) {
-            isc_throw(AddError, "RRSIG is being added, but no RR of "
-                      "covered type found: " << sig_rrset->toText());
-        }
-
-        // The current implementation doesn't allow an existing RRSIG to be
-        // overridden (or updated with additional ones).
-        if (covered_rrset->getRRsig()) {
-            isc_throw(AddError,
-                      "RRSIG is being added to override an existing one: "
-                      << sig_rrset->toText());
-        }
-
-        // All okay, setting the RRSIG.
-        // XXX: we break const-ness of the covered RRsets.  In practice the
-        // ownership of these RRsets would have been given to us so it should
-        // be safe, but it's still a very bad practice.
-        // We'll fix this problem anyway when we update the underlying
-        // representation so that it's more space efficient.
-        // Note: there's a slight chance of getting an exception.
-        // As noted in add(), we give up strong exception guarantee in such
-        // cases.
-        boost::const_pointer_cast<AbstractRRset>(covered_rrset)->addRRsig(sig_rrset);
-
-        return (result::SUCCESS);
-    }
-
-    result::Result addNSEC3(const ConstRRsetPtr rrset, ZoneData& zone_data) {
-        // We know rrset has exactly one RDATA
-        const generic::NSEC3& nsec3_rdata =
-            dynamic_cast<const generic::NSEC3&>(
-                rrset->getRdataIterator()->getCurrent());
-
-        // If we've not done any NSEC3 setup for the zone, do it now;
-        // otherwise check parameter consistency.
-        if (!zone_data.nsec3_data_) {
-            zone_data.nsec3_data_.reset(new ZoneData::NSEC3Data(nsec3_rdata));
-        } else if (!zone_data.nsec3_data_->hash_->match(nsec3_rdata)) {
-            isc_throw(AddError, "NSEC3 with inconsistent parameters: " <<
-                      rrset->toText());
-        }
-
-        string fst_label = rrset->getName().split(0, 1).toText(true);
-        transform(fst_label.begin(), fst_label.end(), fst_label.begin(),
-                  ::toupper);
-
-        // Our current implementation doesn't allow an existing NSEC3 to be
-        // updated/overridden.
-        if (zone_data.nsec3_data_->map_.find(fst_label) !=
-            zone_data.nsec3_data_->map_.end()) {
-            return (result::EXIST);
-        }
-
-        zone_data.nsec3_data_->map_.insert(
-            NSEC3Pair(fst_label, ConstRBNodeRRsetPtr(new RBNodeRRset(rrset))));
-        return (result::SUCCESS);
-    }
-
-    /*
-     * Implementation of longer methods. We put them here, because the
-     * access is without the impl_-> and it will get inlined anyway.
-     */
-    // Implementation of InMemoryZoneFinder::add
-    result::Result add(const ConstRRsetPtr& rawrrset, ZoneData& zone_data,
-                       vector<RBNodeRRset*>* need_additionals)
-    {
-        // Sanitize input.  This will cause an exception to be thrown
-        // if the input RRset is empty.
-        addValidation(rawrrset);
-
-        // OK, can add the RRset.
-        LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEM_ADD_RRSET).
-            arg(rawrrset->getName()).arg(rawrrset->getType()).arg(origin_);
-
-        // ... although instead of loading the RRset directly, we encapsulate
-        // it within an RBNodeRRset.  This contains additional information that
-        // speeds up queries.
-        RBNodeRRsetPtr rrset(new RBNodeRRset(rawrrset));
-
-        if (rrset->getType() == RRType::NSEC3()) {
-            return (addNSEC3(rrset, zone_data));
-        }
-
-        // RRSIGs are special in various points, so we handle it in a
-        // separate dedicated method.
-        if (rrset->getType() == RRType::RRSIG()) {
-            return (addRRsig(rrset, zone_data));
-        }
-
-        // Add wildcards possibly contained in the owner name to the domain
-        // tree.
-        // Note: this can throw an exception, breaking strong exception
-        // guarantee.  (see also the note for contextCheck() below).
-        addWildcards(zone_data.local_mem_sgmt_, zone_data.domains_,
-                     rrset->getName());
-
-        // Get the node
-        DomainNode* node;
-        DomainTree::Result result =
-            zone_data.domains_.insert(zone_data.local_mem_sgmt_,
-                                      rrset->getName(), &node);
-        // Just check it returns reasonable results
-        assert((result == DomainTree::SUCCESS ||
-                result == DomainTree::ALREADYEXISTS) && node!= NULL);
-
-        // Now get the domain
-        DomainPtr domain;
-        // It didn't exist yet, create it
-        if (node->isEmpty()) {
-            domain.reset(new Domain);
-            node->setData(domain);
-        } else { // Get existing one
-            domain = node->getData();
-        }
-
-        // Checks related to the surrounding data.
-        // Note: when the check fails and the exception is thrown, it may
-        // break strong exception guarantee.  At the moment we prefer
-        // code simplicity and don't bother to introduce complicated
-        // recovery code.
-        contextCheck(*rrset, *domain);
-
-        // Try inserting the rrset there
-        if (domain->insert(DomainPair(rrset->getType(), rrset)).second) {
-            // Ok, we just put it in
-
-            // If this RRset creates a zone cut at this node, mark the node
-            // indicating the need for callback in find().
-            if (rrset->getType() == RRType::NS() &&
-                rrset->getName() != origin_) {
-                node->setFlag(DomainNode::FLAG_CALLBACK);
-                // If it is DNAME, we have a callback as well here
-            } else if (rrset->getType() == RRType::DNAME()) {
-                node->setFlag(DomainNode::FLAG_CALLBACK);
-            }
-
-            if (need_additionals != NULL &&
-                (rrset->getType() == RRType::NS() ||
-                 rrset->getType() == RRType::MX())) {
-                need_additionals->push_back(rrset.get());
-            }
-
-            // If we've added NSEC3PARAM at zone origin, set up NSEC3 specific
-            // data or check consistency with already set up parameters.
-            if (rrset->getType() == RRType::NSEC3PARAM() &&
-                rrset->getName() == origin_) {
-                // We know rrset has exactly one RDATA
-                const generic::NSEC3PARAM& param =
-                    dynamic_cast<const generic::NSEC3PARAM&>(
-                        rrset->getRdataIterator()->getCurrent());
-
-                if (!zone_data.nsec3_data_) {
-                    zone_data.nsec3_data_.reset(
-                        new ZoneData::NSEC3Data(param));
-                } else if (!zone_data.nsec3_data_->hash_->match(param)) {
-                    isc_throw(AddError, "NSEC3PARAM with inconsistent "
-                              "parameters: " << rrset->toText());
-                }
-            } else if (rrset->getType() == RRType::NSEC()) {
-                // If it is NSEC signed zone, so we put a flag there
-                // (flag is enough)
-                zone_data.nsec_signed_ = true;
-            }
-            return (result::SUCCESS);
-        } else {
-            // The RRSet of given type was already there
-            return (result::EXIST);
-        }
-    }
-
-    /*
-     * Same as above, but it checks the return value and if it already exists,
-     * it throws.
-     */
-    void addFromLoad(const ConstRRsetPtr& set, ZoneData* zone_data,
-                     vector<RBNodeRRset*>* need_additionals)
-    {
-        switch (add(set, *zone_data, need_additionals)) {
-        case result::EXIST:
-            LOG_ERROR(logger, DATASRC_MEM_DUP_RRSET).
-                arg(set->getName()).arg(set->getType());
-            isc_throw(dns::MasterLoadError, "Duplicate rrset: " <<
-                      set->toText());
-        case result::SUCCESS:
-            return;
-        default:
-            assert(0);
-        }
-    }
-
-    // A helper function for the NXRRSET case in find().  If the zone is
-    // NSEC-signed and DNSSEC records are requested, try to find NSEC
-    // on the given node, and return it if found; return NULL for all other
-    // cases.
-    ConstRBNodeRRsetPtr getNSECForNXRRSET(FindOptions options,
-                                          const DomainNode& node) const
-    {
-        if (zone_data_->nsec_signed_ &&
-            (options & ZoneFinder::FIND_DNSSEC) != 0) {
-            const Domain::const_iterator found =
-                node.getData()->find(RRType::NSEC());
-            if (found != node.getData()->end()) {
-                return (found->second);
-            }
-        }
-        return (ConstRBNodeRRsetPtr());
-    }
-
-    // Set up FindContext object as a return value of find(), taking into
-    // account wildcard matches and DNSSEC information.  We set the NSEC/NSEC3
-    // flag when applicable regardless of the find option; the caller would
-    // simply ignore these when they didn't request DNSSEC related results.
-    // When the optional parameter 'node' is given (in which case it should be
-    // non NULL), it means it's a result of ANY query and the context should
-    // remember the matched node.
-    RBNodeResultContext createFindResult(Result code,
-                                         ConstRBNodeRRsetPtr rrset,
-                                         bool wild = false,
-                                         const DomainNode* node = NULL) const
-    {
-        FindResultFlags flags = RESULT_DEFAULT;
-        if (wild) {
-            flags = flags | RESULT_WILDCARD;
-        }
-        if (code == NXRRSET || code == NXDOMAIN || wild) {
-            if (zone_data_->nsec3_data_) {
-                flags = flags | RESULT_NSEC3_SIGNED;
-            }
-            if (zone_data_->nsec_signed_) {
-                flags = flags | RESULT_NSEC_SIGNED;
-            }
-        }
-        return (RBNodeResultContext(code, rrset, flags, node));
-    }
-
-    // Implementation of InMemoryZoneFinder::find
-    RBNodeResultContext find(const Name& name, RRType type,
-                             std::vector<ConstRRsetPtr>* target,
-                             const FindOptions options) const
-    {
-        LOG_DEBUG(logger, DBG_TRACE_BASIC, DATASRC_MEM_FIND).arg(name).
-            arg(type);
-
-        // Get the node.  All other cases than an exact match are handled
-        // in findNode().  We simply construct a result structure and return.
-        RBTreeNodeChain<Domain> node_path; // findNode will fill in this
-        const ZoneData::FindNodeResult node_result =
-            zone_data_->findNode<ZoneData::FindNodeResult>(name, node_path,
-                                                           options);
-        if (node_result.code != SUCCESS) {
-            return (createFindResult(node_result.code, node_result.rrset));
-        }
-
-        // We've found an exact match, may or may not be a result of wildcard.
-        const DomainNode* node = node_result.node;
-        assert(node != NULL);
-        const bool rename = ((node_result.flags &
-                              ZoneData::FindNodeResult::FIND_WILDCARD) != 0);
-
-        // If there is an exact match but the node is empty, it's equivalent
-        // to NXRRSET.
-        if (node->isEmpty()) {
-            LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEM_DOMAIN_EMPTY).
-                arg(name);
-            return (createFindResult(NXRRSET,
-                                     zone_data_->getClosestNSEC(node_path,
-                                                                options),
-                                     rename));
-        }
-
-        Domain::const_iterator found;
-
-        // If the node callback is enabled, this may be a zone cut.  If it
-        // has a NS RR, we should return a delegation, but not in the apex.
-        // There is one exception: the case for DS query, which should always
-        // be considered in-zone lookup.
-        if (node->getFlag(DomainNode::FLAG_CALLBACK) &&
-            node != zone_data_->origin_data_ && type != RRType::DS()) {
-            found = node->getData()->find(RRType::NS());
-            if (found != node->getData()->end()) {
-                LOG_DEBUG(logger, DBG_TRACE_DATA,
-                          DATASRC_MEM_EXACT_DELEGATION).arg(name);
-                return (createFindResult(DELEGATION,
-                                         prepareRRset(name, found->second,
-                                                      rename, options)));
-            }
-        }
-
-        // handle type any query
-        if (target != NULL && !node->getData()->empty()) {
-            // Empty domain will be handled as NXRRSET by normal processing
-            for (found = node->getData()->begin();
-                 found != node->getData()->end(); ++found)
-            {
-                target->push_back(prepareRRset(name, found->second, rename,
-                                               options));
-            }
-            LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEM_ANY_SUCCESS).
-                arg(name);
-            return (createFindResult(SUCCESS, ConstRBNodeRRsetPtr(), rename,
-                                     node));
-        }
-
-        found = node->getData()->find(type);
-        if (found != node->getData()->end()) {
-            // Good, it is here
-            LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEM_SUCCESS).arg(name).
-                arg(type);
-            return (createFindResult(SUCCESS, prepareRRset(name,
-                                                           found->second,
-                                                           rename, options),
-                                     rename));
-        } else {
-            // Next, try CNAME.
-            found = node->getData()->find(RRType::CNAME());
-            if (found != node->getData()->end()) {
-                LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEM_CNAME).arg(name);
-                return (createFindResult(CNAME,
-                                          prepareRRset(name, found->second,
-                                                       rename, options),
-                                          rename));
-            }
-        }
-        // No exact match or CNAME.  Get NSEC if necessary and return NXRRSET.
-        return (createFindResult(NXRRSET, getNSECForNXRRSET(options, *node),
-                                 rename));
-    }
-};
-
-InMemoryZoneFinder::InMemoryZoneFinder(const RRClass& zone_class,
-                                       const Name& origin) :
-    impl_(new InMemoryZoneFinderImpl(zone_class, origin))
-{
-    LOG_DEBUG(logger, DBG_TRACE_BASIC, DATASRC_MEM_CREATE).arg(origin).
-        arg(zone_class);
-}
-
-InMemoryZoneFinder::~InMemoryZoneFinder() {
-    LOG_DEBUG(logger, DBG_TRACE_BASIC, DATASRC_MEM_DESTROY).arg(getOrigin()).
-        arg(getClass());
-    delete impl_;
-}
-
-Name
-InMemoryZoneFinder::getOrigin() const {
-    return (impl_->origin_);
-}
-
-RRClass
-InMemoryZoneFinder::getClass() const {
-    return (impl_->zone_class_);
-}
-
-ZoneFinderContextPtr
-InMemoryZoneFinder::find(const Name& name, const RRType& type,
-                         const FindOptions options)
-{
-    return (ZoneFinderContextPtr(
-                new Context(*this, options, impl_->find(name, type, NULL,
-                                                        options))));
-}
-
-ZoneFinderContextPtr
-InMemoryZoneFinder::findAll(const Name& name,
-                            std::vector<ConstRRsetPtr>& target,
-                            const FindOptions options)
-{
-    return (ZoneFinderContextPtr(
-                new Context(*this, options, impl_->find(name, RRType::ANY(),
-                                                        &target, options))));
-}
-
-ZoneFinder::FindNSEC3Result
-InMemoryZoneFinder::findNSEC3(const Name& name, bool recursive) {
-    LOG_DEBUG(logger, DBG_TRACE_BASIC, DATASRC_MEM_FINDNSEC3).arg(name).
-        arg(recursive ? "recursive" : "non-recursive");
-
-    if (!impl_->zone_data_->nsec3_data_) {
-        isc_throw(DataSourceError,
-                  "findNSEC3 attempt for non NSEC3 signed zone: " <<
-                  impl_->origin_ << "/" << impl_->zone_class_);
-    }
-    const NSEC3Map& map = impl_->zone_data_->nsec3_data_->map_;
-    if (map.empty()) {
-        isc_throw(DataSourceError,
-                  "findNSEC3 attempt but zone has no NSEC3 RR: " <<
-                  impl_->origin_ << "/" << impl_->zone_class_);
-    }
-    const NameComparisonResult cmp_result = name.compare(impl_->origin_);
-    if (cmp_result.getRelation() != NameComparisonResult::EQUAL &&
-        cmp_result.getRelation() != NameComparisonResult::SUBDOMAIN) {
-        isc_throw(OutOfZone, "findNSEC3 attempt for out-of-zone name: "
-                  << name << ", zone: " << impl_->origin_ << "/"
-                  << impl_->zone_class_);
-    }
-
-    // Convenient shortcuts
-    const NSEC3Hash& nsec3hash = *impl_->zone_data_->nsec3_data_->hash_;
-    const unsigned int olabels = impl_->origin_.getLabelCount();
-    const unsigned int qlabels = name.getLabelCount();
-
-    ConstRBNodeRRsetPtr covering_proof; // placeholder of the next closer proof
-    // Examine all names from the query name to the origin name, stripping
-    // the deepest label one by one, until we find a name that has a matching
-    // NSEC3 hash.
-    for (unsigned int labels = qlabels; labels >= olabels; --labels) {
-        const string hlabel = nsec3hash.calculate(
-            labels == qlabels ? name : name.split(qlabels - labels, labels));
-        NSEC3Map::const_iterator found = map.lower_bound(hlabel);
-        LOG_DEBUG(logger, DBG_TRACE_BASIC, DATASRC_MEM_FINDNSEC3_TRYHASH).
-            arg(name).arg(labels).arg(hlabel);
-
-        // If the given hash is larger than the largest stored hash or
-        // the first label doesn't match the target, identify the "previous"
-        // hash value and remember it as the candidate next closer proof.
-        if (found == map.end() || found->first != hlabel) {
-            // If the given hash is larger or smaller than everything,
-            // the covering proof is the NSEC3 that has the largest hash.
-            // Note that we know the map isn't empty, so rbegin() is
-            // safe.
-            if (found == map.end() || found == map.begin()) {
-                covering_proof = map.rbegin()->second;
-            } else {
-                // Otherwise, H(found_entry-1) < given_hash < H(found_entry).
-                // The covering proof is the first one (and it's valid
-                // because found is neither begin nor end)
-                covering_proof = (--found)->second;
-            }
-            if (!recursive) {   // in non recursive mode, we are done.
-                LOG_DEBUG(logger, DBG_TRACE_BASIC,
-                          DATASRC_MEM_FINDNSEC3_COVER).
-                    arg(name).arg(*covering_proof);
-                return (FindNSEC3Result(false, labels, covering_proof,
-                                        ConstRRsetPtr()));
-            }
-        } else {                // found an exact match.
-                LOG_DEBUG(logger, DBG_TRACE_BASIC,
-                          DATASRC_MEM_FINDNSEC3_MATCH).arg(name).arg(labels).
-                    arg(*found->second);
-            return (FindNSEC3Result(true, labels, found->second,
-                                    covering_proof));
-        }
-    }
-
-    isc_throw(DataSourceError, "recursive findNSEC3 mode didn't stop, likely "
-              "a broken NSEC3 zone: " << impl_->origin_ << "/"
-              << impl_->zone_class_);
-}
-
-result::Result
-InMemoryZoneFinder::add(const ConstRRsetPtr& rrset) {
-    return (impl_->add(rrset, *impl_->zone_data_, NULL));
-}
-
-namespace {
-// This should eventually be more generalized.
-const Name
-getAdditionalName(RRType rrtype, const rdata::Rdata& rdata) {
-    if (rrtype == RRType::NS()) {
-        const generic::NS& ns = dynamic_cast<const generic::NS&>(rdata);
-        return (ns.getNSName());
-    } else {
-        // In our usage the only other possible case is MX.
-        assert(rrtype == RRType::MX());
-        const generic::MX& mx = dynamic_cast<const generic::MX&>(rdata);
-        return (mx.getMXName());
-    }
-}
-
-void
-convertAndInsert(const DomainPair& rrset_item, DomainPtr dst_domain,
-                 const Name* dstname)
-{
-    // We copy RRSIGs, too, if they are attached in case we need it in
-    // getAdditional().
-    dst_domain->insert(DomainPair(rrset_item.first,
-                                  prepareRRset(*dstname, rrset_item.second,
-                                               true,
-                                               ZoneFinder::FIND_DNSSEC)));
-}
-
-void
-addAdditional(RBNodeRRset* rrset, ZoneData* zone_data,
-              vector<RBNodeRRset*>* wild_rrsets)
-{
-    RdataIteratorPtr rdata_iterator = rrset->getRdataIterator();
-    bool match_wild = false;    // will be true if wildcard match is found
-    RBTreeNodeChain<Domain> node_path;  // placeholder for findNode()
-    for (; !rdata_iterator->isLast(); rdata_iterator->next()) {
-        // For each domain name that requires additional section processing
-        // in each RDATA, search the tree for the name and remember it if
-        // found.  If the name is under a zone cut (for a delegation to a
-        // child zone), mark the node as "GLUE", so we can selectively
-        // include/exclude them when we use it.
-
-        const Name& name = getAdditionalName(rrset->getType(),
-                                             rdata_iterator->getCurrent());
-        // if the name is not in or below this zone, skip it
-        const NameComparisonResult::NameRelation reln =
-            name.compare(zone_data->origin_data_->getName()).getRelation();
-        if (reln != NameComparisonResult::SUBDOMAIN &&
-            reln != NameComparisonResult::EQUAL) {
-            continue;
-        }
-        node_path.clear();
-        const ZoneData::FindMutableNodeResult result =
-            zone_data->findNode<ZoneData::FindMutableNodeResult>(
-                name, node_path, ZoneFinder::FIND_GLUE_OK);
-        if (result.code != ZoneFinder::SUCCESS) {
-            // We are not interested in anything but a successful match.
-            continue;
-        }
-        DomainNode* node = result.node;
-        assert(node != NULL);
-        if ((result.flags & ZoneData::FindNodeResult::FIND_ZONECUT) != 0 ||
-            (node->getFlag(DomainNode::FLAG_CALLBACK) &&
-             node->getData()->find(RRType::NS()) != node->getData()->end())) {
-            // The node is under or at a zone cut; mark it as a glue.
-            node->setFlag(domain_flag::GLUE);
-        }
-
-        // A rare case: the additional name may have to be expanded with a
-        // wildcard.  We'll store the name in a separate auxiliary tree,
-        // copying all RRsets of the original wildcard node with expanding
-        // the owner name.  This is costly in terms of memory, but this case
-        // should be pretty rare.  On the other hand we won't have to worry
-        // about wildcard expansion in getAdditional, which is quite
-        // performance sensitive.
-        DomainNode* wildnode = NULL;
-        if ((result.flags & ZoneData::FindNodeResult::FIND_WILDCARD) != 0) {
-            // Wildcard and glue shouldn't coexist.  Make it sure here.
-            assert(!node->getFlag(domain_flag::GLUE));
-
-            if (zone_data->getAuxWildDomains().insert(
-                    zone_data->local_mem_sgmt_, name, &wildnode)
-                == DomainTree::SUCCESS) {
-                // If we first insert the node, copy the RRsets.  If the
-                // original node was empty, we add empty data so
-                // addWildAdditional() can get an exactmatch for this name.
-                DomainPtr dst_domain(new Domain);
-                if (!node->isEmpty()) {
-                    for_each(node->getData()->begin(), node->getData()->end(),
-                             boost::bind(convertAndInsert, _1, dst_domain,
-                                         &name));
-                }
-                wildnode->setData(dst_domain);
-                // Mark the node as "wildcard expanded" so it can be
-                // distinguished at lookup time.
-                wildnode->setFlag(domain_flag::WILD_EXPANDED);
-            }
-            match_wild = true;
-            node = wildnode;
-        }
-
-        // If this name wasn't subject to wildcard substitution, we can add
-        // the additional information to the RRset now; otherwise I'll defer
-        // it until the entire auxiliary tree is built (pointers may be
-        // invalidated as we build it).
-        if (wildnode == NULL) {
-            // Note that node may be empty.  We should keep it in the list
-            // in case we dynamically update the tree and it becomes non empty
-            // (which is not supported yet)
-            rrset->addAdditionalNode(AdditionalNodeInfo(node));
-        }
-    }
-
-    if (match_wild) {
-        wild_rrsets->push_back(rrset);
-    }
-}
-
-void
-addWildAdditional(RBNodeRRset* rrset, ZoneData* zone_data) {
-    // Similar to addAdditional(), but due to the first stage we know that
-    // the rrset should contain a name stored in the auxiliary trees, and
-    // that it should be found as an exact match.  The RRset may have other
-    // names that didn't require wildcard expansion, but we can simply ignore
-    // them in this context.  (Note that if we find an exact match in the
-    // auxiliary tree, it shouldn't be in the original zone; otherwise it
-    // shouldn't have resulted in wildcard in the first place).
-
-    RdataIteratorPtr rdata_iterator = rrset->getRdataIterator();
-    for (; !rdata_iterator->isLast(); rdata_iterator->next()) {
-        const Name& name = getAdditionalName(rrset->getType(),
-                                             rdata_iterator->getCurrent());
-        DomainNode* wildnode = NULL;
-        if (zone_data->getAuxWildDomains().find(name, &wildnode) ==
-            DomainTree::EXACTMATCH) {
-            rrset->addAdditionalNode(AdditionalNodeInfo(wildnode));
-        }
-    }
-}
-}
-
-void
-InMemoryZoneFinder::InMemoryZoneFinderImpl::load(
-    const string& filename,
-    boost::function<void(LoadCallback)> rrset_installer)
-{
-    vector<RBNodeRRset*> need_additionals;
-    scoped_ptr<ZoneData> tmp(new ZoneData(origin_));
-
-    rrset_installer(boost::bind(&InMemoryZoneFinderImpl::addFromLoad, this,
-                                _1, tmp.get(), &need_additionals));
-
-    vector<RBNodeRRset*> wild_additionals;
-    for_each(need_additionals.begin(), need_additionals.end(),
-             boost::bind(addAdditional, _1, tmp.get(), &wild_additionals));
-    for_each(wild_additionals.begin(), wild_additionals.end(),
-             boost::bind(addWildAdditional, _1, tmp.get()));
-
-    // If the zone is NSEC3-signed, check if it has NSEC3PARAM
-    if (tmp->nsec3_data_) {
-        // Note: origin_data_ is set on creation of ZoneData, and the load
-        // process only adds new nodes (and their data), so this assertion
-        // should hold.
-        assert(tmp->origin_data_ != NULL && !tmp->origin_data_->isEmpty());
-        if (tmp->origin_data_->getData()->find(RRType::NSEC3PARAM()) ==
-            tmp->origin_data_->getData()->end()) {
-            LOG_WARN(logger, DATASRC_MEM_NO_NSEC3PARAM).
-                arg(origin_).arg(zone_class_);
-        }
-    }
-
-    // If it went well, put it inside
-    file_name_ = filename;
-    tmp.swap(zone_data_);
-    // And let the old data die with tmp
-}
-
-namespace {
-// A wrapper for dns::masterLoad used by load() below.  Essentially it
-// converts the two callback types.  Note the mostly redundant wrapper of
-// boost::bind.  It converts function<void(ConstRRsetPtr)> to
-// function<void(RRsetPtr)> (masterLoad() expects the latter).  SunStudio
-// doesn't seem to do this conversion if we just pass 'callback'.
-void
-masterLoadWrapper(const char* const filename, const Name& origin,
-                  const RRClass& zone_class, LoadCallback callback)
-{
-    masterLoad(filename, origin, zone_class, boost::bind(callback, _1));
-}
-
-// The installer called from Impl::load() for the iterator version of load().
-void
-generateRRsetFromIterator(ZoneIterator* iterator, LoadCallback callback) {
-    ConstRRsetPtr rrset;
-    vector<ConstRRsetPtr> rrsigs; // placeholder for RRSIGs until "commitable".
-
-    // The current internal implementation assumes an RRSIG is always added
-    // after the RRset they cover.  So we store any RRSIGs in 'rrsigs' until
-    // it's safe to add them; based on our assumption if the owner name
-    // changes, all covered RRsets of the previous name should have been
-    // installed and any pending RRSIGs can be added at that point.  RRSIGs
-    // of the last name from the iterator must be added separately.
-    while ((rrset = iterator->getNextRRset()) != NULL) {
-        if (!rrsigs.empty() && rrset->getName() != rrsigs[0]->getName()) {
-            BOOST_FOREACH(ConstRRsetPtr sig_rrset, rrsigs) {
-                callback(sig_rrset);
-            }
-            rrsigs.clear();
-        }
-        if (rrset->getType() == RRType::RRSIG()) {
-            rrsigs.push_back(rrset);
-        } else {
-            callback(rrset);
-        }
-    }
-
-    BOOST_FOREACH(ConstRRsetPtr sig_rrset, rrsigs) {
-        callback(sig_rrset);
-    }
-}
-}
-
-void
-InMemoryZoneFinder::load(const std::string& filename) {
-    LOG_DEBUG(logger, DBG_TRACE_BASIC, DATASRC_MEM_LOAD).arg(getOrigin()).
-        arg(filename);
-
-    impl_->load(filename,
-                boost::bind(masterLoadWrapper, filename.c_str(), getOrigin(),
-                            getClass(), _1));
-}
-
-void
-InMemoryZoneFinder::load(ZoneIterator& iterator) {
-    impl_->load(string(),
-                boost::bind(generateRRsetFromIterator, &iterator, _1));
-}
-
-void
-InMemoryZoneFinder::swap(InMemoryZoneFinder& zone_finder) {
-    LOG_DEBUG(logger, DBG_TRACE_BASIC, DATASRC_MEM_SWAP).arg(getOrigin()).
-        arg(zone_finder.getOrigin());
-    std::swap(impl_, zone_finder.impl_);
-}
-
-const string
-InMemoryZoneFinder::getFileName() const {
-    return (impl_->file_name_);
-}
-
-/// Implementation details for \c InMemoryClient hidden from the public
-/// interface.
-///
-/// For now, \c InMemoryClient only contains a \c ZoneTable object, which
-/// consists of (pointers to) \c InMemoryZoneFinder objects, we may add more
-/// member variables later for new features.
-class InMemoryClient::InMemoryClientImpl {
-public:
-    InMemoryClientImpl() : zone_count(0),
-                           zone_table(ZoneTable::create(local_mem_sgmt))
-    {}
-    ~InMemoryClientImpl() {
-        ZoneTable::destroy(local_mem_sgmt, zone_table);
-
-        // see above for the assert().
-        assert(local_mem_sgmt.allMemoryDeallocated());
-    }
-
-    // Memory segment to allocate/deallocate memory for the zone table.
-    // (This will eventually have to be abstract; for now we hardcode the
-    // specific derived segment class).
-    util::MemorySegmentLocal local_mem_sgmt;
-    unsigned int zone_count;
-    ZoneTable* zone_table;
-};
-
-InMemoryClient::InMemoryClient() : impl_(new InMemoryClientImpl)
-{}
-
-InMemoryClient::~InMemoryClient() {
-    delete impl_;
-}
-
-unsigned int
-InMemoryClient::getZoneCount() const {
-    return (impl_->zone_count);
-}
-
-result::Result
-InMemoryClient::addZone(ZoneFinderPtr zone_finder) {
-    if (!zone_finder) {
-        isc_throw(InvalidParameter,
-                  "Null pointer is passed to InMemoryClient::addZone()");
-    }
-
-    LOG_DEBUG(logger, DBG_TRACE_BASIC, DATASRC_MEM_ADD_ZONE).
-        arg(zone_finder->getOrigin()).arg(zone_finder->getClass().toText());
-
-    const result::Result result =
-        impl_->zone_table->addZone(impl_->local_mem_sgmt, zone_finder);
-    if (result == result::SUCCESS) {
-        ++impl_->zone_count;
-    }
-    return (result);
-}
-
-InMemoryClient::FindResult
-InMemoryClient::findZone(const isc::dns::Name& name) const {
-    LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_MEM_FIND_ZONE).arg(name);
-    ZoneTable::FindResult result(impl_->zone_table->findZone(name));
-    return (FindResult(result.code, result.zone));
-}
-
-namespace {
-
-class MemoryIterator : public ZoneIterator {
-private:
-    RBTreeNodeChain<Domain> chain_;
-    Domain::const_iterator dom_iterator_;
-    const DomainTree& tree_;
-    const DomainNode* node_;
-    // Only used when separate_rrs_ is true
-    RdataIteratorPtr rdata_iterator_;
-    bool separate_rrs_;
-    bool ready_;
-public:
-    MemoryIterator(const DomainTree& tree, const Name& origin, bool separate_rrs) :
-        tree_(tree),
-        separate_rrs_(separate_rrs),
-        ready_(true)
-    {
-        // Find the first node (origin) and preserve the node chain for future
-        // searches
-        DomainTree::Result result(tree_.find(origin, &node_, chain_));
-        // It can't happen that the origin is not in there
-        if (result != DomainTree::EXACTMATCH) {
-            isc_throw(Unexpected,
-                      "In-memory zone corrupted, missing origin node");
-        }
-        // Initialize the iterator if there's somewhere to point to
-        if (node_ != NULL && node_->getData() != DomainPtr()) {
-            dom_iterator_ = node_->getData()->begin();
-            if (separate_rrs_ && dom_iterator_ != node_->getData()->end()) {
-                rdata_iterator_ = dom_iterator_->second->getRdataIterator();
-            }
-        }
-    }
-
-    virtual ConstRRsetPtr getNextRRset() {
-        if (!ready_) {
-            isc_throw(Unexpected, "Iterating past the zone end");
-        }
-        /*
-         * This cycle finds the first nonempty node with yet unused RRset.
-         * If it is NULL, we run out of nodes. If it is empty, it doesn't
-         * contain any RRsets. If we are at the end, just get to next one.
-         */
-        while (node_ != NULL && (node_->getData() == DomainPtr() ||
-                                 dom_iterator_ == node_->getData()->end())) {
-            node_ = tree_.nextNode(chain_);
-            // If there's a node, initialize the iterator and check next time
-            // if the map is empty or not
-            if (node_ != NULL && node_->getData() != NULL) {
-                dom_iterator_ = node_->getData()->begin();
-                // New RRset, so get a new rdata iterator
-                if (separate_rrs_) {
-                    rdata_iterator_ = dom_iterator_->second->getRdataIterator();
-                }
-            }
-        }
-        if (node_ == NULL) {
-            // That's all, folks
-            ready_ = false;
-            return (ConstRRsetPtr());
-        }
-
-        if (separate_rrs_) {
-            // For separate rrs, reconstruct a new RRset with just the
-            // 'current' rdata
-            RRsetPtr result(new RRset(dom_iterator_->second->getName(),
-                                      dom_iterator_->second->getClass(),
-                                      dom_iterator_->second->getType(),
-                                      dom_iterator_->second->getTTL()));
-            result->addRdata(rdata_iterator_->getCurrent());
-            rdata_iterator_->next();
-            if (rdata_iterator_->isLast()) {
-                // all used up, next.
-                ++dom_iterator_;
-                // New RRset, so get a new rdata iterator, but only if this
-                // was not the final RRset in the chain
-                if (dom_iterator_ != node_->getData()->end()) {
-                    rdata_iterator_ = dom_iterator_->second->getRdataIterator();
-                }
-            }
-            return (result);
-        } else {
-            // The iterator points to the next yet unused RRset now
-            ConstRRsetPtr result(dom_iterator_->second);
-
-            // This one is used, move it to the next time for next call
-            ++dom_iterator_;
-
-            return (result);
-        }
-    }
-
-    virtual ConstRRsetPtr getSOA() const {
-        isc_throw(NotImplemented, "Not imelemented");
-    }
-};
-
-} // End of anonymous namespace
-
-ZoneIteratorPtr
-InMemoryClient::getIterator(const Name& name, bool separate_rrs) const {
-    ZoneTable::FindResult result(impl_->zone_table->findZone(name));
-    if (result.code != result::SUCCESS) {
-        isc_throw(DataSourceError, "No such zone: " + name.toText());
-    }
-
-    const InMemoryZoneFinder*
-        zone(dynamic_cast<const InMemoryZoneFinder*>(result.zone.get()));
-    if (zone == NULL) {
-        /*
-         * TODO: This can happen only during some of the tests and only as
-         * a temporary solution. This should be fixed by #1159 and then
-         * this cast and check shouldn't be necessary. We don't have
-         * test for handling a "can not happen" condition.
-         */
-        isc_throw(Unexpected, "The zone at " + name.toText() +
-                  " is not InMemoryZoneFinder");
-    }
-    return (ZoneIteratorPtr(new MemoryIterator(
-                                zone->impl_->zone_data_->domains_, name,
-                                separate_rrs)));
-}
-
-ZoneUpdaterPtr
-InMemoryClient::getUpdater(const isc::dns::Name&, bool, bool) const {
-    isc_throw(isc::NotImplemented, "Update attempt on in memory data source");
-}
-
-pair<ZoneJournalReader::Result, ZoneJournalReaderPtr>
-InMemoryClient::getJournalReader(const isc::dns::Name&, uint32_t,
-                                 uint32_t) const
-{
-    isc_throw(isc::NotImplemented, "Journaling isn't supported for "
-              "in memory data source");
-}
-
-} // end of namespace datasrc
-} // end of namespace isc
diff --git a/src/lib/datasrc/memory_datasrc.h b/src/lib/datasrc/memory_datasrc.h
deleted file mode 100644
index 4e277e0..0000000
--- a/src/lib/datasrc/memory_datasrc.h
+++ /dev/null
@@ -1,366 +0,0 @@
-// Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#ifndef MEMORY_DATA_SOURCE_H
-#define MEMORY_DATA_SOURCE_H 1
-
-#include <string>
-
-#include <boost/noncopyable.hpp>
-
-#include <datasrc/zonetable.h>
-#include <datasrc/client.h>
-
-#include <cc/data.h>
-
-namespace isc {
-namespace dns {
-class Name;
-class RRsetList;
-};
-
-namespace datasrc {
-
-/// A derived zone finder class intended to be used with the memory data source.
-///
-/// Conceptually this "finder" maintains a local in-memory copy of all RRs
-/// of a single zone from some kind of source (right now it's a textual
-/// master file, but it could also be another data source with a database
-/// backend).  This is why the class has methods like \c load() or \c add().
-///
-/// This class is non copyable.
-class InMemoryZoneFinder : boost::noncopyable, public ZoneFinder {
-    ///
-    /// \name Constructors and Destructor.
-public:
-    /// \brief Constructor from zone parameters.
-    ///
-    /// This constructor internally involves resource allocation, and if
-    /// it fails, a corresponding standard exception will be thrown.
-    /// It never throws an exception otherwise.
-    ///
-    /// \param rrclass The RR class of the zone.
-    /// \param origin The origin name of the zone.
-    InMemoryZoneFinder(const isc::dns::RRClass& rrclass,
-                       const isc::dns::Name& origin);
-
-    /// The destructor.
-    virtual ~InMemoryZoneFinder();
-    //@}
-
-    /// \brief Returns the origin of the zone.
-    virtual isc::dns::Name getOrigin() const;
-
-    /// \brief Returns the class of the zone.
-    virtual isc::dns::RRClass getClass() const;
-
-    /// \brief Find an RRset in the datasource
-    virtual ZoneFinderContextPtr find(const isc::dns::Name& name,
-                                      const isc::dns::RRType& type,
-                                      const FindOptions options =
-                                      FIND_DEFAULT);
-
-    /// \brief Version of find that returns all types at once
-    ///
-    /// It acts the same as find, just that when the correct node is found,
-    /// all the RRsets are filled into the target parameter instead of being
-    /// returned by the result.
-    virtual ZoneFinderContextPtr findAll(
-        const isc::dns::Name& name,
-        std::vector<isc::dns::ConstRRsetPtr>& target,
-        const FindOptions options = FIND_DEFAULT);
-
-    /// Look for NSEC3 for proving (non)existence of given name.
-    ///
-    /// See documentation in \c Zone.
-    virtual FindNSEC3Result
-    findNSEC3(const isc::dns::Name& name, bool recursive);
-
-    /// \brief Inserts an rrset into the zone.
-    ///
-    /// It puts another RRset into the zone.
-    ///
-    /// In the current implementation, this method doesn't allow an existing
-    /// RRset to be updated or overridden.  So the caller must make sure that
-    /// all RRs of the same type and name must be given in the form of a
-    /// single RRset.  The current implementation will also require that
-    /// when an RRSIG is added the RRset to be covered has already been
-    /// added.  These restrictions are probably too strict when this data
-    /// source accepts various forms of input, so they should be revisited
-    /// later.
-    ///
-    /// Except for NullRRset and OutOfZone, this method does not guarantee
-    /// strong exception safety (it is currently not needed, if it is needed
-    /// in future, it should be implemented).
-    ///
-    /// \throw NullRRset \c rrset is a NULL pointer.
-    /// \throw OutOfZone The owner name of \c rrset is outside of the
-    /// origin of the zone.
-    /// \throw AddError Other general errors.
-    /// \throw Others This method might throw standard allocation exceptions.
-    ///
-    /// \param rrset The set to add.
-    /// \return SUCCESS or EXIST (if an rrset for given name and type already
-    ///    exists).
-    result::Result add(const isc::dns::ConstRRsetPtr& rrset);
-
-    /// \brief RRset is NULL exception.
-    ///
-    /// This is thrown if the provided RRset parameter is NULL.
-    struct NullRRset : public InvalidParameter {
-        NullRRset(const char* file, size_t line, const char* what) :
-            InvalidParameter(file, line, what)
-        { }
-    };
-
-    /// \brief General failure exception for \c add().
-    ///
-    /// This is thrown against general error cases in adding an RRset
-    /// to the zone.
-    ///
-    /// Note: this exception would cover cases for \c OutOfZone or
-    /// \c NullRRset.  We'll need to clarify and unify the granularity
-    /// of exceptions eventually.  For now, exceptions are added as
-    /// developers see the need for it.
-    struct AddError : public InvalidParameter {
-        AddError(const char* file, size_t line, const char* what) :
-            InvalidParameter(file, line, what)
-        { }
-    };
-
-    /// Return the master file name of the zone
-    ///
-    /// This method returns the name of the zone's master file to be loaded.
-    /// The returned string will be an empty unless the zone finder has
-    /// successfully loaded a zone.
-    ///
-    /// This method should normally not throw an exception.  But the creation
-    /// of the return string may involve a resource allocation, and if it
-    /// fails, the corresponding standard exception will be thrown.
-    ///
-    /// \return The name of the zone file loaded in the zone finder, or an empty
-    /// string if the zone hasn't loaded any file.
-    const std::string getFileName() const;
-
-    /// \brief Load zone from masterfile.
-    ///
-    /// This loads data from masterfile specified by filename. It replaces
-    /// current content. The masterfile parsing ability is kind of limited,
-    /// see isc::dns::masterLoad.
-    ///
-    /// This throws isc::dns::MasterLoadError if there is problem with loading
-    /// (missing file, malformed, it contains different zone, etc - see
-    /// isc::dns::masterLoad for details).
-    ///
-    /// In case of internal problems, OutOfZone, NullRRset or AssertError could
-    /// be thrown, but they should not be expected. Exceptions caused by
-    /// allocation may be thrown as well.
-    ///
-    /// If anything is thrown, the previous content is preserved (so it can
-    /// be used to update the data, but if user makes a typo, the old one
-    /// is kept).
-    ///
-    /// \param filename The master file to load.
-    ///
-    /// \todo We may need to split it to some kind of build and commit/abort.
-    ///     This will probably be needed when a better implementation of
-    ///     configuration reloading is written.
-    void load(const std::string& filename);
-
-    /// \brief Load zone from another data source.
-    ///
-    /// This is similar to the other version, but zone's RRsets are provided
-    /// by an iterator of another data source.  On successful load, the
-    /// internal filename will be cleared.
-    ///
-    /// This implementation assumes the iterator produces combined RRsets,
-    /// that is, there should exactly one RRset for the same owner name and
-    /// RR type.  This means the caller is expected to create the iterator
-    /// with \c separate_rrs being \c false.  This implementation also assumes
-    /// RRsets of different names are not mixed; so if the iterator produces
-    /// an RRset of a different name than that of the previous RRset, that
-    /// previous name must never appear in the subsequent sequence of RRsets.
-    /// Note that the iterator API does not ensure this.  If the underlying
-    /// implementation does not follow it, load() will fail.  Note, however,
-    /// that this whole interface is tentative.  in-memory zone loading will
-    /// have to be revisited fundamentally, and at that point this restriction
-    /// probably won't matter.
-    void load(ZoneIterator& iterator);
-
-    /// Exchanges the content of \c this zone finder with that of the given
-    /// \c zone_finder.
-    ///
-    /// This method never throws an exception.
-    ///
-    /// \param zone_finder Another \c InMemoryZone object which is to
-    /// be swapped with \c this zone finder.
-    void swap(InMemoryZoneFinder& zone_finder);
-
-private:
-    /// \name Hidden private data
-    //@{
-    struct InMemoryZoneFinderImpl;
-    InMemoryZoneFinderImpl* impl_;
-    //@}
-    // The friend here is for InMemoryClient::getIterator. The iterator
-    // needs to access the data inside the zone, so the InMemoryClient
-    // extracts the pointer to data and puts it into the iterator.
-    // The access is read only.
-    friend class InMemoryClient;
-
-    /// \brief In-memory version of finder context.
-    ///
-    /// The implementation (and any specialized interface) is completely local
-    /// to the InMemoryZoneFinder class, so it's defined as private
-    class Context;
-};
-
-/// \brief A data source client that holds all necessary data in memory.
-///
-/// The \c InMemoryClient class provides an access to a conceptual data
-/// source that maintains all necessary data in a memory image, thereby
-/// allowing much faster lookups.  The in memory data is a copy of some
-/// real physical source - in the current implementation a list of zones
-/// are populated as a result of \c addZone() calls; zone data is given
-/// in a standard master file (but there's a plan to use database backends
-/// as a source of the in memory data).
-///
-/// Although every data source client is assumed to be of the same RR class,
-/// the \c InMemoryClient class does not enforce the assumption through
-/// its interface.
-/// For example, the \c addZone() method does not check if the new zone is of
-/// the same RR class as that of the others already in memory.
-/// It is caller's responsibility to ensure this assumption.
-///
-/// <b>Notes to developer:</b>
-///
-/// The addZone() method takes a (Boost) shared pointer because it would be
-/// inconvenient to require the caller to maintain the ownership of zones,
-/// while it wouldn't be safe to delete unnecessary zones inside the dedicated
-/// backend.
-///
-/// The findZone() method takes a domain name and returns the best matching
-/// \c InMemoryZoneFinder in the form of (Boost) shared pointer, so that it can
-/// provide the general interface for all data sources.
-class InMemoryClient : public DataSourceClient {
-public:
-    ///
-    /// \name Constructors and Destructor.
-    ///
-    //@{
-
-    /// Default constructor.
-    ///
-    /// This constructor internally involves resource allocation, and if
-    /// it fails, a corresponding standard exception will be thrown.
-    /// It never throws an exception otherwise.
-    InMemoryClient();
-
-    /// The destructor.
-    ~InMemoryClient();
-    //@}
-
-    /// Return the number of zones stored in the client.
-    ///
-    /// This method never throws an exception.
-    ///
-    /// \return The number of zones stored in the client.
-    virtual unsigned int getZoneCount() const;
-
-    /// Add a zone (in the form of \c ZoneFinder) to the \c InMemoryClient.
-    ///
-    /// \c zone_finder must not be associated with a NULL pointer; otherwise
-    /// an exception of class \c InvalidParameter will be thrown.
-    /// If internal resource allocation fails, a corresponding standard
-    /// exception will be thrown.
-    /// This method never throws an exception otherwise.
-    ///
-    /// \param zone_finder A \c ZoneFinder object to be added.
-    /// \return \c result::SUCCESS If the zone_finder is successfully
-    /// added to the client.
-    /// \return \c result::EXIST The memory data source already
-    /// stores a zone that has the same origin.
-    result::Result addZone(ZoneFinderPtr zone_finder);
-
-    /// Returns a \c ZoneFinder for a zone_finder that best matches the given
-    /// name.
-    ///
-    /// This derived version of the method never throws an exception.
-    /// For other details see \c DataSourceClient::findZone().
-    virtual FindResult findZone(const isc::dns::Name& name) const;
-
-    /// \brief Implementation of the getIterator method
-    virtual ZoneIteratorPtr getIterator(const isc::dns::Name& name,
-                                        bool separate_rrs = false) const;
-
-    /// In-memory data source is read-only, so this derived method will
-    /// result in a NotImplemented exception.
-    ///
-    /// \note We plan to use a database-based data source as a backend
-    /// persistent storage for an in-memory data source.  When it's
-    /// implemented we may also want to allow the user of the in-memory client
-    /// to update via its updater (this may or may not be a good idea and
-    /// is subject to further discussions).
-    virtual ZoneUpdaterPtr getUpdater(const isc::dns::Name& name,
-                                      bool replace, bool journaling = false)
-        const;
-
-    virtual std::pair<ZoneJournalReader::Result, ZoneJournalReaderPtr>
-    getJournalReader(const isc::dns::Name& zone, uint32_t begin_serial,
-                     uint32_t end_serial) const;
-
-private:
-    // TODO: Do we still need the PImpl if nobody should manipulate this class
-    // directly any more (it should be handled through DataSourceClient)?
-    class InMemoryClientImpl;
-    InMemoryClientImpl* impl_;
-};
-
-/// \brief Creates an instance of the Memory datasource client
-///
-/// Currently the configuration passed here must be a MapElement, formed as
-/// follows:
-/// \code
-/// { "type": string ("memory"),
-///   "class": string ("IN"/"CH"/etc),
-///   "zones": list
-/// }
-/// Zones list is a list of maps:
-/// { "origin": string,
-///   "file": string
-/// }
-/// \endcode
-/// (i.e. the configuration that was used prior to the datasource refactor)
-///
-/// This configuration setup is currently under discussion and will change in
-/// the near future.
-///
-/// \param config The configuration for the datasource instance
-/// \param error This string will be set to an error message if an error occurs
-///              during initialization
-/// \return An instance of the memory datasource client, or NULL if there was
-///         an error
-extern "C" DataSourceClient* createInstance(isc::data::ConstElementPtr config,
-                                            std::string& error);
-
-/// \brief Destroy the instance created by createInstance()
-extern "C" void destroyInstance(DataSourceClient* instance);
-
-
-}
-}
-#endif  // MEMORY_DATA_SOURCE_H
-// Local Variables:
-// mode: c++
-// End:
diff --git a/src/lib/datasrc/memory_datasrc_link.cc b/src/lib/datasrc/memory_datasrc_link.cc
deleted file mode 100644
index 857223f..0000000
--- a/src/lib/datasrc/memory_datasrc_link.cc
+++ /dev/null
@@ -1,277 +0,0 @@
-// Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#include <cc/data.h>
-
-#include <dns/rrclass.h>
-
-#include <datasrc/client.h>
-#include <datasrc/factory.h>
-#include <datasrc/memory_datasrc.h>
-
-#include <exceptions/exceptions.h>
-
-#include <boost/foreach.hpp>
-#include <boost/scoped_ptr.hpp>
-
-#include <string>
-
-using namespace isc::dns;
-using namespace isc::data;
-
-namespace isc {
-namespace datasrc {
-
-/// This exception is raised if there is an error in the configuration
-/// that has been passed; missing information, duplicate values, etc.
-class InMemoryConfigError : public isc::Exception {
-public:
-    InMemoryConfigError(const char* file, size_t line, const char* what) :
-        isc::Exception(file, line, what) {}
-};
-
-namespace {
-// convencience function to add an error message to a list of those
-// (TODO: move functions like these to some util lib?)
-void
-addError(ElementPtr errors, const std::string& error) {
-    if (errors != ElementPtr() && errors->getType() == Element::list) {
-        errors->add(Element::create(error));
-    }
-}
-
-/// Check if the given element exists in the map, and if it is a string
-bool
-checkConfigElementString(ConstElementPtr config, const std::string& name,
-                         ElementPtr errors)
-{
-    if (!config->contains(name)) {
-        addError(errors,
-                 "Config for memory backend does not contain a '"
-                 +name+
-                 "' value");
-        return (false);
-    } else if (!config->get(name) ||
-               config->get(name)->getType() != Element::string) {
-        addError(errors, "value of " + name +
-                 " in memory backend config is not a string");
-        return (false);
-    } else {
-        return (true);
-    }
-}
-
-bool
-checkZoneConfig(ConstElementPtr config, ElementPtr errors) {
-    bool result = true;
-    if (!config || config->getType() != Element::map) {
-        addError(errors, "Elements in memory backend's zone list must be maps");
-        result = false;
-    } else {
-        if (!checkConfigElementString(config, "origin", errors)) {
-            result = false;
-        }
-        if (!checkConfigElementString(config, "file", errors)) {
-            result = false;
-        }
-        // we could add some existence/readabilty/parsability checks here
-        // if we want
-    }
-    return result;
-}
-
-bool
-checkConfig(ConstElementPtr config, ElementPtr errors) {
-    /* Specific configuration is under discussion, right now this accepts
-     * the 'old' configuration, see [TODO]
-     * So for memory datasource, we get a structure like this:
-     * { "type": string ("memory"),
-     *   "class": string ("IN"/"CH"/etc),
-     *   "zones": list
-     * }
-     * Zones list is a list of maps:
-     * { "origin": string,
-     *     "file": string
-     * }
-     *
-     * At this moment we cannot be completely sure of the contents of the
-     * structure, so we have to do some more extensive tests than should
-     * strictly be necessary (e.g. existence and type of elements)
-     */
-    bool result = true;
-
-    if (!config || config->getType() != Element::map) {
-        addError(errors, "Base config for memory backend must be a map");
-        result = false;
-    } else {
-        if (!checkConfigElementString(config, "type", errors)) {
-            result = false;
-        } else {
-            if (config->get("type")->stringValue() != "memory") {
-                addError(errors,
-                         "Config for memory backend is not of type \"memory\"");
-                result = false;
-            }
-        }
-        if (config->contains("class")) {
-            if (!checkConfigElementString(config, "class", errors)) {
-                result = false;
-            } else {
-                try {
-                    RRClass(config->get("class")->stringValue());
-                } catch (const isc::Exception& rrce) {
-                    addError(errors,
-                             "Error parsing class config for memory backend: " +
-                             std::string(rrce.what()));
-                    result = false;
-                }
-            }
-        }
-        if (!config->contains("zones")) {
-            // Assume empty list of zones
-        } else if (!config->get("zones") ||
-                   config->get("zones")->getType() != Element::list) {
-            addError(errors,
-                     "'zones' element in memory backend config is not a list");
-            result = false;
-        } else {
-            BOOST_FOREACH(ConstElementPtr zone_config,
-                          config->get("zones")->listValue()) {
-                if (!checkZoneConfig(zone_config, errors)) {
-                    result = false;
-                }
-            }
-        }
-    }
-
-    return (result);
-}
-
-// Apply the given config to the just-initialized client
-// client must be freshly allocated, and config_value should have been
-// checked by the caller
-void
-applyConfig(isc::datasrc::InMemoryClient& client,
-            isc::data::ConstElementPtr config_value)
-{
-    // XXX: We have lost the context to get to the default values here,
-    // as a temporary workaround we hardcode the IN class here.
-    isc::dns::RRClass rrclass = RRClass::IN();
-    if (config_value->contains("class")) {
-        rrclass = RRClass(config_value->get("class")->stringValue());
-    }
-    ConstElementPtr zones_config = config_value->get("zones");
-    if (!zones_config) {
-        // XXX: Like the RR class, we cannot retrieve the default value here,
-        // so we assume an empty zone list in this case.
-        return;
-    }
-
-    BOOST_FOREACH(ConstElementPtr zone_config, zones_config->listValue()) {
-        ConstElementPtr origin = zone_config->get("origin");
-        const std::string origin_txt = origin ? origin->stringValue() : "";
-        if (origin_txt.empty()) {
-            isc_throw(InMemoryConfigError, "Missing zone origin");
-        }
-        ConstElementPtr file = zone_config->get("file");
-        const std::string file_txt = file ? file->stringValue() : "";
-        if (file_txt.empty()) {
-            isc_throw(InMemoryConfigError, "Missing zone file for zone: "
-                      << origin_txt);
-        }
-
-        // We support the traditional text type and SQLite3 backend.  For the
-        // latter we create a client for the underlying SQLite3 data source,
-        // and build the in-memory zone using an iterator of the underlying
-        // zone.
-        ConstElementPtr filetype = zone_config->get("filetype");
-        const std::string filetype_txt = filetype ? filetype->stringValue() :
-            "text";
-        boost::scoped_ptr<DataSourceClientContainer> container;
-        if (filetype_txt == "sqlite3") {
-            container.reset(new DataSourceClientContainer(
-                                "sqlite3",
-                                Element::fromJSON("{\"database_file\": \"" +
-                                                  file_txt + "\"}")));
-        } else if (filetype_txt != "text") {
-            isc_throw(InMemoryConfigError, "Invalid filetype for zone "
-                      << origin_txt << ": " << filetype_txt);
-        }
-
-        // Note: we don't want to have such small try-catch blocks for each
-        // specific error.  We may eventually want to introduce some unified
-        // error handling framework as we have more configuration parameters.
-        // See bug #1627 for the relevant discussion.
-        InMemoryZoneFinder* imzf = NULL;
-        try {
-            imzf = new InMemoryZoneFinder(rrclass, Name(origin_txt));
-        } catch (const isc::dns::NameParserException& ex) {
-            isc_throw(InMemoryConfigError, "unable to parse zone's origin: " <<
-                      ex.what());
-        }
-
-        boost::shared_ptr<InMemoryZoneFinder> zone_finder(imzf);
-        const result::Result result = client.addZone(zone_finder);
-        if (result == result::EXIST) {
-            isc_throw(InMemoryConfigError, "zone "<< origin->str()
-                      << " already exists");
-        }
-
-        /*
-         * TODO: Once we have better reloading of configuration (something
-         * else than throwing everything away and loading it again), we will
-         * need the load method to be split into some kind of build and
-         * commit/abort parts.
-         */
-        if (filetype_txt == "text") {
-            zone_finder->load(file_txt);
-        } else {
-            zone_finder->load(*container->getInstance().getIterator(
-                                  Name(origin_txt)));
-        }
-    }
-}
-
-} // end unnamed namespace
-
-DataSourceClient *
-createInstance(isc::data::ConstElementPtr config, std::string& error) {
-    ElementPtr errors(Element::createList());
-    if (!checkConfig(config, errors)) {
-        error = "Configuration error: " + errors->str();
-        return (NULL);
-    }
-    try {
-        std::auto_ptr<InMemoryClient> client(new isc::datasrc::InMemoryClient());
-        applyConfig(*client, config);
-        return (client.release());
-    } catch (const isc::Exception& isce) {
-        error = isce.what();
-        return (NULL);
-    } catch (const std::exception& exc) {
-        error = std::string("Error creating memory datasource: ") + exc.what();
-        return (NULL);
-    } catch (...) {
-        error = std::string("Error creating memory datasource, "
-                            "unknown exception");
-        return (NULL);
-    }
-}
-
-void destroyInstance(DataSourceClient* instance) {
-    delete instance;
-}
-
-} // end of namespace datasrc
-} // end of namespace isc
diff --git a/src/lib/datasrc/rbnode_rrset.h b/src/lib/datasrc/rbnode_rrset.h
deleted file mode 100644
index cbb1b71..0000000
--- a/src/lib/datasrc/rbnode_rrset.h
+++ /dev/null
@@ -1,230 +0,0 @@
-// Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#ifndef RBNODE_RRSET_H
-#define RBNODE_RRSET_H
-
-#include <dns/messagerenderer.h>
-#include <dns/name.h>
-#include <dns/rrclass.h>
-#include <dns/rrset.h>
-#include <dns/rrttl.h>
-#include <dns/rrtype.h>
-#include <util/buffer.h>
-
-#include <string>
-#include <vector>
-
-namespace isc {
-namespace datasrc {
-namespace internal {
-
-/// \brief The actual content of \c RBNodeRRset
-///
-///  This is defined in the namespace-scope (not hidden in the main class)
-/// so that the In-memory data source implementation can refer to it.
-struct RBNodeRRsetImpl;
-
-// Forward declaration of an opaque data type defined and used within the
-// implementation.  This is public only because it needs to be used within
-// the in-memory data source implementation, but conceptually this is a
-// private type for the in-memory data source implementation.
-// Note that the definition of the structure is still hidden within the
-// implementation, so, basically, a normal application should never be able
-// to use it directly even if it peeks into the "internal" namespace.
-struct AdditionalNodeInfo;
-
-/// \brief Special RRset for optimizing memory datasource requirement
-///
-/// To speed up the performance of the in-memory data source, at load time
-/// associate relevant "additional section" data with each RRset in the
-/// data source.
-///
-/// This class, derived from AbstractRRset, holds a "const" pointer to the
-/// underlying RRset object.  All calls to methods on the class are passed to
-/// the underlying object.  However, there are some restrictions:
-///
-/// - Calls to methods that change attributes of the underlying RRset (such as
-///   TTL or Name) cause an exception to be thrown.  The in-memory data source
-///   does not allow modification of these attributes.  In theory, it is a bad
-///   practice in that it doesn't preserve the assumed behavior of the base
-///   class.  In practice, however, it should be acceptable because this
-///   class is effectively hidden from applications and will only be given
-///   to them as a const pointer to the base class via find() variants.
-///   So the application cannot call non const methods anyway unless it
-///   intentionally breaks the constness.
-///
-/// - Calls that add the pointer to the associated RRSIG to the RRset are
-///   allowed (even though the pointer is to a "const" RRset).  The reason here
-///   is that RRSIGs are added to the in-memory data source after the
-///   RBNodeRRset objects have been created.  Thus there has to be the
-///   capability of modifying this information.
-///
-/// The class is not derived from RRset itself to simplify coding: part of the
-/// loading of the memory data source is handled in the BIND 10 "libdns++"
-/// code, which creates RRsets and passes them to the data source code.  This
-/// does not have to be altered if encapsulation, rather than inheritance, is
-/// used.
-///
-/// \note This class is exposed in this separate header file so that test code
-/// can refer to its definition, and only for that purpose.  Otherwise this is
-/// essentially a private class of the in-memory data source implementation,
-/// and an application shouldn't directly refer to this class.
-///
-// Note: non-Doxygen-documented methods are documented in the base class.
-
-class RBNodeRRset : public isc::dns::AbstractRRset {
-
-private:
-    // Note: The copy constructor and the assignment operator are intentionally
-    // defined as private as we would normally not duplicate a RBNodeRRset.
-    // (We use the "private" method instead of inheriting from
-    // boost::noncopyable so as to avoid multiple inheritance.)
-    RBNodeRRset(const RBNodeRRset& source);
-    RBNodeRRset& operator=(const RBNodeRRset& source);
-
-public:
-    /// \brief Usual Constructor
-    ///
-    /// Creates an RBNodeRRset from the pointer to the RRset passed to it.
-    ///
-    /// \param rrset Pointer to underlying RRset encapsulated by this object.
-    explicit RBNodeRRset(const isc::dns::ConstRRsetPtr& rrset);
-
-    /// \brief Destructor
-    virtual ~RBNodeRRset();
-
-    // Getter and Setter Methods
-    //
-    // The getter methods pass the call through to the underlying RRset.  The
-    // setter methods thrown an exception - this specialisation of the RRset
-    // object does not expect the underlying RRset to be modified.
-
-    virtual unsigned int getRdataCount() const;
-
-    virtual const isc::dns::Name& getName() const;
-
-    virtual const isc::dns::RRClass& getClass() const;
-
-    virtual const isc::dns::RRType& getType() const;
-
-    virtual const isc::dns::RRTTL& getTTL() const;
-
-    virtual void setName(const isc::dns::Name&);
-
-    virtual void setTTL(const isc::dns::RRTTL&);
-
-    virtual std::string toText() const;
-
-    virtual bool isSameKind(const AbstractRRset& other) const {
-        // This code is an optimisation for comparing
-        // RBNodeRRsets. However, in doing this optimisation,
-        // semantically the code is not "is same kind" but is instead
-        // "is identical object" in the case where RBNodeRRsets are compared.
-
-        const RBNodeRRset* rb = dynamic_cast<const RBNodeRRset*>(&other);
-        if (rb != NULL) {
-            return (this == rb);
-        } else {
-            return (AbstractRRset::isSameKind(other));
-        }
-    }
-
-    virtual unsigned int toWire(
-        isc::dns::AbstractMessageRenderer& renderer) const;
-
-    virtual unsigned int toWire(isc::util::OutputBuffer& buffer) const;
-
-    virtual void addRdata(isc::dns::rdata::ConstRdataPtr);
-
-    virtual void addRdata(const isc::dns::rdata::Rdata&);
-
-    virtual isc::dns::RdataIteratorPtr getRdataIterator() const;
-
-    virtual isc::dns::RRsetPtr getRRsig() const;
-
-    virtual unsigned int getRRsigDataCount() const;
-
-    // With all the RRsig methods, we have the problem that we store the
-    // underlying RRset using a ConstRRsetPtr - a pointer to a "const" RRset -
-    // but we need to modify it by adding or removing an RRSIG.  We overcome
-    // this by temporarily violating the "const" nature of the RRset to add the
-    // data.
-
-    virtual void addRRsig(const isc::dns::rdata::ConstRdataPtr& rdata);
-
-    virtual void addRRsig(const isc::dns::rdata::RdataPtr& rdata);
-
-    virtual void addRRsig(const AbstractRRset& sigs);
-
-    virtual void addRRsig(const isc::dns::ConstRRsetPtr& sigs);
-
-    virtual void addRRsig(const isc::dns::RRsetPtr& sigs);
-
-    virtual void removeRRsig();
-
-    /// \brief Associate a link to an RB node of the additional record.
-    ///
-    /// This method adds a given opaque object that holds a link to an RB node
-    /// of the underlying in-memory data source that is corresponding to an
-    /// RDATA of this RRset.
-    ///
-    /// This method is exposed as public so it can be used within the in-memory
-    /// data source implementation, and only for that purpose.
-    ///
-    /// \param additional An opaque \c AdditionalNodeInfo object to be
-    /// associated with this RRset.
-    void addAdditionalNode(const AdditionalNodeInfo& additional);
-
-    /// \brief Return a pointer to the list (vector) of additional RB nodes.
-    ///
-    /// This method returns a pointer to a vector storing the opaque
-    /// \c AdditionalNodeInfo object that may be possibly set in this RRset.
-    /// Not all RRsets are associated with additional nodes; if no
-    /// such node is stored, this method returns NULL.
-    ///
-    /// Like \c addAdditionalNode(), this method is exposed as public only for
-    /// the in-memory data source implementation.
-    ///
-    /// \return A pointer to the associated vector of \c AdditionalNodeInfo;
-    /// NULL if no additional nodes are associated to this RRset.
-    const std::vector<AdditionalNodeInfo>* getAdditionalNodes() const;
-
-    /// \brief Copy the list of additional RB nodes to another RRset.
-    ///
-    /// This method copies the internal list (an STL vector in the actual
-    /// implementation) of additional RB nodes for this RRset to another
-    /// \c RBNodeRRset object.  The copy destination is generally expected to
-    /// be newly created and have an empty list, but this method does not
-    /// check the condition.  If the destination already has a non empty list,
-    /// the existing entries will be lost.
-    ///
-    /// \param dst The \c RBNodeRRset object to which the additional
-    /// RB node list is to be copied.
-    void copyAdditionalNodes(RBNodeRRset& dst) const;
-
-    /// \brief Return underlying RRset pointer
-    ///
-    /// ... mainly for testing.
-    isc::dns::ConstRRsetPtr getUnderlyingRRset() const;
-
-private:
-    RBNodeRRsetImpl* impl_;
-};
-
-}   // namespace internal
-}   // namespace datasrc
-}   // namespace isc
-
-#endif  // RBNODE_RRSET_H
diff --git a/src/lib/datasrc/rbtree.h b/src/lib/datasrc/rbtree.h
deleted file mode 100644
index d0efa0a..0000000
--- a/src/lib/datasrc/rbtree.h
+++ /dev/null
@@ -1,1993 +0,0 @@
-// Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#ifndef RBTREE_H
-#define RBTREE_H 1
-
-//! \file datasrc/rbtree.h
-///
-/// \note The purpose of the RBTree is to provide a generic map with
-///     domain names as the key that can be used by various BIND 10 modules or
-///     even by other applications.  However, because of some unresolved design
-///     issue, the design and interface are not fixed, and RBTree isn't ready
-///     to be used as a base data structure by other modules.
-
-#include <exceptions/exceptions.h>
-#include <util/memory_segment.h>
-#include <dns/name.h>
-#include <dns/labelsequence.h>
-
-#include <boost/utility.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/interprocess/offset_ptr.hpp>
-#include <boost/static_assert.hpp>
-
-#include <ostream>
-#include <algorithm>
-#include <cassert>
-
-namespace isc {
-namespace datasrc {
-
-/// Forward declare RBTree class here is convinent for following friend
-/// class declare inside RBNode and RBTreeNodeChain
-template <typename T>
-class RBTree;
-
-/// \brief \c RBNode is used by RBTree to store any data related to one domain
-///     name.
-///
-/// This is meant to be used only from RBTree. It is meaningless to inherit it
-/// or create instances of it from elsewhere. For that reason, the constructor
-/// (and the allocator, see below) is private.
-///
-/// It serves three roles. One is to keep structure of the \c RBTree as a
-/// red-black tree. For that purpose, it has left, right and parent pointers
-/// and color member. These are private and accessed only from within the tree.
-///
-/// The second one is to store data for one domain name. The data related
-/// functions can be used to access and set the data.
-///
-/// The third role is to keep the hierarchy of domains. The down pointer
-/// points to a subtree of subdomains. The parent pointer of a subtree's
-/// root node points to the parent leaf of the upper tree.
-///
-/// One special kind of node is non-terminal node. It has subdomains with
-/// RRsets, but doesn't have any RRsets itself.
-///
-/// In order to keep memory footprint as small as possible, the node data
-/// are heavily packed.  Specifically, some internal node properties (such as
-/// the node color) are encoded as part of "flags", some of the flag bits
-/// can also be set by the user application.  Each node is associated with
-/// a sequence of domain name labels, which is essentially the search/insert
-/// key for the node (see also the description of RBTree).  This is encoded
-/// as opaque binary immediately following the main node object.  The size
-/// of the allocated space for the labels data is encoded by borrowing some
-/// bits of the "flags" field.
-template <typename T>
-class RBNode : public boost::noncopyable {
-private:
-    /// The RBNode is meant for use from within RBTree, so it has access to
-    /// it.
-    friend class RBTree<T>;
-
-    /// \brief Just a type alias
-    ///
-    /// We are going to use a lot of these offset pointers here and they
-    /// have a long name.
-    typedef boost::interprocess::offset_ptr<RBNode<T> > RBNodePtr;
-
-    /// \name Constructors
-    ///
-    /// \note The existence of a RBNode without a RBTree is meaningless.
-    ///     Therefore the constructors are private.
-    //@{
-
-    /// \brief Constructor from normal nodes.
-    RBNode(size_t labels_capacity);
-
-    /// \brief Destructor
-    ~RBNode();
-
-    //@}
-
-    /// \brief Accessor to the memory region for node labels.
-    ///
-    /// The only valid usage of the returned pointer is to pass it to the
-    /// corresponding constructor of \c dns::LabelSequence.
-    const void* getLabelsData() const { return (this + 1); }
-
-    /// \brief Accessor to the memory region for node labels, mutable version.
-    ///
-    /// The only valid usage of the returned pointer is to pass it to
-    /// \c LabelSequence::serialize() with the node's labels_capacity_ member
-    /// (which should be sufficiently large for the \c LabelSequence in that
-    /// context).
-    void* getLabelsData() { return (this + 1); }
-
-    /// \brief Allocate and construct \c RBNode
-    ///
-    /// This static method allocates memory for a new \c RBNode object
-    /// from the given memory segment, constructs the object, and returns
-    /// a pointer to it.
-    ///
-    /// \throw std::bad_alloc Memory allocation fails.
-    ///
-    /// \param mem_sgmt A \c MemorySegment from which memory for the new
-    /// \c RBNode is allocated.
-    static RBNode<T>* create(util::MemorySegment& mem_sgmt,
-                             const dns::LabelSequence& labels)
-    {
-        const size_t labels_len = labels.getSerializedLength();
-        void* p = mem_sgmt.allocate(sizeof(RBNode<T>) + labels_len);
-        RBNode<T>* node = new(p) RBNode<T>(labels_len);
-        labels.serialize(node->getLabelsData(), labels_len);
-        return (node);
-    }
-
-    /// \brief Destruct and deallocate \c RBNode
-    ///
-    /// \throw none
-    ///
-    /// \param mem_sgmt The \c MemorySegment that allocated memory for
-    /// \c rbnode.
-    /// \param rbnode A non NULL pointer to a valid \c RBNode object
-    /// that was originally created by the \c create() method (the behavior
-    /// is undefined if this condition isn't met).
-    static void destroy(util::MemorySegment& mem_sgmt, RBNode<T>* rbnode) {
-        const size_t labels_capacity = rbnode->labels_capacity_;
-        rbnode->~RBNode<T>();
-        mem_sgmt.deallocate(rbnode, sizeof(RBNode<T>) + labels_capacity);
-    }
-
-    /// \brief Reset node's label sequence to a new one.
-    ///
-    /// The new labels must be a sub sequence of the current label sequence;
-    /// otherwise the serialize() method will throw an exception.
-    void resetLabels(const dns::LabelSequence& labels) {
-        labels.serialize(getLabelsData(), labels_capacity_);
-    }
-
-public:
-    /// \brief Alias for shared pointer to the data.
-    typedef boost::shared_ptr<T> NodeDataPtr;
-
-    /// Node flags.
-    ///
-    /// Each flag value defines a non default property for a specific node.
-    /// These are defined as bitmask type values for the convenience of
-    /// internal implementation, but applications are expected to use
-    /// each flag separately via the enum definitions.
-    ///
-    /// All (settable) flags are off by default; they must be explicitly
-    /// set to on by the \c setFlag() method.
-    enum Flags {
-        FLAG_CALLBACK = 1, ///< Callback enabled. See \ref callback
-        FLAG_RED = 2, ///< Node color; 1 if node is red, 0 if node is black.
-        FLAG_SUBTREE_ROOT = 4, ///< Set if the node is the root of a subtree
-        FLAG_USER1 = 0x400000U, ///< Application specific flag
-        FLAG_USER2 = 0x200000U, ///< Application specific flag
-        FLAG_USER3 = 0x100000U, ///< Application specific flag
-        FLAG_MAX = 0x400000U    // for integrity check
-    };
-private:
-    // Some flag values are expected to be used for internal purposes
-    // (e.g., representing the node color) in future versions, so we
-    // limit the settable flags via the \c setFlag() method to those
-    // explicitly defined in \c Flags.  This constant represents all
-    // such flags.
-    static const uint32_t SETTABLE_FLAGS = (FLAG_CALLBACK | FLAG_USER1 |
-                                            FLAG_USER2 | FLAG_USER3);
-
-public:
-
-    /// \name Getter functions.
-    //@{
-    /// \brief Return the name of current node.
-    ///
-    /// It's relative to its containing node.
-    ///
-    /// To get the absolute name of one node, the node path from the top node
-    /// to current node has to be recorded.
-    ///
-    /// \note We should eventually deprecate this method and revise all its
-    /// usage with \c getLabels().  At this point the only user of this method
-    /// is getAbsoluteName()::getAbsoluteName(), which would have to be revised
-    /// using \c LabelSequence.  Until then we keep this interface as a
-    /// simplest form of wrapper; it's not efficient, but should be replaced
-    /// before we need to worry about that.
-    const isc::dns::Name getName() const {
-        return (dns::Name(dns::LabelSequence(getLabelsData()).toText()));
-    }
-
-    /// \brief Return the label sequence of the node.
-    ///
-    /// This method returns the label sequence corresponding to this node
-    /// in the form of \c dns::LabelSequence object.  Any modification to
-    /// the tree can invalidate the returned \c LabelSequence object or copy
-    /// of it; in general, it's expected to be used in a very limited scope.
-    dns::LabelSequence getLabels() const {
-        return (dns::LabelSequence(getLabelsData()));
-    }
-
-    /// \brief Return the absolute label sequence of the node.
-    ///
-    /// This method returns the label sequence corresponding to the full
-    /// name of the node; i.e. the entire name as it appears in the zone.
-    ///
-    /// It takes the (partial) name of the node itself, and extends it
-    /// with all upper nodes.
-    ///
-    /// \note Care must be taken with the buffer that is used here; this
-    /// method overwrites its data, so it should not be associated with
-    /// any other LabelSequence during the lifetime of the LabelSequence
-    /// returned by this method. See LabelSequence::extend(), which is used
-    /// by this method.
-    ///
-    /// \param buf A data buffer where the label sequence will be built.
-    ///            The data in this buffer will be overwritten by this call.
-    /// \return A LabelSequence with the absolute name of this node.
-    isc::dns::LabelSequence getAbsoluteLabels(
-        uint8_t buf[isc::dns::LabelSequence::MAX_SERIALIZED_LENGTH]) const;
-
-    /// \brief Return the data stored in this node.
-    ///
-    /// You should not delete the data, it is handled by shared pointers.
-    NodeDataPtr& getData() { return (data_); }
-    /// \brief Return the data stored in this node.
-    const NodeDataPtr& getData() const { return (data_); }
-
-    /// \brief return whether the node has related data.
-    ///
-    /// There can be empty nodes inside the RBTree. They are usually the
-    /// non-terminal domains, but it is possible (yet probably meaningless)
-    /// empty nodes anywhere.
-    bool isEmpty() const { return (data_.get() == NULL); }
-    //@}
-
-    /// \name Setter functions.
-    //@{
-    /// \brief Set the data stored in the node.
-    void setData(const NodeDataPtr& data) { data_ = data; }
-    //@}
-
-    /// \name Node flag manipulation methods
-    //@{
-    /// Get the status of a node flag.
-    ///
-    /// This method returns whether the given node flag is set (enabled)
-    /// on the node.  The \c flag parameter is expected to be one of the
-    /// defined \c Flags constants.  For simplicity, the method interface
-    /// does not prohibit passing an undefined flag or combined flags, but
-    /// the return value in such a case will be meaningless for the caller
-    /// (an application would have to use an ugly cast for such an unintended
-    /// form of call, which will hopefully avoid accidental misuse).
-    ///
-    /// \exception None
-    /// \param flag The flag to be tested.
-    /// \return \c true if the \c flag is set; \c false otherwise.
-    bool getFlag(Flags flag) const {
-        return ((flags_ & flag) != 0);
-    }
-
-    /// Set or clear a node flag.
-    ///
-    /// This method changes the status of the specified node flag to either
-    /// "on" (enabled) or "off" (disabled).  The new status is specified by
-    /// the \c on parameter.
-    /// Like the \c getFlag() method, \c flag is expected to be one of the
-    /// defined \c Flags constants.  If an undefined or unsettable flag is
-    /// specified, \c isc::InvalidParameter exception will be thrown.
-    ///
-    /// \exception isc::InvalidParameter Unsettable flag is specified
-    /// \exception None otherwise
-    /// \param flag The node flag to be changed.
-    /// \param on If \c true, set the flag to on; otherwise set it to off.
-    void setFlag(Flags flag, bool on = true) {
-        if ((flag & ~SETTABLE_FLAGS) != 0) {
-            isc_throw(isc::InvalidParameter,
-                      "Unsettable RBTree flag is being set");
-        }
-        if (on) {
-            flags_ |= flag;
-        } else {
-            flags_ &= ~flag;
-        }
-    }
-    //@}
-
-private:
-    /// \name Callback related methods
-    ///
-    /// See the description of \c RBTree<T>::find() at \ref callback
-    /// about callbacks.
-    ///
-    /// These methods never throw an exception.
-    //@{
-    /// Return if callback is enabled at the node.
-    //@}
-
-
-    /// \brief Define rbnode color
-    enum RBNodeColor {BLACK, RED};
-
-    /// \brief Returns the color of this node
-    RBNodeColor getColor() const {
-        if ((flags_ & FLAG_RED) != 0) {
-            return (RED);
-        } else {
-            return (BLACK);
-        }
-    }
-
-    /// \brief Sets the color of this node
-    void setColor(const RBNodeColor color) {
-        if (color == RED) {
-            flags_ |= FLAG_RED;
-        } else {
-            flags_ &= ~FLAG_RED;
-        }
-    }
-
-    void setSubTreeRoot(bool root) {
-        if (root) {
-            flags_ |= FLAG_SUBTREE_ROOT;
-        } else {
-            flags_ &= ~FLAG_SUBTREE_ROOT;
-        }
-    }
-
-    bool isSubTreeRoot() const {
-        return ((flags_ & FLAG_SUBTREE_ROOT) != 0);
-    }
-
-public:
-    /// \brief returns the parent of the root of its subtree
-    ///
-    /// This method takes a node and returns the parent of the root of
-    /// its subtree (i.e, it returns the node's immediate ancestor in
-    /// the tree-of-tree hierarchy). If the node is at the top level
-    /// (which should be absolute), it will return \c NULL.
-    ///
-    /// This method never throws an exception.
-    const RBNode<T>* getUpperNode() const;
-
-private:
-    /// \brief return the next node which is bigger than current node
-    /// in the same subtree
-    ///
-    /// The next successor for this node is the next bigger node in terms of
-    /// the DNSSEC order relation within the same single subtree.
-    /// Note that it may NOT be the next bigger node in the entire RBTree;
-    ///  RBTree is a tree in tree, and the real next node may reside in
-    /// an upper or lower subtree of the subtree where this node belongs.
-    /// For example, if this node has a sub domain, the real next node is
-    /// the smallest node in the sub domain tree.
-    ///
-    /// If this node is the biggest node within the subtree, this method
-    /// returns \c NULL.
-    ///
-    /// This method never throws an exception.
-    const RBNode<T>* successor() const;
-
-    /// \brief return the next node which is smaller than current node
-    /// in the same subtree
-    ///
-    /// The predecessor for this node is the next smaller node in terms of
-    /// the DNSSEC order relation within the same single subtree.
-    /// Note that it may NOT be the next smaller node in the entire RBTree;
-    /// RBTree is a tree in tree, and the real next node may reside in
-    /// an upper or lower subtree of the subtree where this node belongs.
-    /// For example, if the predecessor node has a sub domain, the real next
-    /// node is the largest node in the sub domain tree.
-    ///
-    /// If this node is the smallest node within the subtree, this method
-    /// returns \c NULL.
-    ///
-    /// This method never throws an exception.
-    const RBNode<T>* predecessor() const;
-
-    /// \brief private shared implementation of successor and predecessor
-    ///
-    /// As the two mentioned functions are merely mirror images of each other,
-    /// it makes little sense to keep both versions. So this is the body of the
-    /// functions and we call it with the correct pointers.
-    ///
-    /// Not to be called directly, not even by friends.
-    ///
-    /// The overhead of the member pointers should be optimised out, as this
-    /// will probably get completely inlined into predecessor and successor
-    /// methods.
-    const RBNode<T>*
-        abstractSuccessor(typename RBNode<T>::RBNodePtr RBNode<T>::*left,
-                          typename RBNode<T>::RBNodePtr RBNode<T>::*right)
-        const;
-
-    /// \name Data to maintain the rbtree structure.
-    ///
-    /// We keep them as offset pointers. This is part of a future plan, when we
-    /// want to share the image of the tree between multiple processes.
-    /// However, whenever we have a chance, we switch to bare pointers during
-    /// the processing. The pointers on stack are never shared and the offset
-    /// pointers have non-trivial performance impact.
-    //@{
-    RBNodePtr parent_;
-    /// \brief Access the parent_ as bare pointer.
-    RBNode<T>* getParent() {
-        return (parent_.get());
-    }
-    /// \brief Access the parent_ as bare pointer, const.
-    const RBNode<T>* getParent() const {
-        return (parent_.get());
-    }
-    RBNodePtr left_;
-    /// \brief Access the left_ as bare pointer.
-    RBNode<T>* getLeft() {
-        return (left_.get());
-    }
-    /// \brief Access the left_ as bare pointer, const.
-    const RBNode<T>* getLeft() const {
-        return (left_.get());
-    }
-    RBNodePtr right_;
-    /// \brief Access the right_ as bare pointer.
-    RBNode<T>* getRight() {
-        return (right_.get());
-    }
-    /// \brief Access the right_ as bare pointer, const.
-    const RBNode<T>* getRight() const {
-        return (right_.get());
-    }
-    //@}
-
-    /// \brief Data stored here.
-    NodeDataPtr       data_;
-
-    /// \brief The subdomain tree.
-    ///
-    /// This points to the root node of trees of subdomains of this domain.
-    ///
-    /// \par Adding down pointer to \c RBNode has two purposes:
-    /// \li Accelerate the search process, with sub domain tree, it splits the
-    ///     big flat tree into several hierarchy trees.
-    /// \li It saves memory usage as it allows storing only relative names,
-    ///     avoiding storage of the same domain labels multiple times.
-    RBNodePtr down_;
-    /// \brief Access the down_ as bare pointer.
-    RBNode<T>* getDown() {
-        return (down_.get());
-    }
-    /// \brief Access the down_ as bare pointer, const.
-    const RBNode<T>* getDown() const {
-        return (down_.get());
-    }
-
-    /// \brief Internal or user-configurable flags of node's properties.
-    ///
-    /// See the \c Flags enum for available flags.
-    ///
-    /// For memory efficiency reasons, we only use a subset of the 32-bit
-    /// space, and use the rest to store the allocated size for the node's
-    /// label sequence data.
-    uint32_t flags_ : 23;          // largest flag being 0x400000
-    BOOST_STATIC_ASSERT((1 << 23) > FLAG_MAX); // assumption check
-
-    const uint32_t labels_capacity_ : 9; // size for labelseq; range is 0..511
-    // Make sure the reserved space for labels_capacity_ is sufficiently
-    // large.  In effect, we use the knowledge of the implementation of the
-    // serialization, but we still only use its public interface, and the
-    // public interface of this class doesn't rely on this assumption.
-    // So we can change this implementation without affecting its users if
-    // a future change to LabelSequence breaks this assumption.
-    BOOST_STATIC_ASSERT((1 << 9) > dns::LabelSequence::MAX_SERIALIZED_LENGTH);
-};
-
-template <typename T>
-RBNode<T>::RBNode(size_t labels_capacity) :
-    parent_(NULL),
-    left_(NULL),
-    right_(NULL),
-    down_(NULL),
-    flags_(FLAG_RED | FLAG_SUBTREE_ROOT),
-    labels_capacity_(labels_capacity)
-{
-}
-
-template <typename T>
-RBNode<T>::~RBNode() {
-}
-
-template <typename T>
-const RBNode<T>*
-RBNode<T>::getUpperNode() const {
-    const RBNode<T>* current = this;
-
-    // current would never be equal to NULL here (in a correct tree
-    // implementation)
-    while (!current->isSubTreeRoot()) {
-        current = current->getParent();
-    }
-
-    return (current->getParent());
-}
-
-template <typename T>
-isc::dns::LabelSequence
-RBNode<T>::getAbsoluteLabels(
-    uint8_t buf[isc::dns::LabelSequence::MAX_SERIALIZED_LENGTH]) const
-{
-    isc::dns::LabelSequence result(getLabels(), buf);
-    const RBNode<T>* upper = getUpperNode();
-    while (upper != NULL) {
-        result.extend(upper->getLabels(), buf);
-        upper = upper->getUpperNode();
-    }
-
-    return (result);
-}
-
-template <typename T>
-const RBNode<T>*
-RBNode<T>::abstractSuccessor(typename RBNode<T>::RBNodePtr RBNode<T>::*left,
-                             typename RBNode<T>::RBNodePtr RBNode<T>::*right)
-    const
-{
-    // This function is written as a successor. It becomes predecessor if
-    // the left and right pointers are swapped. So in case of predecessor,
-    // the left pointer points to right and vice versa. Don't get confused
-    // by the idea, just imagine the pointers look into a mirror.
-
-    const RBNode<T>* current = this;
-    // If it has right node, the successor is the left-most node of the right
-    // subtree.
-    if ((current->*right).get() != NULL) {
-        current = (current->*right).get();
-        const RBNode<T>* left_n;
-        while ((left_n = (current->*left).get()) != NULL) {
-            current = left_n;
-        }
-        return (current);
-    }
-
-    // Otherwise go up until we find the first left branch on our path to
-    // root.  If found, the parent of the branch is the successor.
-    // Otherwise, we return the null node
-    const RBNode<T>* parent = current->getParent();
-    while ((!current->isSubTreeRoot()) &&
-           (current == (parent->*right).get())) {
-        current = parent;
-        parent = parent->getParent();
-    }
-
-    if (!current->isSubTreeRoot()) {
-        return (parent);
-    } else {
-        return (NULL);
-    }
-}
-
-template <typename T>
-const RBNode<T>*
-RBNode<T>::successor() const {
-    return (abstractSuccessor(&RBNode<T>::left_, &RBNode<T>::right_));
-}
-
-template <typename T>
-const RBNode<T>*
-RBNode<T>::predecessor() const {
-    // Swap the left and right pointers for the abstractSuccessor
-    return (abstractSuccessor(&RBNode<T>::right_, &RBNode<T>::left_));
-}
-
-/// \brief RBTreeNodeChain stores detailed information of \c RBTree::find()
-/// result.
-///
-/// - The \c RBNode that was last compared with the search name, and
-///   the comparison result at that point in the form of
-///   \c isc::dns::NameComparisonResult.
-/// - A sequence of nodes that forms a path to the found node.
-///
-/// The comparison result can be used to handle some rare cases such as
-/// empty node processing.
-/// The node sequence keeps track of the nodes to reach any given node from
-/// the root of RBTree.
-///
-/// Currently, RBNode does not have "up" pointers in them (i.e., back pointers
-/// from the root of one level of tree of trees to the node in the parent
-/// tree whose down pointer points to that root node) for memory usage
-/// reasons, so there is no other way to find the path back to the root from
-/// any given RBNode.
-///
-/// \note This design may change in future versions.  In particular, it's
-/// quite likely we want to have that pointer if we want to optimize name
-/// compression by exploiting the structure of the zone.  If and when that
-/// happens we should also revisit the need for the chaining.
-/// Also, the class name may not be appropriate now that it contains other
-/// information than a node "chain", and the chain itself may even be
-/// deprecated.  Something like "RBTreeFindContext" may be a better name.
-/// This point should be revisited later.
-///
-/// RBTreeNodeChain is constructed and manipulated only inside the \c RBTree
-/// class.
-/// \c RBTree uses it as an inner data structure to iterate over the whole
-/// RBTree.
-/// This is the reason why manipulation methods such as \c push() and \c pop()
-/// are private (and not shown in the doxygen document).
-template <typename T>
-class RBTreeNodeChain {
-    /// RBTreeNodeChain is initialized by RBTree, only RBTree has
-    /// knowledge to manipulate it.
-    friend class RBTree<T>;
-public:
-    /// \name Constructors and Assignment Operator.
-    ///
-    /// \note The copy constructor and the assignment operator are
-    /// intentionally defined as private, making this class non copyable.
-    /// This may have to be changed in a future version with newer need.
-    /// For now we explicitly disable copy to avoid accidental copy happens
-    /// unintentionally.
-    //{@
-    /// The default constructor.
-    ///
-    /// \exception None
-    RBTreeNodeChain() : node_count_(0), last_compared_(NULL),
-                        // XXX: meaningless initial values:
-                        last_comparison_(0, 0,
-                                         isc::dns::NameComparisonResult::EQUAL)
-    {}
-
-private:
-    RBTreeNodeChain(const RBTreeNodeChain<T>&);
-    RBTreeNodeChain<T>& operator=(const RBTreeNodeChain<T>&);
-    //@}
-
-public:
-    /// Clear the state of the chain.
-    ///
-    /// This method re-initializes the internal state of the chain so that
-    /// it can be reused for subsequent operations.
-    ///
-    /// \exception None
-    void clear() {
-        node_count_ = 0;
-        last_compared_ = NULL;
-    }
-
-    /// Return the \c RBNode that was last compared in \c RBTree::find().
-    ///
-    /// If this chain has been passed to \c RBTree::find() and there has
-    /// been name comparison against the search name, the last compared
-    /// \c RBNode is recorded within the chain.  This method returns that
-    /// node.
-    /// If \c RBTree::find() hasn't been called with this chain or name
-    /// comparison hasn't taken place (which is possible if the tree is empty),
-    /// this method returns \c NULL.
-    ///
-    /// \exception None
-    const RBNode<T>* getLastComparedNode() const {
-        return (last_compared_);
-    }
-
-    /// Return the result of last name comparison in \c RBTree::find().
-    ///
-    /// Like \c getLastComparedNode(), \c RBTree::find() records the result
-    /// of the last name comparison in the chain.  This method returns the
-    /// result.
-    /// The return value of this method is only meaningful when comparison
-    /// has taken place, i.e, when \c getLastComparedNode() would return a
-    /// non \c NULL value.
-    ///
-    /// \exception None
-    const isc::dns::NameComparisonResult& getLastComparisonResult() const {
-        return (last_comparison_);
-    }
-
-    /// \brief Return the number of levels stored in the chain.
-    ///
-    /// It's equal to the number of nodes in the chain; for an empty
-    /// chain, 0 will be returned.
-    ///
-    /// \exception None
-    unsigned int getLevelCount() const { return (node_count_); }
-
-    /// \brief return the absolute name for the node which this
-    /// \c RBTreeNodeChain currently refers to.
-    ///
-    /// The chain must not be empty.
-    ///
-    /// \exception isc::BadValue the chain is empty.
-    /// \exception std::bad_alloc memory allocation for the new name fails.
-    isc::dns::Name getAbsoluteName() const {
-        if (isEmpty()) {
-            isc_throw(isc::BadValue,
-                      "RBTreeNodeChain::getAbsoluteName is called on an empty "
-                      "chain");
-        }
-
-        const RBNode<T>* top_node = top();
-        isc::dns::Name absolute_name = top_node->getName();
-        int node_count = node_count_ - 1;
-        while (node_count > 0) {
-            top_node = nodes_[node_count - 1];
-            absolute_name = absolute_name.concatenate(top_node->getName());
-            --node_count;
-        }
-        return (absolute_name);
-    }
-
-private:
-    // the following private functions check invariants about the internal
-    // state using assert() instead of exception.  The state of a chain
-    // can only be modified by operations within this file, so if any of the
-    // assumptions fails it means an internal bug.
-
-    /// \brief return whether node chain has node in it.
-    ///
-    /// \exception None
-    bool isEmpty() const { return (node_count_ == 0); }
-
-    /// \brief return the top node for the node chain
-    ///
-    /// RBTreeNodeChain store all the nodes along top node to
-    /// root node of RBTree
-    ///
-    /// \exception None
-    const RBNode<T>* top() const {
-        assert(!isEmpty());
-        return (nodes_[node_count_ - 1]);
-    }
-
-    /// \brief pop the top node from the node chain
-    ///
-    /// After pop, up/super node of original top node will be
-    /// the top node
-    ///
-    /// \exception None
-    void pop() {
-        assert(!isEmpty());
-        --node_count_;
-    }
-
-    /// \brief add the node into the node chain
-    ///
-    /// If the node chain isn't empty, the node should be
-    /// the sub domain of the original top node in node chain
-    /// otherwise the node should be the root node of RBTree.
-    ///
-    /// \exception None
-    void push(const RBNode<T>* node) {
-        assert(node_count_ < RBT_MAX_LEVEL);
-        nodes_[node_count_++] = node;
-    }
-
-private:
-    // The max label count for one domain name is Name::MAX_LABELS (128).
-    // Since each node in rbtree stores at least one label, it's also equal
-    // to the possible maximum level.
-    const static int RBT_MAX_LEVEL = isc::dns::Name::MAX_LABELS;
-
-    int node_count_;
-    const RBNode<T>* nodes_[RBT_MAX_LEVEL];
-    const RBNode<T>* last_compared_;
-    isc::dns::NameComparisonResult last_comparison_;
-};
-
-
-// note: the following class description is documented using multiline comments
-// because the verbatim diagram contain a backslash, which could be interpreted
-// as escape of newline in singleline comment.
-/**
- *  \brief \c RBTree class represents all the domains with the same suffix.
- *      It can be used to store the domains in one zone, for example.
- *
- *  RBTree is a generic map from domain names to any kind of data. Internally,
- *  it uses a red-black tree. However, it isn't one tree containing everything.
- *  Subdomains are trees, so this structure is recursive - trees inside trees.
- *  But, from the interface point of view, it is opaque data structure.
- *
- *  \c RBTree splits the domain space into hierarchy red black trees; nodes
- * in one tree has the same base name. The benefit of this struct is that:
- *  - Enhances the query performace compared with one big flat red black tree.
- *  - Decreases the memory footprint, as it doesn't store the suffix labels
- *      multiple times.
- *
- * Depending on different usage, rbtree will support different search policies.
- * Whether to return an empty node to end user is one policy among them.
- * The default policy is to NOT return an empty node to end user;
- * to change the behavior, specify \c true for the constructor parameter
- * \c returnEmptyNode.
- * \note The search policy only affects the \c find() behavior of RBTree.
- * When inserting one name into RBTree, if the node with the name already
- * exists in the RBTree and it's an empty node which doesn't have any data,
- * the \c insert() method will still return \c ALREADYEXISTS regardless of
- * the search policy.
- *
- * \anchor diagram
- *
- * with the following names:
- *  - a
- *  - b
- *  - c
- *  - x.d.e.f
- *  - z.d.e.f
- *  - g.h
- *  - o.w.y.d.e.f
- *  - p.w.y.d.e.f
- *  - q.w.y.d.e.f
- *
- * the tree will look like:
- *  \verbatim
-                                .
-                                |
-                                b
-                              /   \
-                             a    d.e.f
-                                    /|\
-                                   c | g.h
-                                     |
-                                    w.y
-                                    /|\
-                                   x | z
-                                     |
-                                     p
-                                    / \
-                                   o   q
-   \endverbatim
- *  \todo
- *  - add remove interface
- */
-template <typename T>
-class RBTree : public boost::noncopyable {
-    friend class RBNode<T>;
-public:
-    /// \brief The return value for the \c find() and insert() methods
-    enum Result {
-        SUCCESS,    ///< Insert was successful
-        /// \brief The node returned from find mathes exactly the name given
-        EXACTMATCH,
-        PARTIALMATCH, ///< A superdomain node was found
-        NOTFOUND,   ///< Not even any superdomain was found
-        /// \brief Returned by insert() if a node of the name already exists
-        ALREADYEXISTS,
-    };
-
-    /// \brief Allocate and construct \c RBTree
-    ///
-    /// This static method allocates memory for a new \c RBTree object
-    /// from the given memory segment, constructs the object, and returns
-    /// a pointer to it.
-    ///
-    /// \throw std::bad_alloc Memory allocation fails.
-    ///
-    /// \param mem_sgmt A \c MemorySegment from which memory for the new
-    /// \c RBTree is allocated.
-    static RBTree* create(util::MemorySegment& mem_sgmt,
-                          bool return_empty_node = false)
-    {
-        void* p = mem_sgmt.allocate(sizeof(RBTree<T>));
-        return (new(p) RBTree<T>(return_empty_node));
-    }
-
-    /// \brief Destruct and deallocate \c RBTree
-    ///
-    /// This method also destroys and deallocates all nodes inserted to the
-    /// tree.
-    ///
-    /// \note The memory segment (\c mem_sgmt) must be the same one that
-    /// was originally used to allocate memory for the tree (and for all
-    /// nodes inserted to the tree, due to the requirement of \c insert()),
-    /// since the tree itself doesn't maintain a reference to the segment.
-    /// This is not a robust interface, but since we plan to share the tree
-    /// structure by multiple processes via shared memory or possibly allow
-    /// the memory image to be dumped to a file for later reload, there
-    /// doesn't seem to be an easy way to store such reference in the data
-    /// itself.  We should probably consider a wrapper interface that
-    /// encapsulates the corresponding segment and always use it for any
-    /// allocation/deallocation of tree related data (the tree itself, their
-    /// nodes, and node data) to keep the usage as safe as possible.
-    ///
-    /// \throw none
-    ///
-    /// \param mem_sgmt The \c MemorySegment that allocated memory for
-    /// \c rbtree and for all nodes inserted to the tree.
-    /// \param rbtree A non NULL pointer to a valid \c RBTree object
-    /// that was originally created by the \c create() method (the behavior
-    /// is undefined if this condition isn't met).
-    static void destroy(util::MemorySegment& mem_sgmt, RBTree<T>* rbtree) {
-        rbtree->deleteAllNodes(mem_sgmt);
-        rbtree->~RBTree<T>();
-        mem_sgmt.deallocate(rbtree, sizeof(RBTree<T>));
-    }
-
-private:
-    /// \name Constructor and Destructor
-    //@{
-    /// \brief The constructor.
-    ///
-    /// An object of this class is always expected to be created by the
-    /// allocator (\c create()), so the constructor is hidden as private.
-    ///
-    /// It never throws an exception.
-    explicit RBTree(bool returnEmptyNode = false);
-
-    /// \brief The destructor.
-    ///
-    /// An object of this class is always expected to be destroyed explicitly
-    /// by \c destroy(), so the constructor is hidden as private.
-    ///
-    /// \note RBTree is not intended to be inherited so the destructor
-    /// is not virtual
-    ~RBTree();
-    //@}
-
-public:
-
-    /// \name Find methods
-    ///
-    /// \brief Find the node that gives a longest match against the given name.
-    ///
-    /// \anchor find
-    ///
-    /// These methods search the RBTree for a node whose name is longest
-    /// against name. The found node, if any, is returned via the node pointer.
-    ///
-    /// By default, nodes that don't have data (see RBNode::isEmpty) are
-    /// ignored and the result can be NOTFOUND even if there's a node whose
-    /// name matches.  If the \c RBTree is constructed with its
-    /// \c returnEmptyNode parameter being \c true, empty nodes will also
-    /// be match candidates.
-    ///
-    /// \note Even when \c returnEmptyNode is \c true, not all empty nodes
-    /// in terms of the DNS protocol may necessarily be found by this method.
-    /// For example, in the \ref diagram shown in the class description,
-    /// the name y.d.e.f is logically contained in the tree as part of the
-    /// node w.y, but the \c find() variants cannot find the former for
-    /// the search key of y.d.e.f, no matter how the \c RBTree is constructed.
-    /// The caller of this method must use a different way to identify the
-    /// hidden match when necessary.
-    ///
-    /// These methods involve operations on names that can throw an exception.
-    /// If that happens the exception will be propagated to the caller.
-    /// The callback function should generally not throw an exception, but
-    /// if it throws, the exception will be propagated to the caller.
-    ///
-    /// The \c name parameter says what should be found. The node parameter
-    /// is output-only, and in case of EXACTMATCH or PARTIALMATCH, it is set
-    /// to a pointer to the found node.
-    ///
-    /// They return:
-    ///  - EXACTMATCH when a node with the same name as requested exists.
-    ///  - PARTIALMATCH when a node with the same name does not exist (or is
-    ///    empty), but there's a (nonempty) superdomain of the requested one.
-    ///    The superdomain with longest name is returned through the node
-    ///    parameter. Beware that if you store a zone in the tree, you may get
-    ///    PARTIALMATCH with zone apex when the given domain name is not there.
-    ///    You should not try to delegate into another zone in that case.
-    ///  - NOTFOUND if there's no node with the same name nor any superdomain
-    ///    of it. In that case, node parameter is left intact.
-    //@{
-
-    /// \brief Simple find.
-    ///
-    /// Acts as described in the \ref find section.
-    Result find(const isc::dns::Name& name, RBNode<T>** node) const {
-        RBTreeNodeChain<T> node_path;
-        const isc::dns::LabelSequence ls(name);
-        return (find<void*>(ls, node, node_path, NULL, NULL));
-    }
-
-    /// \brief Simple find returning immutable node.
-    ///
-    /// Acts as described in the \ref find section, but returns immutable node
-    /// pointer.
-    Result find(const isc::dns::Name& name, const RBNode<T>** node) const {
-        RBTreeNodeChain<T> node_path;
-        RBNode<T> *target_node = NULL;
-        const isc::dns::LabelSequence ls(name);
-        Result ret = (find<void*>(ls, &target_node, node_path, NULL, NULL));
-        if (ret != NOTFOUND) {
-            *node = target_node;
-        }
-        return (ret);
-    }
-
-    /// \brief Simple find, with node_path tracking
-    ///
-    /// Acts as described in the \ref find section.
-    Result find(const isc::dns::Name& name, RBNode<T>** node,
-                RBTreeNodeChain<T>& node_path) const
-    {
-        const isc::dns::LabelSequence ls(name);
-        return (find<void*>(ls, node, node_path, NULL, NULL));
-    }
-
-    /// \brief Simple find returning immutable node, with node_path tracking
-    ///
-    /// Acts as described in the \ref find section, but returns immutable node
-    /// pointer.
-    Result find(const isc::dns::Name& name, const RBNode<T>** node,
-                RBTreeNodeChain<T>& node_path) const
-    {
-        RBNode<T> *target_node = NULL;
-        const isc::dns::LabelSequence ls(name);
-        Result ret = (find<void*>(ls, &target_node, node_path, NULL, NULL));
-        if (ret != NOTFOUND) {
-            *node = target_node;
-        }
-        return (ret);
-    }
-
-    /// \brief Simple find returning immutable node.
-    ///
-    /// Acts as described in the \ref find section, but returns immutable
-    /// node pointer.
-    template <typename CBARG>
-    Result find(const isc::dns::Name& name,
-                const RBNode<T>** node,
-                RBTreeNodeChain<T>& node_path,
-                bool (*callback)(const RBNode<T>&, CBARG),
-                CBARG callback_arg) const
-    {
-        RBNode<T>* target_node = NULL;
-        const isc::dns::LabelSequence ls(name);
-        Result ret = find(ls, &target_node, node_path, callback,
-                          callback_arg);
-        if (ret != NOTFOUND) {
-            *node = target_node;
-        }
-        return (ret);
-    }
-
-    /// \brief Find with callback and node chain
-    /// \anchor callback
-    ///
-    /// This version of \c find() is specifically designed for the backend
-    /// of the \c InMemoryZoneFinder class, and implements all necessary
-    /// features for that purpose.  Other applications shouldn't need these
-    /// additional features, and should normally use the simpler versions.
-    ///
-    /// This version of \c find() calls the callback whenever traversing (on
-    /// the way from root down the tree) a marked node on the way down through
-    /// the domain namespace (see \c RBNode::FLAG_CALLBACK).
-    ///
-    /// Also, this version takes a \c LabelSequence object, not a \c Name
-    /// object to be as efficient as possible; operations on the former
-    /// needed for the search are generally much more efficient than those
-    /// for the latter.  Since \c Name objects are more commonly used
-    /// in other parts of the implementation, other versions take a \c Name
-    /// and convert it to \c LabelSequence.  This conversion is cheap,
-    /// while the other direction isn't, and since there would be cases
-    /// where an implementation primarily handles \c LabelSequence objects
-    /// as an efficient representation of names, it would make most sense
-    /// to provide the interface that takes \c LabelSequence.
-    ///
-    /// If you return true from the callback, the search is stopped and a
-    /// PARTIALMATCH is returned with the given node. Note that this node
-    /// doesn't really need to be the one with longest possible match.
-    ///
-    /// The callback is not called for the node which matches exactly
-    /// (EXACTMATCH is returned). This is typically the last node in the
-    /// traversal during a successful search.
-    ///
-    /// This callback mechanism was designed with zone cut (delegation)
-    /// processing in mind. The marked nodes would be the ones at delegation
-    /// points. It is not expected that any other applications would need
-    /// callbacks; they should use the versions of find without callbacks.
-    /// The callbacks are not general functors for the same reason - we don't
-    /// expect it to be needed.
-    ///
-    /// Another special feature of this version is the ability to record
-    /// more detailed information regarding the search result.
-    ///
-    /// This information will be returned via the \c node_path parameter,
-    /// which is an object of class \c RBTreeNodeChain.
-    /// The passed parameter must be empty.
-    ///
-    /// On success, the node sequence stored in \c node_path will contain all
-    /// the ancestor nodes from the found node towards the root.
-    /// For example, if we look for o.w.y.d.e.f in the example \ref diagram,
-    /// \c node_path will contain w.y and d.e.f; the \c top() node of the
-    /// chain will be o, w.y and d.e.f will be stored below it.
-    ///
-    /// This feature can be used to get the absolute name for a node;
-    /// to do so, we need to travel upside from the node toward the root,
-    /// concatenating all ancestor labels.  A node chain can also be used to
-    /// find the next and previous nodes of a given node in the entire RBTree;
-    /// the \c nextNode() and \c previousNode() methods take a node
-    /// chain as a parameter.
-    ///
-    /// \exception isc::BadValue node_path is not empty.
-    ///
-    /// \param target_labels_orig Target to be found
-    /// \param node On success (either \c EXACTMATCH or \c PARTIALMATCH)
-    ///     it will store a pointer to the matching node
-    /// \param node_path Other search details will be stored (see the
-    ///        description)
-    /// \param callback If non- \c NULL, a call back function to be called
-    ///     at marked nodes (see the description).
-    /// \param callback_arg A caller supplied argument to be passed to
-    ///     \c callback.
-    ///
-    /// \return As in the description, but in case of callback returning
-    ///     \c true, it returns immediately with the current node.
-    template <typename CBARG>
-    Result find(const isc::dns::LabelSequence& target_labels_orig,
-                RBNode<T>** node,
-                RBTreeNodeChain<T>& node_path,
-                bool (*callback)(const RBNode<T>&, CBARG),
-                CBARG callback_arg) const;
-
-    /// \brief Simple find returning immutable node.
-    ///
-    /// Acts as described in the \ref find section, but returns immutable
-    /// node pointer.
-    template <typename CBARG>
-    Result find(const isc::dns::LabelSequence& target_labels,
-                const RBNode<T>** node,
-                RBTreeNodeChain<T>& node_path,
-                bool (*callback)(const RBNode<T>&, CBARG),
-                CBARG callback_arg) const
-    {
-        RBNode<T>* target_node = NULL;
-        Result ret = find(target_labels, &target_node, node_path,
-                          callback, callback_arg);
-        if (ret != NOTFOUND) {
-            *node = target_node;
-        }
-        return (ret);
-    }
-    //@}
-
-    /// \brief return the next bigger node in DNSSEC order from a given node
-    /// chain.
-    ///
-    /// This method identifies the next bigger node of the node currently
-    /// referenced in \c node_path and returns it.
-    /// This method also updates the passed \c node_path so that it will store
-    /// the path for the returned next node.
-    /// It will be convenient when we want to iterate over the all nodes
-    /// of \c RBTree; we can do this by calling this method repeatedly
-    /// starting from the root node.
-    ///
-    /// \note \c nextNode() will iterate over all the nodes in RBTree including
-    /// empty nodes. If empty node isn't desired, it's easy to add logic to
-    /// check return node and keep invoking \c nextNode() until the non-empty
-    /// node is retrieved.
-    ///
-    /// \exception isc::BadValue node_path is empty.
-    ///
-    /// \param node_path A node chain that stores all the nodes along the path
-    /// from root to node.
-    ///
-    /// \return An \c RBNode that is next bigger than \c node; if \c node is
-    /// the largest, \c NULL will be returned.
-    const RBNode<T>* nextNode(RBTreeNodeChain<T>& node_path) const;
-
-    /// \brief return the next smaller node in DNSSEC order from a node
-    ///     searched by RBTree::find().
-    ///
-    /// This acts similarly to \c nextNode(), but it walks in the other
-    /// direction. But unlike \c nextNode(), this can start even if the
-    /// node requested by \c find() was not found. In that case, it will
-    /// identify the node that is previous to the queried name.
-    ///
-    /// \note \c previousNode() will iterate over all the nodes in RBTree
-    /// including empty nodes. If empty node isn't desired, it's easy to add
-    /// logic to check return node and keep invoking \c previousNode() until the
-    /// non-empty node is retrieved.
-    ///
-    /// \exception isc::BadValue node_path is empty.
-    ///
-    /// \param node_path A node chain that stores all the nodes along the path
-    /// from root to node and the result of \c find(). This will get modified.
-    /// You should not use the node_path again except for repetitive calls
-    /// of this method.
-    ///
-    /// \return An \c RBNode that is next smaller than \c node; if \c node is
-    /// the smallest, \c NULL will be returned.
-    const RBNode<T>* previousNode(RBTreeNodeChain<T>& node_path) const;
-
-    /// \brief Get the total number of nodes in the tree
-    ///
-    /// It includes nodes internally created as a result of adding a domain
-    /// name that is a subdomain of an existing node of the tree.
-    /// This function is mainly intended to be used for debugging.
-    int getNodeCount() const { return (node_count_); }
-
-    /// \name Debug function
-    //@{
-    /// \brief Print the nodes in the trees.
-    ///
-    /// \param os A \c std::ostream object to which the tree is printed.
-    /// \param depth A factor of the initial indentation.  Each line
-    /// will begin with space character repeating <code>5 * depth</code>
-    /// times.
-    void dumpTree(std::ostream& os, unsigned int depth = 0) const;
-
-    /// \brief Print the nodes in the trees for processing with
-    /// Graphviz's dot.
-    ///
-    /// \param os A \c std::ostream object to which the tree is printed.
-    /// \param show_pointers Show node and parent pointers in the node
-    void dumpDot(std::ostream& os, bool show_pointers = false) const;
-    //@}
-
-    /// \name Modify functions
-    //@{
-    /// \brief Insert the domain name into the tree.
-    ///
-    /// It either finds an already existing node of the given name, or inserts
-    /// a new one if none exists yet. In any case, the \c inserted_node parameter
-    /// is set to point to that node. You can fill data into it or modify it.
-    /// So, if you don't know if a node exists or not and you need to modify
-    /// it, just call insert and act by the result.
-    ///
-    /// Please note that the tree can add some empty nodes by itself, so don't
-    /// assume that if you didn't insert a node of that name it doesn't exist.
-    ///
-    /// This method normally involves resource allocation.  If it fails
-    /// the corresponding standard exception will be thrown.
-    ///
-    /// This method does not provide the strong exception guarantee in its
-    /// strict sense; if an exception is thrown in the middle of this
-    /// method, the internal structure may change.  However, it should
-    /// still retain the same property as a mapping container before this
-    /// method is called.  For example, the result of \c find() should be
-    /// the same.  This method provides the weak exception guarantee in its
-    /// normal sense.
-    ///
-    /// \param mem_sgmt A \c MemorySegment object for allocating memory of
-    /// a new node to be inserted.  Must be the same segment as that used
-    /// for creating the tree itself.
-    /// \param name The name to be inserted into the tree.
-    /// \param inserted_node This is an output parameter and is set to the
-    ///     node.
-    ///
-    /// \return
-    ///  - SUCCESS The node was added.
-    ///  - ALREADYEXISTS There was already a node of that name, so it was not
-    ///     added.
-    Result insert(util::MemorySegment& mem_sgmt, const isc::dns::Name& name,
-                  RBNode<T>** inserted_node);
-
-    /// \brief Delete all tree nodes.
-    ///
-    /// \throw none.
-    ///
-    /// \param mem_sgmt The \c MemorySegment object used to insert the nodes
-    /// (which was also used for creating the tree due to the requirement of
-    /// \c inert()).
-    void deleteAllNodes(util::MemorySegment& mem_sgmt);
-
-    /// \brief Swaps two tree's contents.
-    ///
-    /// This and \c other trees must have been created with the same
-    /// memory segment (see the discussion in \c create()); otherwise the
-    /// behavior is undefined.
-    ///
-    /// This acts the same as many std::*.swap functions, exchanges the
-    /// contents. This doesn't throw anything.
-    void swap(RBTree<T>& other) {
-        std::swap(root_, other.root_);
-        std::swap(node_count_, other.node_count_);
-    }
-    //@}
-
-private:
-    /// \name RBTree balance functions
-    //@{
-    void insertRebalance(typename RBNode<T>::RBNodePtr* root, RBNode<T>* node);
-    RBNode<T>* rightRotate(typename RBNode<T>::RBNodePtr* root,
-                           RBNode<T>* node);
-    RBNode<T>* leftRotate(typename RBNode<T>::RBNodePtr* root,
-                          RBNode<T>* node);
-    //@}
-
-    /// \name Helper functions
-    //@{
-    /// \brief delete tree whose root is equal to node
-    void deleteHelper(util::MemorySegment& mem_sgmt, RBNode<T> *node);
-
-    /// \brief Print the information of given RBNode.
-    void dumpTreeHelper(std::ostream& os, const RBNode<T>* node,
-                        unsigned int depth) const;
-
-    /// \brief Print the information of given RBNode for dot.
-    int dumpDotHelper(std::ostream& os, const RBNode<T>* node,
-                      int* nodecount, bool show_pointers) const;
-
-    /// \brief Indentation helper function for dumpTree
-    static void indent(std::ostream& os, unsigned int depth);
-
-    /// Split one node into two nodes for "prefix" and "suffix" parts of
-    /// the labels of the original node, respectively.  The given node
-    /// will hold the prefix, while a newly created node will hold the prefix.
-    /// Note that the original node still represents the same domain name in
-    /// the entire tree.  This ensures that a pointer to a node keeps its
-    /// semantics even if the tree structure is changed (as long as the node
-    /// itself remains valid).
-    void nodeFission(util::MemorySegment& mem_sgmt, RBNode<T>& node,
-                     const isc::dns::LabelSequence& new_prefix,
-                     const isc::dns::LabelSequence& new_suffix);
-    //@}
-
-    typename RBNode<T>::RBNodePtr root_;
-    /// the node count of current tree
-    unsigned int node_count_;
-    /// search policy for rbtree
-    const bool needsReturnEmptyNode_;
-};
-
-template <typename T>
-RBTree<T>::RBTree(bool returnEmptyNode) :
-    root_(NULL),
-    node_count_(0),
-    needsReturnEmptyNode_(returnEmptyNode)
-{
-}
-
-template <typename T>
-RBTree<T>::~RBTree() {
-    assert(node_count_ == 0);
-}
-
-template <typename T>
-void
-RBTree<T>::deleteHelper(util::MemorySegment& mem_sgmt, RBNode<T>* root) {
-    while (root != NULL) {
-        // If there is a left, right or down node, walk into it and
-        // iterate.
-        if (root->getLeft() != NULL) {
-            RBNode<T>* node = root;
-            root = root->getLeft();
-            node->left_ = NULL;
-        } else if (root->getRight() != NULL) {
-            RBNode<T>* node = root;
-            root = root->getRight();
-            node->right_ = NULL;
-        } else if (root->getDown() != NULL) {
-            RBNode<T>* node = root;
-            root = root->getDown();
-            node->down_ = NULL;
-        } else {
-            // There are no left, right or down nodes, so we can
-            // free this one and go back to its parent.
-            RBNode<T>* node = root;
-            root = root->getParent();
-            RBNode<T>::destroy(mem_sgmt, node);
-            --node_count_;
-        }
-    }
-}
-
-template <typename T>
-template <typename CBARG>
-typename RBTree<T>::Result
-RBTree<T>::find(const isc::dns::LabelSequence& target_labels_orig,
-                RBNode<T>** target,
-                RBTreeNodeChain<T>& node_path,
-                bool (*callback)(const RBNode<T>&, CBARG),
-                CBARG callback_arg) const
-{
-    if (!node_path.isEmpty()) {
-        isc_throw(isc::BadValue, "RBTree::find is given a non empty chain");
-    }
-
-    RBNode<T>* node = root_.get();
-    Result ret = NOTFOUND;
-    dns::LabelSequence target_labels(target_labels_orig);
-
-    while (node != NULL) {
-        node_path.last_compared_ = node;
-        node_path.last_comparison_ = target_labels.compare(node->getLabels());
-        const isc::dns::NameComparisonResult::NameRelation relation =
-            node_path.last_comparison_.getRelation();
-
-        if (relation == isc::dns::NameComparisonResult::EQUAL) {
-            if (needsReturnEmptyNode_ || !node->isEmpty()) {
-                node_path.push(node);
-                *target = node;
-                ret = EXACTMATCH;
-            }
-            break;
-        } else if (relation == isc::dns::NameComparisonResult::NONE) {
-            // If the two labels have no hierarchical relationship in terms
-            // of matching, we should continue the binary search.
-            node = (node_path.last_comparison_.getOrder() < 0) ?
-                node->getLeft() : node->getRight();
-        } else {
-            if (relation == isc::dns::NameComparisonResult::SUBDOMAIN) {
-                if (needsReturnEmptyNode_ || !node->isEmpty()) {
-                    ret = PARTIALMATCH;
-                    *target = node;
-                    if (callback != NULL &&
-                        node->getFlag(RBNode<T>::FLAG_CALLBACK)) {
-                        if ((callback)(*node, callback_arg)) {
-                            break;
-                        }
-                    }
-                }
-                node_path.push(node);
-                target_labels.stripRight(
-                    node_path.last_comparison_.getCommonLabels());
-                node = node->getDown();
-            } else {
-                break;
-            }
-        }
-    }
-
-    return (ret);
-}
-
-template <typename T>
-const RBNode<T>*
-RBTree<T>::nextNode(RBTreeNodeChain<T>& node_path) const {
-    if (node_path.isEmpty()) {
-        isc_throw(isc::BadValue, "RBTree::nextNode is given an empty chain");
-    }
-
-    const RBNode<T>* node = node_path.top();
-    // if node has sub domain, the next domain is the smallest
-    // domain in sub domain tree
-    const RBNode<T>* down = node->getDown();
-    if (down != NULL) {
-        const RBNode<T>* left_most = down;
-        while (left_most->getLeft() != NULL) {
-            left_most = left_most->getLeft();
-        }
-        node_path.push(left_most);
-        return (left_most);
-    }
-
-    // try to find a successor.
-    // if no successor found move to up level, the next successor
-    // is the successor of up node in the up level tree, if
-    // up node doesn't have successor we gonna keep moving to up
-    // level
-    while (!node_path.isEmpty()) {
-        const RBNode<T>* up_node_successor = node_path.top()->successor();
-        node_path.pop();
-        if (up_node_successor != NULL) {
-            node_path.push(up_node_successor);
-            return (up_node_successor);
-        }
-    }
-
-    return (NULL);
-}
-
-template <typename T>
-const RBNode<T>*
-RBTree<T>::previousNode(RBTreeNodeChain<T>& node_path) const {
-    if (getNodeCount() == 0) {
-        // Special case for empty trees. It would look every time like
-        // we didn't search, because the last compared is empty. This is
-        // a slight hack and not perfect, but this is better than throwing
-        // on empty tree. And we probably won't meet an empty tree in practice
-        // anyway.
-        return (NULL);
-    }
-    if (node_path.last_compared_ == NULL) {
-        isc_throw(isc::BadValue,
-                  "RBTree::previousNode() called before find()");
-    }
-
-    // If the relation isn't EQUAL, it means the find was called previously
-    // and didn't find the exact node. Therefore we need to locate the place
-    // to start iterating the chain of domains.
-    //
-    // The logic here is not too complex, we just need to take care to handle
-    // all the cases and decide where to go from there.
-    switch (node_path.last_comparison_.getRelation()) {
-        case dns::NameComparisonResult::COMMONANCESTOR:
-        case dns::NameComparisonResult::NONE:
-            // We compared with a leaf in the tree and wanted to go to one of
-            // the children. But the child was not there. It now depends on the
-            // direction in which we wanted to go.
-            if (node_path.last_comparison_.getOrder() < 0) {
-                // We wanted to go left. So the one we compared with is
-                // the one higher than we wanted. If we just put it into
-                // the node_path, then the following algorithm below will find
-                // the smaller one.
-                //
-                // This is exactly the same as with superdomain below.
-                // Therefore, we just fall through to the next case.
-            } else {
-                // We wanted to go right. That means we want to output the
-                // one which is the largest in the tree defined by the
-                // compared one (it is either the compared one, or some
-                // subdomain of it). There probably is not an easy trick
-                // for this, so we just find the correct place.
-                const RBNode<T>* current(node_path.last_compared_);
-                while (current != NULL) {
-                    node_path.push(current);
-                    // Go a level down and as much right there as possible
-                    current = current->getDown();
-                    if (current != NULL) {
-                        const RBNode<T>* right;
-                        while ((right = current->getRight()) != NULL) {
-                            current = right;
-                        }
-                    }
-                }
-                // Now, the one on top of the path is the one we want. We
-                // return it now and leave it there, so we can search for
-                // previous of it the next time we'are called.
-                node_path.last_comparison_ =
-                    dns::NameComparisonResult(0, 0,
-                                              dns::NameComparisonResult::EQUAL);
-                return (node_path.top());
-            }
-            // No break; here - we want to fall through. See above.
-        case dns::NameComparisonResult::SUPERDOMAIN:
-            // This is the case there's a "compressed" node and we looked for
-            // only part of it. The node itself is larger than we wanted, but
-            // if we put it to the node_path and then go one step left from it,
-            // we get the correct result.
-            node_path.push(node_path.last_compared_);
-            // Correct the comparison result, so we won't trigger this case
-            // next time previousNode is called. We already located the correct
-            // place to start. The value is partly nonsense, but that doesn't
-            // matter any more.
-            node_path.last_comparison_ =
-                dns::NameComparisonResult(0, 0,
-                                          dns::NameComparisonResult::EQUAL);
-            break;
-        case dns::NameComparisonResult::SUBDOMAIN:
-            // A subdomain means we returned the one above the searched one
-            // already and it is on top of the stack. This is was smaller
-            // than the one already, but we want to return yet smaller one.
-            // So we act as if it was EQUAL.
-            break;
-        case dns::NameComparisonResult::EQUAL:
-            // The find gave us an exact match or the previousNode was called
-            // already, which located the exact node. The rest of the function
-            // goes one domain left and returns it for us.
-            break;
-    }
-
-    // So, the node_path now contains the path to a node we want previous for.
-    // We just need to go one step left.
-
-    if (node_path.isEmpty()) {
-        // We got past the first one. So, we're returning NULL from
-        // now on.
-        return (NULL);
-    }
-
-    const RBNode<T>* node(node_path.top());
-
-    // Try going left in this tree
-    node = node->predecessor();
-    if (node == NULL) {
-        // We are the smallest ones in this tree. We go one level
-        // up. That one is the smaller one than us.
-
-        node_path.pop();
-        if (node_path.isEmpty()) {
-            // We're past the first one
-            return (NULL);
-        } else {
-            return (node_path.top());
-        }
-    }
-
-    // Exchange the node at the top of the path, as we move horizontaly
-    // through the domain tree
-    node_path.pop();
-    node_path.push(node);
-
-    // Try going as deep as possible, keeping on the right side of the trees
-    const RBNode<T>* down;
-    while ((down = node->getDown()) != NULL) {
-        // Move to the tree below
-        node = down;
-        if (node != NULL) {
-            // And get as much to the right of the tree as possible
-            const RBNode<T>* right;
-            while ((right = node->getRight()) != NULL) {
-                node = right;
-            }
-        }
-        // Now, we found the right-most node in the sub-tree, we need to
-        // include it in the path
-        node_path.push(node);
-    }
-
-    // Now, if the current node has no down_ pointer any more, it's the
-    // correct one.
-    return (node);
-}
-
-template <typename T>
-typename RBTree<T>::Result
-RBTree<T>::insert(util::MemorySegment& mem_sgmt,
-                  const isc::dns::Name& target_name, RBNode<T>** new_node)
-{
-    RBNode<T>* parent = NULL;
-    RBNode<T>* current = root_.get();
-    RBNode<T>* up_node = NULL;
-    isc::dns::LabelSequence target_labels(target_name);
-
-    int order = -1;
-    // For possible LabelSequence serialization we always store labels data
-    // in the separate local buffer.
-    uint8_t labels_buf[dns::LabelSequence::MAX_SERIALIZED_LENGTH];
-    while (current != NULL) {
-        const dns::LabelSequence current_labels(
-            dns::LabelSequence(current->getLabels(), labels_buf));
-        const isc::dns::NameComparisonResult compare_result =
-            target_labels.compare(current_labels);
-        const isc::dns::NameComparisonResult::NameRelation relation =
-            compare_result.getRelation();
-        if (relation == isc::dns::NameComparisonResult::EQUAL) {
-            if (new_node != NULL) {
-                *new_node = current;
-            }
-            return (ALREADYEXISTS);
-        } else if (relation == isc::dns::NameComparisonResult::NONE) {
-            parent = current;
-            order = compare_result.getOrder();
-            current = order < 0 ? current->getLeft() : current->getRight();
-        } else if (relation == isc::dns::NameComparisonResult::SUBDOMAIN) {
-            // insert sub domain to sub tree
-            parent = NULL;
-            up_node = current;
-            target_labels.stripRight(compare_result.getCommonLabels());
-            current = current->getDown();
-        } else {
-            // The number of labels in common is fewer than the number of
-            // labels at the current node, so the current node must be
-            // adjusted to have just the common suffix, and a down pointer
-            // made to a new tree.
-            dns::LabelSequence common_ancestor = target_labels;
-            common_ancestor.stripLeft(target_labels.getLabelCount() -
-                                      compare_result.getCommonLabels());
-            dns::LabelSequence new_prefix = current_labels;
-            new_prefix.stripRight(compare_result.getCommonLabels());
-            nodeFission(mem_sgmt, *current, new_prefix, common_ancestor);
-            current = current->getParent();
-        }
-    }
-
-    typename RBNode<T>::RBNodePtr* current_root = (up_node != NULL) ?
-        &(up_node->down_) : &root_;
-    // Once a new node is created, no exception will be thrown until the end
-    // of the function, so we can simply create and hold a new node pointer.
-    RBNode<T>* node = RBNode<T>::create(mem_sgmt, target_labels);
-    node->parent_ = parent;
-    if (parent == NULL) {
-        *current_root = node;
-        // node is the new root of sub tree, so its init color is BLACK
-        node->setColor(RBNode<T>::BLACK);
-        node->setSubTreeRoot(true);
-        node->parent_ = up_node;
-    } else if (order < 0) {
-        node->setSubTreeRoot(false);
-        parent->left_ = node;
-    } else {
-        node->setSubTreeRoot(false);
-        parent->right_ = node;
-    }
-    insertRebalance(current_root, node);
-    if (new_node != NULL) {
-        *new_node = node;
-    }
-
-    ++node_count_;
-    return (SUCCESS);
-}
-
-template <typename T>
-void
-RBTree<T>::deleteAllNodes(util::MemorySegment& mem_sgmt) {
-    deleteHelper(mem_sgmt, root_.get());
-    root_ = NULL;
-}
-
-template <typename T>
-void
-RBTree<T>::nodeFission(util::MemorySegment& mem_sgmt, RBNode<T>& node,
-                       const isc::dns::LabelSequence& new_prefix,
-                       const isc::dns::LabelSequence& new_suffix)
-{
-    // Create and reset the labels.
-    // Once a new node is created, no exception will be thrown until
-    // the end of the function, and it will keep consistent behavior
-    // (i.e., a weak form of strong exception guarantee) even if code
-    // after the call to this function throws an exception.
-    RBNode<T>* up_node = RBNode<T>::create(mem_sgmt, new_suffix);
-    node.resetLabels(new_prefix);
-
-    up_node->parent_ = node.getParent();
-    if (node.getParent() != NULL) {
-        if (node.getParent()->getLeft() == &node) {
-            node.getParent()->left_ = up_node;
-        } else if (node.getParent()->getRight() == &node) {
-            node.getParent()->right_ = up_node;
-        } else {
-            node.getParent()->down_ = up_node;
-        }
-    } else {
-        this->root_ = up_node;
-    }
-
-    up_node->down_ = &node;
-    node.parent_ = up_node;
-
-    // inherit the left/right pointers from the original node, and set
-    // the original node's left/right pointers to NULL.
-    up_node->left_ = node.getLeft();
-    if (node.getLeft() != NULL) {
-        node.getLeft()->parent_ = up_node;
-    }
-    up_node->right_ = node.getRight();
-    if (node.getRight() != NULL) {
-        node.getRight()->parent_ = up_node;
-    }
-    node.left_ = NULL;
-    node.right_ = NULL;
-
-    // set color of both nodes; the initial subtree node color is BLACK
-    up_node->setColor(node.getColor());
-    node.setColor(RBNode<T>::BLACK);
-
-    // set the subtree root flag of both nodes
-    up_node->setSubTreeRoot(node.isSubTreeRoot());
-    node.setSubTreeRoot(true);
-
-    ++node_count_;
-}
-
-
-template <typename T>
-void
-RBTree<T>::insertRebalance(typename RBNode<T>::RBNodePtr* root,
-                           RBNode<T>* node)
-{
-    RBNode<T>* uncle;
-    RBNode<T>* parent;
-    while (node != (*root).get() &&
-           (parent = node->getParent())->getColor() == RBNode<T>::RED) {
-        // Here, node->parent_ is not NULL and it is also red, so
-        // node->parent_->parent_ is also not NULL.
-        if (parent == parent->getParent()->getLeft()) {
-            uncle = parent->getParent()->getRight();
-
-            if (uncle != NULL && uncle->getColor() == RBNode<T>::RED) {
-                parent->setColor(RBNode<T>::BLACK);
-                uncle->setColor(RBNode<T>::BLACK);
-                parent->getParent()->setColor(RBNode<T>::RED);
-                node = parent->getParent();
-            } else {
-                if (node == parent->getRight()) {
-                    node = parent;
-                    leftRotate(root, node);
-                    parent = node->getParent();
-                }
-                parent->setColor(RBNode<T>::BLACK);
-                parent->getParent()->setColor(RBNode<T>::RED);
-                rightRotate(root, parent->getParent());
-            }
-        } else {
-            uncle = parent->getParent()->getLeft();
-            if (uncle != NULL && uncle->getColor() == RBNode<T>::RED) {
-                parent->setColor(RBNode<T>::BLACK);
-                uncle->setColor(RBNode<T>::BLACK);
-                parent->getParent()->setColor(RBNode<T>::RED);
-                node = parent->getParent();
-            } else {
-                if (node == parent->getLeft()) {
-                    node = parent;
-                    rightRotate(root, node);
-                    parent = node->getParent();
-                }
-                parent->setColor(RBNode<T>::BLACK);
-                parent->getParent()->setColor(RBNode<T>::RED);
-                leftRotate(root, parent->getParent());
-            }
-        }
-    }
-
-    (*root)->setColor(RBNode<T>::BLACK);
-}
-
-
-template <typename T>
-RBNode<T>*
-RBTree<T>::leftRotate(typename RBNode<T>::RBNodePtr* root, RBNode<T>* node) {
-    RBNode<T>* const right = node->getRight();
-    RBNode<T>* const rleft = right->getLeft();
-    node->right_ = rleft;
-    if (rleft != NULL) {
-        rleft->parent_ = node;
-    }
-
-    RBNode<T>* const parent = node->getParent();
-    right->parent_ = parent;
-
-    if (!node->isSubTreeRoot()) {
-        right->setSubTreeRoot(false);
-        if (node == parent->getLeft()) {
-            parent->left_ = right;
-        } else  {
-            parent->right_ = right;
-        }
-    } else {
-        right->setSubTreeRoot(true);
-        *root = right;
-    }
-
-    right->left_ = node;
-    node->parent_ = right;
-    node->setSubTreeRoot(false);
-    return (node);
-}
-
-template <typename T>
-RBNode<T>*
-RBTree<T>::rightRotate(typename RBNode<T>::RBNodePtr* root, RBNode<T>* node) {
-    RBNode<T>* const left = node->getLeft();
-    RBNode<T>* const lright = left->getRight();
-    node->left_ = lright;
-    if (lright != NULL) {
-        lright->parent_ = node;
-    }
-
-    RBNode<T>* const parent = node->getParent();
-    left->parent_ = parent;
-
-    if (!node->isSubTreeRoot()) {
-        left->setSubTreeRoot(false);
-        if (node == parent->getRight()) {
-            parent->right_ = left;
-        } else  {
-            parent->left_ = left;
-        }
-    } else {
-        left->setSubTreeRoot(true);
-        *root = left;
-    }
-    left->right_ = node;
-    node->parent_ = left;
-    node->setSubTreeRoot(false);
-
-    return (node);
-}
-
-
-template <typename T>
-void
-RBTree<T>::dumpTree(std::ostream& os, unsigned int depth) const {
-    indent(os, depth);
-    os << "tree has " << node_count_ << " node(s)\n";
-    dumpTreeHelper(os, root_.get(), depth);
-}
-
-template <typename T>
-void
-RBTree<T>::dumpTreeHelper(std::ostream& os, const RBNode<T>* node,
-                          unsigned int depth) const
-{
-    if (node == NULL) {
-        indent(os, depth);
-        os << "NULL\n";
-        return;
-    }
-
-    indent(os, depth);
-    os << node->getLabels() << " ("
-       << ((node->getColor() == RBNode<T>::BLACK) ? "black" : "red")
-       << ")";
-    if (node->isEmpty()) {
-        os << " [invisible]";
-    }
-    if (node->isSubTreeRoot()) {
-        os << " [subtreeroot]";
-    }
-    os << "\n";
-
-    const RBNode<T>* down = node->getDown();
-    if (down != NULL) {
-        indent(os, depth + 1);
-        os << "begin down from " << node->getLabels() << "\n";
-        dumpTreeHelper(os, down, depth + 1);
-        indent(os, depth + 1);
-        os << "end down from " << node->getLabels() << "\n";
-    }
-    dumpTreeHelper(os, node->getLeft(), depth + 1);
-    dumpTreeHelper(os, node->getRight(), depth + 1);
-}
-
-template <typename T>
-void
-RBTree<T>::indent(std::ostream& os, unsigned int depth) {
-    static const unsigned int INDENT_FOR_EACH_DEPTH = 5;
-    os << std::string(depth * INDENT_FOR_EACH_DEPTH, ' ');
-}
-
-template <typename T>
-void
-RBTree<T>::dumpDot(std::ostream& os, bool show_pointers) const {
-    int nodecount = 0;
-
-    os << "digraph g {\n";
-    os << "node [shape = record,height=.1];\n";
-    dumpDotHelper(os, root_.get(), &nodecount, show_pointers);
-    os << "}\n";
-}
-
-template <typename T>
-int
-RBTree<T>::dumpDotHelper(std::ostream& os, const RBNode<T>* node,
-                         int* nodecount, bool show_pointers) const
-{
-    if (node == NULL) {
-        return 0;
-    }
-
-    int l = dumpDotHelper(os, node->getLeft(), nodecount, show_pointers);
-    int r = dumpDotHelper(os, node->getRight(), nodecount, show_pointers);
-    int d = dumpDotHelper(os, node->getDown(), nodecount, show_pointers);
-
-    *nodecount += 1;
-
-    os << "node" << *nodecount <<
-          "[label = \"<f0> |<f1> " << node->getLabels() <<
-          "|<f2>";
-    if (show_pointers) {
-        os << "|<f3> n=" << node << "|<f4> p=" << node->getParent();
-    }
-    os << "\"] [";
-
-    if (node->getColor() == RBNode<T>::RED) {
-        os << "color=red";
-    } else {
-        os << "color=black";
-    }
-
-    if (node->isSubTreeRoot()) {
-        os << ",penwidth=3";
-    }
-
-    if (node->isEmpty()) {
-        os << ",style=filled,fillcolor=lightgrey";
-    }
-
-    os << "];\n";
-
-    if (node->getLeft() != NULL) {
-        os << "\"node" << *nodecount << "\":f0 -> \"node" << l << "\":f1;\n";
-    }
-
-    if (node->getDown() != NULL) {
-        os << "\"node" << *nodecount << "\":f1 -> \"node" << d << "\":f1 [penwidth=5];\n";
-    }
-
-    if (node->getRight() != NULL) {
-        os << "\"node" << *nodecount << "\":f2 -> \"node" << r << "\":f1;\n";
-    }
-
-    return (*nodecount);
-}
-
-}
-}
-
-#endif  // RBTREE_H
-
-// Local Variables:
-// mode: c++
-// End:
diff --git a/src/lib/datasrc/static_datasrc.h b/src/lib/datasrc/static_datasrc.h
new file mode 100644
index 0000000..d5d8875
--- /dev/null
+++ b/src/lib/datasrc/static_datasrc.h
@@ -0,0 +1,50 @@
+// Copyright (C) 2013  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+
+#ifndef DATASRC_STATIC_H
+#define DATASRC_STATIC_H
+
+#include <datasrc/database.h>
+#include <cc/data.h>
+
+#include <string>
+
+namespace isc {
+namespace datasrc {
+
+/// \brief Creates an instance of the static datasource client
+///
+/// Currently the configuration passed here must be a StringElement,
+/// containing the path to a zone file for the BIND./CH zone.
+///
+/// \param config The configuration for the datasource instance (see above)
+/// \param error This string will be set to an error message if an error occurs
+///              during initialization
+/// \return An instance of the static datasource client, or NULL if there was
+///         an error
+extern "C" DataSourceClient* createInstance(isc::data::ConstElementPtr config,
+                                            std::string& error);
+
+/// \brief Destroy the instance created by createInstance()
+extern "C" void destroyInstance(DataSourceClient* instance);
+
+}
+}
+
+#endif  // DATASRC_STATIC_H
+
+// Local Variables:
+// mode: c++
+// End:
diff --git a/src/lib/datasrc/static_datasrc_link.cc b/src/lib/datasrc/static_datasrc_link.cc
index 789580d..1b767a4 100644
--- a/src/lib/datasrc/static_datasrc_link.cc
+++ b/src/lib/datasrc/static_datasrc_link.cc
@@ -13,7 +13,9 @@
 // PERFORMANCE OF THIS SOFTWARE.
 
 #include "client.h"
-#include "memory_datasrc.h"
+#include "static_datasrc.h"
+#include <datasrc/memory/memory_client.h>
+#include <datasrc/memory/zone_table_segment.h>
 
 #include <cc/data.h>
 #include <dns/rrclass.h>
@@ -32,16 +34,20 @@ namespace datasrc {
 DataSourceClient*
 createInstance(ConstElementPtr config, string& error) {
     try {
+        // FIXME: Fix the config that should be passed to
+        // ZoneTableSegment::create() when it actually uses the config
+        // to do something.
+        shared_ptr<memory::ZoneTableSegment> ztable_segment(
+            memory::ZoneTableSegment::create(isc::data::NullElement(),
+                                             RRClass::CH()));
         // Create the data source
-        auto_ptr<InMemoryClient> client(new InMemoryClient());
-        // Hardcode the origin and class
-        shared_ptr<InMemoryZoneFinder>
-            finder(new InMemoryZoneFinder(RRClass::CH(), Name("BIND")));
+        auto_ptr<memory::InMemoryClient> client
+            (new memory::InMemoryClient(ztable_segment, RRClass::CH()));
+
         // Fill it with data
         const string path(config->stringValue());
-        finder->load(path);
-        // And put the zone inside
-        client->addZone(finder);
+        client->load(Name("BIND"), path);
+
         return (client.release());
     }
     catch (const std::exception& e) {
diff --git a/src/lib/datasrc/tests/Makefile.am b/src/lib/datasrc/tests/Makefile.am
index 7c61826..c1e7d4e 100644
--- a/src/lib/datasrc/tests/Makefile.am
+++ b/src/lib/datasrc/tests/Makefile.am
@@ -48,14 +48,10 @@ common_ldadd += $(GTEST_LDADD) $(SQLITE_LIBS)
 run_unittests_SOURCES = $(common_sources)
 
 run_unittests_SOURCES += test_client.h test_client.cc
-run_unittests_SOURCES += rbtree_unittest.cc
 run_unittests_SOURCES += logger_unittest.cc
 run_unittests_SOURCES += client_unittest.cc
 run_unittests_SOURCES += database_unittest.cc
 run_unittests_SOURCES += sqlite3_accessor_unittest.cc
-run_unittests_SOURCES += memory_datasrc_unittest.cc
-run_unittests_SOURCES += rbnode_rrset_unittest.cc
-run_unittests_SOURCES += zonetable_unittest.cc
 run_unittests_SOURCES += zone_finder_context_unittest.cc
 run_unittests_SOURCES += faked_nsec3.h faked_nsec3.cc
 run_unittests_SOURCES += client_list_unittest.cc
@@ -118,5 +114,6 @@ EXTRA_DIST += testdata/new_minor_schema.sqlite3
 EXTRA_DIST += testdata/newschema.sqlite3
 EXTRA_DIST += testdata/oldschema.sqlite3
 EXTRA_DIST += testdata/static.zone
+EXTRA_DIST += testdata/static-bad.zone
 EXTRA_DIST += testdata/novalidate.zone
 EXTRA_DIST += testdata/checkwarn.zone
diff --git a/src/lib/datasrc/tests/factory_unittest.cc b/src/lib/datasrc/tests/factory_unittest.cc
index 2031d50..cc03ce3 100644
--- a/src/lib/datasrc/tests/factory_unittest.cc
+++ b/src/lib/datasrc/tests/factory_unittest.cc
@@ -29,6 +29,7 @@ using namespace isc::data;
 
 std::string SQLITE_DBFILE_EXAMPLE_ORG = TEST_DATA_DIR "/example.org.sqlite3";
 const std::string STATIC_DS_FILE = TEST_DATA_DIR "/static.zone";
+const std::string STATIC_BAD_DS_FILE = TEST_DATA_DIR "/static-bad.zone";
 const std::string ROOT_ZONE_FILE = TEST_DATA_DIR "/root.zone";
 
 namespace {
@@ -160,78 +161,6 @@ TEST(FactoryTest, sqlite3ClientBadConfig) {
         isc::dns::Name("example.org."), false));
 }
 
-TEST(FactoryTest, memoryClient) {
-    // We start out by building the configuration data bit by bit,
-    // testing each form of 'bad config', until we have a good one.
-    // Then we do some very basic operation on the client (detailed
-    // tests are left to the implementation-specific backends)
-    ElementPtr config;
-    ASSERT_THROW(DataSourceClientContainer client("memory", config),
-                 DataSourceError);
-
-    config = Element::create("asdf");
-    ASSERT_THROW(DataSourceClientContainer("memory", config),
-                 DataSourceError);
-
-    config = Element::createMap();
-    ASSERT_THROW(DataSourceClientContainer("memory", config),
-                 DataSourceError);
-
-    config->set("type", ElementPtr());
-    ASSERT_THROW(DataSourceClientContainer("memory", config),
-                 DataSourceError);
-
-    config->set("type", Element::create(1));
-    ASSERT_THROW(DataSourceClientContainer("memory", config),
-                 DataSourceError);
-
-    config->set("type", Element::create("FOO"));
-    ASSERT_THROW(DataSourceClientContainer("memory", config),
-                 DataSourceError);
-
-    config->set("type", Element::create("memory"));
-    // no config at all should result in a default empty memory client
-    ASSERT_NO_THROW(DataSourceClientContainer("memory", config));
-
-    config->set("class", ElementPtr());
-    ASSERT_THROW(DataSourceClientContainer("memory", config),
-                 DataSourceError);
-
-    config->set("class", Element::create(1));
-    ASSERT_THROW(DataSourceClientContainer("memory", config),
-                 DataSourceError);
-
-    config->set("class", Element::create("FOO"));
-    ASSERT_THROW(DataSourceClientContainer("memory", config),
-                 DataSourceError);
-
-    config->set("class", Element::create("IN"));
-    ASSERT_NO_THROW(DataSourceClientContainer("memory", config));
-
-    config->set("zones", ElementPtr());
-    ASSERT_THROW(DataSourceClientContainer("memory", config),
-                 DataSourceError);
-
-    config->set("zones", Element::create(1));
-    ASSERT_THROW(DataSourceClientContainer("memory", config),
-                 DataSourceError);
-
-    config->set("zones", Element::createList());
-    DataSourceClientContainer dsc("memory", config);
-
-    // Once it is able to load some zones, we should add a few tests
-    // here to see that it does.
-    DataSourceClient::FindResult result(
-        dsc.getInstance().findZone(isc::dns::Name("no.such.zone.")));
-    ASSERT_EQ(result::NOTFOUND, result.code);
-
-    ASSERT_THROW(dsc.getInstance().getIterator(isc::dns::Name("example.org.")),
-                 DataSourceError);
-
-    ASSERT_THROW(dsc.getInstance().getUpdater(isc::dns::Name("no.such.zone."),
-                                              false), isc::NotImplemented);
-}
-
 TEST(FactoryTest, badType) {
     ASSERT_THROW(DataSourceClientContainer("foo", ElementPtr()),
                                            DataSourceError);
@@ -259,13 +188,9 @@ TEST(FactoryTest, staticDS) {
 }
 
 // Check that file not containing BIND./CH is rejected
-//
-// FIXME: This test is disabled because the InMemoryZoneFinder::load does
-// not check if the data loaded correspond with the origin. The static
-// factory is not the place to fix that.
-TEST(FactoryTest, DISABLED_staticDSBadFile) {
+TEST(FactoryTest, staticDSBadFile) {
     // The only configuration is the file to load.
-    const ConstElementPtr config(new StringElement(STATIC_DS_FILE));
+    const ConstElementPtr config(new StringElement(STATIC_BAD_DS_FILE));
     // See it does not want the file
     EXPECT_THROW(DataSourceClientContainer("static", config), DataSourceError);
 }
diff --git a/src/lib/datasrc/tests/memory_datasrc_unittest.cc b/src/lib/datasrc/tests/memory_datasrc_unittest.cc
deleted file mode 100644
index f7a478b..0000000
--- a/src/lib/datasrc/tests/memory_datasrc_unittest.cc
+++ /dev/null
@@ -1,2246 +0,0 @@
-// Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#include "faked_nsec3.h"
-
-#include <exceptions/exceptions.h>
-
-#include <dns/masterload.h>
-#include <dns/name.h>
-#include <dns/nsec3hash.h>
-#include <dns/rdata.h>
-#include <dns/rdataclass.h>
-#include <dns/rrclass.h>
-#include <dns/rrttl.h>
-#include <dns/masterload.h>
-
-#include <datasrc/client.h>
-#include <datasrc/memory_datasrc.h>
-#include <datasrc/data_source.h>
-#include <datasrc/zone_iterator.h>
-
-#include "test_client.h"
-
-#include <testutils/dnsmessage_test.h>
-
-#include <gtest/gtest.h>
-
-#include <boost/bind.hpp>
-#include <boost/foreach.hpp>
-#include <boost/shared_ptr.hpp>
-
-#include <sstream>
-#include <vector>
-
-using namespace std;
-using namespace isc::dns;
-using namespace isc::dns::rdata;
-using namespace isc::datasrc;
-using namespace isc::testutils;
-using boost::shared_ptr;
-using namespace isc::datasrc::test;
-
-namespace {
-// Commonly used result codes (Who should write the prefix all the time)
-using result::SUCCESS;
-using result::EXIST;
-
-class InMemoryClientTest : public ::testing::Test {
-protected:
-    InMemoryClientTest() : rrclass(RRClass::IN())
-    {}
-    RRClass rrclass;
-    InMemoryClient memory_client;
-};
-
-TEST_F(InMemoryClientTest, add_find_Zone) {
-    // test add zone
-    // Bogus zone (NULL)
-    EXPECT_THROW(memory_client.addZone(ZoneFinderPtr()),
-                 isc::InvalidParameter);
-
-    // add zones with different names one by one
-    EXPECT_EQ(result::SUCCESS, memory_client.addZone(
-                  ZoneFinderPtr(new InMemoryZoneFinder(RRClass::IN(),
-                                                       Name("a")))));
-    EXPECT_EQ(result::SUCCESS, memory_client.addZone(
-                  ZoneFinderPtr(new InMemoryZoneFinder(RRClass::CH(),
-                                                       Name("b")))));
-    EXPECT_EQ(result::SUCCESS, memory_client.addZone(
-                  ZoneFinderPtr(new InMemoryZoneFinder(RRClass::IN(),
-                                                       Name("c")))));
-    // add zones with the same name suffix
-    EXPECT_EQ(result::SUCCESS, memory_client.addZone(
-                  ZoneFinderPtr(new InMemoryZoneFinder(RRClass::CH(),
-                                                       Name("x.d.e.f")))));
-    EXPECT_EQ(result::SUCCESS, memory_client.addZone(
-                  ZoneFinderPtr(new InMemoryZoneFinder(RRClass::CH(),
-                                                       Name("o.w.y.d.e.f")))));
-    EXPECT_EQ(result::SUCCESS, memory_client.addZone(
-                  ZoneFinderPtr(new InMemoryZoneFinder(RRClass::CH(),
-                                                       Name("p.w.y.d.e.f")))));
-    EXPECT_EQ(result::SUCCESS, memory_client.addZone(
-                  ZoneFinderPtr(new InMemoryZoneFinder(RRClass::IN(),
-                                                       Name("q.w.y.d.e.f")))));
-    // add super zone and its subzone
-    EXPECT_EQ(result::SUCCESS, memory_client.addZone(
-                  ZoneFinderPtr(new InMemoryZoneFinder(RRClass::CH(),
-                                                       Name("g.h")))));
-    EXPECT_EQ(result::SUCCESS, memory_client.addZone(
-                  ZoneFinderPtr(new InMemoryZoneFinder(RRClass::IN(),
-                                               Name("i.g.h")))));
-    EXPECT_EQ(result::SUCCESS, memory_client.addZone(
-                  ZoneFinderPtr(new InMemoryZoneFinder(RRClass::IN(),
-                                                       Name("z.d.e.f")))));
-    EXPECT_EQ(result::SUCCESS, memory_client.addZone(
-                  ZoneFinderPtr(new InMemoryZoneFinder(RRClass::IN(),
-                                                       Name("j.z.d.e.f")))));
-
-    // different zone class isn't allowed.
-    EXPECT_EQ(result::EXIST, memory_client.addZone(
-                  ZoneFinderPtr(new InMemoryZoneFinder(RRClass::CH(),
-                                                       Name("q.w.y.d.e.f")))));
-
-    // names are compared in a case insensitive manner.
-    EXPECT_EQ(result::EXIST, memory_client.addZone(
-                  ZoneFinderPtr(new InMemoryZoneFinder(RRClass::IN(),
-                                                       Name("Q.W.Y.d.E.f")))));
-
-    // test find zone
-    EXPECT_EQ(result::SUCCESS, memory_client.findZone(Name("a")).code);
-    EXPECT_EQ(Name("a"),
-              memory_client.findZone(Name("a")).zone_finder->getOrigin());
-
-    EXPECT_EQ(result::SUCCESS,
-              memory_client.findZone(Name("j.z.d.e.f")).code);
-    EXPECT_EQ(Name("j.z.d.e.f"),
-              memory_client.findZone(Name("j.z.d.e.f")).zone_finder->
-                  getOrigin());
-
-    // NOTFOUND
-    EXPECT_EQ(result::NOTFOUND, memory_client.findZone(Name("d.e.f")).code);
-    EXPECT_EQ(ConstZoneFinderPtr(),
-              memory_client.findZone(Name("d.e.f")).zone_finder);
-
-    EXPECT_EQ(result::NOTFOUND,
-              memory_client.findZone(Name("w.y.d.e.f")).code);
-    EXPECT_EQ(ConstZoneFinderPtr(),
-              memory_client.findZone(Name("w.y.d.e.f")).zone_finder);
-
-    // there's no exact match.  the result should be the longest match,
-    // and the code should be PARTIALMATCH.
-    EXPECT_EQ(result::PARTIALMATCH,
-              memory_client.findZone(Name("j.g.h")).code);
-    EXPECT_EQ(Name("g.h"),
-              memory_client.findZone(Name("g.h")).zone_finder->getOrigin());
-
-    EXPECT_EQ(result::PARTIALMATCH,
-              memory_client.findZone(Name("z.i.g.h")).code);
-    EXPECT_EQ(Name("i.g.h"),
-              memory_client.findZone(Name("z.i.g.h")).zone_finder->
-                  getOrigin());
-}
-
-TEST_F(InMemoryClientTest, iterator) {
-    // Just some preparations of data
-    boost::shared_ptr<InMemoryZoneFinder>
-        zone(new InMemoryZoneFinder(RRClass::IN(), Name("a")));
-    RRsetPtr aRRsetA(new RRset(Name("a"), RRClass::IN(), RRType::A(),
-                                  RRTTL(300)));
-    aRRsetA->addRdata(rdata::in::A("192.0.2.1"));
-    RRsetPtr aRRsetAAAA(new RRset(Name("a"), RRClass::IN(), RRType::AAAA(),
-                                  RRTTL(300)));
-    aRRsetAAAA->addRdata(rdata::in::AAAA("2001:db8::1"));
-    aRRsetAAAA->addRdata(rdata::in::AAAA("2001:db8::2"));
-    RRsetPtr subRRsetA(new RRset(Name("sub.x.a"), RRClass::IN(), RRType::A(),
-                                  RRTTL(300)));
-    subRRsetA->addRdata(rdata::in::A("192.0.2.2"));
-    EXPECT_EQ(result::SUCCESS, memory_client.addZone(zone));
-    // First, the zone is not there, so it should throw
-    EXPECT_THROW(memory_client.getIterator(Name("b")), DataSourceError);
-    // This zone is not there either, even when there's a zone containing this
-    EXPECT_THROW(memory_client.getIterator(Name("x.a")), DataSourceError);
-    // Now, an empty zone
-    ZoneIteratorPtr iterator(memory_client.getIterator(Name("a")));
-    EXPECT_EQ(ConstRRsetPtr(), iterator->getNextRRset());
-    // It throws Unexpected when we are past the end
-    EXPECT_THROW(iterator->getNextRRset(), isc::Unexpected);
-    EXPECT_EQ(result::SUCCESS, zone->add(aRRsetA));
-    EXPECT_EQ(result::SUCCESS, zone->add(aRRsetAAAA));
-    EXPECT_EQ(result::SUCCESS, zone->add(subRRsetA));
-
-    // Check it with full zone.
-    vector<ConstRRsetPtr> expected_rrsets;
-    expected_rrsets.push_back(aRRsetA);
-    expected_rrsets.push_back(aRRsetAAAA);
-    expected_rrsets.push_back(subRRsetA);
-
-    iterator = memory_client.getIterator(Name("a"));
-    vector<ConstRRsetPtr> actual_rrsets;
-    ConstRRsetPtr actual;
-    while ((actual = iterator->getNextRRset()) != NULL) {
-        actual_rrsets.push_back(actual);
-    }
-
-    rrsetsCheck(expected_rrsets.begin(), expected_rrsets.end(),
-                actual_rrsets.begin(), actual_rrsets.end());
-
-}
-
-TEST_F(InMemoryClientTest, iterator_separate_rrs) {
-    // Exactly the same tests as for iterator, but now with separate_rrs = true
-    // For the one that returns actual data, the AAAA should now be split up
-    boost::shared_ptr<InMemoryZoneFinder>
-        zone(new InMemoryZoneFinder(RRClass::IN(), Name("a")));
-    RRsetPtr aRRsetA(new RRset(Name("a"), RRClass::IN(), RRType::A(),
-                                  RRTTL(300)));
-    aRRsetA->addRdata(rdata::in::A("192.0.2.1"));
-    RRsetPtr aRRsetAAAA(new RRset(Name("a"), RRClass::IN(), RRType::AAAA(),
-                                  RRTTL(300)));
-    aRRsetAAAA->addRdata(rdata::in::AAAA("2001:db8::1"));
-    aRRsetAAAA->addRdata(rdata::in::AAAA("2001:db8::2"));
-    RRsetPtr aRRsetAAAA_r1(new RRset(Name("a"), RRClass::IN(), RRType::AAAA(),
-                                  RRTTL(300)));
-    aRRsetAAAA_r1->addRdata(rdata::in::AAAA("2001:db8::1"));
-    RRsetPtr aRRsetAAAA_r2(new RRset(Name("a"), RRClass::IN(), RRType::AAAA(),
-                                  RRTTL(300)));
-    aRRsetAAAA_r2->addRdata(rdata::in::AAAA("2001:db8::2"));
-
-    RRsetPtr subRRsetA(new RRset(Name("sub.x.a"), RRClass::IN(), RRType::A(),
-                                  RRTTL(300)));
-    subRRsetA->addRdata(rdata::in::A("192.0.2.2"));
-    EXPECT_EQ(result::SUCCESS, memory_client.addZone(zone));
-
-    // First, the zone is not there, so it should throw
-    EXPECT_THROW(memory_client.getIterator(Name("b"), true), DataSourceError);
-    // This zone is not there either, even when there's a zone containing this
-    EXPECT_THROW(memory_client.getIterator(Name("x.a")), DataSourceError);
-    // Now, an empty zone
-    ZoneIteratorPtr iterator(memory_client.getIterator(Name("a"), true));
-    EXPECT_EQ(ConstRRsetPtr(), iterator->getNextRRset());
-    // It throws Unexpected when we are past the end
-    EXPECT_THROW(iterator->getNextRRset(), isc::Unexpected);
-
-    ASSERT_EQ(result::SUCCESS, zone->add(aRRsetA));
-    ASSERT_EQ(result::SUCCESS, zone->add(aRRsetAAAA));
-    ASSERT_EQ(result::SUCCESS, zone->add(subRRsetA));
-    // Check it with full zone, one by one.
-    // It should be in ascending order in case of InMemory data source
-    // (isn't guaranteed in general)
-    iterator = memory_client.getIterator(Name("a"), true);
-    EXPECT_EQ(aRRsetA->toText(), iterator->getNextRRset()->toText());
-    EXPECT_EQ(aRRsetAAAA_r1->toText(), iterator->getNextRRset()->toText());
-    EXPECT_EQ(aRRsetAAAA_r2->toText(), iterator->getNextRRset()->toText());
-    EXPECT_EQ(subRRsetA->toText(), iterator->getNextRRset()->toText());
-    EXPECT_EQ(ConstRRsetPtr(), iterator->getNextRRset());
-}
-
-TEST_F(InMemoryClientTest, getZoneCount) {
-    EXPECT_EQ(0, memory_client.getZoneCount());
-    memory_client.addZone(
-                  ZoneFinderPtr(new InMemoryZoneFinder(rrclass,
-                                                       Name("example.com"))));
-    EXPECT_EQ(1, memory_client.getZoneCount());
-
-    // duplicate add.  counter shouldn't change
-    memory_client.addZone(
-                  ZoneFinderPtr(new InMemoryZoneFinder(rrclass,
-                                                       Name("example.com"))));
-    EXPECT_EQ(1, memory_client.getZoneCount());
-
-    // add one more
-    memory_client.addZone(
-                  ZoneFinderPtr(new InMemoryZoneFinder(rrclass,
-                                                       Name("example.org"))));
-    EXPECT_EQ(2, memory_client.getZoneCount());
-}
-
-TEST_F(InMemoryClientTest, startUpdateZone) {
-    EXPECT_THROW(memory_client.getUpdater(Name("example.org"), false),
-                 isc::NotImplemented);
-}
-
-// Commonly used RRSIG data
-const char* const rrsig_a_txt =
-    "example.org. 300 IN RRSIG A 5 3 3600 20000101000000 20000201000000 12345 "
-    "example.org. FAKEFAKEFAKE\n";
-const char* const rrsig_ns_txt =
-    "example.org. 300 IN RRSIG NS 5 3 3600 20000101000000 20000201000000 "
-    "54321 example.org. FAKEFAKEFAKEFAKE\n";
-// This RRset has two RRSIGs
-const char* const rrsig_aaaa_txt =
-    "ns.example.org. 300 IN RRSIG AAAA 5 3 3600 20000101000000 20000201000000 "
-    "12345 example.org. FAKEFAKEFAKE\n"
-    "ns.example.org. 300 IN RRSIG AAAA 5 3 3600 20000101000000 20000201000000 "
-    "54321 example.org. FAKEFAKEFAKEFAKE\n";
-
-// A helper callback of masterLoad() used in InMemoryZoneFinderTest.
-void
-setRRset(RRsetPtr rrset, vector<RRsetPtr*>::iterator& it) {
-    *(*it) = rrset;
-    ++it;
-}
-
-/// \brief Test fixture for the InMemoryZoneFinder class
-class InMemoryZoneFinderTest : public ::testing::Test {
-    // A straightforward pair of textual RR(set) and a RRsetPtr variable
-    // to store the RRset.  Used to build test data below.
-    struct RRsetData {
-        const char* const text; // textual representation of an RRset
-        RRsetPtr* rrset;
-    };
-protected:
-    // The following sub tests are shared by multiple test cases, changing
-    // the zone's DNSSEC status (unsigned, NSEC-signed or NSEC3-signed).
-    // expected_flags is set to either RESULT_NSEC_SIGNED or
-    // RESULT_NSEC3_SIGNED when it's NSEC/NSEC3 signed respectively and
-    // find() is expected to set the corresponding flags.
-    // find_options should be set to FIND_DNSSEC for NSEC-signed case when
-    // NSEC is expected to be returned.
-    void findCheck(ZoneFinder::FindResultFlags expected_flags =
-                   ZoneFinder::RESULT_DEFAULT,
-                   ZoneFinder::FindOptions find_options =
-                   ZoneFinder::FIND_DEFAULT);
-    void emptyNodeCheck(ZoneFinder::FindResultFlags expected_flags =
-                        ZoneFinder::RESULT_DEFAULT);
-    void wildcardCheck(ZoneFinder::FindResultFlags expected_flags =
-                       ZoneFinder::RESULT_DEFAULT,
-                       ZoneFinder::FindOptions find_options =
-                       ZoneFinder::FIND_DEFAULT);
-    void doCancelWildcardCheck(ZoneFinder::FindResultFlags expected_flags =
-                               ZoneFinder::RESULT_DEFAULT,
-                               ZoneFinder::FindOptions find_options =
-                               ZoneFinder::FIND_DEFAULT);
-    void anyWildcardCheck(ZoneFinder::FindResultFlags expected_flags =
-                          ZoneFinder::RESULT_DEFAULT);
-    void emptyWildcardCheck(ZoneFinder::FindResultFlags expected_flags =
-                            ZoneFinder::RESULT_DEFAULT);
-    void findNSECENTCheck(const Name& ent_name,
-                          ConstRRsetPtr expected_nsec,
-                          ZoneFinder::FindResultFlags expected_flags =
-                          ZoneFinder::RESULT_DEFAULT);
-
-public:
-    InMemoryZoneFinderTest() :
-        class_(RRClass::IN()),
-        origin_("example.org"),
-        zone_finder_(class_, origin_)
-    {
-        // Build test RRsets.  Below, we construct an RRset for
-        // each textual RR(s) of zone_data, and assign it to the corresponding
-        // rr_xxx.
-        // Note that this contains an out-of-zone RR, and due to the
-        // validation check of masterLoad() used below, we cannot add SOA.
-        const RRsetData zone_data[] = {
-            {"example.org. 300 IN NS ns.example.org.", &rr_ns_},
-            {"example.org. 300 IN A 192.0.2.1", &rr_a_},
-            {"ns.example.org. 300 IN A 192.0.2.2", &rr_ns_a_},
-            {"ns.example.org. 300 IN AAAA 2001:db8::2", &rr_ns_aaaa_},
-            {"cname.example.org. 300 IN CNAME canonical.example.org.",
-             &rr_cname_},
-            {"cname.example.org. 300 IN A 192.0.2.3", &rr_cname_a_},
-            {"dname.example.org. 300 IN DNAME target.example.org.",
-             &rr_dname_},
-            {"dname.example.org. 300 IN A 192.0.2.39", &rr_dname_a_},
-            {"dname.example.org. 300 IN NS ns.dname.example.org.",
-             &rr_dname_ns_},
-            {"example.org. 300 IN DNAME example.com.", &rr_dname_apex_},
-            {"child.example.org. 300 IN NS ns.child.example.org.",
-             &rr_child_ns_},
-            {"child.example.org. 300 IN DS 12345 5 1 DEADBEEF",
-             &rr_child_ds_},
-            {"ns.child.example.org. 300 IN A 192.0.2.153",
-             &rr_child_glue_},
-            {"grand.child.example.org. 300 IN NS ns.grand.child.example.org.",
-             &rr_grandchild_ns_},
-            {"ns.grand.child.example.org. 300 IN AAAA 2001:db8::253",
-             &rr_grandchild_glue_},
-            {"dname.child.example.org. 300 IN DNAME example.com.",
-             &rr_child_dname_},
-            {"example.com. 300 IN A 192.0.2.10", &rr_out_},
-            {"*.wild.example.org. 300 IN A 192.0.2.1", &rr_wild_},
-            {"*.cnamewild.example.org. 300 IN CNAME canonial.example.org.",
-             &rr_cnamewild_},
-            {"foo.wild.example.org. 300 IN A 192.0.2.3", &rr_under_wild_},
-            {"wild.*.foo.example.org. 300 IN A 192.0.2.1", &rr_emptywild_},
-            {"wild.*.foo.*.bar.example.org. 300 IN A 192.0.2.1",
-             &rr_nested_emptywild_},
-            {"*.nswild.example.org. 300 IN NS nswild.example.", &rr_nswild_},
-            {"*.dnamewild.example.org. 300 IN DNAME dnamewild.example.",
-             &rr_dnamewild_},
-            {"*.child.example.org. 300 IN A 192.0.2.1", &rr_child_wild_},
-            {"bar.foo.wild.example.org. 300 IN A 192.0.2.2", &rr_not_wild_},
-            {"baz.foo.wild.example.org. 300 IN A 192.0.2.3",
-             &rr_not_wild_another_},
-            {"0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM.example.org. 300 IN "
-             "NSEC3 1 1 12 aabbccdd 2T7B4G4VSA5SMI47K61MV5BV1A22BOJR A RRSIG",
-             &rr_nsec3_},
-            {"example.org. 300 IN NSEC wild.*.foo.example.org. "
-             "NS SOA RRSIG NSEC DNSKEY", &rr_nsec_},
-            // Together with the apex NSEC, these next NSECs make a complete
-            // chain in the case of the zone for the emptyNonterminal tests
-            // (We may want to clean up this generator code and/or masterLoad
-            // so that we can prepare conflicting datasets better)
-            {"wild.*.foo.example.org. 3600 IN NSEC ns.example.org. "
-             "A RRSIG NSEC", &rr_ent_nsec2_},
-            {"ns.example.org. 3600 IN NSEC foo.wild.example.org. A RRSIG NSEC",
-             &rr_ent_nsec3_},
-            {"foo.wild.example.org. 3600 IN NSEC example.org. A RRSIG NSEC",
-             &rr_ent_nsec4_},
-            // And these are NSECs used in different tests
-            {"ns.example.org. 300 IN NSEC *.nswild.example.org. A AAAA NSEC",
-             &rr_ns_nsec_},
-            {"*.wild.example.org. 300 IN NSEC foo.wild.example.org. A NSEC",
-             &rr_wild_nsec_},
-            {NULL, NULL}
-        };
-
-        stringstream zone_data_stream;
-        vector<RRsetPtr*> rrsets;
-        for (unsigned int i = 0; zone_data[i].text != NULL; ++i) {
-            zone_data_stream << zone_data[i].text << "\n";
-            rrsets.push_back(zone_data[i].rrset);
-        }
-
-        masterLoad(zone_data_stream, Name::ROOT_NAME(), class_,
-                   boost::bind(setRRset, _1, rrsets.begin()));
-    }
-
-    ~InMemoryZoneFinderTest() {
-        // Make sure we reset the hash creator to the default
-        setNSEC3HashCreator(NULL);
-    }
-
-    // Some data to test with
-    const RRClass class_;
-    const Name origin_;
-    // The zone finder to torture by tests
-    InMemoryZoneFinder zone_finder_;
-
-    // Placeholder for storing RRsets to be checked with rrsetsCheck()
-    vector<ConstRRsetPtr> actual_rrsets_;
-
-    /*
-     * Some RRsets to put inside the zone.
-     */
-    RRsetPtr
-        // Out of zone RRset
-        rr_out_,
-        // NS of example.org
-        rr_ns_,
-        // A of ns.example.org
-        rr_ns_a_,
-        // AAAA of ns.example.org
-        rr_ns_aaaa_,
-        // A of example.org
-        rr_a_;
-    RRsetPtr rr_cname_;         // CNAME in example.org (RDATA will be added)
-    RRsetPtr rr_cname_a_; // for mixed CNAME + A case
-    RRsetPtr rr_dname_;         // DNAME in example.org (RDATA will be added)
-    RRsetPtr rr_dname_a_; // for mixed DNAME + A case
-    RRsetPtr rr_dname_ns_; // for mixed DNAME + NS case
-    RRsetPtr rr_dname_apex_; // for mixed DNAME + NS case in the apex
-    RRsetPtr rr_child_ns_; // NS of a child domain (for delegation)
-    RRsetPtr rr_child_ds_; // DS of a child domain (for delegation, auth data)
-    RRsetPtr rr_child_glue_; // glue RR of the child domain
-    RRsetPtr rr_grandchild_ns_; // NS below a zone cut (unusual)
-    RRsetPtr rr_grandchild_glue_; // glue RR below a deeper zone cut
-    RRsetPtr rr_child_dname_; // A DNAME under NS
-    RRsetPtr rr_wild_;        // Wildcard record
-    RRsetPtr rr_cnamewild_;     // CNAME at a wildcard
-    RRsetPtr rr_emptywild_;
-    RRsetPtr rr_nested_emptywild_;
-    RRsetPtr rr_nswild_, rr_dnamewild_;
-    RRsetPtr rr_child_wild_;
-    RRsetPtr rr_under_wild_;
-    RRsetPtr rr_not_wild_;
-    RRsetPtr rr_not_wild_another_;
-    RRsetPtr rr_nsec3_;
-    RRsetPtr rr_nsec_;
-    RRsetPtr rr_ent_nsec2_;
-    RRsetPtr rr_ent_nsec3_;
-    RRsetPtr rr_ent_nsec4_;
-    RRsetPtr rr_ns_nsec_;
-    RRsetPtr rr_wild_nsec_;
-
-    // A faked NSEC3 hash calculator for convenience.
-    // Tests that need to use the faked hashed values should call
-    // setNSEC3HashCreator() with a pointer to this variable at the beginning
-    // of the test (at least before adding any NSEC3/NSEC3PARAM RR).
-    TestNSEC3HashCreator nsec3_hash_creator_;
-
-    /**
-     * \brief Test one find query to the zone finder.
-     *
-     * Asks a query to the zone finder and checks it does not throw and returns
-     * expected results. It returns nothing, it just signals failures
-     * to GTEST.
-     *
-     * \param name The name to ask for.
-     * \param rrtype The RRType to ask of.
-     * \param result The expected code of the result.
-     * \param check_answer Should a check against equality of the answer be
-     *     done?
-     * \param answer The expected rrset, if any should be returned.
-     * \param expected_flags The expected result flags returned via find().
-     *     These can be tested using isWildcard() etc.
-     * \param zone_finder Check different InMemoryZoneFinder object than
-     *     zone_finder_ (if NULL, uses zone_finder_)
-     * \param check_wild_answer Checks that the answer has the same RRs, type
-     *     class and TTL as the eqxpected answer and that the name corresponds
-     *     to the one searched. It is meant for checking answers for wildcard
-     *     queries.
-     */
-    void findTest(const Name& name, const RRType& rrtype,
-                  ZoneFinder::Result result,
-                  bool check_answer = true,
-                  const ConstRRsetPtr& answer = ConstRRsetPtr(),
-                  ZoneFinder::FindResultFlags expected_flags =
-                  ZoneFinder::RESULT_DEFAULT,
-                  InMemoryZoneFinder* zone_finder = NULL,
-                  ZoneFinder::FindOptions options = ZoneFinder::FIND_DEFAULT,
-                  bool check_wild_answer = false)
-    {
-        SCOPED_TRACE("findTest for " + name.toText() + "/" + rrtype.toText());
-
-        if (zone_finder == NULL) {
-            zone_finder = &zone_finder_;
-        }
-        const ConstRRsetPtr answer_sig = answer ? answer->getRRsig() :
-            RRsetPtr(); // note we use the same type as of retval of getRRsig()
-        // The whole block is inside, because we need to check the result and
-        // we can't assign to FindResult
-        EXPECT_NO_THROW({
-                ZoneFinderContextPtr find_result(zone_finder->find(
-                                                     name, rrtype, options));
-                // Check it returns correct answers
-                EXPECT_EQ(result, find_result->code);
-                EXPECT_EQ((expected_flags & ZoneFinder::RESULT_WILDCARD) != 0,
-                          find_result->isWildcard());
-                EXPECT_EQ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED)
-                          != 0, find_result->isNSECSigned());
-                EXPECT_EQ((expected_flags & ZoneFinder::RESULT_NSEC3_SIGNED)
-                          != 0, find_result->isNSEC3Signed());
-                if (check_answer) {
-                    if (!answer) {
-                        ASSERT_FALSE(find_result->rrset);
-                    } else {
-                        ASSERT_TRUE(find_result->rrset);
-                        rrsetCheck(answer, find_result->rrset);
-                        if (answer_sig) {
-                            ASSERT_TRUE(find_result->rrset->getRRsig());
-                            rrsetCheck(answer_sig,
-                                       find_result->rrset->getRRsig());
-                        }
-                    }
-                } else if (check_wild_answer) {
-                    ASSERT_NE(ConstRRsetPtr(), answer) <<
-                        "Wrong test, don't check for wild names if you expect "
-                        "empty answer";
-                    ASSERT_NE(ConstRRsetPtr(), find_result->rrset) <<
-                        "No answer found";
-                    // Build the expected answer using the given name and
-                    // other parameter of the base wildcard RRset.
-                    RRsetPtr wildanswer(new RRset(name, answer->getClass(),
-                                                  answer->getType(),
-                                                  answer->getTTL()));
-                    RdataIteratorPtr expectedIt(answer->getRdataIterator());
-                    for (; !expectedIt->isLast(); expectedIt->next()) {
-                        wildanswer->addRdata(expectedIt->getCurrent());
-                    }
-                    rrsetCheck(wildanswer, find_result->rrset);
-
-                    // Same for the RRSIG, if any.
-                    if (answer_sig) {
-                        ASSERT_TRUE(find_result->rrset->getRRsig());
-
-                        RRsetPtr wildsig(new RRset(name,
-                                                   answer_sig->getClass(),
-                                                   RRType::RRSIG(),
-                                                   answer_sig->getTTL()));
-                        RdataIteratorPtr expectedIt(
-                            answer_sig->getRdataIterator());
-                        for (; !expectedIt->isLast(); expectedIt->next()) {
-                            wildsig->addRdata(expectedIt->getCurrent());
-                        }
-                        rrsetCheck(wildsig, find_result->rrset->getRRsig());
-                    }
-                }
-            });
-    }
-    /**
-     * \brief Calls the findAll on the finder and checks the result.
-     */
-    void findAllTest(const Name& name, ZoneFinder::Result result,
-                     const vector<ConstRRsetPtr>& expected_rrsets,
-                     ZoneFinder::FindResultFlags expected_flags =
-                     ZoneFinder::RESULT_DEFAULT,
-                     InMemoryZoneFinder* finder = NULL,
-                     const ConstRRsetPtr &rrset_result = ConstRRsetPtr(),
-                     ZoneFinder::FindOptions options =
-                     ZoneFinder::FIND_DEFAULT)
-    {
-        if (finder == NULL) {
-            finder = &zone_finder_;
-        }
-        std::vector<ConstRRsetPtr> target;
-        ZoneFinderContextPtr find_result(finder->findAll(name, target,
-                                                         options));
-        EXPECT_EQ(result, find_result->code);
-        if (!rrset_result) {
-            EXPECT_FALSE(find_result->rrset);
-        } else {
-            ASSERT_TRUE(find_result->rrset);
-            rrsetCheck(rrset_result, find_result->rrset);
-        }
-        EXPECT_EQ((expected_flags & ZoneFinder::RESULT_WILDCARD) != 0,
-                  find_result->isWildcard());
-        EXPECT_EQ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED)
-                  != 0, find_result->isNSECSigned());
-        EXPECT_EQ((expected_flags & ZoneFinder::RESULT_NSEC3_SIGNED)
-                  != 0, find_result->isNSEC3Signed());
-        rrsetsCheck(expected_rrsets.begin(), expected_rrsets.end(),
-                    target.begin(), target.end());
-    }
-};
-
-/**
- * \brief Test InMemoryZoneFinder::InMemoryZoneFinder constructor.
- *
- * Takes the created zone finder and checks its properties they are the same
- * as passed parameters.
- */
-TEST_F(InMemoryZoneFinderTest, constructor) {
-    ASSERT_EQ(class_, zone_finder_.getClass());
-    ASSERT_EQ(origin_, zone_finder_.getOrigin());
-}
-/**
- * \brief Test adding.
- *
- * We test that it throws at the correct moments and the correct exceptions.
- * And we test the return value.
- */
-TEST_F(InMemoryZoneFinderTest, add) {
-    // This one does not belong to this zone
-    EXPECT_THROW(zone_finder_.add(rr_out_), OutOfZone);
-    // Test null pointer
-    EXPECT_THROW(zone_finder_.add(ConstRRsetPtr()),
-                 InMemoryZoneFinder::NullRRset);
-
-    // Now put all the data we have there. It should throw nothing
-    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_)));
-    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_a_)));
-    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_aaaa_)));
-    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_a_)));
-
-    // Try putting there something twice, it should be rejected
-    EXPECT_NO_THROW(EXPECT_EQ(EXIST, zone_finder_.add(rr_ns_)));
-    EXPECT_NO_THROW(EXPECT_EQ(EXIST, zone_finder_.add(rr_ns_a_)));
-}
-
-TEST_F(InMemoryZoneFinderTest, addMultipleCNAMEs) {
-    rr_cname_->addRdata(generic::CNAME("canonical2.example.org."));
-    EXPECT_THROW(zone_finder_.add(rr_cname_), InMemoryZoneFinder::AddError);
-}
-
-TEST_F(InMemoryZoneFinderTest, addCNAMEThenOther) {
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_cname_));
-    EXPECT_THROW(zone_finder_.add(rr_cname_a_), InMemoryZoneFinder::AddError);
-}
-
-TEST_F(InMemoryZoneFinderTest, addOtherThenCNAME) {
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_cname_a_));
-    EXPECT_THROW(zone_finder_.add(rr_cname_), InMemoryZoneFinder::AddError);
-}
-
-TEST_F(InMemoryZoneFinderTest, addCNAMEAndDNSSECRecords) {
-    // CNAME and RRSIG can coexist
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_cname_));
-    EXPECT_EQ(SUCCESS, zone_finder_.add(
-                  textToRRset("cname.example.org. 300 IN RRSIG CNAME 5 3 "
-                              "3600 20000101000000 20000201000000 12345 "
-                              "example.org. FAKEFAKEFAKE")));
-
-    // Same for NSEC
-    EXPECT_EQ(SUCCESS, zone_finder_.add(
-                  textToRRset("cname.example.org. 300 IN NSEC "
-                              "dname.example.org. CNAME RRSIG NSEC")));
-
-    // Same as above, but adding NSEC first.
-    EXPECT_EQ(SUCCESS, zone_finder_.add(
-                  textToRRset("cname2.example.org. 300 IN NSEC "
-                              "dname.example.org. CNAME RRSIG NSEC")));
-    EXPECT_EQ(SUCCESS, zone_finder_.add(
-                  textToRRset("cname2.example.org. 300 IN CNAME c.example.")));
-
-    // If there's another type of RRset with NSEC, it should still fail.
-    EXPECT_EQ(SUCCESS, zone_finder_.add(
-                  textToRRset("cname3.example.org. 300 IN A 192.0.2.1")));
-    EXPECT_EQ(SUCCESS, zone_finder_.add(
-                  textToRRset("cname3.example.org. 300 IN NSEC "
-                              "dname.example.org. CNAME RRSIG NSEC")));
-    EXPECT_THROW(zone_finder_.add(textToRRset("cname3.example.org. 300 "
-                                              "IN CNAME c.example.")),
-                 InMemoryZoneFinder::AddError);
-}
-
-TEST_F(InMemoryZoneFinderTest, findCNAME) {
-    // install CNAME RR
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_cname_));
-
-    // Find A RR of the same.  Should match the CNAME
-    findTest(rr_cname_->getName(), RRType::NS(), ZoneFinder::CNAME, true,
-             rr_cname_);
-
-    // Find the CNAME itself.  Should result in normal SUCCESS
-    findTest(rr_cname_->getName(), RRType::CNAME(), ZoneFinder::SUCCESS, true,
-             rr_cname_);
-}
-
-TEST_F(InMemoryZoneFinderTest, findCNAMEUnderZoneCut) {
-    // There's nothing special when we find a CNAME under a zone cut
-    // (with FIND_GLUE_OK).  The behavior is different from BIND 9,
-    // so we test this case explicitly.
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_ns_));
-    ConstRRsetPtr rr_cname_under_cut_ = textToRRset(
-        "cname.child.example.org. 300 IN CNAME target.child.example.org.");
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_cname_under_cut_));
-    findTest(Name("cname.child.example.org"), RRType::AAAA(),
-             ZoneFinder::CNAME, true, rr_cname_under_cut_,
-             ZoneFinder::RESULT_DEFAULT, NULL, ZoneFinder::FIND_GLUE_OK);
-}
-
-// Two DNAMEs at single domain are disallowed by RFC 2672, section 3)
-// Having a CNAME there is disallowed too, but it is tested by
-// addOtherThenCNAME and addCNAMEThenOther.
-TEST_F(InMemoryZoneFinderTest, addMultipleDNAMEs) {
-    rr_dname_->addRdata(generic::DNAME("target2.example.org."));
-    EXPECT_THROW(zone_finder_.add(rr_dname_), InMemoryZoneFinder::AddError);
-}
-
-/*
- * These two tests ensure that we can't have DNAME and NS at the same
- * node with the exception of the apex of zone (forbidden by RFC 2672)
- */
-TEST_F(InMemoryZoneFinderTest, addDNAMEThenNS) {
-    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_dname_)));
-    EXPECT_THROW(zone_finder_.add(rr_dname_ns_), InMemoryZoneFinder::AddError);
-}
-
-TEST_F(InMemoryZoneFinderTest, addNSThenDNAME) {
-    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_dname_ns_)));
-    EXPECT_THROW(zone_finder_.add(rr_dname_), InMemoryZoneFinder::AddError);
-}
-
-// It is allowed to have NS and DNAME at apex
-TEST_F(InMemoryZoneFinderTest, DNAMEAndNSAtApex) {
-    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_dname_apex_)));
-    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_)));
-
-    // The NS should be possible to be found, below should be DNAME, not
-    // delegation
-    findTest(origin_, RRType::NS(), ZoneFinder::SUCCESS, true, rr_ns_);
-    findTest(rr_child_ns_->getName(), RRType::A(), ZoneFinder::DNAME, true,
-             rr_dname_apex_);
-}
-
-TEST_F(InMemoryZoneFinderTest, NSAndDNAMEAtApex) {
-    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_)));
-    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_dname_apex_)));
-}
-
-// TODO: Test (and implement) adding data under DNAME. That is forbidden by
-// 2672 as well.
-
-// Search under a DNAME record. It should return the DNAME
-TEST_F(InMemoryZoneFinderTest, findBelowDNAME) {
-    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_dname_)));
-    findTest(Name("below.dname.example.org"), RRType::A(), ZoneFinder::DNAME,
-             true, rr_dname_);
-}
-
-// Search at the domain with DNAME. It should act as DNAME isn't there, DNAME
-// influences only the data below (see RFC 2672, section 3)
-TEST_F(InMemoryZoneFinderTest, findAtDNAME) {
-    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_dname_)));
-    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_dname_a_)));
-
-    const Name dname_name(rr_dname_->getName());
-    findTest(dname_name, RRType::A(), ZoneFinder::SUCCESS, true, rr_dname_a_);
-    findTest(dname_name, RRType::DNAME(), ZoneFinder::SUCCESS, true,
-             rr_dname_);
-    findTest(dname_name, RRType::TXT(), ZoneFinder::NXRRSET, true);
-}
-
-// Try searching something that is both under NS and DNAME, without and with
-// GLUE_OK mode (it should stop at the NS and DNAME respectively).
-TEST_F(InMemoryZoneFinderTest, DNAMEUnderNS) {
-    zone_finder_.add(rr_child_ns_);
-    zone_finder_.add(rr_child_dname_);
-
-    Name lowName("below.dname.child.example.org.");
-
-    findTest(lowName, RRType::A(), ZoneFinder::DELEGATION, true, rr_child_ns_);
-    findTest(lowName, RRType::A(), ZoneFinder::DNAME, true, rr_child_dname_,
-             ZoneFinder::RESULT_DEFAULT, NULL, ZoneFinder::FIND_GLUE_OK);
-}
-
-// Test adding child zones and zone cut handling
-TEST_F(InMemoryZoneFinderTest, delegationNS) {
-    // add in-zone data
-    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_)));
-
-    // install a zone cut
-    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_ns_)));
-
-    // below the zone cut
-    findTest(Name("www.child.example.org"), RRType::A(),
-             ZoneFinder::DELEGATION, true, rr_child_ns_);
-
-    // at the zone cut
-    findTest(Name("child.example.org"), RRType::A(), ZoneFinder::DELEGATION,
-             true, rr_child_ns_);
-    findTest(Name("child.example.org"), RRType::NS(), ZoneFinder::DELEGATION,
-             true, rr_child_ns_);
-
-    // finding NS for the apex (origin) node.  This must not be confused
-    // with delegation due to the existence of an NS RR.
-    findTest(origin_, RRType::NS(), ZoneFinder::SUCCESS, true, rr_ns_);
-
-    // unusual case of "nested delegation": the highest cut should be used.
-    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_grandchild_ns_)));
-    findTest(Name("www.grand.child.example.org"), RRType::A(),
-             // note: !rr_grandchild_ns_
-             ZoneFinder::DELEGATION, true, rr_child_ns_);
-}
-
-TEST_F(InMemoryZoneFinderTest, delegationWithDS) {
-    // Similar setup to the previous one, but with DS RR at the delegation
-    // point.
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_));
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_ns_));
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_ds_));
-
-    // Normal types of query should result in delegation, but DS query
-    // should be considered in-zone (but only exactly at the delegation point).
-    findTest(Name("child.example.org"), RRType::A(), ZoneFinder::DELEGATION,
-             true, rr_child_ns_);
-    findTest(Name("child.example.org"), RRType::DS(), ZoneFinder::SUCCESS,
-             true, rr_child_ds_);
-    findTest(Name("grand.child.example.org"), RRType::DS(),
-             ZoneFinder::DELEGATION, true, rr_child_ns_);
-
-    // There's nothing special for DS query at the zone apex.  It would
-    // normally result in NXRRSET.
-    findTest(Name("example.org"), RRType::DS(), ZoneFinder::NXRRSET,
-             true, ConstRRsetPtr());
-}
-
-TEST_F(InMemoryZoneFinderTest, findAny) {
-    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_a_)));
-    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_)));
-    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_glue_)));
-
-    vector<ConstRRsetPtr> expected_sets;
-
-    // origin
-    expected_sets.push_back(rr_a_);
-    expected_sets.push_back(rr_ns_);
-    findAllTest(origin_, ZoneFinder::SUCCESS, expected_sets);
-
-    // out zone name
-    EXPECT_THROW(findAllTest(Name("example.com"), ZoneFinder::NXDOMAIN,
-                             vector<ConstRRsetPtr>()),
-                 OutOfZone);
-
-    expected_sets.clear();
-    expected_sets.push_back(rr_child_glue_);
-    findAllTest(rr_child_glue_->getName(), ZoneFinder::SUCCESS, expected_sets);
-
-    // add zone cut
-    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_ns_)));
-
-    // zone cut
-    findAllTest(rr_child_ns_->getName(), ZoneFinder::DELEGATION,
-                vector<ConstRRsetPtr>(), ZoneFinder::RESULT_DEFAULT,
-                NULL, rr_child_ns_);
-
-    // glue for this zone cut
-    findAllTest(rr_child_glue_->getName(),ZoneFinder::DELEGATION,
-                vector<ConstRRsetPtr>(), ZoneFinder::RESULT_DEFAULT,
-                NULL, rr_child_ns_);
-}
-
-TEST_F(InMemoryZoneFinderTest, glue) {
-    // install zone data:
-    // a zone cut
-    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_ns_)));
-    // glue for this cut
-    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_glue_)));
-    // a nested zone cut (unusual)
-    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_grandchild_ns_)));
-    // glue under the deeper zone cut
-    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_grandchild_glue_)));
-
-    // by default glue is hidden due to the zone cut
-    findTest(rr_child_glue_->getName(), RRType::A(), ZoneFinder::DELEGATION,
-             true, rr_child_ns_);
-
-
-    // If we do it in the "glue OK" mode, we should find the exact match.
-    findTest(rr_child_glue_->getName(), RRType::A(), ZoneFinder::SUCCESS, true,
-             rr_child_glue_, ZoneFinder::RESULT_DEFAULT, NULL,
-             ZoneFinder::FIND_GLUE_OK);
-
-    // glue OK + NXRRSET case
-    findTest(rr_child_glue_->getName(), RRType::AAAA(), ZoneFinder::NXRRSET,
-             true, ConstRRsetPtr(), ZoneFinder::RESULT_DEFAULT, NULL,
-             ZoneFinder::FIND_GLUE_OK);
-
-    // glue OK + NXDOMAIN case
-    findTest(Name("www.child.example.org"), RRType::A(),
-             ZoneFinder::DELEGATION, true, rr_child_ns_,
-             ZoneFinder::RESULT_DEFAULT, NULL, ZoneFinder::FIND_GLUE_OK);
-
-    // nested cut case.  The glue should be found.
-    findTest(rr_grandchild_glue_->getName(), RRType::AAAA(),
-             ZoneFinder::SUCCESS,
-             true, rr_grandchild_glue_, ZoneFinder::RESULT_DEFAULT, NULL,
-             ZoneFinder::FIND_GLUE_OK);
-
-    // A non-existent name in nested cut.  This should result in delegation
-    // at the highest zone cut.
-    findTest(Name("www.grand.child.example.org"), RRType::TXT(),
-             ZoneFinder::DELEGATION, true, rr_child_ns_,
-             ZoneFinder::RESULT_DEFAULT, NULL, ZoneFinder::FIND_GLUE_OK);
-}
-
-/**
- * \brief Test searching.
- *
- * Check it finds or does not find correctly and does not throw exceptions.
- * \todo This doesn't do any kind of CNAME and so on. If it isn't
- *     directly there, it just tells it doesn't exist.
- */
-void
-InMemoryZoneFinderTest::findCheck(ZoneFinder::FindResultFlags expected_flags,
-                                  ZoneFinder::FindOptions find_options)
-{
-    // Fill some data inside
-    // Now put all the data we have there. It should throw nothing
-    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_)));
-    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_a_)));
-    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_aaaa_)));
-    EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_a_)));
-    if ((expected_flags & ZoneFinder::RESULT_NSEC3_SIGNED) != 0) {
-        EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec3_));
-    }
-    if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0) {
-        EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec_));
-    }
-
-    // These two should be successful
-    findTest(origin_, RRType::NS(), ZoneFinder::SUCCESS, true, rr_ns_);
-    findTest(rr_ns_a_->getName(), RRType::A(), ZoneFinder::SUCCESS, true,
-             rr_ns_a_);
-
-    // These domains don't exist. (and one is out of the zone).  In an
-    // NSEC-signed zone with DNSSEC records requested, it should return the
-    // covering NSEC for the query name (the actual NSEC in the test data may
-    // not really "cover" it, but for the purpose of this test it's okay).
-    ConstRRsetPtr expected_nsec; // by default it's NULL
-    if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0 &&
-        (find_options & ZoneFinder::FIND_DNSSEC) != 0) {
-        expected_nsec = rr_nsec_;
-    }
-
-    // There's no other name between this one and the origin, so when NSEC
-    // is to be returned it should be the origin NSEC.
-    findTest(Name("nothere.example.org"), RRType::A(),
-             ZoneFinder::NXDOMAIN, true, expected_nsec, expected_flags,
-             NULL, find_options);
-
-    // The previous name in the zone is "ns.example.org", but it doesn't
-    // have an NSEC.  It should be skipped and the origin NSEC will be
-    // returned as the "closest NSEC".
-    findTest(Name("nxdomain.example.org"), RRType::A(),
-             ZoneFinder::NXDOMAIN, true, expected_nsec, expected_flags,
-             NULL, find_options);
-    EXPECT_THROW(zone_finder_.find(Name("example.net"), RRType::A()),
-                 OutOfZone);
-
-    // These domain exist but don't have the provided RRType.  For the latter
-    // one we now add its NSEC (which was delayed so that it wouldn't break
-    // other cases above).
-    findTest(origin_, RRType::AAAA(), ZoneFinder::NXRRSET, true,
-             expected_nsec, expected_flags, NULL, find_options);
-    if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0) {
-        EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_nsec_));
-        if ((find_options & ZoneFinder::FIND_DNSSEC) != 0) {
-            expected_nsec = rr_ns_nsec_;
-        }
-    }
-    findTest(rr_ns_a_->getName(), RRType::NS(), ZoneFinder::NXRRSET, true,
-             expected_nsec, expected_flags, NULL, find_options);
-}
-
-TEST_F(InMemoryZoneFinderTest, find) {
-    findCheck();
-}
-
-TEST_F(InMemoryZoneFinderTest, findNSEC3Signed) {
-    findCheck(ZoneFinder::RESULT_NSEC3_SIGNED);
-}
-
-TEST_F(InMemoryZoneFinderTest, findNSEC3SignedWithDNSSEC) {
-    // For NSEC3-signed zones, specifying the DNSSEC option shouldn't change
-    // anything (the NSEC3_SIGNED flag is always set, and no records are
-    // returned for negative cases regardless).
-    findCheck(ZoneFinder::RESULT_NSEC3_SIGNED, ZoneFinder::FIND_DNSSEC);
-}
-
-TEST_F(InMemoryZoneFinderTest, findNSECSigned) {
-    // NSEC-signed zone, without requesting DNSSEC (no NSEC should be provided)
-    findCheck(ZoneFinder::RESULT_NSEC_SIGNED);
-}
-
-// Generalized test for Empty Nonterminal (ENT) cases with NSEC
-void
-InMemoryZoneFinderTest::findNSECENTCheck(const Name& ent_name,
-    ConstRRsetPtr expected_nsec,
-    ZoneFinder::FindResultFlags expected_flags)
-{
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_emptywild_));
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_under_wild_));
-
-    // Sanity check: Should result in NXRRSET
-    findTest(ent_name, RRType::A(), ZoneFinder::NXRRSET, true,
-             ConstRRsetPtr(), expected_flags);
-    // Sanity check: No NSEC added yet
-    findTest(ent_name, RRType::A(), ZoneFinder::NXRRSET, true,
-             ConstRRsetPtr(), expected_flags,
-             NULL, ZoneFinder::FIND_DNSSEC);
-
-    // Now add the NSEC rrs making it a 'complete' zone (in terms of NSEC,
-    // there are no sigs)
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec_));
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ent_nsec2_));
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ent_nsec3_));
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ent_nsec4_));
-
-    // Should result in NXRRSET, and RESULT_NSEC_SIGNED
-    findTest(ent_name, RRType::A(), ZoneFinder::NXRRSET, true,
-             ConstRRsetPtr(),
-             expected_flags | ZoneFinder::RESULT_NSEC_SIGNED);
-
-    // And check for the NSEC if DNSSEC_OK
-    findTest(ent_name, RRType::A(), ZoneFinder::NXRRSET, true,
-             expected_nsec, expected_flags | ZoneFinder::RESULT_NSEC_SIGNED,
-             NULL, ZoneFinder::FIND_DNSSEC);
-}
-
-TEST_F(InMemoryZoneFinderTest,findNSECEmptyNonterminal) {
-    // Non-wildcard case
-    findNSECENTCheck(Name("wild.example.org"), rr_ent_nsec3_);
-}
-
-TEST_F(InMemoryZoneFinderTest,findNSECEmptyNonterminalWildcard) {
-    // Wildcard case, above actual wildcard
-    findNSECENTCheck(Name("foo.example.org"), rr_nsec_);
-}
-
-TEST_F(InMemoryZoneFinderTest,findNSECEmptyNonterminalAtWildcard) {
-    // Wildcard case, at actual wildcard
-    findNSECENTCheck(Name("bar.foo.example.org"), rr_nsec_,
-                     ZoneFinder::RESULT_WILDCARD);
-}
-
-TEST_F(InMemoryZoneFinderTest, findNSECSignedWithDNSSEC) {
-    // NSEC-signed zone, requesting DNSSEC (NSEC should be provided)
-    findCheck(ZoneFinder::RESULT_NSEC_SIGNED, ZoneFinder::FIND_DNSSEC);
-}
-
-void
-InMemoryZoneFinderTest::emptyNodeCheck(
-    ZoneFinder::FindResultFlags expected_flags)
-{
-    /*
-     * The backend RBTree for this test should look like as follows:
-     *          example.org
-     *               |
-     *              baz (empty; easy case)
-     *            /  |  \
-     *          bar  |  x.foo ('foo' part is empty; a bit trickier)
-     *              bbb
-     *             /
-     *           aaa
-     */
-
-    // Construct the test zone
-    const char* const names[] = {
-        "bar.example.org.", "x.foo.example.org.", "aaa.baz.example.org.",
-        "bbb.baz.example.org.", NULL};
-    for (int i = 0; names[i] != NULL; ++i) {
-        ConstRRsetPtr rrset = textToRRset(string(names[i]) +
-                                          " 300 IN A 192.0.2.1");
-        EXPECT_EQ(SUCCESS, zone_finder_.add(rrset));
-    }
-    if ((expected_flags & ZoneFinder::RESULT_NSEC3_SIGNED) != 0) {
-        EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec3_));
-    }
-    if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0) {
-        EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec_));
-    }
-
-    // empty node matching, easy case: the node for 'baz' exists with
-    // no data.
-    findTest(Name("baz.example.org"), RRType::A(), ZoneFinder::NXRRSET, true,
-             ConstRRsetPtr(), expected_flags);
-
-    // empty node matching, a trickier case: the node for 'foo' is part of
-    // "x.foo", which should be considered an empty node.
-    findTest(Name("foo.example.org"), RRType::A(), ZoneFinder::NXRRSET, true,
-             ConstRRsetPtr(), expected_flags);
-
-    // "org" is contained in "example.org", but it shouldn't be treated as
-    // NXRRSET because it's out of zone.
-    // Note: basically we don't expect such a query to be performed (the common
-    // operation is to identify the best matching zone first then perform
-    // search it), but we shouldn't be confused even in the unexpected case.
-    EXPECT_THROW(zone_finder_.find(Name("org"), RRType::A()), OutOfZone);
-}
-
-TEST_F(InMemoryZoneFinderTest, emptyNode) {
-    emptyNodeCheck();
-}
-
-TEST_F(InMemoryZoneFinderTest, emptyNodeNSEC3) {
-    emptyNodeCheck(ZoneFinder::RESULT_NSEC3_SIGNED);
-}
-
-TEST_F(InMemoryZoneFinderTest, emptyNodeNSEC) {
-    emptyNodeCheck(ZoneFinder::RESULT_NSEC_SIGNED);
-}
-
-TEST_F(InMemoryZoneFinderTest, load) {
-    // Put some data inside the zone
-    EXPECT_NO_THROW(EXPECT_EQ(result::SUCCESS, zone_finder_.add(rr_ns_)));
-    // Loading with different origin should fail
-    EXPECT_THROW(zone_finder_.load(TEST_DATA_DIR "/root.zone"),
-                 MasterLoadError);
-    // See the original data is still there, survived the exception
-    findTest(origin_, RRType::NS(), ZoneFinder::SUCCESS, true, rr_ns_);
-    // Create correct zone
-    InMemoryZoneFinder rootzone(class_, Name("."));
-    // Try putting something inside
-    EXPECT_NO_THROW(EXPECT_EQ(result::SUCCESS, rootzone.add(rr_ns_aaaa_)));
-    // Load the zone. It should overwrite/remove the above RRset
-    EXPECT_NO_THROW(rootzone.load(TEST_DATA_DIR "/root.zone"));
-
-    // Now see there are some rrsets (we don't look inside, though)
-    findTest(Name("."), RRType::SOA(), ZoneFinder::SUCCESS, false,
-             ConstRRsetPtr(), ZoneFinder::RESULT_DEFAULT, &rootzone);
-    findTest(Name("."), RRType::NS(), ZoneFinder::SUCCESS, false,
-             ConstRRsetPtr(), ZoneFinder::RESULT_DEFAULT, &rootzone);
-    findTest(Name("a.root-servers.net."), RRType::A(), ZoneFinder::SUCCESS,
-             false, ConstRRsetPtr(), ZoneFinder::RESULT_DEFAULT, &rootzone);
-    // But this should no longer be here
-    findTest(rr_ns_a_->getName(), RRType::AAAA(), ZoneFinder::NXDOMAIN, true,
-             ConstRRsetPtr(), ZoneFinder::RESULT_DEFAULT, &rootzone);
-
-    // Try loading zone that is wrong in a different way
-    EXPECT_THROW(zone_finder_.load(TEST_DATA_DIR "/duplicate_rrset.zone"),
-                 MasterLoadError);
-}
-
-TEST_F(InMemoryZoneFinderTest, loadFromIterator) {
-    // The initial test set doesn't have SOA at the apex.
-    findTest(origin_, RRType::SOA(), ZoneFinder::NXRRSET, false,
-             ConstRRsetPtr());
-
-    // The content of the new version of zone to be first installed to
-    // the SQLite3 data source, then to in-memory via SQLite3.  The data are
-    // chosen to cover major check points of the implementation:
-    // - the previously non-existent record is added (SOA)
-    // - An RRSIG is given from the iterator before the RRset it covers
-    //   (RRSIG for SOA, because they are sorted by name then rrtype as text)
-    // - An RRset containing multiple RRs (ns1/A)
-    // - RRSIGs for different owner names
-    stringstream ss;
-    const char* const soa_txt = "example.org. 300 IN SOA . . 0 0 0 0 0\n";
-    const char* const soa_sig_txt = "example.org. 300 IN RRSIG SOA 5 3 300 "
-        "20000101000000 20000201000000 12345 example.org. FAKEFAKE\n";
-    const char* const a_txt =
-        "ns1.example.org. 300 IN A 192.0.2.1\n"
-        "ns1.example.org. 300 IN A 192.0.2.2\n";
-    const char* const a_sig_txt = "ns1.example.org. 300 IN RRSIG A 5 3 300 "
-        "20000101000000 20000201000000 12345 example.org. FAKEFAKE\n";
-    ss << soa_txt << soa_sig_txt << a_txt << a_sig_txt;
-    shared_ptr<DataSourceClient> db_client = unittest::createSQLite3Client(
-        class_, origin_, TEST_DATA_BUILDDIR "/contexttest.sqlite3.copied", ss);
-    zone_finder_.load(*db_client->getIterator(origin_));
-
-    // The new content should be visible, including the previously-nonexistent
-    // SOA.
-    RRsetPtr expected_answer = textToRRset(soa_txt, RRClass::IN(), origin_);
-    expected_answer->addRRsig(textToRRset(soa_sig_txt));
-    findTest(origin_, RRType::SOA(), ZoneFinder::SUCCESS, true,
-             expected_answer, ZoneFinder::RESULT_DEFAULT, NULL,
-             ZoneFinder::FIND_DNSSEC);
-
-    expected_answer = textToRRset(a_txt);
-    expected_answer->addRRsig(textToRRset(a_sig_txt));
-    findTest(Name("ns1.example.org"), RRType::A(), ZoneFinder::SUCCESS, true,
-             expected_answer, ZoneFinder::RESULT_DEFAULT, NULL,
-             ZoneFinder::FIND_DNSSEC);
-
-    // File name should be (re)set to empty.
-    EXPECT_TRUE(zone_finder_.getFileName().empty());
-
-    // Loading the zone with an iterator separating RRs of the same RRset
-    // will fail because the resulting sequence doesn't meet assumptions of
-    // the (current) in-memory implementation.
-    EXPECT_THROW(zone_finder_.load(*db_client->getIterator(origin_, true)),
-                 MasterLoadError);
-
-    // Load the zone from a file that contains more realistic data (borrowed
-    // from a different test).  There's nothing special in this case for the
-    // purpose of this test, so it should just succeed.
-    db_client = unittest::createSQLite3Client(
-        class_, origin_, TEST_DATA_BUILDDIR "/contexttest.sqlite3.copied",
-        TEST_DATA_DIR "/contexttest-almost-obsolete.zone");
-    zone_finder_.load(*db_client->getIterator(origin_));
-
-    // just checking a couple of RRs in the new version of zone.
-    findTest(Name("mx1.example.org"), RRType::A(), ZoneFinder::SUCCESS, true,
-             textToRRset("mx1.example.org. 3600 IN A 192.0.2.10"));
-    findTest(Name("ns1.example.org"), RRType::AAAA(), ZoneFinder::SUCCESS,
-             true, textToRRset("ns1.example.org. 3600 IN AAAA 2001:db8::1"));
-}
-
-/*
- * Test that puts a (simple) wildcard into the zone and checks we can
- * correctly find the data.
- */
-void
-InMemoryZoneFinderTest::wildcardCheck(
-    ZoneFinder::FindResultFlags expected_flags,
-    ZoneFinder::FindOptions find_options)
-{
-    /*
-     *            example.org.
-     *                 |
-     *             [cname]wild (not *.wild, should have wild mark)
-     *                 |
-     *                 *
-     */
-
-    // If the zone is "signed" (detecting it by the NSEC/NSEC3 signed flags),
-    // add RRSIGs to the records.
-    if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0 ||
-        (expected_flags & ZoneFinder::RESULT_NSEC3_SIGNED) != 0) {
-        // Convenience shortcut.  The RDATA is not really validatable, but
-        // it doesn't matter for our tests.
-        const char* const rrsig_common = "5 3 3600 "
-            "20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE";
-
-        find_options = find_options | ZoneFinder::FIND_DNSSEC;
-        rr_wild_->addRRsig(textToRRset("*.wild.example.org. 300 IN RRSIG A " +
-                                       string(rrsig_common)));
-        rr_cnamewild_->addRRsig(textToRRset("*.cnamewild.example.org. 300 IN "
-                                            "RRSIG CNAME " +
-                                            string(rrsig_common)));
-    }
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_wild_));
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_cnamewild_));
-    // If the zone is expected to be "signed" with NSEC3, add an NSEC3.
-    // (the content of the NSEC3 shouldn't matter)
-    if ((expected_flags & ZoneFinder::RESULT_NSEC3_SIGNED) != 0) {
-        EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec3_));
-    }
-    if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0) {
-        EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec_));
-    }
-
-    // Search at the parent. The parent will not have the A, but it will
-    // be in the wildcard (so check the wildcard isn't matched at the parent)
-    {
-        SCOPED_TRACE("Search at parent");
-        if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0) {
-            findTest(Name("wild.example.org"), RRType::A(),
-                     ZoneFinder::NXRRSET, true, rr_nsec_, expected_flags,
-                     NULL, find_options);
-        } else {
-            findTest(Name("wild.example.org"), RRType::A(),
-                     ZoneFinder::NXRRSET, true, ConstRRsetPtr(),
-                     expected_flags, NULL, find_options);
-        }
-    }
-
-    // For the test setup of "NSEC-signed" zone, we might expect it will
-    // be returned with a negative result, either because wildcard match is
-    // disabled by the search option or because wildcard match is canceled
-    // per protocol.
-    ConstRRsetPtr expected_nsec; // by default it's NULL
-    if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0 &&
-        (find_options & ZoneFinder::FIND_DNSSEC) != 0) {
-        expected_nsec = rr_nsec_;
-    }
-    // Explicitly converting the following to const pointers; some compilers
-    // would complain about mixed use of const and non const in ?: below.
-    const ConstRRsetPtr rr_wild = rr_wild_;
-    const ConstRRsetPtr rr_cnamewild = rr_cnamewild_;
-
-    // Search the original name of wildcard
-    {
-        SCOPED_TRACE("Search directly at *");
-        findTest(Name("*.wild.example.org"), RRType::A(), ZoneFinder::SUCCESS,
-                 true, rr_wild_, ZoneFinder::RESULT_DEFAULT, NULL,
-                 find_options);
-    }
-
-    // Below some of the test cases will normally result in a wildcard match;
-    // if NO_WILDCARD is specified, it should result in NXDOMAIN instead,
-    // and, when available and requested, the covering NSEC will be returned.
-    // The following are shortcut parameters to unify these cases.
-    const bool wild_ok = ((find_options & ZoneFinder::NO_WILDCARD) == 0);
-    const ZoneFinder::FindResultFlags wild_expected_flags =
-        wild_ok ? (ZoneFinder::RESULT_WILDCARD | expected_flags) :
-        expected_flags;
-
-    // Search "created" name.
-    {
-        SCOPED_TRACE("Search at created child");
-        findTest(Name("a.wild.example.org"), RRType::A(),
-                 wild_ok ? ZoneFinder::SUCCESS : ZoneFinder::NXDOMAIN, false,
-                 wild_ok ? rr_wild : expected_nsec,
-                 wild_expected_flags, NULL, find_options, wild_ok);
-    }
-
-    // Search name that has CNAME.
-    {
-        SCOPED_TRACE("Matching CNAME");
-        findTest(Name("a.cnamewild.example.org"), RRType::A(),
-                 wild_ok ? ZoneFinder::CNAME : ZoneFinder::NXDOMAIN, false,
-                 wild_ok ? rr_cnamewild : expected_nsec,
-                 wild_expected_flags, NULL, find_options, wild_ok);
-    }
-
-    // Search another created name, this time little bit lower
-    {
-        SCOPED_TRACE("Search at created grand-child");
-        findTest(Name("a.b.wild.example.org"), RRType::A(),
-                 wild_ok ? ZoneFinder::SUCCESS : ZoneFinder::NXDOMAIN, false,
-                 wild_ok ? rr_wild : expected_nsec,
-                 wild_expected_flags, NULL, find_options, wild_ok);
-    }
-
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_under_wild_));
-    {
-        SCOPED_TRACE("Search under non-wildcard");
-        findTest(Name("bar.foo.wild.example.org"), RRType::A(),
-                 ZoneFinder::NXDOMAIN, true, expected_nsec, expected_flags,
-                 NULL, find_options);
-    }
-
-    // Wildcard match, but no data.  We add the additional NSEC at the wildcard
-    // at this point so that it wouldn't break other tests above.  Note also
-    // that in the NO_WILDCARD case the resulting NSEC is the same.  Ideally
-    // we could use a more tricky setup so we can distinguish these cases,
-    // but for this purpose it's not bad; what we'd like to test here is that
-    // wildcard substitution doesn't happen for either case, and the
-    // NO_WILDCARD effect itself can be checked by the result code (NXDOMAIN).
-    ConstRRsetPtr expected_wild_nsec; // by default it's NULL
-    if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0) {
-        EXPECT_EQ(SUCCESS, zone_finder_.add(rr_wild_nsec_));
-        expected_wild_nsec = rr_wild_nsec_;
-    }
-    {
-        SCOPED_TRACE("Search at wildcard, no data");
-        findTest(Name("a.wild.example.org"), RRType::AAAA(),
-                 wild_ok ? ZoneFinder::NXRRSET : ZoneFinder::NXDOMAIN, true,
-                 wild_ok ? expected_wild_nsec : expected_wild_nsec,
-                 wild_expected_flags, NULL, find_options);
-    }
-}
-
-TEST_F(InMemoryZoneFinderTest, wildcard) {
-    // Normal case
-    wildcardCheck();
-}
-
-TEST_F(InMemoryZoneFinderTest, wildcardNSEC3) {
-    // Similar to the previous one, but the zone signed with NSEC3
-    wildcardCheck(ZoneFinder::RESULT_NSEC3_SIGNED);
-}
-
-TEST_F(InMemoryZoneFinderTest, wildcardNSEC) {
-    // Similar to the previous one, but the zone is signed with NSEC
-    wildcardCheck(ZoneFinder::RESULT_NSEC_SIGNED);
-}
-
-TEST_F(InMemoryZoneFinderTest, wildcardDisabledWithNSEC) {
-    // Wildcard is disabled.  In practice, this is used as part of query
-    // processing for an NSEC-signed zone, so we test that case specifically.
-    wildcardCheck(ZoneFinder::RESULT_NSEC_SIGNED, ZoneFinder::NO_WILDCARD);
-}
-
-TEST_F(InMemoryZoneFinderTest, wildcardDisabledWithoutNSEC) {
-    // Similar to the previous once, but check the behavior for a non signed
-    // zone just in case.
-    wildcardCheck(ZoneFinder::RESULT_DEFAULT, ZoneFinder::NO_WILDCARD);
-}
-
-/*
- * Test that we don't match a wildcard if we get under delegation.
- * By 4.3.3 of RFC1034:
- * "Wildcard RRs do not apply:
- *   - When the query is in another zone.  That is, delegation cancels
- *     the wildcard defaults."
- */
-TEST_F(InMemoryZoneFinderTest, delegatedWildcard) {
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_wild_));
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_ns_));
-
-    {
-        SCOPED_TRACE("Looking under delegation point");
-        findTest(Name("a.child.example.org"), RRType::A(),
-                 ZoneFinder::DELEGATION, true, rr_child_ns_);
-    }
-
-    {
-        SCOPED_TRACE("Looking under delegation point in GLUE_OK mode");
-        findTest(Name("a.child.example.org"), RRType::A(),
-                 ZoneFinder::DELEGATION, true, rr_child_ns_,
-                 ZoneFinder::RESULT_DEFAULT, NULL, ZoneFinder::FIND_GLUE_OK);
-    }
-}
-
-// Tests combination of wildcard and ANY.
-void
-InMemoryZoneFinderTest::anyWildcardCheck(
-    ZoneFinder::FindResultFlags expected_flags)
-{
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_wild_));
-    if ((expected_flags & ZoneFinder::RESULT_NSEC3_SIGNED) != 0) {
-        EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec3_));
-    }
-    if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0) {
-        EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec_));
-    }
-
-    vector<ConstRRsetPtr> expected_sets;
-
-    // First try directly the name (normal match)
-    {
-        SCOPED_TRACE("Asking directly for *");
-        expected_sets.push_back(rr_wild_);
-        findAllTest(Name("*.wild.example.org"), ZoneFinder::SUCCESS,
-                    expected_sets);
-    }
-
-    // Then a wildcard match
-    {
-        SCOPED_TRACE("Asking in the wild way");
-        expected_sets.clear();
-        RRsetPtr expected(new RRset(Name("a.wild.example.org"),
-                                    rr_wild_->getClass(), rr_wild_->getType(),
-                                    rr_wild_->getTTL()));
-        expected->addRdata(rr_wild_->getRdataIterator()->getCurrent());
-        expected_sets.push_back(expected);
-        findAllTest(Name("a.wild.example.org"), ZoneFinder::SUCCESS,
-                    expected_sets,
-                    ZoneFinder::RESULT_WILDCARD | expected_flags);
-    }
-}
-
-TEST_F(InMemoryZoneFinderTest, anyWildcard) {
-    anyWildcardCheck();
-}
-
-TEST_F(InMemoryZoneFinderTest, anyWildcardNSEC3) {
-    anyWildcardCheck(ZoneFinder::RESULT_NSEC3_SIGNED);
-}
-
-TEST_F(InMemoryZoneFinderTest, anyWildcardNSEC) {
-    anyWildcardCheck(ZoneFinder::RESULT_NSEC_SIGNED);
-}
-
-// Test there's nothing in the wildcard in the middle if we load
-// wild.*.foo.example.org.
-void
-InMemoryZoneFinderTest::emptyWildcardCheck(
-    ZoneFinder::FindResultFlags expected_flags)
-{
-    /*
-     *            example.org.
-     *                foo
-     *                 *
-     *               wild
-     */
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_emptywild_));
-    if ((expected_flags & ZoneFinder::RESULT_NSEC3_SIGNED) != 0) {
-        EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec3_));
-    }
-    if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0) {
-        EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec_));
-    }
-
-    {
-        SCOPED_TRACE("Asking for the original record under wildcard");
-        findTest(Name("wild.*.foo.example.org"), RRType::A(),
-                 ZoneFinder::SUCCESS, true, rr_emptywild_);
-    }
-
-    {
-        SCOPED_TRACE("Asking for A record");
-        findTest(Name("a.foo.example.org"), RRType::A(), ZoneFinder::NXRRSET,
-                 true, ConstRRsetPtr(),
-                 ZoneFinder::RESULT_WILDCARD | expected_flags);
-        findTest(Name("*.foo.example.org"), RRType::A(), ZoneFinder::NXRRSET,
-                 true, ConstRRsetPtr(), expected_flags);
-        findTest(Name("foo.example.org"), RRType::A(), ZoneFinder::NXRRSET,
-                 true, ConstRRsetPtr(), expected_flags);
-    }
-
-    {
-        SCOPED_TRACE("Asking for ANY record");
-        findAllTest(Name("*.foo.example.org"), ZoneFinder::NXRRSET,
-                    vector<ConstRRsetPtr>(), expected_flags);
-
-        findAllTest(Name("a.foo.example.org"), ZoneFinder::NXRRSET,
-                    vector<ConstRRsetPtr>(),
-                    ZoneFinder::RESULT_WILDCARD | expected_flags);
-    }
-
-    {
-        SCOPED_TRACE("Asking on the non-terminal");
-        findTest(Name("wild.bar.foo.example.org"), RRType::A(),
-                 ZoneFinder::NXRRSET, true, ConstRRsetPtr(),
-                 ZoneFinder::RESULT_WILDCARD | expected_flags);
-    }
-}
-
-TEST_F(InMemoryZoneFinderTest, emptyWildcard) {
-    emptyWildcardCheck();
-}
-
-TEST_F(InMemoryZoneFinderTest, emptyWildcardNSEC3) {
-    emptyWildcardCheck(ZoneFinder::RESULT_NSEC3_SIGNED);
-}
-
-TEST_F(InMemoryZoneFinderTest, emptyWildcardNSEC) {
-    emptyWildcardCheck(ZoneFinder::RESULT_NSEC_SIGNED);
-}
-
-// Same as emptyWildcard, but with multiple * in the path.
-TEST_F(InMemoryZoneFinderTest, nestedEmptyWildcard) {
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nested_emptywild_));
-
-    {
-        SCOPED_TRACE("Asking for the original record under wildcards");
-        findTest(Name("wild.*.foo.*.bar.example.org"), RRType::A(),
-            ZoneFinder::SUCCESS, true, rr_nested_emptywild_);
-    }
-
-    {
-        SCOPED_TRACE("Matching wildcard against empty nonterminal");
-
-        const char* names[] = {
-            "baz.foo.*.bar.example.org",
-            "baz.foo.baz.bar.example.org",
-            "*.foo.baz.bar.example.org",
-            NULL
-        };
-
-        for (const char** name = names; *name != NULL; ++ name) {
-            SCOPED_TRACE(string("Node ") + *name);
-            findTest(Name(*name), RRType::A(), ZoneFinder::NXRRSET, true,
-                     ConstRRsetPtr(), ZoneFinder::RESULT_WILDCARD);
-        }
-    }
-
-    // Domains to test
-    const char* names[] = {
-        "*.foo.*.bar.example.org",
-        "foo.*.bar.example.org",
-        "*.bar.example.org",
-        "bar.example.org",
-        NULL
-    };
-
-    {
-        SCOPED_TRACE("Asking directly for A on parent nodes");
-
-        for (const char** name = names; *name != NULL; ++ name) {
-            SCOPED_TRACE(string("Node ") + *name);
-            findTest(Name(*name), RRType::A(), ZoneFinder::NXRRSET);
-        }
-    }
-
-    {
-        SCOPED_TRACE("Asking for ANY on parent nodes");
-
-        for (const char** name = names; *name != NULL; ++ name) {
-            SCOPED_TRACE(string("Node ") + *name);
-
-            findAllTest(Name(*name), ZoneFinder::NXRRSET,
-                        vector<ConstRRsetPtr>());
-        }
-    }
-}
-
-// We run this part twice from the below test, in two slightly different
-// situations
-void
-InMemoryZoneFinderTest::doCancelWildcardCheck(
-    ZoneFinder::FindResultFlags expected_flags,
-    ZoneFinder::FindOptions find_options)
-{
-    // These should be canceled
-    {
-        SCOPED_TRACE("Canceled under foo.wild.example.org");
-
-        // For an NSEC-signed zone with DNSSEC requested, the covering NSEC
-        // should be returned.  The expected NSEC is actually just the only
-        // NSEC in the test data, but in this context it doesn't matter;
-        // it's sufficient just to check any NSEC is returned (or not).
-        ConstRRsetPtr expected_nsec; // by default it's NULL
-        if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0 &&
-            (find_options & ZoneFinder::FIND_DNSSEC)) {
-            expected_nsec = rr_nsec_;
-        }
-
-        findTest(Name("aaa.foo.wild.example.org"), RRType::A(),
-                 ZoneFinder::NXDOMAIN, true, expected_nsec, expected_flags,
-                 NULL, find_options);
-        findTest(Name("zzz.foo.wild.example.org"), RRType::A(),
-                 ZoneFinder::NXDOMAIN, true, expected_nsec, expected_flags,
-                 NULL, find_options);
-    }
-
-    // This is existing, non-wildcard domain, shouldn't wildcard at all
-    {
-        SCOPED_TRACE("Existing domain under foo.wild.example.org");
-        findTest(Name("bar.foo.wild.example.org"), RRType::A(),
-                 ZoneFinder::SUCCESS, true, rr_not_wild_);
-    }
-
-    // These should be caught by the wildcard
-    {
-        SCOPED_TRACE("Neighbor wildcards to foo.wild.example.org");
-
-        const char* names[] = {
-            "aaa.bbb.wild.example.org",
-            "aaa.zzz.wild.example.org",
-            "zzz.wild.example.org",
-            NULL
-        };
-
-        for (const char** name = names; *name != NULL; ++ name) {
-            SCOPED_TRACE(string("Node ") + *name);
-
-            findTest(Name(*name), RRType::A(), ZoneFinder::SUCCESS, false,
-                     rr_wild_,
-                     ZoneFinder::RESULT_WILDCARD | expected_flags, NULL,
-                     ZoneFinder::FIND_DEFAULT, true);
-        }
-    }
-
-    // This shouldn't be wildcarded, it's an existing domain
-    {
-        SCOPED_TRACE("The foo.wild.example.org itself");
-        findTest(Name("foo.wild.example.org"), RRType::A(),
-                 ZoneFinder::NXRRSET, true, ConstRRsetPtr(), expected_flags);
-    }
-}
-
-/*
- * This tests that if there's a name between the wildcard domain and the
- * searched one, it will not trigger wildcard, for example, if we have
- * *.wild.example.org and bar.foo.wild.example.org, then we know
- * foo.wild.example.org exists and is not wildcard. Therefore, search for
- * aaa.foo.wild.example.org should return NXDOMAIN.
- *
- * Tests few cases "around" the canceled wildcard match, to see something that
- * shouldn't be canceled isn't.
- */
-TEST_F(InMemoryZoneFinderTest, cancelWildcard) {
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_wild_));
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_not_wild_));
-
-    {
-        SCOPED_TRACE("Runnig with single entry under foo.wild.example.org");
-        doCancelWildcardCheck();
-    }
-
-    // Try putting another one under foo.wild....
-    // The result should be the same but it will be done in another way in the
-    // code, because the foo.wild.example.org will exist in the tree.
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_not_wild_another_));
-    {
-        SCOPED_TRACE("Runnig with two entries under foo.wild.example.org");
-        doCancelWildcardCheck();
-    }
-}
-
-// Same tests as cancelWildcard for NSEC3-signed zone
-TEST_F(InMemoryZoneFinderTest, cancelWildcardNSEC3) {
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_wild_));
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_not_wild_));
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec3_));
-
-    {
-        SCOPED_TRACE("Runnig with single entry under foo.wild.example.org");
-        doCancelWildcardCheck(ZoneFinder::RESULT_NSEC3_SIGNED);
-    }
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_not_wild_another_));
-    {
-        SCOPED_TRACE("Runnig with two entries under foo.wild.example.org");
-        doCancelWildcardCheck(ZoneFinder::RESULT_NSEC3_SIGNED);
-    }
-}
-
-// Same tests as cancelWildcard for NSEC-signed zone.  Check both cases with
-// or without FIND_DNSSEC option.  NSEC should be returned only when the option
-// is given.
-TEST_F(InMemoryZoneFinderTest, cancelWildcardNSEC) {
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_wild_));
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_not_wild_));
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec_));
-
-    {
-        SCOPED_TRACE("Runnig with single entry under foo.wild.example.org");
-        doCancelWildcardCheck(ZoneFinder::RESULT_NSEC_SIGNED,
-                              ZoneFinder::FIND_DNSSEC);
-        doCancelWildcardCheck(ZoneFinder::RESULT_NSEC_SIGNED);
-    }
-    EXPECT_EQ(SUCCESS, zone_finder_.add(rr_not_wild_another_));
-    {
-        SCOPED_TRACE("Runnig with two entries under foo.wild.example.org");
-        doCancelWildcardCheck(ZoneFinder::RESULT_NSEC_SIGNED,
-                              ZoneFinder::FIND_DNSSEC);
-        doCancelWildcardCheck(ZoneFinder::RESULT_NSEC_SIGNED);
-    }
-}
-
-TEST_F(InMemoryZoneFinderTest, loadBadWildcard) {
-    // We reject loading the zone if it contains a wildcard name for
-    // NS or DNAME.
-    EXPECT_THROW(zone_finder_.add(rr_nswild_), InMemoryZoneFinder::AddError);
-    EXPECT_THROW(zone_finder_.add(rr_dnamewild_),
-                 InMemoryZoneFinder::AddError);
-}
-
-TEST_F(InMemoryZoneFinderTest, swap) {
-    // build one zone finder with some data
-    InMemoryZoneFinder finder1(class_, origin_);
-    EXPECT_EQ(result::SUCCESS, finder1.add(rr_ns_));
-    EXPECT_EQ(result::SUCCESS, finder1.add(rr_ns_aaaa_));
-
-    // build another zone finder of a different RR class with some other data
-    const Name other_origin("version.bind");
-    ASSERT_NE(origin_, other_origin); // make sure these two are different
-    InMemoryZoneFinder finder2(RRClass::CH(), other_origin);
-    EXPECT_EQ(result::SUCCESS,
-              finder2.add(textToRRset("version.bind. 0 CH TXT \"test\"",
-                                      RRClass::CH())));
-
-    finder1.swap(finder2);
-    EXPECT_EQ(other_origin, finder1.getOrigin());
-    EXPECT_EQ(origin_, finder2.getOrigin());
-    EXPECT_EQ(RRClass::CH(), finder1.getClass());
-    EXPECT_EQ(RRClass::IN(), finder2.getClass());
-    // make sure the zone data is swapped, too
-    EXPECT_THROW(finder1.find(origin_, RRType::NS()), OutOfZone);
-    findTest(other_origin, RRType::TXT(), ZoneFinder::SUCCESS, false,
-             ConstRRsetPtr(), ZoneFinder::RESULT_DEFAULT, &finder1);
-    findTest(origin_, RRType::NS(), ZoneFinder::SUCCESS, false,
-             ConstRRsetPtr(), ZoneFinder::RESULT_DEFAULT, &finder2);
-    EXPECT_THROW(finder2.find(other_origin, RRType::TXT()), OutOfZone);
-}
-
-TEST_F(InMemoryZoneFinderTest, getFileName) {
-    // for an empty zone the file name should also be empty.
-    EXPECT_TRUE(zone_finder_.getFileName().empty());
-
-    // if loading a zone fails the file name shouldn't be set.
-    EXPECT_THROW(zone_finder_.load(TEST_DATA_DIR "/root.zone"),
-                 MasterLoadError);
-    EXPECT_TRUE(zone_finder_.getFileName().empty());
-
-    // after a successful load, the specified file name should be set
-    InMemoryZoneFinder rootzone(class_, Name("."));
-    EXPECT_NO_THROW(rootzone.load(TEST_DATA_DIR "/root.zone"));
-    EXPECT_EQ(TEST_DATA_DIR "/root.zone", rootzone.getFileName());
-    // overriding load, which will fail
-    EXPECT_THROW(rootzone.load(TEST_DATA_DIR "/duplicate_rrset.zone"),
-                 MasterLoadError);
-    // the file name should be intact.
-    EXPECT_EQ(TEST_DATA_DIR "/root.zone", rootzone.getFileName());
-
-    // After swap, file names should also be swapped.
-    zone_finder_.swap(rootzone);
-    EXPECT_EQ(TEST_DATA_DIR "/root.zone", zone_finder_.getFileName());
-    EXPECT_TRUE(rootzone.getFileName().empty());
-}
-
-TEST_F(InMemoryZoneFinderTest, addRRsig) {
-    // A simple valid case: adding an RRset to be signed followed by an RRSIG
-    // that covers the first RRset
-    zone_finder_.add(rr_a_);
-    zone_finder_.add(textToRRset(rrsig_a_txt));
-    ZoneFinderContextPtr result = zone_finder_.find(origin_, RRType::A(),
-                                                    ZoneFinder::FIND_DNSSEC);
-    EXPECT_EQ(ZoneFinder::SUCCESS, result->code);
-    ASSERT_TRUE(result->rrset);
-    ASSERT_TRUE(result->rrset->getRRsig());
-    actual_rrsets_.push_back(result->rrset->getRRsig());
-    rrsetsCheck(rrsig_a_txt, actual_rrsets_.begin(), actual_rrsets_.end());
-
-    // Confirm a separate RRISG for a different type can be added
-    actual_rrsets_.clear();
-    zone_finder_.add(rr_ns_);
-    zone_finder_.add(textToRRset(rrsig_ns_txt));
-    result = zone_finder_.find(origin_, RRType::NS(), ZoneFinder::FIND_DNSSEC);
-    EXPECT_EQ(ZoneFinder::SUCCESS, result->code);
-    ASSERT_TRUE(result->rrset);
-    ASSERT_TRUE(result->rrset->getRRsig());
-    actual_rrsets_.push_back(result->rrset->getRRsig());
-    rrsetsCheck(rrsig_ns_txt, actual_rrsets_.begin(), actual_rrsets_.end());
-
-    // Check a case with multiple RRSIGs
-    actual_rrsets_.clear();
-    zone_finder_.add(rr_ns_aaaa_);
-    zone_finder_.add(textToRRset(rrsig_aaaa_txt));
-    result = zone_finder_.find(Name("ns.example.org"), RRType::AAAA(),
-                               ZoneFinder::FIND_DNSSEC);
-    EXPECT_EQ(ZoneFinder::SUCCESS, result->code);
-    ASSERT_TRUE(result->rrset);
-    ASSERT_TRUE(result->rrset->getRRsig());
-    actual_rrsets_.push_back(result->rrset->getRRsig());
-    rrsetsCheck(rrsig_aaaa_txt, actual_rrsets_.begin(), actual_rrsets_.end());
-}
-
-TEST_F(InMemoryZoneFinderTest, addRRsigWithoutCovered) {
-    // The current implementation rejects attempts of adding RRSIG without
-    // covered RRsets already in the zone.
-
-    // Name doesn't exist
-    EXPECT_THROW(zone_finder_.add(
-                     textToRRset("notexist.example.org. 300 IN RRSIG A 5 3 "
-                                 "3600 20000101000000 20000201000000 12345 "
-                                 "example.org. FAKEFAKEFAKE\n")),
-                 InMemoryZoneFinder::AddError);
-
-    // Name exists, but is empty.
-    zone_finder_.add(rr_emptywild_);
-    EXPECT_THROW(zone_finder_.add(
-                     textToRRset("foo.example.org. 300 IN RRSIG A 5 3 "
-                                 "3600 20000101000000 20000201000000 12345 "
-                                 "example.org. FAKEFAKEFAKE\n")),
-                 InMemoryZoneFinder::AddError);
-
-    // Add RRSIG RRset without covered RR
-    zone_finder_.add(rr_a_);
-    EXPECT_THROW(zone_finder_.add(textToRRset(rrsig_ns_txt)),
-                 InMemoryZoneFinder::AddError);
-}
-
-TEST_F(InMemoryZoneFinderTest, addbadRRsig) {
-    // Tests with other types of bogus input
-
-    // Empty RRSIG RRset.
-    EXPECT_THROW(zone_finder_.add(RRsetPtr(new RRset(origin_, class_,
-                                                     RRType::RRSIG(),
-                                                     RRTTL(300)))),
-                                  InMemoryZoneFinder::AddError);
-
-    // RRSIG with mixed covered types
-    zone_finder_.add(rr_a_);    // make sure the covered name exists
-    // textToRRset() doesn't work as intended for this pathological case,
-    // so we need to construct the RRset by hand.
-    RRsetPtr rrset(new RRset(origin_, class_, RRType::RRSIG(), RRTTL(300)));
-    rrset->addRdata(generic::RRSIG("A 5 3 3600 20000101000000 20000201000000 "
-                                   "12345 example.org. FAKEFAKEFAKE"));
-    rrset->addRdata(generic::RRSIG("NS 5 3 3600 20000101000000 20000201000000 "
-                                   "54321 example.org. FAKEFAKEFAKEFAKE"));
-    EXPECT_THROW(zone_finder_.add(rrset), InMemoryZoneFinder::AddError);
-
-    // An attempt of overriding an existing RRSIG.  The current implementation
-    // prohibits that.
-    zone_finder_.add(textToRRset(rrsig_a_txt));
-    EXPECT_THROW(zone_finder_.add(textToRRset(rrsig_a_txt)),
-                 InMemoryZoneFinder::AddError);
-}
-
-TEST_F(InMemoryZoneFinderTest, addNSEC3) {
-    // Set up the faked hash calculator.
-    setNSEC3HashCreator(&nsec3_hash_creator_);
-
-    const string nsec3_text = string(apex_hash) + ".example.org." +
-        string(nsec3_common);
-    // This name shouldn't be found in the normal domain tree.
-    EXPECT_EQ(result::SUCCESS, zone_finder_.add(textToRRset(nsec3_text)));
-    EXPECT_EQ(ZoneFinder::NXDOMAIN,
-              zone_finder_.find(Name(string(apex_hash) + ".example.org"),
-                                RRType::NSEC3())->code);
-    // Dedicated NSEC3 find should be able to find it.
-    findNSEC3Check(true, origin_.getLabelCount(), nsec3_text, "",
-                   zone_finder_.findNSEC3(Name("example.org"), false));
-
-    // This implementation rejects duplicate/update add of the same hash name
-    EXPECT_EQ(result::EXIST,
-              zone_finder_.add(textToRRset(
-                                   string(apex_hash) + ".example.org." +
-                                   string(nsec3_common) + " AAAA")));
-    // The original NSEC3 should be intact
-    findNSEC3Check(true, origin_.getLabelCount(), nsec3_text, "",
-                   zone_finder_.findNSEC3(Name("example.org"), false));
-
-    // NSEC3-like name but of ordinary RR type should go to normal tree.
-    const string nonsec3_text = string(apex_hash) + ".example.org. " +
-        "300 IN A 192.0.2.1";
-    EXPECT_EQ(result::SUCCESS, zone_finder_.add(textToRRset(nonsec3_text)));
-    EXPECT_EQ(ZoneFinder::SUCCESS,
-              zone_finder_.find(Name(string(apex_hash) + ".example.org"),
-                                RRType::A())->code);
-}
-
-TEST_F(InMemoryZoneFinderTest, addNSEC3Lower) {
-    // Set up the faked hash calculator.
-    setNSEC3HashCreator(&nsec3_hash_creator_);
-
-    // Similar to the previous case, but NSEC3 owner name is lower-cased.
-    const string nsec3_text = string(apex_hash_lower) + ".example.org." +
-        string(nsec3_common);
-    EXPECT_EQ(result::SUCCESS, zone_finder_.add(textToRRset(nsec3_text)));
-    findNSEC3Check(true, origin_.getLabelCount(), nsec3_text, "",
-                   zone_finder_.findNSEC3(Name("example.org"), false));
-}
-
-TEST_F(InMemoryZoneFinderTest, addNSEC3Ordering) {
-    // Set up the faked hash calculator.
-    setNSEC3HashCreator(&nsec3_hash_creator_);
-
-    // Check that the internal storage ensures comparison based on the NSEC3
-    // semantics, regardless of the add order or the letter-case of hash.
-
-    // Adding "0P..", "2v..", then "2T..".
-    const string smallest = string(apex_hash) + ".example.org." +
-        string(nsec3_common);
-    const string middle = string(ns1_hash) + ".example.org." +
-        string(nsec3_common);
-    const string largest = string(xyw_hash) + ".example.org." +
-        string(nsec3_common);
-    zone_finder_.add(textToRRset(smallest));
-    zone_finder_.add(textToRRset(largest));
-    zone_finder_.add(textToRRset(middle));
-
-    // Then look for NSEC3 that covers a name whose hash is "2S.."
-    // The covering NSEC3 should be "0P.."
-    findNSEC3Check(false, 4, smallest, "",
-                   zone_finder_.findNSEC3(Name("www.example.org"), false));
-
-    // Look for NSEC3 that covers names whose hash are "Q0.." and "0A.."
-    // The covering NSEC3 should be "2v.." in both cases
-    findNSEC3Check(false, 4, largest, "",
-                   zone_finder_.findNSEC3(Name("xxx.example.org"), false));
-    findNSEC3Check(false, 4, largest, "",
-                   zone_finder_.findNSEC3(Name("yyy.example.org"), false));
-}
-
-TEST_F(InMemoryZoneFinderTest, badNSEC3Name) {
-    // Our implementation refuses to load NSEC3 at a wildcard name
-    EXPECT_THROW(zone_finder_.add(textToRRset("*.example.org." +
-                                              string(nsec3_common))),
-                 InMemoryZoneFinder::AddError);
-
-    // Likewise, if the owner name of NSEC3 has too many labels, it's refused.
-    EXPECT_THROW(zone_finder_.add(textToRRset("a." + string(apex_hash) +
-                                              ".example.org." +
-                                              string(nsec3_common))),
-                 InMemoryZoneFinder::AddError);
-}
-
-TEST_F(InMemoryZoneFinderTest, addMultiNSEC3) {
-    // In this current implementation multiple NSEC3 RDATA isn't supported.
-    RRsetPtr nsec3(new RRset(Name(string(apex_hash) + ".example.org"),
-                             RRClass::IN(), RRType::NSEC3(), RRTTL(300)));
-    nsec3->addRdata(
-        generic::NSEC3("1 0 12 aabbccdd 2T7B4G4VSA5SMI47K61MV5BV1A22BOJR A"));
-    nsec3->addRdata(
-        generic::NSEC3("1 1 1 ddccbbaa 2T7B4G4VSA5SMI47K61MV5BV1A22BOJR A"));
-    EXPECT_THROW(zone_finder_.add(nsec3), InMemoryZoneFinder::AddError);
-}
-
-TEST_F(InMemoryZoneFinderTest, addNSEC3WithRRSIG) {
-    // Set up the faked hash calculator.
-    setNSEC3HashCreator(&nsec3_hash_creator_);
-
-    // Adding NSEC3 and its RRSIG
-    const string nsec3_text = string(apex_hash) + ".example.org." +
-        string(nsec3_common);
-    EXPECT_EQ(result::SUCCESS, zone_finder_.add(textToRRset(nsec3_text)));
-    const string nsec3_rrsig_text = string(apex_hash) + ".example.org." +
-        string(nsec3_rrsig_common);
-    EXPECT_EQ(result::SUCCESS, zone_finder_.add(textToRRset(nsec3_rrsig_text)));
-
-    // Then look for it.  The NSEC3 should have the RRSIG that was just added.
-    findNSEC3Check(true, origin_.getLabelCount(),
-                   nsec3_text + "\n" + nsec3_rrsig_text, "",
-                   zone_finder_.findNSEC3(Name("example.org"), false));
-
-    // Duplicate add of RRSIG for the same NSEC3 is prohibited.
-    EXPECT_THROW(zone_finder_.add(textToRRset(nsec3_rrsig_text)),
-                 InMemoryZoneFinder::AddError);
-
-    // Same check using the lower-cased name.  This also confirms matching
-    // is case-insensitive.
-    EXPECT_THROW(zone_finder_.add(textToRRset(string(apex_hash_lower) +
-                                              ".example.org."
-                                              + string(nsec3_rrsig_common))),
-                 InMemoryZoneFinder::AddError);
-}
-
-TEST_F(InMemoryZoneFinderTest, badRRsigForNSEC3) {
-    // adding RRSIG for NSEC3 even before adding any NSEC3 (internally,
-    // a space for NSEC3 namespace isn't yet allocated)
-    EXPECT_THROW(zone_finder_.add(textToRRset(string(apex_hash) +
-                                              ".example.org." +
-                                              string(nsec3_rrsig_common))),
-                 InMemoryZoneFinder::AddError);
-
-    // Add an NSEC3
-    EXPECT_EQ(result::SUCCESS, zone_finder_.add(
-                  textToRRset(string(apex_hash) + ".example.org." +
-                              string(nsec3_common))));
-
-    // Then add an NSEC3 for a non existent NSEC3.  It should fail in the
-    // current implementation.
-    EXPECT_THROW(zone_finder_.add(textToRRset(string(ns1_hash) +
-                                              ".example.org." +
-                                              string(nsec3_rrsig_common))),
-                 InMemoryZoneFinder::AddError);
-}
-
-TEST_F(InMemoryZoneFinderTest, paramConsistencyWithNSEC3PARAM) {
-    // First, add an NSEC3PARAM RR
-    EXPECT_EQ(result::SUCCESS,
-              zone_finder_.add(textToRRset("example.org. 300 IN NSEC3PARAM "
-                                           "1 0 12 aabbccdd")));
-    // Adding an NSEC3 that has matching parameters is okay.
-    EXPECT_EQ(result::SUCCESS, zone_finder_.add(
-                  textToRRset(string(apex_hash) + ".example.org." +
-                              string(nsec3_common))));
-    // NSEC3 with inconsistent parameter will be rejected
-    EXPECT_THROW(zone_finder_.add(
-                     textToRRset("a.example.org. 300 IN NSEC3 1 0 1 aabbccdd "
-                                 "2T7B4G4VSA5SMI47K61MV5BV1A22BOJR A RRSIG")),
-                 InMemoryZoneFinder::AddError);
-}
-
-TEST_F(InMemoryZoneFinderTest, paramConsistencyWithNSEC3) {
-    // Add an NSEC3 without adding NSEC3PARAM
-    EXPECT_EQ(result::SUCCESS, zone_finder_.add(
-                  textToRRset(string(apex_hash) + ".example.org." +
-                              string(nsec3_common))));
-    // Adding an NSEC3 with inconsistent parameter will be rejected at this pt.
-    EXPECT_THROW(zone_finder_.add(
-                     textToRRset("a.example.org. 300 IN NSEC3 1 0 1 aabbccdd "
-                                 "2T7B4G4VSA5SMI47K61MV5BV1A22BOJR A RRSIG")),
-                 InMemoryZoneFinder::AddError);
-
-    // Likewise, NSEC3PARAM with inconsistent parameter will be rejected.
-    EXPECT_THROW(zone_finder_.add(textToRRset("example.org. 300 IN NSEC3PARAM "
-                                              "1 0 1 aabbccdd")),
-                 InMemoryZoneFinder::AddError);
-}
-
-TEST_F(InMemoryZoneFinderTest, multiNSEC3PARAM) {
-    // In this current implementation multiple NSEC3PARAM isn't supported.
-    RRsetPtr nsec3param(new RRset(Name("example.org"), RRClass::IN(),
-                                  RRType::NSEC3PARAM(), RRTTL(300)));
-    nsec3param->addRdata(generic::NSEC3PARAM("1 0 12 aabbccdd"));
-    nsec3param->addRdata(generic::NSEC3PARAM("1 1 1 ddccbbaa"));
-    EXPECT_THROW(zone_finder_.add(nsec3param), InMemoryZoneFinder::AddError);
-}
-
-TEST_F(InMemoryZoneFinderTest, nonOriginNSEC3PARAM) {
-    // This is a normal NSEC3PARAM at the zone origin
-    EXPECT_EQ(result::SUCCESS,
-              zone_finder_.add(textToRRset("example.org. 300 IN NSEC3PARAM "
-                                           "1 0 12 aabbccdd")));
-    // Add another (with different param) at a non origin node.  This is
-    // awkward, but the implementation accepts it as an ordinary RR.
-    EXPECT_EQ(result::SUCCESS,
-              zone_finder_.add(textToRRset("a.example.org. 300 IN NSEC3PARAM "
-                                           "1 1 1 aabbccdd")));
-}
-
-TEST_F(InMemoryZoneFinderTest, loadNSEC3Zone) {
-    // Check if it can load validly NSEC3-signed zone.  At this moment
-    // it's sufficient to see it doesn't crash
-    zone_finder_.load(TEST_DATA_DIR "/example.org.nsec3-signed");
-
-    // Reload the zone with a version that doesn't have NSEC3PARAM.
-    // This is an abnormal case, but the implementation accepts it.
-    zone_finder_.load(TEST_DATA_DIR "/example.org.nsec3-signed-noparam");
-}
-
-// This test checks that the NSEC3 names don't really exist in the real
-// namespace.
-TEST_F(InMemoryZoneFinderTest, queryToNSEC3Name) {
-    // Add the NSEC3 and NSEC3PARAM there.
-    EXPECT_EQ(result::SUCCESS,
-              zone_finder_.add(textToRRset("example.org. 300 IN NSEC3PARAM "
-                                           "1 0 12 aabbccdd")));
-    const Name nsec3domain(string(apex_hash) + ".example.org.");
-    // Adding an NSEC3 that has matching parameters is okay.
-    EXPECT_EQ(result::SUCCESS, zone_finder_.add(
-                  textToRRset(string(apex_hash) + ".example.org." +
-                              string(nsec3_common))));
-    // Now, the domain should not exist
-    findTest(nsec3domain, RRType::AAAA(), ZoneFinder::NXDOMAIN, false,
-             ConstRRsetPtr(), ZoneFinder::RESULT_NSEC3_SIGNED, &zone_finder_,
-             ZoneFinder::FIND_DNSSEC);
-    // If we add an A record, the domain should exist
-    ConstRRsetPtr rrset(textToRRset(string(apex_hash) +
-                                    ".example.org. 300 IN A 192.0.2.1"));
-    EXPECT_EQ(result::SUCCESS, zone_finder_.add(rrset));
-    // Searching for a different RRType will tell us this RRset doesn't exist
-    findTest(nsec3domain, RRType::AAAA(), ZoneFinder::NXRRSET, false,
-             ConstRRsetPtr(), ZoneFinder::RESULT_NSEC3_SIGNED, &zone_finder_,
-             ZoneFinder::FIND_DNSSEC);
-    // Searching for the A record would find it
-    findTest(nsec3domain, RRType::A(), ZoneFinder::SUCCESS, true,
-             rrset, ZoneFinder::RESULT_DEFAULT, &zone_finder_,
-             ZoneFinder::FIND_DNSSEC);
-}
-
-// Continuation of the previous test (queryToNSEC3Name), we check we don't break
-// the empty nonterminal case by existence of NSEC3 record with that name.
-TEST_F(InMemoryZoneFinderTest, queryToNSEC3NameNonterminal) {
-    // Add the NSEC3 and NSEC3PARAM there.
-    EXPECT_EQ(result::SUCCESS,
-              zone_finder_.add(textToRRset("example.org. 300 IN NSEC3PARAM "
-                                           "1 0 12 aabbccdd")));
-    const Name nsec3domain(string(apex_hash) + ".example.org.");
-    // Adding an NSEC3 that has matching parameters is okay.
-    EXPECT_EQ(result::SUCCESS, zone_finder_.add(
-                  textToRRset(string(apex_hash) + ".example.org." +
-                              string(nsec3_common))));
-    // Something below the name
-    ConstRRsetPtr rrset(textToRRset("below." + string(apex_hash) +
-                                    ".example.org. 300 IN A 192.0.2.1"));
-    EXPECT_EQ(result::SUCCESS, zone_finder_.add(rrset));
-    // Now, the node is empty non-terminal.
-    findTest(nsec3domain, RRType::AAAA(), ZoneFinder::NXRRSET, false,
-             ConstRRsetPtr(), ZoneFinder::RESULT_NSEC3_SIGNED, &zone_finder_,
-             ZoneFinder::FIND_DNSSEC);
-}
-
-TEST_F(InMemoryZoneFinderTest, findNSEC3) {
-    // Set up the faked hash calculator.
-    setNSEC3HashCreator(&nsec3_hash_creator_);
-
-    // Add a few NSEC3 records:
-    // apex (example.org.): hash=0P..
-    // ns1.example.org:     hash=2T..
-    // w.example.org:       hash=01..
-    // zzz.example.org:     hash=R5..
-    const string apex_nsec3_text = string(apex_hash) + ".example.org." +
-        string(nsec3_common);
-    EXPECT_EQ(result::SUCCESS, zone_finder_.add(textToRRset(apex_nsec3_text)));
-    const string ns1_nsec3_text = string(ns1_hash) + ".example.org." +
-        string(nsec3_common);
-    EXPECT_EQ(result::SUCCESS, zone_finder_.add(textToRRset(ns1_nsec3_text)));
-    const string w_nsec3_text = string(w_hash) + ".example.org." +
-        string(nsec3_common);
-    EXPECT_EQ(result::SUCCESS, zone_finder_.add(textToRRset(w_nsec3_text)));
-    const string zzz_nsec3_text = string(zzz_hash) + ".example.org." +
-        string(nsec3_common);
-    EXPECT_EQ(result::SUCCESS, zone_finder_.add(textToRRset(zzz_nsec3_text)));
-
-    performNSEC3Test(zone_finder_);
-}
-
-TEST_F(InMemoryZoneFinderTest, findNSEC3ForBadZone) {
-    // Set up the faked hash calculator.
-    setNSEC3HashCreator(&nsec3_hash_creator_);
-
-    // If the zone has nothing about NSEC3 (neither NSEC3 or NSEC3PARAM),
-    // findNSEC3() should be rejected.
-    EXPECT_THROW(zone_finder_.findNSEC3(Name("www.example.org"), true),
-                 DataSourceError);
-
-    // Only having NSEC3PARAM isn't enough
-    EXPECT_EQ(result::SUCCESS,
-              zone_finder_.add(textToRRset("example.org. 300 IN NSEC3PARAM "
-                                           "1 0 12 aabbccdd")));
-    EXPECT_THROW(zone_finder_.findNSEC3(Name("www.example.org"), true),
-                 DataSourceError);
-
-    // Unless NSEC3 for apex is added the result in the recursive mode
-    // is guaranteed.
-    const string ns1_nsec3_text = string(ns1_hash) + ".example.org." +
-        string(nsec3_common);
-    EXPECT_EQ(result::SUCCESS, zone_finder_.add(textToRRset(ns1_nsec3_text)));
-    EXPECT_THROW(zone_finder_.findNSEC3(Name("www.example.org"), true),
-                 DataSourceError);
-}
-
-TEST_F(InMemoryZoneFinderTest, loadAndFindNSEC3) {
-    // Using more realistic example, borrowed from RFC5155, with compliant
-    // hash calculator.  We only confirm the data source can load it
-    // successfully and find correct NSEC3 RRs for some selected cases
-    // (detailed tests have been done above).
-
-    InMemoryZoneFinder finder(class_, Name("example"));
-    finder.load(TEST_DATA_COMMONDIR "/rfc5155-example.zone.signed");
-
-    // See RFC5155 B.1
-    ZoneFinder::FindNSEC3Result result1 =
-        finder.findNSEC3(Name("c.x.w.example"), true);
-    ASSERT_TRUE(result1.closest_proof);
-    // We compare closest_labels as int so the error report will be more
-    // readable in case it fails.
-    EXPECT_EQ(4, static_cast<int>(result1.closest_labels));
-    EXPECT_EQ(Name("b4um86eghhds6nea196smvmlo4ors995.example"),
-              result1.closest_proof->getName());
-    ASSERT_TRUE(result1.next_proof);
-    EXPECT_EQ(Name("0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example"),
-              result1.next_proof->getName());
-
-    // See RFC5155 B.2.
-    ZoneFinder::FindNSEC3Result result2 =
-        finder.findNSEC3(Name("ns1.example"), true);
-    ASSERT_TRUE(result2.closest_proof);
-    EXPECT_EQ(3, static_cast<int>(result2.closest_labels));
-    EXPECT_EQ(Name("2t7b4g4vsa5smi47k61mv5bv1a22bojr.example"),
-              result2.closest_proof->getName());
-    ASSERT_FALSE(result2.next_proof);
-
-    // See RFC5155 B.5.
-    ZoneFinder::FindNSEC3Result result3 =
-        finder.findNSEC3(Name("a.z.w.example"), true);
-    ASSERT_TRUE(result3.closest_proof);
-    EXPECT_EQ(3, static_cast<int>(result3.closest_labels));
-    EXPECT_EQ(Name("k8udemvp1j2f7eg6jebps17vp3n8i58h.example"),
-              result3.closest_proof->getName());
-    ASSERT_TRUE(result3.next_proof);
-    EXPECT_EQ(Name("q04jkcevqvmu85r014c7dkba38o0ji5r.example"),
-              result3.next_proof->getName());
-}
-}
diff --git a/src/lib/datasrc/tests/rbnode_rrset_unittest.cc b/src/lib/datasrc/tests/rbnode_rrset_unittest.cc
deleted file mode 100644
index 57e8dbd..0000000
--- a/src/lib/datasrc/tests/rbnode_rrset_unittest.cc
+++ /dev/null
@@ -1,276 +0,0 @@
-// Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#include <exceptions/exceptions.h>
-#include <dns/rdataclass.h>
-#include <datasrc/rbnode_rrset.h>
-#include <testutils/dnsmessage_test.h>
-
-#include <dns/tests/unittest_util.h>
-
-#include <gtest/gtest.h>
-
-#include <sstream>
-#include <stdexcept>
-
-using isc::UnitTestUtil;
-
-using namespace isc;
-using namespace isc::datasrc;
-using namespace isc::datasrc::internal;
-using namespace isc::dns;
-using namespace isc::dns::rdata;
-using namespace isc::testutils;
-using namespace isc::util;
-using namespace std;
-
-// These tests are very similar to those for RRset - indeed, this file was
-// created from those tests.  However, the significant difference in behaviour
-// between RRset and RBNodeRRset - that the "set" methods in the latter mostly
-// result in exceptions being thrown - preclude use of full type
-// parameterisation of the tests.
-
-namespace {
-const char* const RRSIG_TXT =
-    "A 5 4 43200 20100223214617 20100222214617 8496 isc.org. "
-    "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
-    "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
-    "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU"
-    "f49t+sXKPzbipN9g+s1ZPiIyofc=";
-
-class RBNodeRRsetTest : public ::testing::Test {
-protected:
-    RBNodeRRsetTest() :
-        test_name("test.example.com"),
-        test_domain("example.com"),
-        test_nsname("ns.example.com"),
-        rrset_a(ConstRRsetPtr(new RRset(
-                test_name, RRClass::IN(), RRType::A(), RRTTL(3600)))),
-        rrset_a_empty(ConstRRsetPtr(new RRset(
-                      test_name, RRClass::IN(), RRType::A(), RRTTL(3600)))),
-        rrset_ns(ConstRRsetPtr(new RRset(
-                 test_domain, RRClass::IN(), RRType::NS(), RRTTL(86400)))),
-        rrset_ch_txt(ConstRRsetPtr(new RRset(
-                     test_domain, RRClass::CH(), RRType::TXT(), RRTTL(0)))),
-        rrset_siga(new RRset(test_name, RRClass::IN(), RRType::RRSIG(),
-                   RRTTL(3600)))
-
-    {
-        // Add a couple of Rdata elements to the A RRset.  The easiest way to
-        // do this is to override the "const" restrictions.  As this is a test,
-        // we don't feel too bad about doing so.
-        AbstractRRset* a_rrset =
-            const_cast<AbstractRRset*>(rrset_a.getUnderlyingRRset().get());
-        a_rrset->addRdata(in::A("192.0.2.1"));
-        a_rrset->addRdata(in::A("192.0.2.2"));
-
-        // Create the RRSIG corresponding to the rrset_a record.  The RDATA
-        // won't match the A record it covers, although it is internally
-        // self-consistent.
-        AbstractRRset* sig_rrset =
-            const_cast<AbstractRRset*>(rrset_siga.get());
-        sig_rrset->addRdata(generic::RRSIG(RRSIG_TXT));
-    }
-
-    const Name test_name;
-    const Name test_domain;
-    const Name test_nsname;
-
-    RBNodeRRset rrset_a;
-    RBNodeRRset rrset_a_empty;
-    const RBNodeRRset rrset_ns;
-    const RBNodeRRset rrset_ch_txt;
-
-    ConstRRsetPtr rrset_siga;
-};
-
-TEST_F(RBNodeRRsetTest, getRdataCount) {
-    EXPECT_EQ(0, rrset_a_empty.getRdataCount());
-    EXPECT_EQ(2, rrset_a.getRdataCount());
-}
-
-TEST_F(RBNodeRRsetTest, getName) {
-    EXPECT_EQ(test_name, rrset_a.getName());
-    EXPECT_EQ(test_domain, rrset_ns.getName());
-}
-
-TEST_F(RBNodeRRsetTest, getClass) {
-    EXPECT_EQ(RRClass("IN"), rrset_a.getClass());
-    EXPECT_EQ(RRClass("CH"), rrset_ch_txt.getClass());
-}
-
-TEST_F(RBNodeRRsetTest, getType) {
-    EXPECT_EQ(RRType("A"), rrset_a.getType());
-    EXPECT_EQ(RRType("NS"), rrset_ns.getType());
-    EXPECT_EQ(RRType("TXT"), rrset_ch_txt.getType());
-}
-
-TEST_F(RBNodeRRsetTest, getTTL) {
-    EXPECT_EQ(RRTTL(3600), rrset_a.getTTL());
-    EXPECT_EQ(RRTTL(86400), rrset_ns.getTTL());
-    EXPECT_EQ(RRTTL(0), rrset_ch_txt.getTTL());
-}
-
-TEST_F(RBNodeRRsetTest, setName) {
-    EXPECT_THROW(rrset_a.setName(test_nsname), NotImplemented);
-}
-
-TEST_F(RBNodeRRsetTest, setTTL) {
-    EXPECT_THROW(rrset_a.setTTL(RRTTL(86400)), NotImplemented);
-}
-
-TEST_F(RBNodeRRsetTest, toText) {
-    EXPECT_EQ("test.example.com. 3600 IN A 192.0.2.1\n"
-              "test.example.com. 3600 IN A 192.0.2.2\n",
-              rrset_a.toText());
-
-    // toText() cannot be performed for an empty RRset.
-    EXPECT_THROW(rrset_a_empty.toText(), EmptyRRset);
-}
-
-TEST_F(RBNodeRRsetTest, isSameKind) {
-    RBNodeRRset rrset_p(ConstRRsetPtr(new RRset(test_name, RRClass::IN(), RRType::A(), RRTTL(3600))));
-    RBNodeRRset rrset_q(ConstRRsetPtr(new RRset(test_name, RRClass::IN(), RRType::A(), RRTTL(3600))));
-    RRset rrset_w(test_name, RRClass::IN(), RRType::A(), RRTTL(3600));
-    RRset rrset_x(test_nsname, RRClass::IN(), RRType::A(), RRTTL(3600));
-    RRset rrset_y(test_name, RRClass::IN(), RRType::NS(), RRTTL(3600));
-    RRset rrset_z(test_name, RRClass::CH(), RRType::A(), RRTTL(3600));
-
-    EXPECT_TRUE(rrset_p.isSameKind(rrset_p));
-    EXPECT_FALSE(rrset_p.isSameKind(rrset_q));
-
-    EXPECT_TRUE(rrset_p.isSameKind(rrset_w));
-    EXPECT_FALSE(rrset_p.isSameKind(rrset_x));
-    EXPECT_FALSE(rrset_p.isSameKind(rrset_y));
-    EXPECT_FALSE(rrset_p.isSameKind(rrset_z));
-}
-
-// Note: although the next two tests are essentially the same and used common
-// test code, they use different test data: the MessageRenderer produces
-// compressed wire data whereas the OutputBuffer does not.
-
-template <typename T>
-void
-performToWireTest(T& dataHolder, const RBNodeRRset& rrset,
-                  const RBNodeRRset& rrset_empty, const char* testdata)
-{
-    rrset.toWire(dataHolder);
-
-    std::vector<unsigned char> wiredata;
-    UnitTestUtil::readWireData(testdata, wiredata);
-    EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, dataHolder.getData(),
-                        dataHolder.getLength(), &wiredata[0], wiredata.size());
-
-    // toWire() cannot be performed for an empty RRset.
-    dataHolder.clear();
-    EXPECT_THROW(rrset_empty.toWire(dataHolder), EmptyRRset);
-}
-
-TEST_F(RBNodeRRsetTest, toWireRenderer) {
-    MessageRenderer renderer;
-    performToWireTest(renderer, rrset_a, rrset_a_empty, "rrset_toWire2");
-}
-
-TEST_F(RBNodeRRsetTest, toWireBuffer) {
-    OutputBuffer buffer(0);
-    performToWireTest(buffer, rrset_a, rrset_a_empty, "rrset_toWire1");
-}
-
-TEST_F(RBNodeRRsetTest, addRdata) {
-    EXPECT_THROW(rrset_a.addRdata(in::A("192.0.2.3")), NotImplemented);
-
-    // Check the same goes for trying to add the wrong type of data
-    EXPECT_THROW(rrset_a.addRdata(generic::NS(test_nsname)), NotImplemented);
-}
-
-TEST_F(RBNodeRRsetTest, addRdataPtr) {
-    EXPECT_THROW(rrset_a_empty.addRdata(createRdata(rrset_a_empty.getType(),
-                                                    rrset_a_empty.getClass(),
-                                                    "192.0.2.1")),
-                 NotImplemented);
-}
-
-TEST_F(RBNodeRRsetTest, getRDataIterator) {
-    RdataIteratorPtr it = rrset_a.getRdataIterator();
-    for (int i = 0; i < 2; ++i) {
-        ASSERT_FALSE(it->isLast());
-        ASSERT_EQ(0, it->getCurrent().compare(in::A("192.0.2.1")));
-
-        it->next();
-        ASSERT_FALSE(it->isLast());
-        ASSERT_EQ(0, it->getCurrent().compare(in::A("192.0.2.2")));
-
-        it->next();
-        ASSERT_TRUE(it->isLast());
-
-        // Should be able repeat the iteration by calling first().
-        it->first();
-    }
-}
-
-// test operator<<.  We simply confirm it appends the result of toText().
-TEST_F(RBNodeRRsetTest, LeftShiftOperator) {
-    ostringstream oss;
-    oss << rrset_a;
-    EXPECT_EQ("test.example.com. 3600 IN A 192.0.2.1\n"
-              "test.example.com. 3600 IN A 192.0.2.2\n", oss.str());
-}
-
-// addRRSIG tests.
-TEST_F(RBNodeRRsetTest, addRRsigConstRdataPointer) {
-    EXPECT_FALSE(rrset_a.getRRsig());
-    ConstRdataPtr data = createRdata(rrset_siga->getType(),
-                                     rrset_siga->getClass(), RRSIG_TXT);
-    rrset_a.addRRsig(data);
-    rrsetCheck(rrset_siga, rrset_a.getRRsig());
-}
-
-TEST_F(RBNodeRRsetTest, addRRsigRdataPointer) {
-    EXPECT_FALSE(rrset_a.getRRsig());
-    RdataPtr data = createRdata(rrset_siga->getType(), rrset_siga->getClass(),
-                                RRSIG_TXT);
-    rrset_a.addRRsig(data);
-    rrsetCheck(rrset_siga, rrset_a.getRRsig());
-}
-
-TEST_F(RBNodeRRsetTest, addRRsigAbstractRRset) {
-    EXPECT_FALSE(rrset_a.getRRsig());
-    rrset_a.addRRsig(*(rrset_siga.get()));
-    rrsetCheck(rrset_siga, rrset_a.getRRsig());
-}
-
-TEST_F(RBNodeRRsetTest, addRRsigConstantRRsetPointer) {
-    EXPECT_FALSE(rrset_a.getRRsig());
-    rrset_a.addRRsig(rrset_siga);
-    rrsetCheck(rrset_siga, rrset_a.getRRsig());
-}
-
-TEST_F(RBNodeRRsetTest, addRRsigRRsetPointer) {
-    EXPECT_FALSE(rrset_a.getRRsig());
-    RRsetPtr rrsig(new RRset(test_name, RRClass::IN(), RRType::RRSIG(),
-                   RRTTL(3600)));
-    rrsig->addRdata(generic::RRSIG(RRSIG_TXT));
-    rrset_a.addRRsig(rrsig);
-    rrsetCheck(rrset_siga, rrset_a.getRRsig());
-}
-
-TEST_F(RBNodeRRsetTest, removeRRsig) {
-    EXPECT_FALSE(rrset_a.getRRsig());
-    rrset_a.addRRsig(*(rrset_siga.get()));
-    EXPECT_TRUE(rrset_a.getRRsig());
-    rrset_a.removeRRsig();
-    EXPECT_FALSE(rrset_a.getRRsig());
-}
-
-}   // Anonymous namespace
diff --git a/src/lib/datasrc/tests/rbtree_unittest.cc b/src/lib/datasrc/tests/rbtree_unittest.cc
deleted file mode 100644
index 2370631..0000000
--- a/src/lib/datasrc/tests/rbtree_unittest.cc
+++ /dev/null
@@ -1,1074 +0,0 @@
-// Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#include <gtest/gtest.h>
-
-#include <exceptions/exceptions.h>
-
-#include <util/memory_segment_local.h>
-
-#include <dns/name.h>
-#include <dns/rrclass.h>
-#include <dns/rrset.h>
-#include <dns/rrtype.h>
-#include <dns/rrttl.h>
-
-#include <datasrc/rbtree.h>
-
-#include <dns/tests/unittest_util.h>
-
-using namespace std;
-using namespace isc;
-using namespace isc::dns;
-using isc::UnitTestUtil;
-using namespace isc::datasrc;
-
-// XXX: some compilers cannot find class static constants used in
-// EXPECT_xxx macros, for which we need an explicit empty definition.
-const size_t Name::MAX_LABELS;
-
-/* The initial structure of rbtree
- *
- *             .
- *             |
- *             b
- *           /   \
- *          a    d.e.f
- *              /  |   \
- *             c   |    g.h
- *                 |     |
- *                w.y    i
- *              /  |  \   \
- *             x   |   z   k
- *                 |   |
- *                 p   j
- *               /   \
- *              o     q
- */
-
-namespace {
-class TreeHolder {
-public:
-    TreeHolder(util::MemorySegment& mem_sgmt, RBTree<int>* tree) :
-        mem_sgmt_(mem_sgmt), tree_(tree)
-    {}
-    ~TreeHolder() {
-        RBTree<int>::destroy(mem_sgmt_, tree_);
-    }
-    RBTree<int>* get() { return (tree_); }
-private:
-    util::MemorySegment& mem_sgmt_;
-    RBTree<int>* tree_;
-};
-
-class RBTreeTest : public::testing::Test {
-protected:
-    RBTreeTest() :
-        rbtree_holder_(mem_sgmt_, RBTree<int>::create(mem_sgmt_)),
-        rbtree_expose_empty_node_holder_(mem_sgmt_,
-                                         RBTree<int>::create(mem_sgmt_, true)),
-        rbtree(*rbtree_holder_.get()),
-        rbtree_expose_empty_node(*rbtree_expose_empty_node_holder_.get()),
-        crbtnode(NULL)
-    {
-        const char* const domain_names[] = {
-            "c", "b", "a", "x.d.e.f", "z.d.e.f", "g.h", "i.g.h", "o.w.y.d.e.f",
-            "j.z.d.e.f", "p.w.y.d.e.f", "q.w.y.d.e.f", "k.g.h"};
-        int name_count = sizeof(domain_names) / sizeof(domain_names[0]);
-        for (int i = 0; i < name_count; ++i) {
-            rbtree.insert(mem_sgmt_, Name(domain_names[i]), &rbtnode);
-            rbtnode->setData(RBNode<int>::NodeDataPtr(new int(i + 1)));
-
-            rbtree_expose_empty_node.insert(mem_sgmt_, Name(domain_names[i]),
-                                            &rbtnode);
-            rbtnode->setData(RBNode<int>::NodeDataPtr(new int(i + 1)));
-
-        }
-    }
-
-    util::MemorySegmentLocal mem_sgmt_;
-    TreeHolder rbtree_holder_;
-    TreeHolder rbtree_expose_empty_node_holder_;
-    RBTree<int>& rbtree;
-    RBTree<int>& rbtree_expose_empty_node;
-    RBNode<int>* rbtnode;
-    const RBNode<int>* crbtnode;
-    uint8_t buf[LabelSequence::MAX_SERIALIZED_LENGTH];
-};
-
-TEST_F(RBTreeTest, nodeCount) {
-    EXPECT_EQ(15, rbtree.getNodeCount());
-
-    // Delete all nodes, then the count should be set to 0.  This also tests
-    // the behavior of deleteAllNodes().
-    rbtree.deleteAllNodes(mem_sgmt_);
-    EXPECT_EQ(0, rbtree.getNodeCount());
-}
-
-TEST_F(RBTreeTest, setGetData) {
-    rbtnode->setData(RBNode<int>::NodeDataPtr(new int(11)));
-    EXPECT_EQ(11, *(rbtnode->getData()));
-}
-
-TEST_F(RBTreeTest, insertNames) {
-    EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree.insert(mem_sgmt_,
-                                                        Name("d.e.f"),
-                                                        &rbtnode));
-    EXPECT_EQ(Name("d.e.f"), rbtnode->getName());
-    EXPECT_EQ(15, rbtree.getNodeCount());
-
-    // insert not exist node
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_, Name("0"),
-                                                  &rbtnode));
-    EXPECT_EQ(Name("0"), rbtnode->getName());
-    EXPECT_EQ(16, rbtree.getNodeCount());
-
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_,
-                                                  Name("example.com"),
-                                                  &rbtnode));
-    EXPECT_EQ(17, rbtree.getNodeCount());
-    rbtnode->setData(RBNode<int>::NodeDataPtr(new int(12)));
-
-    // return ALREADYEXISTS, since node "example.com" already has
-    // been explicitly inserted
-    EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree.insert(mem_sgmt_,
-                                                        Name("example.com"),
-                                                        &rbtnode));
-    EXPECT_EQ(17, rbtree.getNodeCount());
-
-    // split the node "d.e.f"
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_, Name("k.e.f"),
-                                                  &rbtnode));
-    EXPECT_EQ(Name("k"), rbtnode->getName());
-    EXPECT_EQ(19, rbtree.getNodeCount());
-
-    // split the node "g.h"
-    EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree.insert(mem_sgmt_, Name("h"),
-                                                        &rbtnode));
-    EXPECT_EQ(Name("h"), rbtnode->getName());
-    EXPECT_EQ(20, rbtree.getNodeCount());
-
-    // add child domain
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_,
-                                                  Name("m.p.w.y.d.e.f"),
-                                                  &rbtnode));
-    EXPECT_EQ(Name("m"), rbtnode->getName());
-    EXPECT_EQ(21, rbtree.getNodeCount());
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_,
-                                                  Name("n.p.w.y.d.e.f"),
-                                                  &rbtnode));
-    EXPECT_EQ(Name("n"), rbtnode->getName());
-    EXPECT_EQ(22, rbtree.getNodeCount());
-
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_, Name("l.a"),
-                                                  &rbtnode));
-    EXPECT_EQ(Name("l"), rbtnode->getName());
-    EXPECT_EQ(23, rbtree.getNodeCount());
-
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_, Name("r.d.e.f"),
-                                                  &rbtnode));
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_, Name("s.d.e.f"),
-                                                  &rbtnode));
-    EXPECT_EQ(25, rbtree.getNodeCount());
-
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_,
-                                                  Name("h.w.y.d.e.f"),
-                                                  &rbtnode));
-
-    // add more nodes one by one to cover leftRotate and rightRotate
-    EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree.insert(mem_sgmt_, Name("f"),
-                                                        &rbtnode));
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_, Name("m"),
-                                                  &rbtnode));
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_, Name("nm"),
-                                                  &rbtnode));
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_, Name("om"),
-                                                  &rbtnode));
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_, Name("k"),
-                                                  &rbtnode));
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_, Name("l"),
-                                                  &rbtnode));
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_, Name("fe"),
-                                                  &rbtnode));
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_, Name("ge"),
-                                                  &rbtnode));
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_, Name("i"),
-                                                  &rbtnode));
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_, Name("ae"),
-                                                  &rbtnode));
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_, Name("n"),
-                                                  &rbtnode));
-}
-
-TEST_F(RBTreeTest, subTreeRoot) {
-    // This is a testcase for a particular issue that went unchecked in
-    // #2089's implementation, but was fixed in #2092. The issue was
-    // that when a node was fissioned, FLAG_SUBTREE_ROOT was not being
-    // copied correctly.
-
-    EXPECT_EQ(RBTree<int>::ALREADYEXISTS,
-              rbtree_expose_empty_node.insert(mem_sgmt_, Name("d.e.f"),
-                                              &rbtnode));
-    EXPECT_EQ(RBTree<int>::SUCCESS,
-              rbtree_expose_empty_node.insert(mem_sgmt_, Name("0"),
-                                              &rbtnode));
-    EXPECT_EQ(RBTree<int>::SUCCESS,
-              rbtree_expose_empty_node.insert(mem_sgmt_, Name("example.com"),
-                                              &rbtnode));
-    EXPECT_EQ(RBTree<int>::ALREADYEXISTS,
-              rbtree_expose_empty_node.insert(mem_sgmt_, Name("example.com"),
-                                              &rbtnode));
-    EXPECT_EQ(RBTree<int>::SUCCESS,
-              rbtree_expose_empty_node.insert(mem_sgmt_, Name("k.e.f"),
-                                              &rbtnode));
-
-    // "g.h" is not a subtree root
-    EXPECT_EQ(RBTree<int>::EXACTMATCH,
-              rbtree_expose_empty_node.find(Name("g.h"), &rbtnode));
-    EXPECT_FALSE(rbtnode->getFlag(RBNode<int>::FLAG_SUBTREE_ROOT));
-
-    // fission the node "g.h"
-    EXPECT_EQ(RBTree<int>::ALREADYEXISTS,
-              rbtree_expose_empty_node.insert(mem_sgmt_, Name("h"),
-                                              &rbtnode));
-
-    // the node "h" (h.down_ -> "g") should not be a subtree root. "g"
-    // should be a subtree root.
-    EXPECT_FALSE(rbtnode->getFlag(RBNode<int>::FLAG_SUBTREE_ROOT));
-
-    // "g.h" should be a subtree root now.
-    EXPECT_EQ(RBTree<int>::EXACTMATCH,
-              rbtree_expose_empty_node.find(Name("g.h"), &rbtnode));
-    EXPECT_TRUE(rbtnode->getFlag(RBNode<int>::FLAG_SUBTREE_ROOT));
-}
-
-TEST_F(RBTreeTest, additionalNodeFission) {
-    // These are additional nodeFission tests added by #2054's rewrite
-    // of RBTree::nodeFission(). These test specific corner cases that
-    // are not covered by other tests.
-
-    // Insert "t.0" (which becomes the left child of its parent)
-    EXPECT_EQ(RBTree<int>::SUCCESS,
-              rbtree_expose_empty_node.insert(mem_sgmt_, Name("t.0"),
-                                              &rbtnode));
-
-    // "t.0" is not a subtree root
-    EXPECT_EQ(RBTree<int>::EXACTMATCH,
-              rbtree_expose_empty_node.find(Name("t.0"), &rbtnode));
-    EXPECT_FALSE(rbtnode->getFlag(RBNode<int>::FLAG_SUBTREE_ROOT));
-
-    // fission the node "t.0"
-    EXPECT_EQ(RBTree<int>::ALREADYEXISTS,
-              rbtree_expose_empty_node.insert(mem_sgmt_, Name("0"),
-                                              &rbtnode));
-
-    // the node "0" ("0".down_ -> "t") should not be a subtree root. "t"
-    // should be a subtree root.
-    EXPECT_FALSE(rbtnode->getFlag(RBNode<int>::FLAG_SUBTREE_ROOT));
-
-    // "t.0" should be a subtree root now.
-    EXPECT_EQ(RBTree<int>::EXACTMATCH,
-              rbtree_expose_empty_node.find(Name("t.0"), &rbtnode));
-    EXPECT_TRUE(rbtnode->getFlag(RBNode<int>::FLAG_SUBTREE_ROOT));
-}
-
-TEST_F(RBTreeTest, findName) {
-    // find const rbtnode
-    // exact match
-    EXPECT_EQ(RBTree<int>::EXACTMATCH, rbtree.find(Name("a"), &crbtnode));
-    EXPECT_EQ(Name("a"), crbtnode->getName());
-
-    // not found
-    EXPECT_EQ(RBTree<int>::NOTFOUND, rbtree.find(Name("d.e.f"), &crbtnode));
-    EXPECT_EQ(RBTree<int>::NOTFOUND, rbtree.find(Name("y.d.e.f"), &crbtnode));
-    EXPECT_EQ(RBTree<int>::NOTFOUND, rbtree.find(Name("x"), &crbtnode));
-    EXPECT_EQ(RBTree<int>::NOTFOUND, rbtree.find(Name("m.n"), &crbtnode));
-
-    // if we expose empty node, we can get the empty node created during insert
-    EXPECT_EQ(RBTree<int>::EXACTMATCH,
-              rbtree_expose_empty_node.find(Name("d.e.f"), &crbtnode));
-    EXPECT_EQ(RBTree<int>::EXACTMATCH,
-              rbtree_expose_empty_node.find(Name("w.y.d.e.f"), &crbtnode));
-
-    // partial match
-    EXPECT_EQ(RBTree<int>::PARTIALMATCH, rbtree.find(Name("m.b"), &crbtnode));
-    EXPECT_EQ(Name("b"), crbtnode->getName());
-    EXPECT_EQ(RBTree<int>::PARTIALMATCH,
-              rbtree_expose_empty_node.find(Name("m.d.e.f"), &crbtnode));
-
-    // find rbtnode
-    EXPECT_EQ(RBTree<int>::EXACTMATCH, rbtree.find(Name("q.w.y.d.e.f"),
-                                                   &rbtnode));
-    EXPECT_EQ(Name("q"), rbtnode->getName());
-}
-
-TEST_F(RBTreeTest, findError) {
-    // For the version that takes a node chain, the chain must be empty.
-    RBTreeNodeChain<int> chain;
-    EXPECT_EQ(RBTree<int>::EXACTMATCH, rbtree.find(Name("a"), &crbtnode,
-                                                   chain));
-    // trying to reuse the same chain.  it should result in an exception.
-    EXPECT_THROW(rbtree.find(Name("a"), &crbtnode, chain),
-                 BadValue);
-}
-
-TEST_F(RBTreeTest, flags) {
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_,
-                                                  Name("flags.example"),
-                                                  &rbtnode));
-
-    // by default, flags are all off
-    EXPECT_FALSE(rbtnode->getFlag(RBNode<int>::FLAG_CALLBACK));
-
-    // set operation, by default it enables the flag
-    rbtnode->setFlag(RBNode<int>::FLAG_CALLBACK);
-    EXPECT_TRUE(rbtnode->getFlag(RBNode<int>::FLAG_CALLBACK));
-
-    // try disable the flag explicitly
-    rbtnode->setFlag(RBNode<int>::FLAG_CALLBACK, false);
-    EXPECT_FALSE(rbtnode->getFlag(RBNode<int>::FLAG_CALLBACK));
-
-    // try enable the flag explicitly
-    rbtnode->setFlag(RBNode<int>::FLAG_CALLBACK, true);
-    EXPECT_TRUE(rbtnode->getFlag(RBNode<int>::FLAG_CALLBACK));
-
-    // setting an unknown flag will trigger an exception
-    EXPECT_THROW(rbtnode->setFlag(static_cast<RBNode<int>::Flags>(2), true),
-                 isc::InvalidParameter);
-}
-
-bool
-testCallback(const RBNode<int>&, bool* callback_checker) {
-    *callback_checker = true;
-    return (false);
-}
-
-template <typename T>
-void
-performCallbackTest(RBTree<int>& rbtree,
-                    util::MemorySegmentLocal& mem_sgmt,
-                    const T& name_called,
-                    const T& name_not_called)
-{
-    RBNode<int>* rbtnode;
-    const RBNode<int>* crbtnode;
-
-    // by default callback isn't enabled
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt,
-                                                  Name("callback.example"),
-                                                  &rbtnode));
-    rbtnode->setData(RBNode<int>::NodeDataPtr(new int(1)));
-    EXPECT_FALSE(rbtnode->getFlag(RBNode<int>::FLAG_CALLBACK));
-
-    // enable/re-disable callback
-    rbtnode->setFlag(RBNode<int>::FLAG_CALLBACK);
-    EXPECT_TRUE(rbtnode->getFlag(RBNode<int>::FLAG_CALLBACK));
-    rbtnode->setFlag(RBNode<int>::FLAG_CALLBACK, false);
-    EXPECT_FALSE(rbtnode->getFlag(RBNode<int>::FLAG_CALLBACK));
-
-    // enable again for subsequent tests
-    rbtnode->setFlag(RBNode<int>::FLAG_CALLBACK);
-    // add more levels below and above the callback node for partial match.
-    RBNode<int>* subrbtnode;
-    EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt,
-                                                  Name("sub.callback.example"),
-                                                  &subrbtnode));
-    subrbtnode->setData(RBNode<int>::NodeDataPtr(new int(2)));
-    RBNode<int>* parentrbtnode;
-    EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree.insert(mem_sgmt,
-                                                        Name("example"),
-                                                        &parentrbtnode));
-    // the child/parent nodes shouldn't "inherit" the callback flag.
-    // "rbtnode" may be invalid due to the insertion, so we need to re-find
-    // it.
-    EXPECT_EQ(RBTree<int>::EXACTMATCH, rbtree.find(Name("callback.example"),
-                                                   &rbtnode));
-    EXPECT_TRUE(rbtnode->getFlag(RBNode<int>::FLAG_CALLBACK));
-    EXPECT_FALSE(subrbtnode->getFlag(RBNode<int>::FLAG_CALLBACK));
-    EXPECT_FALSE(parentrbtnode->getFlag(RBNode<int>::FLAG_CALLBACK));
-
-    // check if the callback is called from find()
-    RBTreeNodeChain<int> node_path1;
-    bool callback_called = false;
-    EXPECT_EQ(RBTree<int>::EXACTMATCH,
-              rbtree.find(name_called, &crbtnode, node_path1,
-                          testCallback, &callback_called));
-    EXPECT_TRUE(callback_called);
-
-    // enable callback at the parent node, but it doesn't have data so
-    // the callback shouldn't be called.
-    RBTreeNodeChain<int> node_path2;
-    parentrbtnode->setFlag(RBNode<int>::FLAG_CALLBACK);
-    callback_called = false;
-    EXPECT_EQ(RBTree<int>::EXACTMATCH,
-              rbtree.find(name_not_called, &crbtnode, node_path2,
-                          testCallback, &callback_called));
-    EXPECT_FALSE(callback_called);
-}
-
-TEST_F(RBTreeTest, callbackName) {
-    const Name n1("sub.callback.example");
-    const Name n2("callback.example");
-
-    performCallbackTest(rbtree, mem_sgmt_, n1, n2);
-}
-
-TEST_F(RBTreeTest, callbackLabelSequence) {
-    const Name n1("sub.callback.example");
-    const Name n2("callback.example");
-    const LabelSequence ls1(n1);
-    const LabelSequence ls2(n2);
-
-    performCallbackTest(rbtree, mem_sgmt_, ls1, ls2);
-}
-
-TEST_F(RBTreeTest, chainLevel) {
-    RBTreeNodeChain<int> chain;
-
-    // by default there should be no level in the chain.
-    EXPECT_EQ(0, chain.getLevelCount());
-
-    // insert one node to the tree and find it.  there should be exactly
-    // one level in the chain.
-    TreeHolder tree_holder(mem_sgmt_, RBTree<int>::create(mem_sgmt_, true));
-    RBTree<int>& tree(*tree_holder.get());
-    Name node_name(Name::ROOT_NAME());
-    EXPECT_EQ(RBTree<int>::SUCCESS, tree.insert(mem_sgmt_, node_name,
-                                                &rbtnode));
-    EXPECT_EQ(RBTree<int>::EXACTMATCH,
-              tree.find(node_name, &crbtnode, chain));
-    EXPECT_EQ(1, chain.getLevelCount());
-
-    // Check the name of the found node (should have '.' as both non-absolute
-    // and absolute name
-    EXPECT_EQ(".", crbtnode->getLabels().toText());
-    EXPECT_EQ(".", crbtnode->getAbsoluteLabels(buf).toText());
-
-    /*
-     * Now creating a possibly deepest tree with MAX_LABELS levels.
-     * it should look like:
-     *           (.)
-     *            |
-     *            a
-     *            |
-     *            a
-     *            : (MAX_LABELS - 1) "a"'s
-     *
-     * then confirm that find() for the deepest name succeeds without any
-     * disruption, and the resulting chain has the expected level.
-     * Note that the root name (".") solely belongs to a single level,
-     * so the levels begin with 2.
-     */
-    for (unsigned int i = 2; i <= Name::MAX_LABELS; ++i) {
-        node_name = Name("a.").concatenate(node_name);
-        EXPECT_EQ(RBTree<int>::SUCCESS, tree.insert(mem_sgmt_, node_name,
-                                                    &rbtnode));
-        RBTreeNodeChain<int> found_chain;
-        EXPECT_EQ(RBTree<int>::EXACTMATCH,
-                  tree.find(node_name, &crbtnode, found_chain));
-        EXPECT_EQ(i, found_chain.getLevelCount());
-
-        // The non-absolute name should only have the first label
-        EXPECT_EQ("a", crbtnode->getLabels().toText());
-        // But the absolute name should have all labels
-        EXPECT_EQ(node_name.toText(),
-                  crbtnode->getAbsoluteLabels(buf).toText());
-    }
-
-    // Confirm the last inserted name has the possible maximum length with
-    // maximum label count.  This confirms the rbtree and chain level cannot
-    // be larger.
-    EXPECT_EQ(Name::MAX_LABELS, node_name.getLabelCount());
-    EXPECT_THROW(node_name.concatenate(Name("a.")), TooLongName);
-}
-
-TEST_F(RBTreeTest, getAbsoluteNameError) {
-    // an empty chain isn't allowed.
-    RBTreeNodeChain<int> chain;
-    EXPECT_THROW(chain.getAbsoluteName(), BadValue);
-}
-
-/*
- * The domain order should be:
- * ., a, b, c, d.e.f, x.d.e.f, w.y.d.e.f, o.w.y.d.e.f, p.w.y.d.e.f,
- * q.w.y.d.e.f, z.d.e.f, j.z.d.e.f, g.h, i.g.h, k.g.h
- *             . (no data, can't be found)
- *             |
- *             b
- *           /   \
- *          a    d.e.f
- *              /  |   \
- *             c   |    g.h
- *                 |     |
- *                w.y    i
- *              /  |  \   \
- *             x   |   z   k
- *                 |   |
- *                 p   j
- *               /   \
- *              o     q
- */
-const char* const names[] = {
-    "a", "b", "c", "d.e.f", "x.d.e.f", "w.y.d.e.f", "o.w.y.d.e.f",
-    "p.w.y.d.e.f", "q.w.y.d.e.f", "z.d.e.f", "j.z.d.e.f",
-    "g.h", "i.g.h", "k.g.h"};
-const size_t name_count(sizeof(names) / sizeof(*names));
-
-const char* const upper_node_names[] = {
-    ".", ".", ".", ".", "d.e.f", "d.e.f", "w.y.d.e.f",
-    "w.y.d.e.f", "w.y.d.e.f", "d.e.f", "z.d.e.f",
-    ".", "g.h", "g.h"};
-
-TEST_F(RBTreeTest, getUpperNode) {
-    RBTreeNodeChain<int> node_path;
-    const RBNode<int>* node = NULL;
-    EXPECT_EQ(RBTree<int>::EXACTMATCH,
-              rbtree_expose_empty_node.find(Name(names[0]),
-                                            &node,
-                                            node_path));
-    for (int i = 0; i < name_count; ++i) {
-        EXPECT_NE(static_cast<void*>(NULL), node);
-
-        const RBNode<int>* upper_node = node->getUpperNode();
-        if (upper_node_names[i] != NULL) {
-            const RBNode<int>* upper_node2 = NULL;
-            EXPECT_EQ(RBTree<int>::EXACTMATCH,
-                      rbtree_expose_empty_node.find(Name(upper_node_names[i]),
-                                                    &upper_node2));
-            EXPECT_NE(static_cast<void*>(NULL), upper_node2);
-            EXPECT_EQ(upper_node, upper_node2);
-        } else {
-            EXPECT_EQ(static_cast<void*>(NULL), upper_node);
-        }
-
-        node = rbtree_expose_empty_node.nextNode(node_path);
-    }
-
-    // We should have reached the end of the tree.
-    EXPECT_EQ(static_cast<void*>(NULL), node);
-}
-
-TEST_F(RBTreeTest, nextNode) {
-    RBTreeNodeChain<int> node_path;
-    const RBNode<int>* node = NULL;
-    EXPECT_EQ(RBTree<int>::EXACTMATCH,
-              rbtree.find(Name(names[0]), &node, node_path));
-    for (int i = 0; i < name_count; ++i) {
-        EXPECT_NE(static_cast<void*>(NULL), node);
-        EXPECT_EQ(Name(names[i]), node_path.getAbsoluteName());
-        node = rbtree.nextNode(node_path);
-    }
-
-    // We should have reached the end of the tree.
-    EXPECT_EQ(static_cast<void*>(NULL), node);
-}
-
-// Just walk using previousNode until the beginning of the tree and check it is
-// OK
-//
-// rbtree - the tree to walk
-// node - result of previous call to find(), starting position of the walk
-// node_path - the path from the previous call to find(), will be modified
-// chain_length - the number of names that should be in the chain to be walked
-//   (0 means it should be empty, 3 means 'a', 'b' and 'c' should be there -
-//   this is always from the beginning of the names[] list).
-// skip_first - if this is false, the node should already contain the node with
-//   the first name of the chain. If it is true, the node should be NULL
-//   (true is for finds that return no match, false for the ones that return
-//   match)
-void
-previousWalk(RBTree<int>& rbtree, const RBNode<int>* node,
-             RBTreeNodeChain<int>& node_path, size_t chain_length,
-             bool skip_first)
-{
-    if (skip_first) {
-        // If the first is not found, this is supposed to be NULL and we skip
-        // it in our checks.
-        EXPECT_EQ(static_cast<void*>(NULL), node);
-        node = rbtree.previousNode(node_path);
-    }
-    for (size_t i(chain_length); i > 0; --i) {
-        EXPECT_NE(static_cast<void*>(NULL), node);
-        EXPECT_EQ(Name(names[i - 1]), node_path.getAbsoluteName());
-        // Find the node at the path and check the value is the same
-        // (that it really returns the correct corresponding node)
-        //
-        // The "empty" nodes can not be found
-        if (node->getData()) {
-            const RBNode<int>* node2(NULL);
-            RBTreeNodeChain<int> node_path2;
-            EXPECT_EQ(RBTree<int>::EXACTMATCH,
-                      rbtree.find(Name(names[i - 1]), &node2, node_path2));
-            EXPECT_EQ(node, node2);
-        }
-        node = rbtree.previousNode(node_path);
-    }
-
-    // We should have reached the start of the tree.
-    ASSERT_NE(static_cast<void*>(NULL), node);
-    EXPECT_EQ(".", node->getLabels().toText());
-
-    // With one more call it results in NULL
-    node = rbtree.previousNode(node_path);
-    EXPECT_EQ(static_cast<void*>(NULL), node);
-
-    // Calling previousNode() yet again should still return NULL without
-    // fail.
-    node = rbtree.previousNode(node_path);
-    EXPECT_EQ(static_cast<void*>(NULL), node);
-}
-
-// Check the previousNode
-TEST_F(RBTreeTest, previousNode) {
-    // First, iterate the whole tree from the end to the beginning.
-    RBTreeNodeChain<int> node_path;
-    EXPECT_THROW(rbtree.previousNode(node_path), isc::BadValue) <<
-        "Throw before a search was done on the path";
-    const RBNode<int>* node(NULL);
-    {
-        SCOPED_TRACE("Iterate through");
-        EXPECT_EQ(RBTree<int>::EXACTMATCH,
-                  rbtree.find(Name(names[name_count - 1]), &node, node_path));
-        previousWalk(rbtree, node, node_path, name_count, false);
-        node = NULL;
-        node_path.clear();
-    }
-
-    {
-        SCOPED_TRACE("Iterate from the middle");
-        // Now, start somewhere in the middle, but within the real node.
-        EXPECT_EQ(RBTree<int>::EXACTMATCH,
-                  rbtree.find(Name(names[4]), &node, node_path));
-        previousWalk(rbtree, node, node_path, 5, false);
-        node = NULL;
-        node_path.clear();
-    }
-
-    {
-        SCOPED_TRACE("Start at the first");
-        // If we start at the lowest (which is "a"), we get to the beginning
-        // right away.
-        EXPECT_EQ(RBTree<int>::EXACTMATCH,
-                  rbtree.find(Name(names[0]), &node, node_path));
-        EXPECT_NE(static_cast<void*>(NULL), node);
-        node = rbtree.previousNode(node_path);
-        ASSERT_NE(static_cast<void*>(NULL), node);
-        EXPECT_EQ(".", node->getLabels().toText());
-        node = NULL;
-        node_path.clear();
-    }
-
-    {
-        SCOPED_TRACE("Start before the first");
-        // If we start before the lowest (. < 0. < a.), we should not get a
-        // node.  Its previous node should be the root.
-        EXPECT_EQ(RBTree<int>::NOTFOUND,
-                  rbtree.find<void*>(Name("0"), &node, node_path, NULL, NULL));
-        EXPECT_EQ(static_cast<void*>(NULL), node);
-        node = rbtree.previousNode(node_path);
-        ASSERT_NE(static_cast<void*>(NULL), node);
-        EXPECT_EQ(".", node->getLabels().toText());
-        node = NULL;
-        node_path.clear();
-    }
-
-    {
-        SCOPED_TRACE("Start after the last");
-        EXPECT_EQ(RBTree<int>::NOTFOUND,
-                  rbtree.find(Name("z"), &node, node_path));
-        previousWalk(rbtree, node, node_path, name_count, true);
-        node = NULL;
-        node_path.clear();
-    }
-
-    {
-        SCOPED_TRACE("Start below a leaf");
-        // We exit a leaf by going down. We should start by the one
-        // we exited - 'c' (actually, we should get it by the find, as partial
-        // match).
-        EXPECT_EQ(RBTree<int>::PARTIALMATCH,
-                  rbtree.find(Name("b.c"), &node, node_path));
-        previousWalk(rbtree, node, node_path, 3, false);
-        node = NULL;
-        node_path.clear();
-    }
-
-    {
-        SCOPED_TRACE("Start to the right of a leaf");
-        // When searching for this, we exit the 'x' node to the right side,
-        // so we should go x afterwards.
-
-        // The d.e.f is empty node, so it is hidden by find. Therefore NOTFOUND
-        // and not PARTIALMATCH.
-        EXPECT_EQ(RBTree<int>::NOTFOUND,
-                  rbtree.find(Name("xy.d.e.f"), &node, node_path));
-        previousWalk(rbtree, node, node_path, 5, true);
-        node = NULL;
-        node_path.clear();
-    }
-
-    {
-        SCOPED_TRACE("Start to the left of a leaf");
-        // This is similar to the previous, but we exit the 'z' leaf to the
-        // left side, so should not visit z at all then.
-
-        // The d.e.f is empty node, so it is hidden by find. Therefore NOTFOUND
-        // and not PARTIALMATCH.
-        EXPECT_EQ(RBTree<int>::NOTFOUND,
-                  rbtree.find(Name("yz.d.e.f"), &node, node_path));
-        previousWalk(rbtree, node, node_path, 9, true);
-        node = NULL;
-        node_path.clear();
-    }
-
-    {
-        SCOPED_TRACE("Start to the right of a parent");
-        // When searching for this, we exit the 'g.h' node to the right
-        // side, so we should go to g.h's children afterwards.
-
-        // 'g.h' is an empty node, so we get a NOTFOUND and not
-        // PARTIALMATCH.
-        EXPECT_EQ(RBTree<int>::NOTFOUND,
-                  rbtree.find(Name("x.h"), &node, node_path));
-        // 'g.h' is the COMMONANCESTOR.
-        EXPECT_EQ(node_path.getLastComparedNode()->getName(), Name("g.h"));
-        EXPECT_EQ(NameComparisonResult::COMMONANCESTOR,
-                  node_path.getLastComparisonResult().getRelation());
-        // find() exits to the right of 'g.h'
-        EXPECT_GT(node_path.getLastComparisonResult().getOrder(), 0);
-        // We then descend into 'i.g.h' and walk all the nodes in the
-        // tree.
-        previousWalk(rbtree, node, node_path, name_count, true);
-        node = NULL;
-        node_path.clear();
-    }
-
-    {
-        SCOPED_TRACE("Start inside a wrong node");
-        // The d.e.f is a single node, but we want only part of it. We
-        // should start iterating before it.
-        EXPECT_EQ(RBTree<int>::NOTFOUND,
-                  rbtree.find(Name("e.f"), &node, node_path));
-        previousWalk(rbtree, node, node_path, 3, true);
-        node = NULL;
-        node_path.clear();
-    }
-
-    {
-        SCOPED_TRACE("Lookup in empty tree");
-        // Just check it doesn't crash, etc.
-        TreeHolder tree_holder(mem_sgmt_, RBTree<int>::create(mem_sgmt_));
-        RBTree<int>& empty_tree(*tree_holder.get());
-        EXPECT_EQ(RBTree<int>::NOTFOUND,
-                  empty_tree.find(Name("x"), &node, node_path));
-        EXPECT_EQ(static_cast<void*>(NULL), node);
-        EXPECT_EQ(static_cast<void*>(NULL),
-                  empty_tree.previousNode(node_path));
-        node = NULL;
-        node_path.clear();
-    }
-}
-
-TEST_F(RBTreeTest, nextNodeError) {
-    // Empty chain for nextNode() is invalid.
-    RBTreeNodeChain<int> chain;
-    EXPECT_THROW(rbtree.nextNode(chain), BadValue);
-}
-
-// A helper function for getLastComparedNode() below.
-void
-comparisonChecks(const RBTreeNodeChain<int>& chain,
-                 int expected_order, int expected_common_labels,
-                 NameComparisonResult::NameRelation expected_reln)
-{
-    if (expected_order > 0) {
-        EXPECT_LT(0, chain.getLastComparisonResult().getOrder());
-    } else if (expected_order < 0) {
-        EXPECT_GT(0, chain.getLastComparisonResult().getOrder());
-    } else {
-        EXPECT_EQ(0, chain.getLastComparisonResult().getOrder());
-    }
-    EXPECT_EQ(expected_common_labels,
-              chain.getLastComparisonResult().getCommonLabels());
-    EXPECT_EQ(expected_reln,
-              chain.getLastComparisonResult().getRelation());
-}
-
-TEST_F(RBTreeTest, getLastComparedNode) {
-    RBTree<int>& tree = rbtree_expose_empty_node; // use the "empty OK" mode
-    RBTreeNodeChain<int> chain;
-
-    // initially there should be no 'last compared'.
-    EXPECT_EQ(static_cast<void*>(NULL), chain.getLastComparedNode());
-
-    // A search for an empty tree should result in no 'last compared', too.
-    TreeHolder tree_holder(mem_sgmt_, RBTree<int>::create(mem_sgmt_));
-    RBTree<int>& empty_tree(*tree_holder.get());
-    EXPECT_EQ(RBTree<int>::NOTFOUND,
-              empty_tree.find(Name("a"), &crbtnode, chain));
-    EXPECT_EQ(static_cast<void*>(NULL), chain.getLastComparedNode());
-    chain.clear();
-
-    const RBNode<int>* expected_node = NULL;
-
-    // Exact match case.  The returned node should be last compared.
-    EXPECT_EQ(RBTree<int>::EXACTMATCH,
-              tree.find(Name("x.d.e.f"), &expected_node, chain));
-    EXPECT_EQ(expected_node, chain.getLastComparedNode());
-    // 1 = # labels of "x" (note: excluding ".")
-    comparisonChecks(chain, 0, 1, NameComparisonResult::EQUAL);
-    chain.clear();
-
-    // Partial match, search stopped at the matching node, which should be
-    // the last compared node.
-    EXPECT_EQ(RBTree<int>::EXACTMATCH,
-              tree.find(Name("k.g.h"), &expected_node));
-    EXPECT_EQ(RBTree<int>::PARTIALMATCH,
-              tree.find(Name("x.k.g.h"), &crbtnode, chain));
-    EXPECT_EQ(expected_node, chain.getLastComparedNode());
-    // k.g.h < x.k.g.h, 1 = # labels of "k"
-    comparisonChecks(chain, 1, 1, NameComparisonResult::SUBDOMAIN);
-    chain.clear();
-
-    // Partial match, search stopped in the subtree below the matching node
-    // after following a left branch.
-    EXPECT_EQ(RBTree<int>::EXACTMATCH,
-              tree.find(Name("x.d.e.f"), &expected_node));
-    EXPECT_EQ(RBTree<int>::PARTIALMATCH,
-              tree.find(Name("a.d.e.f"), &crbtnode, chain));
-    EXPECT_EQ(expected_node, chain.getLastComparedNode());
-    // a < x, no common labels
-    comparisonChecks(chain, -1, 0, NameComparisonResult::NONE);
-    chain.clear();
-
-    // Partial match, search stopped in the subtree below the matching node
-    // after following a right branch.
-    EXPECT_EQ(RBTree<int>::EXACTMATCH,
-              tree.find(Name("z.d.e.f"), &expected_node));
-    EXPECT_EQ(RBTree<int>::PARTIALMATCH,
-              tree.find(Name("zz.d.e.f"), &crbtnode, chain));
-    EXPECT_EQ(expected_node, chain.getLastComparedNode());
-    // zz > z, no common label
-    comparisonChecks(chain, 1, 0, NameComparisonResult::NONE);
-    chain.clear();
-
-    // Partial match, search stopped at a node for a super domain of the
-    // search name in the subtree below the matching node.
-    EXPECT_EQ(RBTree<int>::EXACTMATCH,
-              tree.find(Name("w.y.d.e.f"), &expected_node));
-    EXPECT_EQ(RBTree<int>::PARTIALMATCH,
-              tree.find(Name("y.d.e.f"), &crbtnode, chain));
-    EXPECT_EQ(expected_node, chain.getLastComparedNode());
-    // y < w.y, 1 = # labels of "y"
-    comparisonChecks(chain, -1, 1, NameComparisonResult::SUPERDOMAIN);
-    chain.clear();
-
-    // Partial match, search stopped at a node that share a common ancestor
-    // with the search name in the subtree below the matching node.
-    // (the expected node is the same as the previous case)
-    EXPECT_EQ(RBTree<int>::PARTIALMATCH,
-              tree.find(Name("z.y.d.e.f"), &crbtnode, chain));
-    EXPECT_EQ(expected_node, chain.getLastComparedNode());
-    // z.y > w.y, 1 = # labels of "y"
-    comparisonChecks(chain, 1, 1, NameComparisonResult::COMMONANCESTOR);
-    chain.clear();
-
-    // Search stops in the highest level (under ".") after following a left
-    // branch. (find() still returns PARTIALMATCH due to the top level ".")
-    EXPECT_EQ(RBTree<int>::EXACTMATCH, tree.find(Name("c"), &expected_node));
-    EXPECT_EQ(RBTree<int>::PARTIALMATCH,
-              tree.find(Name("bb"), &crbtnode, chain));
-    EXPECT_EQ(expected_node, chain.getLastComparedNode());
-    // bb < c, no common label
-    comparisonChecks(chain, -1, 0, NameComparisonResult::NONE);
-    chain.clear();
-
-    // Search stops in the highest level (under ".") after following a right
-    // branch. (the expected node is the same as the previous case)
-    EXPECT_EQ(RBTree<int>::PARTIALMATCH,
-              tree.find(Name("d"), &crbtnode, chain));
-    EXPECT_EQ(expected_node, chain.getLastComparedNode());
-    // d > c, no common label
-    comparisonChecks(chain, 1, 0, NameComparisonResult::NONE);
-    chain.clear();
-}
-
-TEST_F(RBTreeTest, dumpTree) {
-    std::ostringstream str;
-    std::ostringstream str2;
-    rbtree.dumpTree(str);
-    str2 << "tree has 15 node(s)\n"
-            ". (black) [invisible] [subtreeroot]\n"
-            "     begin down from .\n"
-            "     b (black) [subtreeroot]\n"
-            "          a (black)\n"
-            "               NULL\n"
-            "               NULL\n"
-            "          d.e.f (black) [invisible]\n"
-            "               begin down from d.e.f\n"
-            "               w.y (black) [invisible] [subtreeroot]\n"
-            "                    begin down from w.y\n"
-            "                    p (black) [subtreeroot]\n"
-            "                         o (red)\n"
-            "                              NULL\n"
-            "                              NULL\n"
-            "                         q (red)\n"
-            "                              NULL\n"
-            "                              NULL\n"
-            "                    end down from w.y\n"
-            "                    x (red)\n"
-            "                         NULL\n"
-            "                         NULL\n"
-            "                    z (red)\n"
-            "                         begin down from z\n"
-            "                         j (black) [subtreeroot]\n"
-            "                              NULL\n"
-            "                              NULL\n"
-            "                         end down from z\n"
-            "                         NULL\n"
-            "                         NULL\n"
-            "               end down from d.e.f\n"
-            "               c (red)\n"
-            "                    NULL\n"
-            "                    NULL\n"
-            "               g.h (red)\n"
-            "                    begin down from g.h\n"
-            "                    i (black) [subtreeroot]\n"
-            "                         NULL\n"
-            "                         k (red)\n"
-            "                              NULL\n"
-            "                              NULL\n"
-            "                    end down from g.h\n"
-            "                    NULL\n"
-            "                    NULL\n"
-            "     end down from .\n"
-            "     NULL\n"
-            "     NULL\n";
-    EXPECT_EQ(str2.str(), str.str());
-}
-
-TEST_F(RBTreeTest, swap) {
-    // Store info about the first tree
-    std::ostringstream str1;
-    rbtree.dumpTree(str1);
-    size_t count1(rbtree.getNodeCount());
-
-    // Create second one and store state
-    TreeHolder tree_holder(mem_sgmt_, RBTree<int>::create(mem_sgmt_));
-    RBTree<int>& tree2(*tree_holder.get());
-    RBNode<int>* node;
-    tree2.insert(mem_sgmt_, Name("second"), &node);
-    std::ostringstream str2;
-    tree2.dumpTree(str2);
-
-    // Swap them
-    ASSERT_NO_THROW(tree2.swap(rbtree));
-
-    // Check their sizes
-    ASSERT_EQ(1, rbtree.getNodeCount());
-    ASSERT_EQ(count1, tree2.getNodeCount());
-
-    // And content
-    std::ostringstream out;
-    rbtree.dumpTree(out);
-    ASSERT_EQ(str2.str(), out.str());
-    out.str("");
-    tree2.dumpTree(out);
-    ASSERT_EQ(str1.str(), out.str());
-}
-
-// Matching in the "root zone" may be special (e.g. there's no parent,
-// any domain names should be considered a subdomain of it), so it makes
-// sense to test cases with the root zone explicitly.
-TEST_F(RBTreeTest, root) {
-    TreeHolder tree_holder(mem_sgmt_, RBTree<int>::create(mem_sgmt_));
-    RBTree<int>& root(*tree_holder.get());
-    root.insert(mem_sgmt_, Name::ROOT_NAME(), &rbtnode);
-    rbtnode->setData(RBNode<int>::NodeDataPtr(new int(1)));
-
-    EXPECT_EQ(RBTree<int>::EXACTMATCH,
-              root.find(Name::ROOT_NAME(), &crbtnode));
-    EXPECT_EQ(rbtnode, crbtnode);
-    EXPECT_EQ(RBTree<int>::PARTIALMATCH,
-              root.find(Name("example.com"), &crbtnode));
-    EXPECT_EQ(rbtnode, crbtnode);
-
-    // Insert a new name that better matches the query name.  find() should
-    // find the better one.
-    root.insert(mem_sgmt_, Name("com"), &rbtnode);
-    rbtnode->setData(RBNode<int>::NodeDataPtr(new int(2)));
-    EXPECT_EQ(RBTree<int>::PARTIALMATCH,
-              root.find(Name("example.com"), &crbtnode));
-    EXPECT_EQ(rbtnode, crbtnode);
-
-    // Perform the same tests for the tree that allows matching against empty
-    // nodes.
-    TreeHolder tree_holder_emptyok(mem_sgmt_,
-                                   RBTree<int>::create(mem_sgmt_, true));
-    RBTree<int>& root_emptyok(*tree_holder_emptyok.get());
-    root_emptyok.insert(mem_sgmt_, Name::ROOT_NAME(), &rbtnode);
-    EXPECT_EQ(RBTree<int>::EXACTMATCH,
-              root_emptyok.find(Name::ROOT_NAME(), &crbtnode));
-    EXPECT_EQ(rbtnode, crbtnode);
-    EXPECT_EQ(RBTree<int>::PARTIALMATCH,
-              root_emptyok.find(Name("example.com"), &crbtnode));
-    EXPECT_EQ(rbtnode, crbtnode);
-
-    root.insert(mem_sgmt_, Name("com"), &rbtnode);
-    EXPECT_EQ(RBTree<int>::PARTIALMATCH,
-              root.find(Name("example.com"), &crbtnode));
-    EXPECT_EQ(rbtnode, crbtnode);
-}
-
-TEST_F(RBTreeTest, getAbsoluteLabels) {
-    // The full absolute names of the nodes in the tree
-    // with the addition of the explicit root node
-    const char* const domain_names[] = {
-        "c", "b", "a", "x.d.e.f", "z.d.e.f", "g.h", "i.g.h", "o.w.y.d.e.f",
-        "j.z.d.e.f", "p.w.y.d.e.f", "q.w.y.d.e.f", "k.g.h"};
-    // The names of the nodes themselves, as they end up in the tree
-    const char* const first_labels[] = {
-        "c", "b", "a", "x", "z", "g.h", "i", "o",
-        "j", "p", "q", "k"};
-
-    const int name_count = sizeof(domain_names) / sizeof(domain_names[0]);
-    for (int i = 0; i < name_count; ++i) {
-        EXPECT_EQ(RBTree<int>::EXACTMATCH, rbtree.find(Name(domain_names[i]),
-                  &crbtnode));
-
-        // First make sure the names themselves are not absolute
-        const LabelSequence ls(crbtnode->getLabels());
-        EXPECT_EQ(first_labels[i], ls.toText());
-        EXPECT_FALSE(ls.isAbsolute());
-
-        // Now check the absolute names
-        const LabelSequence abs_ls(crbtnode->getAbsoluteLabels(buf));
-        EXPECT_EQ(Name(domain_names[i]).toText(), abs_ls.toText());
-        EXPECT_TRUE(abs_ls.isAbsolute());
-    }
-
-    // Explicitly add and find a root node, to see that getAbsoluteLabels
-    // also works when getLabels() already returns an absolute LabelSequence
-    rbtree.insert(mem_sgmt_, Name("."), &rbtnode);
-    rbtnode->setData(RBNode<int>::NodeDataPtr(new int(1)));
-
-    EXPECT_EQ(RBTree<int>::EXACTMATCH, rbtree.find(Name("."), &crbtnode));
-
-    EXPECT_TRUE(crbtnode->getLabels().isAbsolute());
-    EXPECT_EQ(".", crbtnode->getLabels().toText());
-    EXPECT_TRUE(crbtnode->getAbsoluteLabels(buf).isAbsolute());
-    EXPECT_EQ(".", crbtnode->getAbsoluteLabels(buf).toText());
-}
-
-}
diff --git a/src/lib/datasrc/tests/testdata/static-bad.zone b/src/lib/datasrc/tests/testdata/static-bad.zone
new file mode 100644
index 0000000..500ccca
--- /dev/null
+++ b/src/lib/datasrc/tests/testdata/static-bad.zone
@@ -0,0 +1,3 @@
+NOTBIND.           3600    CH  SOA NOTBIND. NOTBIND. 4 3600 300 36000 3600
+NOTBIND.           3600    CH  NS  NOTBIND.
+VERSION.NOTBIND.   3600    CH  TXT "10"
diff --git a/src/lib/datasrc/tests/testdata/static.zone b/src/lib/datasrc/tests/testdata/static.zone
index 5e9e8a6..51525db 100644
--- a/src/lib/datasrc/tests/testdata/static.zone
+++ b/src/lib/datasrc/tests/testdata/static.zone
@@ -1,2 +1,3 @@
-BIND.           3600    CH  SOA BIND. BIND. 1 3600 300 36000 3600
+BIND.           3600    CH  SOA BIND. BIND. 3 3600 300 36000 3600
+BIND.           3600    CH  NS  BIND.
 VERSION.BIND.   3600    CH  TXT "10"
diff --git a/src/lib/datasrc/tests/zonetable_unittest.cc b/src/lib/datasrc/tests/zonetable_unittest.cc
deleted file mode 100644
index 5a29a44..0000000
--- a/src/lib/datasrc/tests/zonetable_unittest.cc
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#include <exceptions/exceptions.h>
-
-#include <util/memory_segment_local.h>
-
-#include <dns/name.h>
-#include <dns/rrclass.h>
-
-#include <datasrc/zonetable.h>
-// We use InMemoryZone to put something into the table
-#include <datasrc/memory_datasrc.h>
-
-#include <gtest/gtest.h>
-
-using namespace isc::dns;
-using namespace isc::datasrc;
-
-namespace {
-TEST(ZoneTest, init) {
-    InMemoryZoneFinder zone(RRClass::IN(), Name("example.com"));
-    EXPECT_EQ(Name("example.com"), zone.getOrigin());
-    EXPECT_EQ(RRClass::IN(), zone.getClass());
-
-    InMemoryZoneFinder ch_zone(RRClass::CH(), Name("example"));
-    EXPECT_EQ(Name("example"), ch_zone.getOrigin());
-    EXPECT_EQ(RRClass::CH(), ch_zone.getClass());
-}
-
-TEST(ZoneTest, find) {
-    InMemoryZoneFinder zone(RRClass::IN(), Name("example.com"));
-    EXPECT_EQ(ZoneFinder::NXDOMAIN,
-              zone.find(Name("www.example.com"), RRType::A())->code);
-}
-
-class ZoneTableTest : public ::testing::Test {
-protected:
-    ZoneTableTest() : zone1(new InMemoryZoneFinder(RRClass::IN(),
-                                                   Name("example.com"))),
-                      zone2(new InMemoryZoneFinder(RRClass::IN(),
-                                                   Name("example.net"))),
-                      zone3(new InMemoryZoneFinder(RRClass::IN(),
-                                                   Name("example"))),
-                      zone_table(ZoneTable::create(mem_sgmt_))
-    {}
-
-    ~ZoneTableTest() {
-        ZoneTable::destroy(mem_sgmt_, zone_table);
-    }
-    ZoneFinderPtr zone1, zone2, zone3;
-    isc::util::MemorySegmentLocal mem_sgmt_;
-    ZoneTable* zone_table;
-};
-
-TEST_F(ZoneTableTest, addZone) {
-    EXPECT_EQ(result::SUCCESS, zone_table->addZone(mem_sgmt_, zone1));
-    EXPECT_EQ(result::EXIST, zone_table->addZone(mem_sgmt_, zone1));
-    // names are compared in a case insensitive manner.
-    EXPECT_EQ(result::EXIST, zone_table->addZone(
-                  mem_sgmt_,
-                  ZoneFinderPtr(new InMemoryZoneFinder(RRClass::IN(),
-                                                       Name("EXAMPLE.COM")))));
-
-    EXPECT_EQ(result::SUCCESS, zone_table->addZone(mem_sgmt_, zone2));
-    EXPECT_EQ(result::SUCCESS, zone_table->addZone(mem_sgmt_, zone3));
-
-    // Zone table is indexed only by name.  Duplicate origin name with
-    // different zone class isn't allowed.
-    EXPECT_EQ(result::EXIST, zone_table->addZone(
-                  mem_sgmt_,
-                  ZoneFinderPtr(new InMemoryZoneFinder(RRClass::CH(),
-                                                       Name("example.com")))));
-
-    /// Bogus zone (NULL)
-    EXPECT_THROW(zone_table->addZone(mem_sgmt_, ZoneFinderPtr()),
-                 isc::InvalidParameter);
-}
-
-TEST_F(ZoneTableTest, DISABLED_removeZone) {
-    EXPECT_EQ(result::SUCCESS, zone_table->addZone(mem_sgmt_, zone1));
-    EXPECT_EQ(result::SUCCESS, zone_table->addZone(mem_sgmt_, zone2));
-    EXPECT_EQ(result::SUCCESS, zone_table->addZone(mem_sgmt_, zone3));
-
-    EXPECT_EQ(result::SUCCESS, zone_table->removeZone(Name("example.net")));
-    EXPECT_EQ(result::NOTFOUND, zone_table->removeZone(Name("example.net")));
-}
-
-TEST_F(ZoneTableTest, findZone) {
-    EXPECT_EQ(result::SUCCESS, zone_table->addZone(mem_sgmt_, zone1));
-    EXPECT_EQ(result::SUCCESS, zone_table->addZone(mem_sgmt_, zone2));
-    EXPECT_EQ(result::SUCCESS, zone_table->addZone(mem_sgmt_, zone3));
-
-    EXPECT_EQ(result::SUCCESS, zone_table->findZone(Name("example.com")).code);
-    EXPECT_EQ(Name("example.com"),
-              zone_table->findZone(Name("example.com")).zone->getOrigin());
-
-    EXPECT_EQ(result::NOTFOUND,
-              zone_table->findZone(Name("example.org")).code);
-    EXPECT_EQ(ConstZoneFinderPtr(),
-              zone_table->findZone(Name("example.org")).zone);
-
-    // there's no exact match.  the result should be the longest match,
-    // and the code should be PARTIALMATCH.
-    EXPECT_EQ(result::PARTIALMATCH,
-              zone_table->findZone(Name("www.example.com")).code);
-    EXPECT_EQ(Name("example.com"),
-              zone_table->findZone(Name("www.example.com")).zone->getOrigin());
-
-    // make sure the partial match is indeed the longest match by adding
-    // a zone with a shorter origin and query again.
-    ZoneFinderPtr zone_com(new InMemoryZoneFinder(RRClass::IN(), Name("com")));
-    EXPECT_EQ(result::SUCCESS, zone_table->addZone(mem_sgmt_, zone_com));
-    EXPECT_EQ(Name("example.com"),
-              zone_table->findZone(Name("www.example.com")).zone->getOrigin());
-}
-}
diff --git a/src/lib/datasrc/zonetable.cc b/src/lib/datasrc/zonetable.cc
deleted file mode 100644
index 1193181..0000000
--- a/src/lib/datasrc/zonetable.cc
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#include <util/memory_segment.h>
-
-#include <dns/name.h>
-
-#include <datasrc/zonetable.h>
-#include <datasrc/rbtree.h>
-
-#include <cassert>
-
-using namespace std;
-using namespace isc::dns;
-
-namespace isc {
-namespace datasrc {
-
-/// \short Private data and implementation of ZoneTable
-struct ZoneTable::ZoneTableImpl {
-    // Type aliases to make it shorter
-    typedef RBTree<ZoneFinder> ZoneTree;
-    typedef RBNode<ZoneFinder> ZoneNode;
-
-    // The actual storage
-    ZoneTree* zones_;
-
-    // Constructor
-    ZoneTableImpl(util::MemorySegment& mem_sgmt) :
-        zones_(ZoneTree::create(mem_sgmt))
-    {}
-
-    /*
-     * The implementation methods are here and just wrap-called in the
-     * ZoneTable. We have variables locally (without impl_->), have
-     * type aliases, etc. And they will get inlined anyway.
-     */
-
-    // Implementation of ZoneTable::addZone
-    result::Result addZone(util::MemorySegment& mem_sgmt, ZoneFinderPtr zone) {
-        // Sanity check
-        if (!zone) {
-            isc_throw(InvalidParameter,
-                      "Null pointer is passed to ZoneTable::addZone()");
-        }
-
-        // Get the node where we put the zone
-        ZoneNode* node(NULL);
-        switch (zones_->insert(mem_sgmt, zone->getOrigin(), &node)) {
-            // This is OK
-            case ZoneTree::SUCCESS:
-            case ZoneTree::ALREADYEXISTS:
-                break;
-            // Can Not Happen
-            default:
-                assert(0);
-        }
-        // Can Not Happen
-        assert(node);
-
-        // Is it empty? We either just created it or it might be nonterminal
-        if (node->isEmpty()) {
-            node->setData(zone);
-            return (result::SUCCESS);
-        } else { // There's something there already
-            return (result::EXIST);
-        }
-    }
-
-    // Implementation of ZoneTable::findZone
-    ZoneTable::FindResult findZone(const Name& name) const {
-        ZoneNode *node(NULL);
-        result::Result my_result;
-
-        // Translate the return codes
-        switch (zones_->find(name, &node)) {
-            case ZoneTree::EXACTMATCH:
-                my_result = result::SUCCESS;
-                break;
-            case ZoneTree::PARTIALMATCH:
-                my_result = result::PARTIALMATCH;
-                break;
-            // We have no data there, so translate the pointer to NULL as well
-            case ZoneTree::NOTFOUND:
-                return (FindResult(result::NOTFOUND, ZoneFinderPtr()));
-            // Can Not Happen
-            default:
-                assert(0);
-                // Because of warning
-                return (FindResult(result::NOTFOUND, ZoneFinderPtr()));
-        }
-
-        // Can Not Happen (remember, NOTFOUND is handled)
-        assert(node);
-
-        return (FindResult(my_result, node->getData()));
-    }
-};
-
-ZoneTable::ZoneTable(util::MemorySegment& mem_sgmt) :
-    impl_(new ZoneTableImpl(mem_sgmt))
-{}
-
-ZoneTable::~ZoneTable() {
-    delete impl_;
-}
-
-ZoneTable*
-ZoneTable::create(util::MemorySegment& mem_sgmt) {
-    // The ZoneTable constructor can throw, so we need to prevent memory leak.
-    // This is ugly, but for now this seems to be the only place we need
-    // this, and since we'll substantially revise this code soon, so we don't
-    // work around it by this hack at the moment.
-    void* p = mem_sgmt.allocate(sizeof(ZoneTable));
-    try {
-        return (new(p) ZoneTable(mem_sgmt));
-    } catch (...) {
-        mem_sgmt.deallocate(p, sizeof(ZoneTable));
-        throw;
-    }
-}
-
-void
-ZoneTable::destroy(util::MemorySegment& mem_sgmt, ZoneTable* ztable) {
-    ZoneTableImpl::ZoneTree::destroy(mem_sgmt, ztable->impl_->zones_);
-    ztable->~ZoneTable();
-    mem_sgmt.deallocate(ztable, sizeof(ZoneTable));
-}
-
-result::Result
-ZoneTable::addZone(util::MemorySegment& mem_sgmt, ZoneFinderPtr zone) {
-    return (impl_->addZone(mem_sgmt, zone));
-}
-
-result::Result
-ZoneTable::removeZone(const Name&) {
-    // TODO Implement
-    assert(0);
-    // This should not ever be returned, the assert should kill us by now
-    return (result::SUCCESS);
-}
-
-ZoneTable::FindResult
-ZoneTable::findZone(const Name& name) const {
-    return (impl_->findZone(name));
-}
-
-} // end of namespace datasrc
-} // end of namespace isc
diff --git a/src/lib/datasrc/zonetable.h b/src/lib/datasrc/zonetable.h
deleted file mode 100644
index ef8a33b..0000000
--- a/src/lib/datasrc/zonetable.h
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#ifndef ZONETABLE_H
-#define ZONETABLE_H 1
-
-#include <util/memory_segment.h>
-
-#include <dns/rrset.h>
-
-#include <datasrc/zone_finder.h>
-
-#include <boost/shared_ptr.hpp>
-
-namespace isc {
-namespace dns {
-class Name;
-class RRClass;
-}
-
-namespace datasrc {
-
-/// \brief A set of authoritative zones.
-///
-/// \c ZoneTable class is primarily intended to be used as a backend for the
-/// \c MemoryDataSrc class, but is exposed as a separate class in case some
-/// application wants to use it directly (e.g. for a customized data source
-/// implementation).
-///
-/// For more descriptions about its struct and interfaces, please refer to the
-/// corresponding struct and interfaces of \c MemoryDataSrc.
-class ZoneTable {
-public:
-    struct FindResult {
-        FindResult(result::Result param_code, const ZoneFinderPtr param_zone) :
-            code(param_code), zone(param_zone)
-        {}
-        const result::Result code;
-        const ZoneFinderPtr zone;
-    };
-    ///
-    /// \name Constructors and Destructor.
-    ///
-    /// \b Note:
-    /// The copy constructor and the assignment operator are intentionally
-    /// defined as private, making this class non copyable.
-    //@{
-private:
-    ZoneTable(const ZoneTable& source);
-    ZoneTable& operator=(const ZoneTable& source);
-
-    /// Constructor.
-    ///
-    /// An object of this class is always expected to be created by the
-    /// allocator (\c create()), so the constructor is hidden as private.
-    ///
-    /// This constructor internally involves resource allocation, and if
-    /// it fails, a corresponding standard exception will be thrown.
-    /// It never throws an exception otherwise.
-    ZoneTable(util::MemorySegment& mem_sgmt);
-
-    /// The destructor.
-    ///
-    /// An object of this class is always expected to be destroyed explicitly
-    /// by \c destroy(), so the constructor is hidden as private.
-    ~ZoneTable();
-    //@}
-
-public:
-    /// \brief Allocate and construct \c ZoneTable
-    ///
-    /// This static method allocates memory for a new \c ZoneTable object
-    /// from the given memory segment, constructs the object, and returns
-    /// a pointer to it.
-    ///
-    /// \throw std::bad_alloc Memory allocation fails.
-    ///
-    /// \param mem_sgmt A \c MemorySegment from which memory for the new
-    /// \c ZoneTable is allocated.
-    static ZoneTable* create(util::MemorySegment& mem_sgmt);
-
-    /// \brief Destruct and deallocate \c ZoneTable
-    ///
-    /// \throw none
-    ///
-    /// \param mem_sgmt The \c MemorySegment that allocated memory for
-    /// \c ztable.
-    /// \param ztable A non NULL pointer to a valid \c ZoneTable object
-    /// that was originally created by the \c create() method (the behavior
-    /// is undefined if this condition isn't met).
-    static void destroy(util::MemorySegment& mem_sgmt, ZoneTable* ztable);
-
-    /// Add a \c Zone to the \c ZoneTable.
-    ///
-    /// \c Zone must not be associated with a NULL pointer; otherwise
-    /// an exception of class \c InvalidParameter will be thrown.
-    /// If internal resource allocation fails, a corresponding standard
-    /// exception will be thrown.
-    /// This method never throws an exception otherwise.
-    ///
-    /// \param zone A \c Zone object to be added.
-    /// \return \c result::SUCCESS If the zone is successfully
-    /// added to the zone table.
-    /// \return \c result::EXIST The zone table already contains
-    /// zone of the same origin.
-    result::Result addZone(util::MemorySegment& mem_sgmt, ZoneFinderPtr zone);
-
-    /// Remove a \c Zone of the given origin name from the \c ZoneTable.
-    ///
-    /// This method never throws an exception.
-    ///
-    /// \param origin The origin name of the zone to be removed.
-    /// \return \c result::SUCCESS If the zone is successfully
-    /// removed from the zone table.
-    /// \return \c result::NOTFOUND The zone table does not
-    /// store the zone that matches \c origin.
-    result::Result removeZone(const isc::dns::Name& origin);
-
-    /// Find a \c Zone that best matches the given name in the \c ZoneTable.
-    ///
-    /// It searches the internal storage for a \c Zone that gives the
-    /// longest match against \c name, and returns the result in the
-    /// form of a \c FindResult object as follows:
-    /// - \c code: The result code of the operation.
-    ///   - \c result::SUCCESS: A zone that gives an exact match
-    ///    is found
-    ///   - \c result::PARTIALMATCH: A zone whose origin is a
-    ///    super domain of \c name is found (but there is no exact match)
-    ///   - \c result::NOTFOUND: For all other cases.
-    /// - \c zone: A "Boost" shared pointer to the found \c Zone object if one
-    ///  is found; otherwise \c NULL.
-    ///
-    /// This method never throws an exception.
-    ///
-    /// \param name A domain name for which the search is performed.
-    /// \return A \c FindResult object enclosing the search result (see above).
-    FindResult findZone(const isc::dns::Name& name) const;
-
-private:
-    struct ZoneTableImpl;
-    ZoneTableImpl* impl_;
-};
-}
-}
-#endif  // ZONETABLE_H
-
-// Local Variables:
-// mode: c++
-// End:
diff --git a/src/lib/python/isc/datasrc/tests/Makefile.am b/src/lib/python/isc/datasrc/tests/Makefile.am
index c16d295..eb82972 100644
--- a/src/lib/python/isc/datasrc/tests/Makefile.am
+++ b/src/lib/python/isc/datasrc/tests/Makefile.am
@@ -11,6 +11,7 @@ EXTRA_DIST += testdata/oldschema.sqlite3
 EXTRA_DIST += testdata/new_minor_schema.sqlite3
 EXTRA_DIST += testdata/example.com
 EXTRA_DIST += testdata/example.com.ch
+EXTRA_DIST += testdata/static.zone
 CLEANFILES = $(abs_builddir)/rwtest.sqlite3.copied
 CLEANFILES += $(abs_builddir)/zoneloadertest.sqlite3
 
diff --git a/src/lib/python/isc/datasrc/tests/datasrc_test.py b/src/lib/python/isc/datasrc/tests/datasrc_test.py
index 64f3e53..abc9739 100644
--- a/src/lib/python/isc/datasrc/tests/datasrc_test.py
+++ b/src/lib/python/isc/datasrc/tests/datasrc_test.py
@@ -34,6 +34,8 @@ WRITE_ZONE_DB_FILE = TESTDATA_WRITE_PATH + "rwtest.sqlite3.copied"
 READ_ZONE_DB_CONFIG = "{ \"database_file\": \"" + READ_ZONE_DB_FILE + "\" }"
 WRITE_ZONE_DB_CONFIG = "{ \"database_file\": \"" + WRITE_ZONE_DB_FILE + "\"}"
 
+STATIC_ZONE_CONFIG = '"' + TESTDATA_PATH + "static.zone" + '"'
+
 def add_rrset(rrset_list, name, rrclass, rrtype, ttl, rdatas):
     rrset_to_add = isc.dns.RRset(name, rrclass, rrtype, ttl)
     if rdatas is not None:
@@ -129,9 +131,6 @@ class DataSrcClient(unittest.TestCase):
         self.assertRaises(isc.datasrc.Error,
                           isc.datasrc.DataSourceClient, "sqlite3",
                           "{ \"foo\": 1 }")
-        self.assertRaises(isc.datasrc.Error,
-                          isc.datasrc.DataSourceClient, "memory",
-                          "{ \"foo\": 1 }")
 
     def test_iterate(self):
         dsc = isc.datasrc.DataSourceClient("sqlite3", READ_ZONE_DB_CONFIG)
@@ -564,14 +563,16 @@ class DataSrcUpdater(unittest.TestCase):
         self.assertEqual(updater_refs, sys.getrefcount(updater))
 
     def test_two_modules(self):
-        # load two modules, and check if they don't interfere
-        mem_cfg = { "type": "memory", "class": "IN", "zones": [] };
-        dsc_mem = isc.datasrc.DataSourceClient("memory", json.dumps(mem_cfg))
+        # load two modules, and check if they don't interfere; as the
+        # memory datasource module no longer exists, we check the static
+        # datasource instead (as that uses the memory datasource
+        # anyway).
+        dsc_static = isc.datasrc.DataSourceClient("static", STATIC_ZONE_CONFIG)
         dsc_sql = isc.datasrc.DataSourceClient("sqlite3", READ_ZONE_DB_CONFIG)
 
         # check if exceptions are working
         self.assertRaises(isc.datasrc.Error, isc.datasrc.DataSourceClient,
-                          "memory", "{}")
+                          "static", "\"\"")
         self.assertRaises(isc.datasrc.Error, isc.datasrc.DataSourceClient,
                           "sqlite3", "{}")
 
@@ -587,11 +588,10 @@ class DataSrcUpdater(unittest.TestCase):
         self.assertEqual("www.example.com. 3600 IN A 192.0.2.1\n",
                          rrset.to_text())
 
-        # see if a lookup fails in mem ds
-        result, finder = dsc_mem.find_zone(isc.dns.Name("example.com"))
+        # see if a lookup fails in static ds
+        result, finder = dsc_static.find_zone(isc.dns.Name("example"))
         self.assertEqual(finder.NXDOMAIN, result)
 
-
     def test_update_delete_abort(self):
         # we don't do enything with this one, just making sure loading two
         # datasources
@@ -724,8 +724,10 @@ class DataSrcUpdater(unittest.TestCase):
         self.assertTrue(dsc.delete_zone(zone_name))
 
     def test_create_zone_not_implemented(self):
-        mem_cfg = '{ "type": "memory", "class": "IN", "zones": [] }';
-        dsc = isc.datasrc.DataSourceClient("memory", mem_cfg)
+        # As the memory datasource module no longer exists, we check the
+        # static datasource instead (as that uses the memory datasource
+        # anyway).
+        dsc = isc.datasrc.DataSourceClient("static", STATIC_ZONE_CONFIG)
         self.assertRaises(isc.datasrc.NotImplemented, dsc.create_zone,
                           isc.dns.Name("example.com"))
 
diff --git a/src/lib/python/isc/datasrc/tests/testdata/static.zone b/src/lib/python/isc/datasrc/tests/testdata/static.zone
new file mode 100644
index 0000000..51525db
--- /dev/null
+++ b/src/lib/python/isc/datasrc/tests/testdata/static.zone
@@ -0,0 +1,3 @@
+BIND.           3600    CH  SOA BIND. BIND. 3 3600 300 36000 3600
+BIND.           3600    CH  NS  BIND.
+VERSION.BIND.   3600    CH  TXT "10"
diff --git a/src/lib/python/isc/datasrc/tests/zone_loader_test.py b/src/lib/python/isc/datasrc/tests/zone_loader_test.py
index 4cd4879..e437e36 100644
--- a/src/lib/python/isc/datasrc/tests/zone_loader_test.py
+++ b/src/lib/python/isc/datasrc/tests/zone_loader_test.py
@@ -34,6 +34,7 @@ ORIG_DB_FILE = TESTDATA_PATH + '/example.com.sqlite3'
 DB_FILE = TESTDATA_WRITE_PATH + '/zoneloadertest.sqlite3'
 DB_CLIENT_CONFIG = '{ "database_file": "' + DB_FILE + '" }'
 DB_SOURCE_CLIENT_CONFIG = '{ "database_file": "' + SOURCE_DB_FILE + '" }'
+STATIC_ZONE_CONFIG = '"' + TESTDATA_PATH + "/static.zone" + '"'
 
 ORIG_SOA_TXT = 'example.com. 3600 IN SOA master.example.com. ' +\
                'admin.example.com. 1234 3600 1800 2419200 7200\n'
@@ -215,10 +216,15 @@ class ZoneLoaderTests(unittest.TestCase):
                           self.client, zone_name, self.source_client)
 
     def test_no_ds_load_support(self):
-        # This may change in the future, but atm, the in-mem ds does
-        # not support the API the zone loader uses (it has direct load calls)
-        inmem_client = isc.datasrc.DataSourceClient('memory',
-                                                    '{ "type": "memory" }');
+        # As the memory datasource module no longer exists, we check the
+        # static datasource instead (as that uses the memory datasource
+        # anyway).
+        #
+        # This may change in the future, but ATM, the static ds does not
+        # support the API the zone loader uses (it has direct load
+        # calls).
+        inmem_client = isc.datasrc.DataSourceClient('static',
+                                                    STATIC_ZONE_CONFIG);
         self.assertRaises(isc.datasrc.NotImplemented,
                           isc.datasrc.ZoneLoader,
                           inmem_client, self.test_name, self.test_file)



More information about the bind10-changes mailing list