BIND 10 trac1331, updated. 3dcdc74a5e0f8cb7fd0c6a3f6dee480e30199f03 [1331] Implement the adding of diffs

BIND 10 source code commits bind10-changes at lists.isc.org
Wed Nov 9 19:18:29 UTC 2011


The branch, trac1331 has been updated
       via  3dcdc74a5e0f8cb7fd0c6a3f6dee480e30199f03 (commit)
       via  7fb9faf4602b6b4feff4c940942c12be838a8153 (commit)
       via  d60907a85ba3f762b81189588d1b7317b95e0521 (commit)
       via  b88b05b2a779554a0e3c345933104d42046fffaa (commit)
      from  046729c74341bb2ed1e6f60f81470cf6a6883000 (commit)

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

- Log -----------------------------------------------------------------
commit 3dcdc74a5e0f8cb7fd0c6a3f6dee480e30199f03
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date:   Wed Nov 9 20:18:07 2011 +0100

    [1331] Implement the adding of diffs

commit 7fb9faf4602b6b4feff4c940942c12be838a8153
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date:   Wed Nov 9 20:17:57 2011 +0100

    [1331] Documentation update

commit d60907a85ba3f762b81189588d1b7317b95e0521
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date:   Wed Nov 9 20:16:07 2011 +0100

    [1331] Fix tests

commit b88b05b2a779554a0e3c345933104d42046fffaa
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date:   Wed Nov 9 20:15:33 2011 +0100

    [1331] Add SOA::getSerial method

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

Summary of changes:
 src/lib/datasrc/database.cc                |   89 +++++++++++++++++++++++++++-
 src/lib/datasrc/tests/database_unittest.cc |   60 ++++++++++++-------
 src/lib/datasrc/zone.h                     |    2 +
 src/lib/dns/rdata/generic/soa_6.cc         |    6 ++
 src/lib/dns/rdata/generic/soa_6.h          |    2 +
 src/lib/dns/tests/rdata_soa_unittest.cc    |    5 ++
 6 files changed, 140 insertions(+), 24 deletions(-)

-----------------------------------------------------------------------
diff --git a/src/lib/datasrc/database.cc b/src/lib/datasrc/database.cc
index 9ee344f..8d4685e 100644
--- a/src/lib/datasrc/database.cc
+++ b/src/lib/datasrc/database.cc
@@ -832,6 +832,7 @@ public:
         committed_(false), accessor_(accessor), zone_id_(zone_id),
         db_name_(accessor->getDBName()), zone_name_(zone_name.toText()),
         zone_class_(zone_class), journaling_(journaling),
+        diff_phase_(NOT_STARTED),
         finder_(new DatabaseClient::Finder(accessor_, zone_id_, zone_name))
     {
         logger.debug(DBG_TRACE_DATA, DATASRC_DATABASE_UPDATER_CREATED)
@@ -874,6 +875,14 @@ private:
     const string zone_name_;
     const RRClass zone_class_;
     const bool journaling_;
+    // For the journals
+    enum DiffPhase {
+        NOT_STARTED,
+        DELETE,
+        ADD
+    };
+    DiffPhase diff_phase_;
+    uint32_t serial_;
     boost::scoped_ptr<DatabaseClient::Finder> finder_;
 };
 
@@ -893,6 +902,19 @@ DatabaseUpdater::addRRset(const RRset& rrset) {
                   << zone_name_ << "/" << zone_class_ << ": "
                   << rrset.toText());
     }
+    if (rrset.getType() == RRType::SOA() && diff_phase_ == ADD &&
+        journaling_) {
+        isc_throw(isc::BadValue, "Another SOA added inside an add sequence");
+    }
+    if (rrset.getType() != RRType::SOA() && diff_phase_ != ADD &&
+        journaling_) {
+        isc_throw(isc::BadValue, "Adding sequence not started by SOA");
+    }
+    if (rrset.getType() == RRType::SOA() && diff_phase_ != DELETE &&
+        journaling_) {
+        isc_throw(isc::BadValue,
+                  "Adding sequence can follow only after delete");
+    }
 
     RdataIteratorPtr it = rrset.getRdataIterator();
     if (it->isLast()) {
@@ -907,6 +929,21 @@ DatabaseUpdater::addRRset(const RRset& rrset) {
         rrset.getName().reverse().toText();
     columns[DatabaseAccessor::ADD_TTL] = rrset.getTTL().toText();
     columns[DatabaseAccessor::ADD_TYPE] = rrset.getType().toText();
+    string journal[DatabaseAccessor::DIFF_PARAM_COUNT];
+    if (journaling_) {
+        journal[DatabaseAccessor::DIFF_NAME] =
+            columns[DatabaseAccessor::ADD_NAME];
+        journal[DatabaseAccessor::DIFF_TYPE] =
+            columns[DatabaseAccessor::ADD_TYPE];
+        journal[DatabaseAccessor::DIFF_TTL] =
+            columns[DatabaseAccessor::ADD_TTL];
+        diff_phase_ = ADD;
+        if (rrset.getType() == RRType::SOA()) {
+            serial_ =
+                dynamic_cast<const rdata::generic::SOA&>(it->getCurrent()).
+                getSerial();
+        }
+    }
     for (; !it->isLast(); it->next()) {
         if (rrset.getType() == RRType::RRSIG()) {
             // XXX: the current interface (based on the current sqlite3
@@ -920,6 +957,16 @@ DatabaseUpdater::addRRset(const RRset& rrset) {
                 rrsig_rdata.typeCovered().toText();
         }
         columns[DatabaseAccessor::ADD_RDATA] = it->getCurrent().toText();
+        if (journaling_) {
+            journal[DatabaseAccessor::DIFF_RDATA] =
+                columns[DatabaseAccessor::ADD_RDATA];
+            try {
+                accessor_->addRecordDiff(zone_id_, serial_,
+                                         DatabaseAccessor::DIFF_ADD, journal);
+            }
+            // We ignore not implemented
+            catch (const isc::NotImplemented&) {}
+        }
         accessor_->addRecordToZone(columns);
     }
 }
@@ -940,6 +987,15 @@ DatabaseUpdater::deleteRRset(const RRset& rrset) {
                   << zone_name_ << "/" << zone_class_ << ": "
                   << rrset.toText());
     }
+    if (rrset.getType() == RRType::SOA() && diff_phase_ == DELETE &&
+        journaling_) {
+        isc_throw(isc::BadValue,
+                  "Another SOA delete inside a delete sequence");
+    }
+    if (rrset.getType() != RRType::SOA() && diff_phase_ != DELETE &&
+        journaling_) {
+        isc_throw(isc::BadValue, "Delete sequence not started by SOA");
+    }
 
     RdataIteratorPtr it = rrset.getRdataIterator();
     if (it->isLast()) {
@@ -951,8 +1007,33 @@ DatabaseUpdater::deleteRRset(const RRset& rrset) {
     string params[DatabaseAccessor::DEL_PARAM_COUNT]; // initialized with ""
     params[DatabaseAccessor::DEL_NAME] = rrset.getName().toText();
     params[DatabaseAccessor::DEL_TYPE] = rrset.getType().toText();
+    string journal[DatabaseAccessor::DIFF_PARAM_COUNT];
+    if (journaling_) {
+        journal[DatabaseAccessor::DIFF_NAME] =
+            params[DatabaseAccessor::DEL_NAME];
+        journal[DatabaseAccessor::DIFF_TYPE] =
+            params[DatabaseAccessor::DEL_TYPE];
+        journal[DatabaseAccessor::DIFF_TTL] = rrset.getTTL().toText();
+        diff_phase_ = DELETE;
+        if (rrset.getType() == RRType::SOA()) {
+            serial_ =
+                dynamic_cast<const rdata::generic::SOA&>(it->getCurrent()).
+                getSerial();
+        }
+    }
     for (; !it->isLast(); it->next()) {
         params[DatabaseAccessor::DEL_RDATA] = it->getCurrent().toText();
+        if (journaling_) {
+            journal[DatabaseAccessor::DIFF_RDATA] =
+                params[DatabaseAccessor::DEL_RDATA];
+            try {
+                accessor_->addRecordDiff(zone_id_, serial_,
+                                         DatabaseAccessor::DIFF_DELETE,
+                                         journal);
+            }
+            // Don't fail if the backend can't store them
+            catch(const isc::NotImplemented&) {}
+        }
         accessor_->deleteRecordInZone(params);
     }
 }
@@ -964,6 +1045,9 @@ DatabaseUpdater::commit() {
                   << zone_name_ << "/" << zone_class_ << " on "
                   << db_name_);
     }
+    if (journaling_ && diff_phase_ == DELETE) {
+        isc_throw(isc::Unexpected, "Update sequence not complete");
+    }
     accessor_->commit();
     committed_ = true; // make sure the destructor won't trigger rollback
 
@@ -980,7 +1064,10 @@ ZoneUpdaterPtr
 DatabaseClient::getUpdater(const isc::dns::Name& name, bool replace,
                            bool journaling) const
 {
-    // TODO: Handle journaling (pass it to the updater)
+    if (replace && journaling) {
+        isc_throw(isc::BadValue, "Can't store journal and replace the whole "
+                  "zone at the same time");
+    }
     shared_ptr<DatabaseAccessor> update_accessor(accessor_->clone());
     const std::pair<bool, int> zone(update_accessor->startUpdateZone(
                                         name.toText(), replace));
diff --git a/src/lib/datasrc/tests/database_unittest.cc b/src/lib/datasrc/tests/database_unittest.cc
index 0748cc0..29fd135 100644
--- a/src/lib/datasrc/tests/database_unittest.cc
+++ b/src/lib/datasrc/tests/database_unittest.cc
@@ -295,8 +295,12 @@ struct JournalEntry {
     DatabaseAccessor::DiffOperation operation_;
     std::string data_[DatabaseAccessor::DIFF_PARAM_COUNT];
     bool operator==(const JournalEntry& other) const {
+        bool data_equal(true);
+        for (size_t i(0); i < DatabaseAccessor::DIFF_PARAM_COUNT; ++ i) {
+            data_equal = data_equal && (data_[i] == other.data_[i]);
+        }
         return (id_ == other.id_ && serial_ == other.serial_ &&
-                operation_ == other.operation_ && data_ == other.data_);
+                operation_ == other.operation_ && data_equal);
     }
 };
 
@@ -324,6 +328,7 @@ public:
         readonly_records_ = &readonly_records_master_;
         update_records_ = &update_records_master_;
         empty_records_ = &empty_records_master_;
+        journal_entries_ = &journal_entries_master_;
         fillData();
     }
 
@@ -332,6 +337,7 @@ public:
         cloned_accessor->readonly_records_ = &readonly_records_master_;
         cloned_accessor->update_records_ = &update_records_master_;
         cloned_accessor->empty_records_ = &empty_records_master_;
+        cloned_accessor->journal_entries_ = &journal_entries_master_;
         latest_clone_ = cloned_accessor;
         return (cloned_accessor);
     }
@@ -568,7 +574,13 @@ public:
             *update_records_ = *readonly_records_;
         }
 
-        return (pair<bool, int>(true, WRITABLE_ZONE_ID));
+        if (zone_name == "bad.example.org.") {
+            return (pair<bool, int>(true, -1));
+        } else if (zone_name == "null.example.org.") {
+            return (pair<bool, int>(true, 13));
+        } else {
+            return (pair<bool, int>(true, WRITABLE_ZONE_ID));
+        }
     }
     virtual void commit() {
         *readonly_records_ = *update_records_;
@@ -691,7 +703,7 @@ public:
         } else if (id == -1) { // Bad zone throws
             isc_throw(DataSourceError, "Test error");
         } else {
-            journal_entries_.push_back(JournalEntry(id, serial, operation,
+            journal_entries_->push_back(JournalEntry(id, serial, operation,
                                                     data));
         }
     }
@@ -700,7 +712,7 @@ public:
     void checkJournal(const std::vector<JournalEntry> &expected) {
         std::vector<JournalEntry> journal;
         // Clean the journal, but keep local copy to check
-        journal.swap(journal_entries_);
+        journal.swap(*journal_entries_);
         ASSERT_EQ(expected.size(), journal.size());
         for (size_t i(0); i < expected.size(); ++ i) {
             EXPECT_TRUE(expected[i] == journal[i]);
@@ -726,7 +738,8 @@ private:
     const Domains* empty_records_;
 
     // The journal data
-    std::vector<JournalEntry> journal_entries_;
+    std::vector<JournalEntry> journal_entries_master_;
+    std::vector<JournalEntry>* journal_entries_;
 
     // used as temporary storage after searchForRecord() and during
     // getNextRecord() calls, as well as during the building of the
@@ -2705,29 +2718,28 @@ TEST_F(MockDatabaseClientTest, journal) {
     soa_.reset(new RRset(zname_, qclass_, RRType::SOA(), rrttl_));
     soa_->addRdata(rdata::createRdata(soa_->getType(), soa_->getClass(),
                                       "ns1.example.org. admin.example.org. "
-                                      "1234 3600 1800 2419201 7200"));
+                                      "1235 3600 1800 2419200 7200"));
     updater_->addRRset(*soa_);
     updater_->addRRset(*rrset_);
     ASSERT_NO_THROW(updater_->commit());
     std::vector<JournalEntry> expected;
-    // For some reason, the example.org is called read only zone here.
-    expected.push_back(JournalEntry(READONLY_ZONE_ID, 2419200,
+    expected.push_back(JournalEntry(WRITABLE_ZONE_ID, 1234,
                                     DatabaseAccessor::DIFF_DELETE,
                                     "example.org.", "SOA", "3600",
                                     "ns1.example.org. admin.example.org. "
                                     "1234 3600 1800 2419200 7200"));
-    expected.push_back(JournalEntry(READONLY_ZONE_ID, 2419200,
+    expected.push_back(JournalEntry(WRITABLE_ZONE_ID, 1234,
                                     DatabaseAccessor::DIFF_DELETE,
-                                    "example.org.", "A", "3600",
+                                    "www.example.org.", "A", "3600",
                                     "192.0.2.2"));
-    expected.push_back(JournalEntry(READONLY_ZONE_ID, 2419201,
+    expected.push_back(JournalEntry(WRITABLE_ZONE_ID, 1235,
                                     DatabaseAccessor::DIFF_ADD,
                                     "example.org.", "SOA", "3600",
                                     "ns1.example.org. admin.example.org. "
-                                    "1234 3600 1800 2419201 7200"));
-    expected.push_back(JournalEntry(READONLY_ZONE_ID, 2419200,
+                                    "1235 3600 1800 2419200 7200"));
+    expected.push_back(JournalEntry(WRITABLE_ZONE_ID, 1235,
                                     DatabaseAccessor::DIFF_ADD,
-                                    "example.org.", "A", "3600",
+                                    "www.example.org.", "A", "3600",
                                     "192.0.2.2"));
     current_accessor_->checkJournal(expected);
 }
@@ -2744,20 +2756,20 @@ TEST_F(MockDatabaseClientTest, journalMultiple) {
     for (size_t i(1); i < 100; ++ i) {
         // Remove the old SOA
         updater_->deleteRRset(*soa_);
-        expected.push_back(JournalEntry(READONLY_ZONE_ID, 2419200 + i - 1,
+        expected.push_back(JournalEntry(WRITABLE_ZONE_ID, 1234 + i - 1,
                                         DatabaseAccessor::DIFF_DELETE,
                                         "example.org.", "SOA", "3600",
                                         soa_rdata));
         // Create a new SOA
-        soa_rdata = "ns1.example.org. admin.example.org. 1234 3600 1800 " +
-            lexical_cast<std::string>(2419200 + i) + " 7200";
+        soa_rdata = "ns1.example.org. admin.example.org. " +
+            lexical_cast<std::string>(1234 + i) + " 3600 1800 2419200 7200";
         soa_.reset(new RRset(zname_, qclass_, RRType::SOA(), rrttl_));
         soa_->addRdata(rdata::createRdata(soa_->getType(), soa_->getClass(),
                                           soa_rdata));
         // Add the new SOA
         updater_->addRRset(*soa_);
-        expected.push_back(JournalEntry(READONLY_ZONE_ID, 2419200 + i,
-                                        DatabaseAccessor::DIFF_DELETE,
+        expected.push_back(JournalEntry(WRITABLE_ZONE_ID, 1234 + i,
+                                        DatabaseAccessor::DIFF_ADD,
                                         "example.org.", "SOA", "3600",
                                         soa_rdata));
     }
@@ -2798,7 +2810,7 @@ TEST_F(MockDatabaseClientTest, journalBadSequence) {
         // But we miss the add SOA here
         EXPECT_THROW(updater_->addRRset(*rrset_), isc::BadValue);
         // Make sure the journal contains only the first one
-        expected.push_back(JournalEntry(READONLY_ZONE_ID, 2419200,
+        expected.push_back(JournalEntry(WRITABLE_ZONE_ID, 1234,
                                         DatabaseAccessor::DIFF_DELETE,
                                         "example.org.", "SOA", "3600",
                                         "ns1.example.org. admin.example.org. "
@@ -2812,28 +2824,30 @@ TEST_F(MockDatabaseClientTest, journalBadSequence) {
         // So far OK
         EXPECT_NO_THROW(updater_->deleteRRset(*soa_));
         // Commit at the wrong time
-        EXPECT_THROW(updater_->commit(), isc::BadValue);
+        EXPECT_THROW(updater_->commit(), isc::Unexpected);
         current_accessor_->checkJournal(expected);
     }
 
     {
         SCOPED_TRACE("Delete two SOAs");
+        updater_ = client_->getUpdater(zname_, false, true);
         // So far OK
         EXPECT_NO_THROW(updater_->deleteRRset(*soa_));
         // Delete the SOA again
-        EXPECT_THROW(updater_->addRRset(*soa_), isc::BadValue);
+        EXPECT_THROW(updater_->deleteRRset(*soa_), isc::BadValue);
         current_accessor_->checkJournal(expected);
     }
 
     {
         SCOPED_TRACE("Add two SOAs");
+        updater_ = client_->getUpdater(zname_, false, true);
         // So far OK
         EXPECT_NO_THROW(updater_->deleteRRset(*soa_));
         // Still OK
         EXPECT_NO_THROW(updater_->addRRset(*soa_));
         // But this one is added again
         EXPECT_THROW(updater_->addRRset(*soa_), isc::BadValue);
-        expected.push_back(JournalEntry(READONLY_ZONE_ID, 2419200,
+        expected.push_back(JournalEntry(WRITABLE_ZONE_ID, 1234,
                                         DatabaseAccessor::DIFF_ADD,
                                         "example.org.", "SOA", "3600",
                                         "ns1.example.org. admin.example.org. "
diff --git a/src/lib/datasrc/zone.h b/src/lib/datasrc/zone.h
index 97ab03d..107e2e1 100644
--- a/src/lib/datasrc/zone.h
+++ b/src/lib/datasrc/zone.h
@@ -552,6 +552,8 @@ public:
     ///
     /// \exception DataSourceError Duplicate call of the method,
     /// internal data source error
+    /// \exception isc::BadValue Journaling is enabled and the update is not
+    ///    complete IXFR sequence.
     virtual void commit() = 0;
 };
 
diff --git a/src/lib/dns/rdata/generic/soa_6.cc b/src/lib/dns/rdata/generic/soa_6.cc
index 7ecd84f..875a957 100644
--- a/src/lib/dns/rdata/generic/soa_6.cc
+++ b/src/lib/dns/rdata/generic/soa_6.cc
@@ -106,6 +106,12 @@ SOA::toWire(AbstractMessageRenderer& renderer) const {
     renderer.writeData(numdata_, sizeof(numdata_));
 }
 
+uint32_t
+SOA::getSerial() const {
+    InputBuffer b(numdata_, sizeof(numdata_));
+    return (b.readUint32());
+}
+
 string
 SOA::toText() const {
     InputBuffer b(numdata_, sizeof(numdata_));
diff --git a/src/lib/dns/rdata/generic/soa_6.h b/src/lib/dns/rdata/generic/soa_6.h
index 3f6185e..4c6b6ec 100644
--- a/src/lib/dns/rdata/generic/soa_6.h
+++ b/src/lib/dns/rdata/generic/soa_6.h
@@ -34,6 +34,8 @@ public:
     SOA(const Name& mname, const Name& rname, uint32_t serial,
         uint32_t refresh, uint32_t retry, uint32_t expire,
         uint32_t minimum);
+    /// \brief Returns the serial stored in the SOA.
+    uint32_t getSerial() const;
 private:
     /// Note: this is a prototype version; we may reconsider
     /// this representation later.
diff --git a/src/lib/dns/tests/rdata_soa_unittest.cc b/src/lib/dns/tests/rdata_soa_unittest.cc
index 63fe1f7..17498eb 100644
--- a/src/lib/dns/tests/rdata_soa_unittest.cc
+++ b/src/lib/dns/tests/rdata_soa_unittest.cc
@@ -74,4 +74,9 @@ TEST_F(Rdata_SOA_Test, toText) {
     EXPECT_EQ("ns.example.com. root.example.com. "
               "2010012601 3600 300 3600000 1200", rdata_soa.toText());
 }
+
+TEST_F(Rdata_SOA_Test, getSerial) {
+    EXPECT_EQ(2010012601, rdata_soa.getSerial());
+}
+
 }




More information about the bind10-changes mailing list