Parcourir la source

[1891] implemented addNSEC3RecordToZone, 1st step.

defined a new statement for updating the nsec3 table, and used it from
addNSEC3RecordToZone.  some validation checks are still missing.
also made simple cleanup of removing unnecessary namespace qualifiers.
JINMEI Tatuya il y a 13 ans
Parent
commit
7aac25a59b

+ 14 - 8
src/lib/datasrc/sqlite3_accessor.cc

@@ -73,7 +73,8 @@ enum StatementID {
     NSEC3 = 16,
     NSEC3_PREVIOUS = 17,
     NSEC3_LAST = 18,
-    NUM_STATEMENTS = 19
+    ADD_NSEC3_RECORD = 19,
+    NUM_STATEMENTS = 20
 };
 
 const char* const text_statements[NUM_STATEMENTS] = {
@@ -135,19 +136,22 @@ const char* const text_statements[NUM_STATEMENTS] = {
         "WHERE zone_id=?1 AND id>=?2 and id<=?3 "
         "ORDER BY id ASC",
 
-    // Query to get the NSEC3 records
+    // NSEC3: Query to get the NSEC3 records
     //
     // The "1" in SELECT is for positioning the rdata column to the
     // expected position, so we can reuse the same code as for other
     // lookups.
     "SELECT rdtype, ttl, 1, rdata FROM nsec3 WHERE zone_id=?1 AND "
         "hash=?2",
-    // For getting the previous NSEC3 hash
+    // NSEC3_PREVIOUS: For getting the previous NSEC3 hash
     "SELECT DISTINCT hash FROM nsec3 WHERE zone_id=?1 AND hash < ?2 "
         "ORDER BY hash DESC LIMIT 1",
-    // And for wrap-around
+    // NSEC3_LAST: And for wrap-around
     "SELECT DISTINCT hash FROM nsec3 WHERE zone_id=?1 "
         "ORDER BY hash DESC LIMIT 1",
+    // ADD_NSEC3_RECORD: Add NSEC3-related (NSEC3 or NSEC3-covering RRSIG) RR
+    "INSERT INTO nsec3 (zone_id, hash, owner, ttl, rdtype, rdata) "
+    "VALUES (?1, ?2, '', ?3, ?4, ?5)"
 };
 
 struct SQLite3Parameters {
@@ -1128,15 +1132,17 @@ SQLite3Accessor::addRecordToZone(const string (&columns)[ADD_COLUMN_COUNT]) {
         isc_throw(DataSourceError, "adding record to SQLite3 "
                   "data source without transaction");
     }
-    doUpdate<const string (&)[DatabaseAccessor::ADD_COLUMN_COUNT]>(
+    doUpdate<const string (&)[ADD_COLUMN_COUNT]>(
         *dbparameters_, ADD_RECORD, columns, "add record to zone");
 }
 
 void
 SQLite3Accessor::addNSEC3RecordToZone(
-    const string (&/*columns*/)[ADD_NSEC3_COLUMN_COUNT])
+    const string (&columns)[ADD_NSEC3_COLUMN_COUNT])
 {
-    isc_throw(NotImplemented, "not yet implemented");
+    // TODO: no transaction case
+    doUpdate<const string (&)[ADD_NSEC3_COLUMN_COUNT]>(
+        *dbparameters_, ADD_NSEC3_RECORD, columns, "add NSEC3 record to zone");
 }
 
 void
@@ -1145,7 +1151,7 @@ SQLite3Accessor::deleteRecordInZone(const string (&params)[DEL_PARAM_COUNT]) {
         isc_throw(DataSourceError, "deleting record in SQLite3 "
                   "data source without transaction");
     }
-    doUpdate<const string (&)[DatabaseAccessor::DEL_PARAM_COUNT]>(
+    doUpdate<const string (&)[DEL_PARAM_COUNT]>(
         *dbparameters_, DEL_RECORD, params, "delete record from zone");
 }
 

+ 80 - 8
src/lib/datasrc/tests/sqlite3_accessor_unittest.cc

@@ -12,8 +12,7 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
-#include <algorithm>
-#include <vector>
+#include "faked_nsec3.h"
 
 #include <datasrc/sqlite3_accessor.h>
 
@@ -21,14 +20,20 @@
 
 #include <dns/rrclass.h>
 
+#include <sqlite3.h>
+
 #include <gtest/gtest.h>
+
 #include <boost/lexical_cast.hpp>
 #include <boost/scoped_ptr.hpp>
+
+#include <algorithm>
+#include <vector>
 #include <fstream>
-#include <sqlite3.h>
 
 using namespace std;
 using namespace isc::datasrc;
+using namespace isc::datasrc::test;
 using boost::lexical_cast;
 using isc::data::ConstElementPtr;
 using isc::data::Element;
@@ -463,11 +468,11 @@ TEST(SQLite3Open, getDBNameExampleROOT) {
 // Simple function to match records
 void
 checkRecordRow(const std::string columns[],
-               const std::string& field0,
-               const std::string& field1,
-               const std::string& field2,
-               const std::string& field3,
-               const std::string& field4)
+               const std::string& field0, // for type
+               const std::string& field1, // for TTL
+               const std::string& field2, // for "sigtype"
+               const std::string& field3, // for rdata
+               const std::string& field4) // for name
 {
     EXPECT_EQ(field0, columns[DatabaseAccessor::TYPE_COLUMN]);
     EXPECT_EQ(field1, columns[DatabaseAccessor::TTL_COLUMN]);
@@ -736,6 +741,18 @@ const char* const deleted_data[] = {
     // Existing data to be removed commonly used by some of the tests below
     "foo.bar.example.com.", "A", "192.0.2.1"
 };
+const char* const nsec3_data[DatabaseAccessor::ADD_NSEC3_COLUMN_COUNT] = {
+    // example NSEC parameters.  Using "apex_hash" just as a convenient
+    // shortcut; otherwise it has nothing to do with the zone apex for the
+    // purpose of this test.
+    apex_hash, "3600", "NSEC3",
+    "1 1 12 AABBCCDD 2T7B4G4VSA5SMI47K61MV5BV1A22BOJR NS SOA"
+};
+const char* const nsec3_sig_data[DatabaseAccessor::ADD_NSEC3_COLUMN_COUNT] = {
+    ns1_hash, "3600", "RRSIG",
+    "NSEC3 5 3 3600 20000101000000 20000201000000 12345 "
+    "example.com. FAKEFAKEFAKE"
+};
 
 class SQLite3Update : public SQLite3AccessorTest {
 protected:
@@ -762,6 +779,7 @@ protected:
     int zone_id;
     std::string get_columns[DatabaseAccessor::COLUMN_COUNT];
     std::string add_columns[DatabaseAccessor::ADD_COLUMN_COUNT];
+    std::string add_nsec3_columns[DatabaseAccessor::ADD_NSEC3_COLUMN_COUNT];
     std::string del_params[DatabaseAccessor::DEL_PARAM_COUNT];
     std::string diff_params[DatabaseAccessor::DIFF_PARAM_COUNT];
 
@@ -789,6 +807,28 @@ checkRecords(SQLite3Accessor& accessor, int zone_id, const std::string& name,
     EXPECT_TRUE(it == expected_rows.end());
 }
 
+// Similar to the previous one, but checking transactions on the nsec3 table.
+void
+checkNSEC3Records(SQLite3Accessor& accessor, int zone_id,
+                  const std::string& hash,
+                  vector<const char* const*> expected_rows)
+{
+    DatabaseAccessor::IteratorContextPtr iterator =
+        accessor.getNSEC3Records(hash, zone_id);
+    std::string columns[DatabaseAccessor::COLUMN_COUNT];
+    vector<const char* const*>::const_iterator it = expected_rows.begin();
+    while (iterator->getNext(columns)) {
+        ASSERT_TRUE(it != expected_rows.end());
+        checkRecordRow(columns, (*it)[DatabaseAccessor::ADD_NSEC3_TYPE],
+                       (*it)[DatabaseAccessor::ADD_NSEC3_TTL],
+                       "",      // sigtype, should always be empty
+                       (*it)[DatabaseAccessor::ADD_NSEC3_RDATA],
+                       "");     // name, always empty
+        ++it;
+    }
+    EXPECT_TRUE(it == expected_rows.end());
+}
+
 TEST_F(SQLite3Update, emptyUpdate) {
     // If we do nothing between start and commit, the zone content
     // should be intact.
@@ -924,6 +964,38 @@ TEST_F(SQLite3Update, addRecord) {
     checkRecords(*accessor, zone_id, "newdata.example.com.", expected_stored);
 }
 
+TEST_F(SQLite3Update, addNSEC3Record) {
+    // Similar to the previous test, but for NSEC3-related records
+    checkRecords(*accessor, zone_id, apex_hash, empty_stored);
+    checkRecords(*accessor, zone_id, ns1_hash, empty_stored);
+
+    zone_id = accessor->startUpdateZone("example.com.", false).second;
+    // Add an NSEC3
+    copy(nsec3_data, nsec3_data + DatabaseAccessor::ADD_NSEC3_COLUMN_COUNT,
+         add_nsec3_columns);
+    accessor->addNSEC3RecordToZone(add_nsec3_columns);
+    // Add an RRSIG for NSEC3
+    copy(nsec3_sig_data,
+         nsec3_sig_data + DatabaseAccessor::ADD_NSEC3_COLUMN_COUNT,
+         add_nsec3_columns);
+    accessor->addNSEC3RecordToZone(add_nsec3_columns);
+
+    // Check the stored data, before and after commit().
+    for (size_t i = 0; i < 2; ++i) {
+        expected_stored.clear();
+        expected_stored.push_back(nsec3_data);
+        checkNSEC3Records(*accessor, zone_id, apex_hash, expected_stored);
+
+        expected_stored.clear();
+        expected_stored.push_back(nsec3_sig_data);
+        checkNSEC3Records(*accessor, zone_id, ns1_hash, expected_stored);
+
+        if (i == 0) {          // make sure commit() happens only once
+            accessor->commit();
+        }
+    }
+}
+
 TEST_F(SQLite3Update, addThenRollback) {
     zone_id = accessor->startUpdateZone("example.com.", false).second;
     copy(new_data, new_data + DatabaseAccessor::ADD_COLUMN_COUNT,