Parcourir la source

merge trac422 : Implement memory Data Source Class

git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@3866 e5f2f494-b856-4b98-b285-d166d9295462
Jerry il y a 14 ans
Parent
commit
41362fbd04

+ 8 - 0
ChangeLog

@@ -1,3 +1,11 @@
+  130.	[func]		jerry
+    src/lib/datasrc: Introduced a new class MemoryDataSrc to provide
+	the general interface for memory data source.  For the initial
+	implementation, we don't make it a derived class of AbstractDataSrc
+	because the interface is so different(we'll eventually consider this
+	as part of the generalization work).
+	(Trac #422, svn r3566)
+
   129.	[func]		jinmei
   129.	[func]		jinmei
 	src/lib/dns: Added new functions masterLoad() for loading master
 	src/lib/dns: Added new functions masterLoad() for loading master
 	zone files.  The initial implementation can only parse a limited
 	zone files.  The initial implementation can only parse a limited

+ 3 - 3
src/bin/auth/query.cc

@@ -26,10 +26,10 @@ namespace isc {
 namespace auth {
 namespace auth {
 void
 void
 Query::process() const {
 Query::process() const {
-    const ZoneTable::FindResult result = zone_table_.find(qname_);
+    const ZoneTable::FindResult result = zone_table_.findZone(qname_);
 
 
-    if (result.code != ZoneTable::SUCCESS &&
-        result.code != ZoneTable::PARTIALMATCH) {
+    if (result.code != isc::datasrc::result::SUCCESS &&
+        result.code != isc::datasrc::result::PARTIALMATCH) {
         response_.setRcode(Rcode::SERVFAIL());
         response_.setRcode(Rcode::SERVFAIL());
         return;
         return;
     }
     }

+ 2 - 2
src/bin/auth/tests/query_unittest.cc

@@ -55,7 +55,7 @@ TEST_F(QueryTest, noZone) {
 TEST_F(QueryTest, matchZone) {
 TEST_F(QueryTest, matchZone) {
     // add a matching zone.  since the zone is empty right now, the response
     // add a matching zone.  since the zone is empty right now, the response
     // should have NXDOMAIN.
     // should have NXDOMAIN.
-    zone_table.add(ZonePtr(new MemoryZone(qclass, Name("example.com"))));
+    zone_table.addZone(ZonePtr(new MemoryZone(qclass, Name("example.com"))));
     query.process();
     query.process();
     EXPECT_EQ(Rcode::NXDOMAIN(), response.getRcode());
     EXPECT_EQ(Rcode::NXDOMAIN(), response.getRcode());
 }
 }
@@ -63,7 +63,7 @@ TEST_F(QueryTest, matchZone) {
 TEST_F(QueryTest, noMatchZone) {
 TEST_F(QueryTest, noMatchZone) {
     // there's a zone in the table but it doesn't match the qname.  should
     // there's a zone in the table but it doesn't match the qname.  should
     // result in SERVFAIL.
     // result in SERVFAIL.
-    zone_table.add(ZonePtr(new MemoryZone(qclass, Name("example.org"))));
+    zone_table.addZone(ZonePtr(new MemoryZone(qclass, Name("example.org"))));
     query.process();
     query.process();
     EXPECT_EQ(Rcode::SERVFAIL(), response.getRcode());
     EXPECT_EQ(Rcode::SERVFAIL(), response.getRcode());
 }
 }

+ 1 - 0
src/lib/datasrc/Makefile.am

@@ -16,3 +16,4 @@ libdatasrc_la_SOURCES += sqlite3_datasrc.h sqlite3_datasrc.cc
 libdatasrc_la_SOURCES += query.h query.cc
 libdatasrc_la_SOURCES += query.h query.cc
 libdatasrc_la_SOURCES += cache.h cache.cc
 libdatasrc_la_SOURCES += cache.h cache.cc
 libdatasrc_la_SOURCES += zonetable.h zonetable.cc
 libdatasrc_la_SOURCES += zonetable.h zonetable.cc
+libdatasrc_la_SOURCES += memory_datasrc.h memory_datasrc.cc

+ 56 - 0
src/lib/datasrc/memory_datasrc.cc

@@ -0,0 +1,56 @@
+// 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 <dns/name.h>
+#include <datasrc/memory_datasrc.h>
+
+using namespace std;
+using namespace isc::dns;
+
+namespace isc {
+namespace datasrc {
+
+/// Implementation details for \c MemoryDataSrc hidden from the public
+/// interface.
+///
+/// For now, \c MemoryDataSrc only contains a \c ZoneTable object, which
+/// consists of (pointers to) \c MemoryZone objects, we may add more
+/// member variables later for new features.
+struct MemoryDataSrc::MemoryDataSrcImpl {
+    ZoneTable zone_table;
+};
+
+MemoryDataSrc::MemoryDataSrc() : impl_(new MemoryDataSrcImpl)
+{}
+
+MemoryDataSrc::~MemoryDataSrc() {
+    delete impl_;
+}
+
+result::Result
+MemoryDataSrc::addZone(ZonePtr zone) {
+    if (!zone) {
+        isc_throw(InvalidParameter,
+                  "Null pointer is passed to MemoryDataSrc::addZone()");
+    }
+    return (impl_->zone_table.addZone(zone));
+}
+
+MemoryDataSrc::FindResult
+MemoryDataSrc::findZone(const isc::dns::Name& name) const {
+    return (FindResult(impl_->zone_table.findZone(name).code,
+                       impl_->zone_table.findZone(name).zone));
+}
+} // end of namespace datasrc
+} // end of namespace dns

+ 151 - 0
src/lib/datasrc/memory_datasrc.h

@@ -0,0 +1,151 @@
+// 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 <datasrc/zonetable.h>
+
+namespace isc {
+namespace dns {
+class Name;
+};
+
+namespace datasrc {
+
+/// \brief A data source that uses in memory dedicated backend.
+///
+/// The \c MemoryDataSrc class represents a data source and provides a
+/// basic interface to help DNS lookup processing. For a given domain
+/// name, its \c findZone() method searches the in memory dedicated backend
+/// for the zone that gives a longest match against that name.
+///
+/// The in memory dedicated backend are assumed to be of the same RR class,
+/// but the \c MemoryDataSrc 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 the dedicated backend.
+/// It is caller's responsibility to ensure this assumption.
+///
+/// <b>Notes to developer:</b>
+///
+/// For now, we don't make it a derived class of AbstractDataSrc because the
+/// interface is so different (we'll eventually consider this as part of the
+/// generalization work).
+///
+/// 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
+/// MemoryZone in the form of (Boost) shared pointer, so that it can provide
+/// the general interface for all data sources.
+///
+/// Currently, \c FindResult::zone is immutable for safety.
+/// In future versions we may want to make it changeable.  For example,
+/// we may want to allow configuration update on an existing zone.
+class MemoryDataSrc {
+public:
+    /// \brief A helper structure to represent the search result of
+    /// <code>MemoryDataSrc::find()</code>.
+    ///
+    /// This is a straightforward pair of the result code and a share pointer
+    /// to the found zone to represent the result of \c find().
+    /// We use this in order to avoid overloading the return value for both
+    /// the result code ("success" or "not found") and the found object,
+    /// i.e., avoid using \c NULL to mean "not found", etc.
+    ///
+    /// This is a simple value class with no internal state, so for
+    /// convenience we allow the applications to refer to the members
+    /// directly.
+    ///
+    /// See the description of \c find() for the semantics of the member
+    /// variables.
+    struct FindResult {
+        FindResult(result::Result param_code, const ConstZonePtr param_zone) :
+            code(param_code), zone(param_zone)
+        {}
+        const result::Result code;
+        const ConstZonePtr 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:
+    MemoryDataSrc(const MemoryDataSrc& source);
+    MemoryDataSrc& operator=(const MemoryDataSrc& source);
+
+public:
+    /// 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.
+    MemoryDataSrc();
+
+    /// The destructor.
+    ~MemoryDataSrc();
+    //@}
+
+    /// Add a \c Zone to the \c MemoryDataSrc.
+    ///
+    /// \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 memory data source.
+    /// \return \c result::EXIST The memory data source already
+    /// stores a zone that has the same origin.
+    result::Result addZone(ZonePtr zone);
+
+    /// Find a \c Zone that best matches the given name in the \c MemoryDataSrc.
+    ///
+    /// 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 MemoryDataSrcImpl;
+    MemoryDataSrcImpl* impl_;
+};
+}
+}
+#endif  // __DATA_SOURCE_MEMORY_H
+// Local Variables:
+// mode: c++
+// End:

+ 2 - 1
src/lib/datasrc/tests/Makefile.am

@@ -25,11 +25,12 @@ run_unittests_SOURCES += query_unittest.cc
 run_unittests_SOURCES += cache_unittest.cc
 run_unittests_SOURCES += cache_unittest.cc
 run_unittests_SOURCES += test_datasrc.h test_datasrc.cc
 run_unittests_SOURCES += test_datasrc.h test_datasrc.cc
 run_unittests_SOURCES += zonetable_unittest.cc
 run_unittests_SOURCES += zonetable_unittest.cc
+run_unittests_SOURCES += memory_datasrc_unittest.cc
 run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
 run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
 run_unittests_LDADD = $(GTEST_LDADD)
 run_unittests_LDADD = $(GTEST_LDADD)
 run_unittests_LDADD += $(SQLITE_LIBS)
 run_unittests_LDADD += $(SQLITE_LIBS)
-run_unittests_LDADD += $(top_builddir)/src/lib/datasrc/libdatasrc.la 
+run_unittests_LDADD += $(top_builddir)/src/lib/datasrc/libdatasrc.la
 run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
 run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
 run_unittests_LDADD += $(top_builddir)/src/lib/cc/libcc.la
 run_unittests_LDADD += $(top_builddir)/src/lib/cc/libcc.la
 run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
 run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la

+ 115 - 0
src/lib/datasrc/tests/memory_datasrc_unittest.cc

@@ -0,0 +1,115 @@
+// 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 <dns/name.h>
+#include <dns/rrclass.h>
+
+#include <datasrc/zonetable.h>
+#include <datasrc/memory_datasrc.h>
+
+#include <gtest/gtest.h>
+
+using namespace isc::dns;
+using namespace isc::datasrc;
+
+namespace {
+
+class MemoryDataSrcTest : public ::testing::Test {
+protected:
+    MemoryDataSrcTest()
+    {}
+    MemoryDataSrc memory_datasrc;
+};
+
+TEST_F(MemoryDataSrcTest, add_find_Zone) {
+    // test add zone
+    // Bogus zone (NULL)
+    EXPECT_THROW(memory_datasrc.addZone(ZonePtr()), isc::InvalidParameter);
+
+    // add zones with different names one by one
+    EXPECT_EQ(result::SUCCESS, memory_datasrc.addZone(
+                  ZonePtr(new MemoryZone(RRClass::IN(), Name("a")))));
+    EXPECT_EQ(result::SUCCESS, memory_datasrc.addZone(
+                  ZonePtr(new MemoryZone(RRClass::CH(), Name("b")))));
+    EXPECT_EQ(result::SUCCESS, memory_datasrc.addZone(
+                  ZonePtr(new MemoryZone(RRClass::IN(), Name("c")))));
+    // add zones with the same name suffix
+    EXPECT_EQ(result::SUCCESS, memory_datasrc.addZone(
+                  ZonePtr(new MemoryZone(RRClass::CH(),
+                                         Name("x.d.e.f")))));
+    EXPECT_EQ(result::SUCCESS, memory_datasrc.addZone(
+                  ZonePtr(new MemoryZone(RRClass::CH(),
+                                         Name("o.w.y.d.e.f")))));
+    EXPECT_EQ(result::SUCCESS, memory_datasrc.addZone(
+                  ZonePtr(new MemoryZone(RRClass::CH(),
+                                         Name("p.w.y.d.e.f")))));
+    EXPECT_EQ(result::SUCCESS, memory_datasrc.addZone(
+                  ZonePtr(new MemoryZone(RRClass::IN(),
+                                         Name("q.w.y.d.e.f")))));
+    // add super zone and its subzone
+    EXPECT_EQ(result::SUCCESS, memory_datasrc.addZone(
+                  ZonePtr(new MemoryZone(RRClass::CH(), Name("g.h")))));
+    EXPECT_EQ(result::SUCCESS, memory_datasrc.addZone(
+                  ZonePtr(new MemoryZone(RRClass::IN(), Name("i.g.h")))));
+    EXPECT_EQ(result::SUCCESS, memory_datasrc.addZone(
+                  ZonePtr(new MemoryZone(RRClass::IN(),
+                                         Name("z.d.e.f")))));
+    EXPECT_EQ(result::SUCCESS, memory_datasrc.addZone(
+                  ZonePtr(new MemoryZone(RRClass::IN(),
+                                         Name("j.z.d.e.f")))));
+
+    // different zone class isn't allowed.
+    EXPECT_EQ(result::EXIST, memory_datasrc.addZone(
+                  ZonePtr(new MemoryZone(RRClass::CH(),
+                                         Name("q.w.y.d.e.f")))));
+
+    // names are compared in a case insensitive manner.
+    EXPECT_EQ(result::EXIST, memory_datasrc.addZone(
+                  ZonePtr(new MemoryZone(RRClass::IN(),
+                                         Name("Q.W.Y.d.E.f")))));
+
+    // test find zone
+    EXPECT_EQ(result::SUCCESS, memory_datasrc.findZone(Name("a")).code);
+    EXPECT_EQ(Name("a"),
+              memory_datasrc.findZone(Name("a")).zone->getOrigin());
+
+    EXPECT_EQ(result::SUCCESS,
+              memory_datasrc.findZone(Name("j.z.d.e.f")).code);
+    EXPECT_EQ(Name("j.z.d.e.f"),
+              memory_datasrc.findZone(Name("j.z.d.e.f")).zone->getOrigin());
+
+    // NOTFOUND
+    EXPECT_EQ(result::NOTFOUND, memory_datasrc.findZone(Name("d.e.f")).code);
+    EXPECT_EQ(ConstZonePtr(), memory_datasrc.findZone(Name("d.e.f")).zone);
+
+    EXPECT_EQ(result::NOTFOUND,
+              memory_datasrc.findZone(Name("w.y.d.e.f")).code);
+    EXPECT_EQ(ConstZonePtr(),
+              memory_datasrc.findZone(Name("w.y.d.e.f")).zone);
+
+    // there's no exact match.  the result should be the longest match,
+    // and the code should be PARTIALMATCH.
+    EXPECT_EQ(result::PARTIALMATCH,
+              memory_datasrc.findZone(Name("j.g.h")).code);
+    EXPECT_EQ(Name("g.h"),
+              memory_datasrc.findZone(Name("g.h")).zone->getOrigin());
+
+    EXPECT_EQ(result::PARTIALMATCH,
+              memory_datasrc.findZone(Name("z.i.g.h")).code);
+    EXPECT_EQ(Name("i.g.h"),
+              memory_datasrc.findZone(Name("z.i.g.h")).zone->getOrigin());
+}
+}

+ 29 - 29
src/lib/datasrc/tests/zonetable_unittest.cc

@@ -53,61 +53,61 @@ protected:
     ZonePtr zone1, zone2, zone3;
     ZonePtr zone1, zone2, zone3;
 };
 };
 
 
-TEST_F(ZoneTableTest, add) {
-    EXPECT_EQ(ZoneTable::SUCCESS, zone_table.add(zone1));
-    EXPECT_EQ(ZoneTable::EXIST, zone_table.add(zone1));
+TEST_F(ZoneTableTest, addZone) {
+    EXPECT_EQ(result::SUCCESS, zone_table.addZone(zone1));
+    EXPECT_EQ(result::EXIST, zone_table.addZone(zone1));
     // names are compared in a case insensitive manner.
     // names are compared in a case insensitive manner.
-    EXPECT_EQ(ZoneTable::EXIST, zone_table.add(
+    EXPECT_EQ(result::EXIST, zone_table.addZone(
                   ZonePtr(new MemoryZone(RRClass::IN(), Name("EXAMPLE.COM")))));
                   ZonePtr(new MemoryZone(RRClass::IN(), Name("EXAMPLE.COM")))));
 
 
-    EXPECT_EQ(ZoneTable::SUCCESS, zone_table.add(zone2));
-    EXPECT_EQ(ZoneTable::SUCCESS, zone_table.add(zone3));
+    EXPECT_EQ(result::SUCCESS, zone_table.addZone(zone2));
+    EXPECT_EQ(result::SUCCESS, zone_table.addZone(zone3));
 
 
     // Zone table is indexed only by name.  Duplicate origin name with
     // Zone table is indexed only by name.  Duplicate origin name with
     // different zone class isn't allowed.
     // different zone class isn't allowed.
-    EXPECT_EQ(ZoneTable::EXIST, zone_table.add(
+    EXPECT_EQ(result::EXIST, zone_table.addZone(
                   ZonePtr(new MemoryZone(RRClass::CH(),
                   ZonePtr(new MemoryZone(RRClass::CH(),
                                          Name("example.com")))));
                                          Name("example.com")))));
 
 
     /// Bogus zone (NULL)
     /// Bogus zone (NULL)
-    EXPECT_THROW(zone_table.add(ZonePtr()), isc::InvalidParameter);
+    EXPECT_THROW(zone_table.addZone(ZonePtr()), isc::InvalidParameter);
 }
 }
 
 
-TEST_F(ZoneTableTest, remove) {
-    EXPECT_EQ(ZoneTable::SUCCESS, zone_table.add(zone1));
-    EXPECT_EQ(ZoneTable::SUCCESS, zone_table.add(zone2));
-    EXPECT_EQ(ZoneTable::SUCCESS, zone_table.add(zone3));
+TEST_F(ZoneTableTest, removeZone) {
+    EXPECT_EQ(result::SUCCESS, zone_table.addZone(zone1));
+    EXPECT_EQ(result::SUCCESS, zone_table.addZone(zone2));
+    EXPECT_EQ(result::SUCCESS, zone_table.addZone(zone3));
 
 
-    EXPECT_EQ(ZoneTable::SUCCESS, zone_table.remove(Name("example.net")));
-    EXPECT_EQ(ZoneTable::NOTFOUND, zone_table.remove(Name("example.net")));
+    EXPECT_EQ(result::SUCCESS, zone_table.removeZone(Name("example.net")));
+    EXPECT_EQ(result::NOTFOUND, zone_table.removeZone(Name("example.net")));
 }
 }
 
 
-TEST_F(ZoneTableTest, find) {
-    EXPECT_EQ(ZoneTable::SUCCESS, zone_table.add(zone1));
-    EXPECT_EQ(ZoneTable::SUCCESS, zone_table.add(zone2));
-    EXPECT_EQ(ZoneTable::SUCCESS, zone_table.add(zone3));
+TEST_F(ZoneTableTest, findZone) {
+    EXPECT_EQ(result::SUCCESS, zone_table.addZone(zone1));
+    EXPECT_EQ(result::SUCCESS, zone_table.addZone(zone2));
+    EXPECT_EQ(result::SUCCESS, zone_table.addZone(zone3));
 
 
-    EXPECT_EQ(ZoneTable::SUCCESS, zone_table.find(Name("example.com")).code);
+    EXPECT_EQ(result::SUCCESS, zone_table.findZone(Name("example.com")).code);
     EXPECT_EQ(Name("example.com"),
     EXPECT_EQ(Name("example.com"),
-              zone_table.find(Name("example.com")).zone->getOrigin());
+              zone_table.findZone(Name("example.com")).zone->getOrigin());
 
 
-    EXPECT_EQ(ZoneTable::NOTFOUND,
-              zone_table.find(Name("example.org")).code);
-    EXPECT_EQ(static_cast<const Zone*>(NULL),
-              zone_table.find(Name("example.org")).zone);
+    EXPECT_EQ(result::NOTFOUND,
+              zone_table.findZone(Name("example.org")).code);
+    EXPECT_EQ(ConstZonePtr(),
+              zone_table.findZone(Name("example.org")).zone);
 
 
     // there's no exact match.  the result should be the longest match,
     // there's no exact match.  the result should be the longest match,
     // and the code should be PARTIALMATCH.
     // and the code should be PARTIALMATCH.
-    EXPECT_EQ(ZoneTable::PARTIALMATCH,
-              zone_table.find(Name("www.example.com")).code);
+    EXPECT_EQ(result::PARTIALMATCH,
+              zone_table.findZone(Name("www.example.com")).code);
     EXPECT_EQ(Name("example.com"),
     EXPECT_EQ(Name("example.com"),
-              zone_table.find(Name("www.example.com")).zone->getOrigin());
+              zone_table.findZone(Name("www.example.com")).zone->getOrigin());
 
 
     // make sure the partial match is indeed the longest match by adding
     // make sure the partial match is indeed the longest match by adding
     // a zone with a shorter origin and query again.
     // a zone with a shorter origin and query again.
     ZonePtr zone_com(new MemoryZone(RRClass::IN(), Name("com")));
     ZonePtr zone_com(new MemoryZone(RRClass::IN(), Name("com")));
-    EXPECT_EQ(ZoneTable::SUCCESS, zone_table.add(zone_com));
+    EXPECT_EQ(result::SUCCESS, zone_table.addZone(zone_com));
     EXPECT_EQ(Name("example.com"),
     EXPECT_EQ(Name("example.com"),
-              zone_table.find(Name("www.example.com")).zone->getOrigin());
+              zone_table.findZone(Name("www.example.com")).zone->getOrigin());
 }
 }
 }
 }

+ 13 - 12
src/lib/datasrc/zonetable.cc

@@ -77,29 +77,30 @@ ZoneTable::~ZoneTable() {
     delete impl_;
     delete impl_;
 }
 }
 
 
-ZoneTable::Result
-ZoneTable::add(ZonePtr zone) {
+result::Result
+ZoneTable::addZone(ZonePtr zone) {
     if (!zone) {
     if (!zone) {
         isc_throw(InvalidParameter,
         isc_throw(InvalidParameter,
-                  "Null pointer is passed to ZoneTable::add()");
+                  "Null pointer is passed to ZoneTable::addZone()");
     }
     }
 
 
     if (impl_->zones.insert(
     if (impl_->zones.insert(
             ZoneTableImpl::NameAndZone(zone->getOrigin(), zone)).second
             ZoneTableImpl::NameAndZone(zone->getOrigin(), zone)).second
         == true) {
         == true) {
-        return (SUCCESS);
+        return (result::SUCCESS);
     } else {
     } else {
-        return (EXIST);
+        return (result::EXIST);
     }
     }
 }
 }
 
 
-ZoneTable::Result
-ZoneTable::remove(const Name& origin) {
-    return (impl_->zones.erase(origin) == 1 ? SUCCESS : NOTFOUND);
+result::Result
+ZoneTable::removeZone(const Name& origin) {
+    return (impl_->zones.erase(origin) == 1 ? result::SUCCESS :
+                                              result::NOTFOUND);
 }
 }
 
 
 ZoneTable::FindResult
 ZoneTable::FindResult
-ZoneTable::find(const Name& name) const {
+ZoneTable::findZone(const Name& name) const {
     // Inefficient internal loop to find a longest match.
     // Inefficient internal loop to find a longest match.
     // This will be replaced with a single call to more intelligent backend.
     // This will be replaced with a single call to more intelligent backend.
     for (int i = 0; i < name.getLabelCount(); ++i) {
     for (int i = 0; i < name.getLabelCount(); ++i) {
@@ -107,11 +108,11 @@ ZoneTable::find(const Name& name) const {
         ZoneTableImpl::ZoneMap::const_iterator found =
         ZoneTableImpl::ZoneMap::const_iterator found =
             impl_->zones.find(matchname);
             impl_->zones.find(matchname);
         if (found != impl_->zones.end()) {
         if (found != impl_->zones.end()) {
-            return (FindResult(i == 0 ? SUCCESS : PARTIALMATCH,
-                               (*found).second.get()));
+            return (FindResult(i == 0 ? result::SUCCESS :
+                               result::PARTIALMATCH, (*found).second));
         }
         }
     }
     }
-    return (FindResult(NOTFOUND, NULL));
+    return (FindResult(result::NOTFOUND, ConstZonePtr()));
 }
 }
 } // end of namespace datasrc
 } // end of namespace datasrc
 } // end of namespace isc
 } // end of namespace isc

+ 35 - 107
src/lib/datasrc/zonetable.h

@@ -26,6 +26,21 @@ class RRClass;
 };
 };
 
 
 namespace datasrc {
 namespace datasrc {
+namespace result {
+/// Result codes of various public methods of in memory data source
+///
+/// The detailed semantics may differ in different methods.
+/// See the description of specific methods for more details.
+///
+/// Note: this is intended to be used from other data sources eventually,
+/// but for now it's specific to in memory data source and its backend.
+enum Result {
+    SUCCESS,  ///< The operation is successful.
+    EXIST,    ///< The search key is already stored.
+    NOTFOUND, ///< The specified object is not found.
+    PARTIALMATCH ///< \c Only a partial match is found.
+};
+}
 
 
 /// \brief The base class for a single authoritative zone
 /// \brief The base class for a single authoritative zone
 ///
 ///
@@ -223,81 +238,22 @@ private:
 
 
 /// \brief A set of authoritative zones.
 /// \brief A set of authoritative zones.
 ///
 ///
-/// The \c ZoneTable class represents a set of zones of the same RR class
-/// and provides a basic interface to help DNS lookup processing.
-/// For a given domain name, its \c find() method searches the set for a zone
-/// that gives a longest match against that name.
-///
-/// The set of zones are assumed to be of the same RR class, but the
-/// \c ZoneTable class does not enforce the assumption through its interface.
-/// For example, the \c add() method does not check if the new zone
-/// is of the same RR class as that of the others already in the table.
-/// It is caller's responsibility to ensure this assumption.
-///
-/// <b>Notes to developer:</b>
-///
-/// The add() 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 zone
-/// table.
-///
-/// On the other hand, the find() method returns a bare pointer, rather than
-/// the shared pointer, in order to minimize the dependency on Boost
-/// definitions in our public interfaces.  This means the caller can only
-/// refer to the returned object (via the pointer) for a short period.
-///  It should be okay for simple lookup purposes, but if we see the need
-/// for keeping a \c Zone object for a longer period of context, we may
-/// have to revisit this decision.
+/// \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).
 ///
 ///
-/// Currently, \c FindResult::zone is immutable for safety.
-/// In future versions we may want to make it changeable.  For example,
-/// we may want to allow configuration update on an existing zone.
-///
-/// In BIND 9's "zt" module, the equivalent of \c find() has an "option"
-/// parameter.  The only defined option is the one to specify the "no exact"
-/// mode, and the only purpose of that mode is to prefer a second longest match
-/// even if there is an exact match in order to deal with type DS query.
-/// This trick may help enhance performance, but it also seems to make the
-/// implementation complicated for a very limited, minor case.  So, for now,
-/// we don't introduce the special mode, and, since it was the only reason to
-/// have search options in BIND 9, our initial implementation doesn't provide
-/// a switch for options.
+/// For more descriptions about its struct and interfaces, please refer to the
+/// corresponding struct and interfaces of \c MemoryDataSrc.
 class ZoneTable {
 class ZoneTable {
 public:
 public:
-    /// Result codes of various public methods of \c ZoneTable.
-    ///
-    /// The detailed semantics may differ in different methods.
-    /// See the description of specific methods for more details.
-    enum Result {
-        SUCCESS,  ///< The operation is successful.
-        EXIST,    ///< A zone is already stored in \c ZoneTable.
-        NOTFOUND, ///< The specified zone is not found in \c ZoneTable.
-        PARTIALMATCH ///< \c Only a partial match is found in \c find(). 
-    };
-
-    /// \brief A helper structure to represent the search result of
-    /// <code>ZoneTable::find()</code>.
-    ///
-    /// This is a straightforward pair of the result code and a pointer
-    /// to the found zone to represent the result of \c find().
-    /// We use this in order to avoid overloading the return value for both
-    /// the result code ("success" or "not found") and the found object,
-    /// i.e., avoid using \c NULL to mean "not found", etc.
-    ///
-    /// This is a simple value class with no internal state, so for
-    /// convenience we allow the applications to refer to the members
-    /// directly.
-    ///
-    /// See the description of \c find() for the semantics of the member
-    /// variables.
     struct FindResult {
     struct FindResult {
-        FindResult(Result param_code, const Zone* param_zone) :
+        FindResult(result::Result param_code, const ConstZonePtr param_zone) :
             code(param_code), zone(param_zone)
             code(param_code), zone(param_zone)
         {}
         {}
-        const Result code;
-        const Zone* const zone;
+        const result::Result code;
+        const ConstZonePtr zone;
     };
     };
-
     ///
     ///
     /// \name Constructors and Destructor.
     /// \name Constructors and Destructor.
     ///
     ///
@@ -322,53 +278,25 @@ public:
     //@}
     //@}
 
 
     /// Add a \c Zone to the \c ZoneTable.
     /// 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 SUCCESS If the zone is successfully added to the zone table.
-    /// \return \c EXIST The zone table already stores a zone that has the
-    /// same origin.
-    Result add(ZonePtr zone);
+    /// See the description of <code>MemoryDataSrc::addZone()</code> for more
+    /// details.
+    result::Result addZone(ZonePtr zone);
 
 
     /// Remove a \c Zone of the given origin name from the \c ZoneTable.
     /// Remove a \c Zone of the given origin name from the \c ZoneTable.
     ///
     ///
     /// This method never throws an exception.
     /// This method never throws an exception.
     ///
     ///
     /// \param origin The origin name of the zone to be removed.
     /// \param origin The origin name of the zone to be removed.
-    /// \return \c SUCCESS If the zone is successfully removed from the
-    /// zone table.
-    /// \return \c NOTFOUND The zone table does not store the zone that matches
-    /// \c origin.
-    Result remove(const isc::dns::Name& origin);
+    /// \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.
     /// 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 SUCCESS: A zone that gives an exact match is found
-    ///   - \c PARTIALMATCH: A zone whose origin is a super domain of
-    ///     \c name is found (but there is no exact match)
-    ///   - \c NOTFOUND: For all other cases.
-    /// - \c zone: A pointer to the found \c Zone object if one is found;
-    /// otherwise \c NULL.
-    ///
-    /// The pointer returned in the \c FindResult object is only valid until
-    /// the corresponding zone is removed from the zone table.
-    /// The caller must ensure that the zone is held in the zone table while
-    /// it needs to refer to it.
-    ///
-    /// 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 find(const isc::dns::Name& name) const;
+    /// See the description of <code>MemoryDataSrc::findZone()</code> for more
+    /// details.
+    FindResult findZone(const isc::dns::Name& name) const;
 
 
 private:
 private:
     struct ZoneTableImpl;
     struct ZoneTableImpl;