Browse Source

[1330] Basic definitions and test data complete

Stephen Morris 13 years ago
parent
commit
01b4b95b5f

+ 50 - 0
src/lib/datasrc/database.h

@@ -249,6 +249,56 @@ public:
      */
     virtual IteratorContextPtr getAllRecords(int id) const = 0;
 
+    /**
+     * \brief Creates an iterator context for a set of differences.
+     *
+     * Returns an IteratorContextPtr that contains all difference records for
+     * the given zone between two versions of a zone.
+     *
+     * The difference records are the set of records that would appear in an
+     * IXFR serving a request for the difference between two versions of a zone.
+     * The records are returned in the same order as they would be in the IXFR.
+     * This means that if the the difference between versions of a zone with SOA
+     * serial numbers of "start" and "end" is required, and the zone contains
+     * the differences between serial number "start" to serial number
+     * "intermediate" and from serial number "intermediate" to serial number
+     * "end", the returned records will be (in order):
+     *
+     * \li SOA for serial "start"
+     * \li Records removed from the zone between versions "start" and
+     *     "intermediate" of the zone.  The order of these is not guaranteed.
+     * \li SOA for serial "intermediate"
+     * \li Records added to the zone between versions "start" and
+     *     "intermediate" of the zone.  The order of these is not guaranteed.
+     * \li SOA for serial "intermediate"
+     * \li Records removed from the zone between versions "intermediate" and
+     *     "end" of the zone.  The order of these is not guaranteed.
+     * \li SOA for serial "end"
+     * \li Records added to the zone between versions "intermediate" and "end"
+     *     of the zone. The order of these is not guaranteed.
+     *
+     * Note that there is no requirement that "start" be less than "end". Owing
+     * to serial number arithmetic, it is entirely possible that a later version
+     * of a zone will have a smaller SOA serial number than an earlier version.
+     *
+     * Each call to getNext() on the returned iterator should copy all
+     * column fields of the array that is passed, as defined in the
+     * RecordColumns enum.
+     *
+     * \exception any Since any implementation can be used, the caller should
+     *                expect any exception to be thrown.
+     *
+     * \param id The ID of the zone, returned from getZone().
+     * \param start The SOA serial number of the version of the zone from
+     *        which the difference sequence should start.
+     * \param end The SOA serial number of the version of the zone at which
+     *        the difference sequence should end.
+     *
+     * \return Newly created iterator context. Must not be NULL.
+     */
+    virtual IteratorContextPtr getDiffs(int id, uint32_t start, uint32_t end)
+                                        const = 0;
+
     /// Start a transaction for updating a zone.
     ///
     /// Each derived class version of this method starts a database

+ 36 - 0
src/lib/datasrc/sqlite3_accessor.cc

@@ -526,6 +526,9 @@ private:
     const std::string name_;
 };
 
+
+// Methods to retrieve the various iterators
+
 DatabaseAccessor::IteratorContextPtr
 SQLite3Accessor::getRecords(const std::string& name, int id,
                             bool subdomains) const
@@ -539,6 +542,39 @@ SQLite3Accessor::getAllRecords(int id) const {
     return (IteratorContextPtr(new Context(shared_from_this(), id)));
 }
 
+
+/// \brief Difference Iterator
+///
+///
+
+class SQLite3Accessor::DiffContext : public DatabaseAccessor::IteratorContext {
+public:
+
+    // Construct an iterator for difference records.
+    DiffContext(const boost::shared_ptr<const SQLite3Accessor>&, int,
+                uint32_t, uint32_t)
+    {
+    }
+
+    virtual ~DiffContext() {}
+
+    virtual bool getNext(std::string (&data)[COLUMN_COUNT]) {
+        static_cast<void>(data[0]);
+        return (false);
+    }
+
+};
+
+// ... and return the iterator
+
+DatabaseAccessor::IteratorContextPtr
+SQLite3Accessor::getDiffs(int id, uint32_t start, uint32_t end) const {
+    return (IteratorContextPtr(new DiffContext(shared_from_this(), id, start,
+                               end)));
+}
+
+
+
 pair<bool, int>
 SQLite3Accessor::startUpdateZone(const string& zone_name, const bool replace) {
     if (dbparameters_->updating_zone) {

+ 41 - 2
src/lib/datasrc/sqlite3_accessor.h

@@ -46,6 +46,18 @@ public:
         isc::Exception(file, line, what) {}
 };
 
+/**
+ * \brief No such serial number when obtaining difference iterator
+ *
+ * Thrown if either the start or end version requested for the difference
+ * iterator doe nsot exist.
+ */
+class NoSuchSerial : public Exception {
+public:
+    NoSuchSerial(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) {}
+};
+
 struct SQLite3Parameters;
 
 /**
@@ -128,6 +140,27 @@ public:
      */
     virtual IteratorContextPtr getAllRecords(int id) const;
 
+    /** \brief Creates an iterator context for a set of differences.
+     *
+     * Implements the getDiffs() method from DatabaseAccessor
+     *
+     * \exception NoSuchSerial if either of the versions do not exist in
+     *            the difference table.
+     * \exception SQLite3Error if there is an sqlite3 error when performing
+     *            the query
+     *
+     * \param id The ID of the zone, returned from getZone().
+     * \param start The SOA serial number of the version of the zone from
+     *        which the difference sequence should start.
+     * \param end The SOA serial number of the version of the zone at which
+     *        the difference sequence should end.
+     *
+     * \return Iterator containing difference records.
+     */
+    virtual IteratorContextPtr getDiffs(int id, uint32_t start, uint32_t end) const;
+                                        
+
+
     virtual std::pair<bool, int> startUpdateZone(const std::string& zone_name,
                                                  bool replace);
 
@@ -175,14 +208,20 @@ private:
     const std::string filename_;
     /// \brief The class for which the queries are done
     const std::string class_;
+    /// \brief Database name
+    const std::string database_name_;
+
     /// \brief Opens the database
     void open(const std::string& filename);
     /// \brief Closes the database
     void close();
-    /// \brief SQLite3 implementation of IteratorContext
+
+    /// \brief SQLite3 implementation of IteratorContext for all records
     class Context;
     friend class Context;
-    const std::string database_name_;
+    /// \brief SQLite3 implementation of IteratorContext for differences
+    class DiffContext;
+    friend class DiffContext;
 };
 
 /// \brief Creates an instance of the SQlite3 datasource client

+ 5 - 0
src/lib/datasrc/tests/database_unittest.cc

@@ -250,6 +250,11 @@ public:
                   "This database datasource can't be iterated");
     }
 
+    virtual IteratorContextPtr getDiffs(int, uint32_t, uint32_t) const {
+        isc_throw(isc::NotImplemented,
+                  "This database datasource can't be iterated");
+    }
+
     virtual std::string findPreviousName(int, const std::string&) const {
         isc_throw(isc::NotImplemented,
                   "This data source doesn't support DNSSEC");

+ 19 - 0
src/lib/datasrc/tests/sqlite3_accessor_unittest.cc

@@ -44,6 +44,7 @@ std::string SQLITE_DBNAME_EXAMPLE_ROOT = "sqlite3_test-root.sqlite3";
 std::string SQLITE_DBFILE_BROKENDB = TEST_DATA_DIR "/brokendb.sqlite3";
 std::string SQLITE_DBFILE_MEMORY = ":memory:";
 std::string SQLITE_DBFILE_EXAMPLE_ORG = TEST_DATA_DIR "/example.org.sqlite3";
+std::string SQLITE_DBFILE_DIFFS = TEST_DATA_DIR "/diffs.sqlite3";
 
 // The following file must be non existent and must be non"creatable";
 // the sqlite3 library will try to create a new DB file if it doesn't exist,
@@ -204,6 +205,24 @@ TEST_F(SQLite3AccessorTest, iterator) {
     EXPECT_FALSE(context->getNext(data));
 }
 
+// This tests the difference iterator context
+
+// Test that at attempt to create a difference iterator for a serial that
+// does not exist throws an exception.
+
+TEST_F(SQLite3AccessorTest, diffIteratorNoVersion) {
+
+    // Our test zone is conveniently small, but not empty
+    initAccessor(SQLITE_DBFILE_DIFFS, "IN");
+
+    const std::pair<bool, int> zone_info(accessor->getZone("example.org."));
+    ASSERT_TRUE(zone_info.first);
+
+    // Get the iterator context.  Difference of version 1 does not exist.
+    EXPECT_THROW(accessor->getDiffs(zone_info.second, 1U, 1234U),
+                 NoSuchSerial);
+}
+
 TEST(SQLite3Open, getDBNameExample2) {
     SQLite3Accessor accessor(SQLITE_DBFILE_EXAMPLE2, "IN");
     EXPECT_EQ(SQLITE_DBNAME_EXAMPLE2, accessor.getDBName());

BIN
src/lib/datasrc/tests/testdata/diffs.sqlite3


+ 122 - 0
src/lib/datasrc/tests/testdata/diffs_table.sql

@@ -0,0 +1,122 @@
+-- Copyright (C) 2011  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.
+
+-- \brief Create Differences Table
+--
+-- This is a short-term solution to creating the differences table for testing
+-- purposes.
+--
+-- It is assumed that the database used is a copy of the "example.org.sqlite3"
+-- database in this test directory.  The diffs table is created and populated
+-- with a set of RRs that purport to represent differences that end in the
+-- zone as is.
+--
+-- The file can be executed by the command:
+-- % sqlite3 -init <this-file> <database-file> ".quit"
+--
+-- The file gets executed as the set of SQL statements on the database file,
+-- the ".quit" on the command line then  getting executed to exit SQLite3.
+
+-- Create the diffs table
+CREATE TABLE diffs (id INTEGER PRIMARY KEY AUTOINCREMENT,
+                    zone_id INTEGER NOT NULL,
+                    version INTEGER NOT NULL,
+                    operation INTEGER NOT NULL,
+                    name STRING NOT NULL COLLATE NOCASE,
+                    rrtype STRING NOT NULL COLLATE NOCASE,
+                    ttl INTEGER NOT NULL,
+                    rdata STRING NOT NULL);
+
+-- Populate it.  A dummy zone_id is used for now - this will be updated last of
+-- all.
+
+-- Change from 4294967280 (0xfffffff0) to 1230 to show serial rollover
+-- Update one record in the zone.
+INSERT INTO diffs(zone_id, version, operation, name, rrtype, ttl, rdata)
+    VALUES(1, 4294967280,  0, "example.org.", "SOA", 3600,
+           "ns1.example.org. admin.example.org. 4294967280 3600 1800 2419200, 7200");
+INSERT INTO diffs(zone_id, version, operation, name, rrtype, ttl, rdata)
+    VALUES(1, 4294967280, 0, "www.example.org.", "A", 3600, "192.0.2.31");
+
+-- Records added in version 1230 of the zone
+INSERT INTO diffs(zone_id, version, operation, name, rrtype, ttl, rdata)
+    VALUES(1, 1230, 1, "example.org.", "SOA", 3600,
+           "ns1.example.org. admin.example.org. 1230 3600 1800 2419200, 7200");
+INSERT INTO diffs(zone_id, version, operation, name, rrtype, ttl, rdata)
+    VALUES(1, 1230, 1, "www.example.org.", "A", 3600, "192.0.2.21");
+
+-- Change 1230 to 1231: Change change a parameter of the SOA record
+-- Records removed from version 1230 of the zone
+INSERT INTO diffs(zone_id, version, operation, name, rrtype, ttl, rdata)
+    VALUES(1, 1230, 0, "example.org.", "SOA", 1800,
+           "ns1.example.org. admin.example.org. 1230 3600 1800 2419200, 7200");
+
+-- Records added in version 1231 of the zone
+INSERT INTO diffs(zone_id, version, operation, name, rrtype, ttl, rdata)
+    VALUES(1, 1231, 1, "example.org.", "SOA", 3600,
+           "ns1.example.org. admin.example.org. 1231 3600 1800 2419200, 7200");
+
+
+-- Change 1231 to 1232: Remove one record, don't add anything.
+-- Records removed from version 1231 of the zone
+INSERT INTO diffs(zone_id, version, operation, name, rrtype, ttl, rdata)
+    VALUES(1, 1231, 0, "example.org.", "SOA", 3600,
+           "ns1.example.org. admin.example.org. 1231 3600 1800 2419200, 7200");
+INSERT INTO diffs(zone_id, version, operation, name, rrtype, ttl, rdata)
+    VALUES(1, 1231, 0, "unused.example.org.", "A", 3600, "192.0.2.102");
+
+-- Records added in version 1232 of the zone
+INSERT INTO diffs(zone_id, version, operation, name, rrtype, ttl, rdata)
+    VALUES(1, 1232, 1, "example.org.", "SOA", 3600,
+           "ns1.example.org. admin.example.org. 1232 3600 1800 2419200, 7200");
+
+-- Change 1232 to 1233: Add two, don't remove anything.
+-- Records removed from version 1232 of the zone
+INSERT INTO diffs(zone_id, version, operation, name, rrtype, ttl, rdata)
+    VALUES(1, 1232, 0, "example.org.", "SOA", 3600,
+           "ns1.example.org. admin.example.org. 1232 3600 1800 2419200, 7200");
+
+-- Records added in version 1233 of the zone
+INSERT INTO diffs(zone_id, version, operation, name, rrtype, ttl, rdata)
+    VALUES(1, 1233, 1, "example.org.", "SOA", 3600,
+           "ns1.example.org. admin.example.org. 1233 3600 1800 2419200, 7200");
+INSERT INTO diffs(zone_id, version, operation, name, rrtype, ttl, rdata)
+    VALUES(1, 1233, 1, "sub.example.org.", "NS", 3600, "ns.sub.example.org.");
+INSERT INTO diffs(zone_id, version, operation, name, rrtype, ttl, rdata)
+    VALUES(1, 1233, 1, "ns.sub.example.org.", "A", 3600, "192.0.2.101");
+
+
+-- Change 1233 to 1234: change addresses of two A records
+-- Records removed from version 1233 of the zone
+INSERT INTO diffs(zone_id, version, operation, name, rrtype, ttl, rdata)
+    VALUES(1, 1233, 0, "example.org.", "SOA", 3600,
+           "ns1.example.org. admin.example.org. 1233 3600 1800 2419200, 7200");
+INSERT INTO diffs(zone_id, version, operation, name, rrtype, ttl, rdata)
+    VALUES(1, 1233, 0, "www.example.org.", "A", 3600, "192.0.2.21");
+INSERT INTO diffs(zone_id, version, operation, name, rrtype, ttl, rdata)
+    VALUES(1, 1233, 0, "mail.example.org.", "A", 3600, "192.0.2.210");
+
+-- Records added in version 1234 of the zone
+INSERT INTO diffs(zone_id, version, operation, name, rrtype, ttl, rdata)
+    VALUES(1, 1234, 1, "example.org.", "SOA", 3600,
+           "ns1.example.org. admin.example.org. 1234 3600 1800 2419200, 7200");
+INSERT INTO diffs(zone_id, version, operation, name, rrtype, ttl, rdata)
+    VALUES(1, 1234, 1, "www.example.org.", "A", 3600, "192.0.2.1");
+INSERT INTO diffs(zone_id, version, operation, name, rrtype, ttl, rdata)
+    VALUES(1, 1234, 1, "mail.example.org.", "A", 3600, "192.0.2.10");
+
+-- Finally, update the zone_id in the diffs table with what is actually
+-- in the zone table.
+UPDATE diffs SET zone_id =
+   (SELECT id FROM ZONES LIMIT 1);