Browse Source

[1287] first step of getSOA(). perform find(SOA) before starting iteration,
and have the new method return the result.
note: I decided to change it from the more generic 'getFinder()', because
I found it wouldn't work for some types of database backend such as MySQL.

JINMEI Tatuya 13 years ago
parent
commit
e5c133124d

+ 19 - 3
src/lib/datasrc/database.cc

@@ -704,16 +704,23 @@ namespace {
  */
 class DatabaseIterator : public ZoneIterator {
 public:
-    DatabaseIterator(const DatabaseAccessor::IteratorContextPtr& context,
-             const RRClass& rrclass) :
+    DatabaseIterator(shared_ptr<DatabaseAccessor> /*accessor*/,
+                     ConstRRsetPtr soa,
+                     const DatabaseAccessor::IteratorContextPtr& context,
+                     const RRClass& rrclass) :
         context_(context),
         class_(rrclass),
+        soa_(soa),
         ready_(true)
     {
         // Prepare data for the next time
         getData();
     }
 
+    virtual ConstRRsetPtr getSOA() const {
+        return (soa_);
+    }
+
     virtual isc::dns::ConstRRsetPtr getNextRRset() {
         if (!ready_) {
             isc_throw(isc::Unexpected, "Iterating past the zone end");
@@ -764,6 +771,8 @@ private:
     const DatabaseAccessor::IteratorContextPtr context_;
     // Class of the zone
     RRClass class_;
+    // SOA of the zone, if any (it should normally exist)
+    ConstRRsetPtr soa_;
     // Status
     bool ready_, data_ready_;
     // Data of the next row
@@ -782,6 +791,12 @@ DatabaseClient::getIterator(const isc::dns::Name& name) const {
                   " can not be iterated, because it doesn't exist "
                   "in this data source");
     }
+
+    // Find the SOA of the zone (may or may not succeed).  Note that
+    // this must be done before starting the iteration context.
+    ConstRRsetPtr soa = DatabaseClient::Finder(accessor_, zone.second, name).
+        find(name, RRType::SOA(), NULL).rrset;
+
     // Request the context
     DatabaseAccessor::IteratorContextPtr
         context(accessor_->getAllRecords(zone.second));
@@ -797,7 +812,8 @@ DatabaseClient::getIterator(const isc::dns::Name& name) const {
     // it each time)
     LOG_DEBUG(logger, DBG_TRACE_DETAILED, DATASRC_DATABASE_ITERATE).
         arg(name);
-    return (ZoneIteratorPtr(new DatabaseIterator(context, RRClass::IN())));
+    return (ZoneIteratorPtr(new DatabaseIterator(accessor_, soa, context,
+                                                 RRClass::IN())));
 }
 
 //

+ 11 - 5
src/lib/datasrc/iterator.h

@@ -12,6 +12,9 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
+#ifndef __DATASRC_ZONE_ITERATOR_H
+#define __DATASRC_ZONE_ITERATOR_H 1
+
 #include <dns/rrset.h>
 
 #include <boost/noncopyable.hpp>
@@ -57,14 +60,17 @@ public:
      *     gets to the end of the zone.
      */
     virtual isc::dns::ConstRRsetPtr getNextRRset() = 0;
+
     /**
-     * \brief Get the finder for the zone being iterated.
-     *
-     * This returns the finder which can be used to query RRs from the zone,
-     * efective to the time when the iterator was created.
+     * \brief TBD
      */
-    virtual ZoneFinder& getFinder() = 0;
+    virtual isc::dns::ConstRRsetPtr getSOA() const = 0;
 };
 
 }
 }
+#endif  // __DATASRC_ZONE_ITERATOR_H
+
+// Local Variables:
+// mode: c++
+// End:

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

@@ -781,7 +781,7 @@ public:
         return (result);
     }
 
-    virtual ZoneFinder& getFinder() {
+    virtual ConstRRsetPtr getSOA() const {
         isc_throw(NotImplemented, "Not imelemented");
     }
 };

+ 20 - 1
src/lib/datasrc/tests/database_unittest.cc

@@ -154,9 +154,13 @@ const char* const TEST_RECORDS[][5] = {
 
     // Put some data into apex (including NS) so we can check our NS
     // doesn't break anything
+    {"example.org.", "SOA", "3600", "", "ns1.example.org. admin.example.org. "
+     "1234 3600 1800 2419200 7200" },
     {"example.org.", "NS", "3600", "", "ns.example.com."},
     {"example.org.", "A", "3600", "", "192.0.2.1"},
     {"example.org.", "NSEC", "3600", "", "acnamesig1.example.org. NS A NSEC RRSIG"},
+    {"example.org.", "RRSIG", "3600", "", "SOA 5 3 3600 20000101000000 "
+              "20000201000000 12345 example.org. FAKEFAKEFAKE"},
     {"example.org.", "RRSIG", "3600", "", "NSEC 5 3 3600 20000101000000 "
               "20000201000000 12345 example.org. FAKEFAKEFAKE"},
     {"example.org.", "RRSIG", "3600", "", "NS 5 3 3600 20000101000000 "
@@ -464,7 +468,11 @@ public:
                         new MockNameIteratorContext(*this, id, name,
                                                     subdomains)));
         } else {
-            isc_throw(isc::Unexpected, "Unknown zone ID");
+            // This iterator is bogus, but for the cases tested below that's
+            // sufficient.
+            return (IteratorContextPtr(
+                        new MockNameIteratorContext(*this, READONLY_ZONE_ID,
+                                                    name, subdomains)));
         }
     }
 
@@ -1031,6 +1039,17 @@ checkRRset(isc::dns::ConstRRsetPtr rrset,
     isc::testutils::rrsetCheck(expected_rrset, rrset);
 }
 
+TYPED_TEST(DatabaseClientTest, getSOAFromIterator) {
+    vector<string> soa_data;
+    soa_data.push_back("ns1.example.org. admin.example.org. "
+                       "1234 3600 1800 2419200 7200");
+
+    ZoneIteratorPtr it(this->client_->getIterator(this->zname_));
+    ASSERT_TRUE(it);
+    checkRRset(it->getSOA(), this->zname_, this->qclass_, RRType::SOA(),
+               this->rrttl_, soa_data);
+}
+
 void
 doFindTest(ZoneFinder& finder,
            const isc::dns::Name& name,