Browse Source

[2440] generalize the merge-start initialization using RdataReader.

JINMEI Tatuya 12 years ago
parent
commit
42a5732b72

+ 48 - 23
src/lib/datasrc/memory/rdata_serialization.cc

@@ -387,7 +387,7 @@ struct RdataEncoder::RdataEncoderImpl {
                          old_varlen_count_(0), old_sig_count_(0),
                          old_data_len_(0), old_sig_len_(0),
                          old_length_fields_(NULL), old_data_(NULL),
-                         old_sig_data_(NULL),
+                         old_sig_data_(NULL), olddata_buffer_(0),
                          rdatas_(boost::bind(RdataLess, _1, _2)),
                          rrsigs_(boost::bind(RdataLess, _1, _2))
     {}
@@ -431,6 +431,7 @@ struct RdataEncoder::RdataEncoderImpl {
     const void* old_length_fields_;
     const void* old_data_;
     const void* old_sig_data_;
+    util::OutputBuffer olddata_buffer_;
 
     // Temporary storage of Rdata and RRSIGs to be encoded.  They are used
     // to detect and ignore duplicate data.
@@ -455,37 +456,61 @@ RdataEncoder::start(RRClass rrclass, RRType rrtype) {
     impl_->start(rrclass, rrtype);
 }
 
+namespace {
+void
+decodeName(const LabelSequence& name_labels, RdataNameAttributes,
+           util::OutputBuffer* buffer, size_t* total_len)
+{
+    size_t name_dlen;
+    const uint8_t* name_data = name_labels.getData(&name_dlen);
+    buffer->writeData(name_data, name_dlen);
+    *total_len += name_labels.getSerializedLength();
+}
+
+void
+decodeData(const void* data, size_t data_len, util::OutputBuffer* buffer,
+           size_t* total_len)
+{
+    buffer->writeData(data, data_len);
+    *total_len += data_len;
+}
+}
+
 void
 RdataEncoder::start(RRClass rrclass, RRType rrtype, const void* old_data,
                     size_t old_rdata_count, size_t old_sig_count)
 {
     impl_->start(rrclass, rrtype);
 
-    // hardcode for initial test
-    assert(old_rdata_count == 1);
-    assert(old_sig_count == 0 || old_sig_count == 1);
     const uint8_t* cp = static_cast<const uint8_t*>(old_data);
+    impl_->old_varlen_count_ =
+        impl_->encode_spec_->varlen_count * old_rdata_count;
+    if (impl_->old_varlen_count_ > 0 || old_sig_count > 0) {
+        impl_->old_length_fields_ = cp;
+        cp += (impl_->old_varlen_count_ + old_sig_count) * sizeof(uint16_t);
+    }
+    impl_->old_data_ = cp;
     impl_->old_sig_count_ = old_sig_count;
-    if (rrtype == RRType::A()) {
-        impl_->old_data_ = cp + (old_sig_count * sizeof(uint16_t));
-        impl_->old_data_len_ = 4;
-        if (old_sig_count > 0) {
-            impl_->old_length_fields_ = old_data;
-            impl_->old_sig_len_ =
-                static_cast<const uint16_t*>(impl_->old_length_fields_)[0];
-        }
-    } else {
-        impl_->old_varlen_count_ = 1;
-        impl_->old_length_fields_ = old_data;
-        impl_->old_data_ = cp +
-            (1 + old_sig_count) * sizeof(uint16_t);
-        impl_->old_data_len_ =
-            static_cast<const uint16_t*>(impl_->old_length_fields_)[0];
-        if (old_sig_count > 0) {
-            impl_->old_sig_len_ =
-                static_cast<const uint16_t*>(impl_->old_length_fields_)[1];
-        }
+
+    size_t total_len = 0;
+    RdataReader reader(rrclass, rrtype, old_data, old_rdata_count,
+                       old_sig_count,
+                       boost::bind(decodeName, _1, _2, &impl_->olddata_buffer_,
+                                   &total_len),
+                       boost::bind(decodeData, _1, _2, &impl_->olddata_buffer_,
+                                   &total_len));
+    for (size_t i = 0; i < old_rdata_count; ++i) {
+        impl_->olddata_buffer_.clear();
+        reader.iterateRdata();
+    }
+    impl_->old_data_len_ = total_len;
+
+    total_len = 0;
+    for (size_t i = 0; i < old_sig_count; ++i) {
+        impl_->olddata_buffer_.clear();
+        reader.iterateSingleSig();
     }
+    impl_->old_sig_len_ = total_len;
 }
 
 void

+ 70 - 29
src/lib/datasrc/tests/memory/rdata_serialization_unittest.cc

@@ -852,42 +852,74 @@ TEST_F(RdataSerializationTest, badAddRdata) {
                  isc::BadValue);
 }
 
+struct MergeTestData {
+    const char* const type_txt; // "AAAA", "NS", etc
+    const char* const rdata_txt1;
+    const char* const rdata_txt2;
+    const char* const rdata_txt3;
+    const size_t varlen_fields; // number of variable-len fields in RDATA
+} merge_test_data[] = {
+    // For test with fixed-length RDATA
+    {"A", "192.0.2.53", "192.0.2.54", "192.0.2.55", 0},
+    // For test with variable-length RDATA
+    {"TXT", "foo bar baz", "another text data", "yet another", 1},
+    // For test with RDATA containing domain name
+    {"MX", "5 mx1.example.com.", "10 mx2.example.com.", "20 mx.example.", 0},
+    {NULL, NULL, NULL, NULL, 0}
+};
+
 template<class DecoderStyle>
 void
 RdataEncodeDecodeTest<DecoderStyle>::
 mergeRdataCommon(const vector<ConstRdataPtr>& old_rrsigs,
                  const vector<ConstRdataPtr>& rrsigs)
 {
-    // Test with fixed-length old RDATA
-    rdata_list_.clear();
-    rdata_list_.push_back(a_rdata_);
-    checkEncode(RRClass::IN(), RRType::A(), rdata_list_, 0, old_rrsigs);
-    vector<uint8_t> old_encoded_data = encoded_data_;
-
-    ConstRdataPtr a_rdata2 = createRdata(RRType::A(), RRClass::IN(),
-                                         "192.0.2.54");
-    rdata_list_.push_back(a_rdata2);
-    vector<ConstRdataPtr> rrsigs_all = old_rrsigs;
-    rrsigs_all.insert(rrsigs_all.end(), rrsigs.begin(), rrsigs.end());
-    checkEncode(RRClass::IN(), RRType::A(), rdata_list_, 0, rrsigs_all,
-                &old_encoded_data[0], 1, old_rrsigs.size());
-
-    // Test with variable-length old RDATA
-    rdata_list_.clear();
-    rrsigs_all.clear();
-    ConstRdataPtr txt_rdata1 = createRdata(RRType::TXT(), RRClass::IN(),
-                                           "foo bar baz");
-    rdata_list_.push_back(txt_rdata1);
-    checkEncode(RRClass::IN(), RRType::TXT(), rdata_list_, 1, old_rrsigs);
-    old_encoded_data = encoded_data_;
+    const RRClass rrclass(RRClass::IN()); // class is fixed in the test
+    vector<uint8_t> old_encoded_data;
+    vector<ConstRdataPtr> rrsigs_all;
+
+    for (const MergeTestData* data = merge_test_data;
+         data->type_txt;
+         ++data) {
+        const RRType rrtype(data->type_txt);
+
+        for (int mode = 0; mode < 3; ++mode) {
+            bool multi_old = false;
+            bool multi_new = false;
+            if (mode == 1) {
+                multi_old = true;
+            } else if (mode == 2) {
+                multi_new = true;
+            }
 
-    ConstRdataPtr txt_rdata2 = createRdata(RRType::TXT(), RRClass::IN(),
-                                          "another text data");
-    rdata_list_.push_back(txt_rdata2);
-    rrsigs_all = old_rrsigs;
-    rrsigs_all.insert(rrsigs_all.end(), rrsigs.begin(), rrsigs.end());
-    checkEncode(RRClass::IN(), RRType::TXT(), rdata_list_, 1, rrsigs_all,
-                &old_encoded_data[0], 1, old_rrsigs.size());
+            // Encode the old data
+            rdata_list_.clear();
+            rdata_list_.push_back(createRdata(rrtype, rrclass,
+                                              data->rdata_txt1));
+            if (multi_old) {
+                rdata_list_.push_back(createRdata(rrtype, rrclass,
+                                                  data->rdata_txt3));
+            }
+            checkEncode(RRClass::IN(), RRType(data->type_txt), rdata_list_,
+                        data->varlen_fields, old_rrsigs);
+            old_encoded_data = encoded_data_; // make a copy of the data
+
+            // Prepare new data.  rrsigs_all is set to "old_rrsigs + rrsigs".
+            // Then check the behavior in the "merge" mode.
+            const size_t old_rdata_count = rdata_list_.size();
+            rdata_list_.push_back(createRdata(rrtype, rrclass,
+                                              data->rdata_txt2));
+            if (multi_new) {
+                rdata_list_.push_back(createRdata(rrtype, rrclass,
+                                                  data->rdata_txt3));
+            }
+            rrsigs_all = old_rrsigs;
+            rrsigs_all.insert(rrsigs_all.end(), rrsigs.begin(), rrsigs.end());
+            checkEncode(rrclass, rrtype, rdata_list_, data->varlen_fields,
+                        rrsigs_all, &old_encoded_data[0], old_rdata_count,
+                        old_rrsigs.size());
+        }
+    }
 }
 
 TYPED_TEST(RdataEncodeDecodeTest, mergeRdata) {
@@ -912,6 +944,15 @@ TYPED_TEST(RdataEncodeDecodeTest, mergeRdata) {
                                  "A 5 2 3600 20120814220826 "
                                  "20120715220826 54321 com. FAKE"));
     this->mergeRdataCommon(old_rrsigs, rrsigs);
+
+    // Tests with multiple old RRSIGs.
+    rrsigs.clear();
+    old_rrsigs.clear();
+    old_rrsigs.push_back(this->rrsig_rdata_);
+    old_rrsigs.push_back(createRdata(RRType::RRSIG(), RRClass::IN(),
+                                     "A 5 2 3600 20120814220826 "
+                                     "20120715220826 54321 com. FAKE"));
+    this->mergeRdataCommon(old_rrsigs, rrsigs);
 }
 
 void