]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[2281] Remove the old in-memory data source code
authorMukund Sivaraman <muks@isc.org>
Thu, 7 Feb 2013 07:28:52 +0000 (12:58 +0530)
committerMukund Sivaraman <muks@isc.org>
Thu, 7 Feb 2013 07:43:29 +0000 (13:13 +0530)
26 files changed:
src/bin/auth/auth_config.cc
src/bin/auth/tests/Makefile.am
src/bin/auth/tests/auth_srv_unittest.cc
src/bin/auth/tests/command_unittest.cc
src/bin/auth/tests/config_unittest.cc
src/bin/auth/tests/query_unittest.cc
src/lib/datasrc/Makefile.am
src/lib/datasrc/factory.cc
src/lib/datasrc/factory_link.h [new file with mode: 0644]
src/lib/datasrc/memory_datasrc.cc [deleted file]
src/lib/datasrc/memory_datasrc.h [deleted file]
src/lib/datasrc/memory_datasrc_link.cc [deleted file]
src/lib/datasrc/rbnode_rrset.h [deleted file]
src/lib/datasrc/rbtree.h [deleted file]
src/lib/datasrc/static_datasrc_link.cc
src/lib/datasrc/tests/Makefile.am
src/lib/datasrc/tests/factory_unittest.cc
src/lib/datasrc/tests/memory_datasrc_unittest.cc [deleted file]
src/lib/datasrc/tests/rbnode_rrset_unittest.cc [deleted file]
src/lib/datasrc/tests/rbtree_unittest.cc [deleted file]
src/lib/datasrc/tests/zonetable_unittest.cc [deleted file]
src/lib/datasrc/zonetable.cc [deleted file]
src/lib/datasrc/zonetable.h [deleted file]
src/lib/python/isc/datasrc/tests/Makefile.am
src/lib/python/isc/datasrc/tests/datasrc_test.py
src/lib/python/isc/datasrc/tests/testdata/static.zone [new file with mode: 0644]

index de8325bed591373d8e183061c21f9b24de7a80cc..58526da7fdce0e2bc97b90cba1d933eb37ab7354 100644 (file)
@@ -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>
index d1bde4d1ce472d8cd97443d67e96b72b16697689..44445b18c80af18f957137210e635a04ed992448 100644 (file)
@@ -50,7 +50,8 @@ run_unittests_SOURCES += config_unittest.cc
 run_unittests_SOURCES += config_syntax_unittest.cc
 run_unittests_SOURCES += command_unittest.cc
 run_unittests_SOURCES += common_unittest.cc
-run_unittests_SOURCES += query_unittest.cc
+# Disabled by #2281
+#run_unittests_SOURCES += query_unittest.cc
 run_unittests_SOURCES += statistics_unittest.cc
 run_unittests_SOURCES += test_datasrc_clients_mgr.h test_datasrc_clients_mgr.cc
 run_unittests_SOURCES += datasrc_clients_builder_unittest.cc
index 826d1b8576688f7dc8150c4e5203423c9461d988..f58d0e0675fadac4f750b9fd38d4e3899be5f4c7 100644 (file)
@@ -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>
index be90d736f84c04fd4b23e23210365cf0f12b2320..180cd2c6288f1fa1bb9a962be4be6c25c8ad5185 100644 (file)
@@ -29,8 +29,6 @@
 
 #include <config/ccsession.h>
 
-#include <datasrc/memory_datasrc.h>
-
 #include <asiolink/asiolink.h>
 
 #include <util/unittests/mock_socketsession.h>
index 05c6cce7905e24eb5613725046b20eea6891e3ac..0d6cbf875dee432132b46cae196beec410b43d92 100644 (file)
@@ -22,7 +22,6 @@
 #include <cc/data.h>
 
 #include <datasrc/data_source.h>
-#include <datasrc/memory_datasrc.h>
 
 #include <xfr/xfrout_client.h>
 
index 9822768a55eb28b6d4e9ac5ecfaf4eb83f460212..ea1f77a1d73218f8f6b95ee6f58087a2480c46ae 100644 (file)
@@ -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>
index a63ece06633fca1142e60d3351918a472c6e7705..4e46c902a9a16fa273eeeead8230d33e544b53e5 100644 (file)
@@ -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,11 +51,6 @@ 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_LDFLAGS = -module -avoid-version
 static_ds_la_LIBADD = $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
@@ -70,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
index 82b4df97eb84d3cc6b91bec0f61fca9add381497..33338db20a1155a3b3e714f9ebdf1a48d4939984 100644 (file)
@@ -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/factory_link.h b/src/lib/datasrc/factory_link.h
new file mode 100644 (file)
index 0000000..de670fc
--- /dev/null
@@ -0,0 +1,39 @@
+// 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_FACTORY_LINK_H
+#define DATASRC_FACTORY_LINK_H
+
+#include <datasrc/database.h>
+#include <cc/data.h>
+
+#include <string>
+
+namespace isc {
+namespace datasrc {
+
+extern "C" DataSourceClient* createInstance(isc::data::ConstElementPtr config,
+                                            std::string& error);
+
+extern "C" void destroyInstance(DataSourceClient* instance);
+
+}
+}
+
+#endif  // DATASRC_FACTORY_LINK_H
+
+// Local Variables:
+// mode: c++
+// End:
diff --git a/src/lib/datasrc/memory_datasrc.cc b/src/lib/datasrc/memory_datasrc.cc
deleted file mode 100644 (file)
index 45d7920..0000000
+++ /dev/null
@@ -1,2044 +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;
-};
-}
-
-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 (file)
index 4e277e0..0000000
+++ /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 (file)
index 857223f..0000000
+++ /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 (file)
index cbb1b71..0000000
+++ /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 (file)
index d0efa0a..0000000
+++ /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:
index 9334dc80488afee96938ea6024ea5aeba9aecceb..82eacaa161035e69c7eba3631adc3bed0745193b 100644 (file)
@@ -13,7 +13,7 @@
 // PERFORMANCE OF THIS SOFTWARE.
 
 #include "client.h"
-#include "memory_datasrc.h"
+#include "factory_link.h"
 #include <datasrc/memory/memory_client.h>
 #include <datasrc/memory/zone_table_segment.h>
 
index 7c61826d3c59ba7e0d46091bb985d539bfdab40b..32e1263da24a3c5fdfecfd0cc67596d3181a6719 100644 (file)
@@ -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
index 2031d5084248174646225cc6d3076935401219c2..12c611de21916720ea007071776723b99dbd3959 100644 (file)
@@ -160,78 +160,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);
diff --git a/src/lib/datasrc/tests/memory_datasrc_unittest.cc b/src/lib/datasrc/tests/memory_datasrc_unittest.cc
deleted file mode 100644 (file)
index f7a478b..0000000
+++ /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 (file)
index 57e8dbd..0000000
+++ /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 (file)
index 2370631..0000000
+++ /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/zonetable_unittest.cc b/src/lib/datasrc/tests/zonetable_unittest.cc
deleted file mode 100644 (file)
index 5a29a44..0000000
+++ /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 (file)
index 1193181..0000000
+++ /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 (file)
index ef8a33b..0000000
+++ /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:
index c16d295095a41f46d52c3023c1a7f5167ffe742e..eb82972f54af853ef9e39bc7e1064bd123cd456e 100644 (file)
@@ -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
 
index 64f3e53d3a6709ab4b3ff22a2c77f3c57246da8c..cf240ce0e3c0e98a5b83ad2c64faf1b2545958a1 100644 (file)
@@ -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)
@@ -565,13 +564,12 @@ class DataSrcUpdater(unittest.TestCase):
 
     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))
+        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 +585,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 +721,7 @@ 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)
+        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 (file)
index 0000000..51525db
--- /dev/null
@@ -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"