Browse Source

[2378] The copy mode of ZoneLoader

At least its basic version. Error handling must still be tested and done.
Michal 'vorner' Vaner 12 years ago
parent
commit
c2d2a53b14

+ 8 - 6
src/lib/datasrc/tests/zone_loader_unittest.cc

@@ -140,24 +140,26 @@ protected:
 
 // Use the loader to load an unsigned zone.
 TEST_F(ZoneLoaderTest, copyUnsigned) {
-    prepareSource(Name("example.org"), "example.org");
-    ZoneLoader loader(destination_client_, Name("example.org"),
+    prepareSource(Name::ROOT_NAME(), "root.zone");
+    ZoneLoader loader(destination_client_, Name::ROOT_NAME(),
                       source_client_);
     // It gets the updater directly in the constructor
     ASSERT_EQ(1, destination_client_.provided_updaters_.size());
-    EXPECT_EQ(Name("example.org"), destination_client_.provided_updaters_[0]);
+    EXPECT_EQ(Name::ROOT_NAME(), destination_client_.provided_updaters_[0]);
     // Now load the whole zone
     loader.load();
     EXPECT_TRUE(destination_client_.commit_called_);
     // We don't check the whole zone. We check the first and last and the
     // count, which should be enough.
-    EXPECT_EQ(7, destination_client_.rrsets_.size());
+
+    // The count is 34 because we expect the RRs to be separated.
+    EXPECT_EQ(34, destination_client_.rrsets_.size());
     // Ensure known order.
     std::sort(destination_client_.rrsets_.begin(),
               destination_client_.rrsets_.end());
-    EXPECT_EQ("TODO - check manually and copy-paste",
+    EXPECT_EQ(". 518400 IN NS a.root-servers.net.\n",
               destination_client_.rrsets_.front());
-    EXPECT_EQ("TODO - check manually and copy-paste",
+    EXPECT_EQ("m.root-servers.net. 3600000 IN AAAA 2001:dc3::35\n",
               destination_client_.rrsets_.back());
 }
 

+ 70 - 0
src/lib/datasrc/zone_loader.cc

@@ -13,3 +13,73 @@
 // PERFORMANCE OF THIS SOFTWARE.
 
 #include <datasrc/zone_loader.h>
+
+#include <datasrc/client.h>
+#include <datasrc/data_source.h>
+#include <datasrc/iterator.h>
+#include <datasrc/zone.h>
+
+#include <dns/rrset.h>
+
+using isc::dns::Name;
+using isc::dns::ConstRRsetPtr;
+
+namespace isc {
+namespace datasrc {
+
+ZoneLoader::ZoneLoader(DataSourceClient& destination, const Name& zone_name,
+                       DataSourceClient& source) :
+    // Separate the RRsets as that is possibly faster (the data source doesn't
+    // have to aggregate them) and also because our limit semantics.
+    iterator_(source.getIterator(zone_name, true)),
+    updater_(destination.getUpdater(zone_name, true, false))
+{
+    // The getIterator should never return NULL. So we check it.
+    // Or should we throw instead?
+    assert(iterator_ != ZoneIteratorPtr());
+    // In case the zone doesn't exist in the destination, throw
+    if (updater_ == ZoneUpdaterPtr()) {
+        isc_throw(DataSourceError, "Zone " << zone_name << " not found in "
+                  "destination data source, can't fill it with data");
+    }
+}
+
+namespace {
+
+// Copy up to limit RRsets from source to destination
+bool
+copyRRsets(const ZoneUpdaterPtr& destination, const ZoneIteratorPtr& source,
+           size_t limit)
+{
+    size_t loaded = 0;
+    while (loaded < limit) {
+        const ConstRRsetPtr rrset(source->getNextRRset());
+        if (rrset == ConstRRsetPtr()) {
+            // Done loading, no more RRsets in the input.
+            return (true);
+        } else {
+            destination->addRRset(*rrset);
+        }
+        ++loaded;
+    }
+    return (false); // Not yet, there may be more
+}
+
+}
+
+bool
+ZoneLoader::loadIncremental(size_t limit) {
+    if (iterator_ != ZoneIteratorPtr()) {
+        if (copyRRsets(updater_, iterator_, limit)) {
+            updater_->commit();
+            return (true);
+        } else {
+            return (false);
+        }
+    } else {
+        isc_throw(isc::NotImplemented, "The master file way is not ready yet");
+    }
+}
+
+}
+}

+ 12 - 2
src/lib/datasrc/zone_loader.h

@@ -16,6 +16,7 @@
 #define DATASRC_ZONE_LOADER_H
 
 #include <cstdlib> // For size_t
+#include <boost/shared_ptr.hpp>
 
 namespace isc {
 namespace dns {
@@ -24,8 +25,12 @@ class Name;
 }
 namespace datasrc {
 
-// Forward declaration
+// Forward declarations
 class DataSourceClient;
+class ZoneIterator;
+typedef boost::shared_ptr<ZoneIterator> ZoneIteratorPtr;
+class ZoneUpdater;
+typedef boost::shared_ptr<ZoneUpdater> ZoneUpdaterPtr;
 
 /// \brief Class to load data into a data source client.
 ///
@@ -85,7 +90,7 @@ public:
     ///     before this call.
     /// \throw DataSourceError in case some error (possibly low-level) happens.
     void load() {
-        while (~loadIncremental(1000)) { // 1000 is arbitrary largish number
+        while (!loadIncremental(1000)) { // 1000 is arbitrary largish number
             // Body intentionally left blank.
         }
     }
@@ -109,6 +114,11 @@ public:
     ///     true).
     /// \throw DataSourceError in case some error (possibly low-level) happens.
     bool loadIncremental(size_t limit);
+private:
+    /// \brief The iterator used as source of data in case of the copy mode.
+    const ZoneIteratorPtr iterator_;
+    /// \brief The destination zone updater
+    const ZoneUpdaterPtr updater_;
 };
 
 }