Browse Source

[2207] Provide strong exception guarantee

Michal 'vorner' Vaner 12 years ago
parent
commit
84e0dc1be1

+ 3 - 3
src/lib/datasrc/memory/zone_writer_local.cc

@@ -48,7 +48,6 @@ ZoneWriterLocal::load() {
     if (loaded_) {
         isc_throw(isc::Unexpected, "Trying to load twice");
     }
-    loaded_ = true;
 
     zone_data_ = load_action_(segment_->getMemorySegment());
 
@@ -57,6 +56,7 @@ ZoneWriterLocal::load() {
         isc_throw(isc::Unexpected, "No data returned from load action");
     }
 
+    loaded_ = true;
     data_ready_ = true;
 }
 
@@ -66,7 +66,6 @@ ZoneWriterLocal::install() {
         isc_throw(isc::Unexpected, "No data to install");
     }
 
-    data_ready_ = false;
 
     ZoneTable* table(segment_->getHeader().getTable());
     if (table == NULL) {
@@ -75,17 +74,18 @@ ZoneWriterLocal::install() {
     ZoneTable::AddResult result(table->addZone(segment_->getMemorySegment(),
                                                rrclass_, origin_, zone_data_));
 
+    data_ready_ = false;
     zone_data_ = result.zone_data;
 }
 
 void
 ZoneWriterLocal::cleanup() {
     // We eat the data (if any) now.
-    data_ready_ = false;
 
     if (zone_data_ != NULL) {
         ZoneData::destroy(segment_->getMemorySegment(), zone_data_, rrclass_);
         zone_data_ = NULL;
+        data_ready_ = false;
     }
 }
 

+ 1 - 2
src/lib/datasrc/memory/zone_writer_local.h

@@ -42,7 +42,7 @@ public:
     /// \param install_action The callback used to install the loaded zone.
     /// \param rrclass The class of the zone.
     ZoneWriterLocal(ZoneTableSegment* segment, const LoadAction& load_action,
-                      const dns::Name& name, const dns::RRClass& rrclass);
+                    const dns::Name& name, const dns::RRClass& rrclass);
 
     /// \brief Destructor
     ~ZoneWriterLocal();
@@ -65,7 +65,6 @@ public:
     /// \throw isc::Unexpected if it is called the second time in lifetime
     ///     of the object or if load() was not called previously or if
     ///     cleanup() was already called.
-    /// \throw Whatever the install_action throws, it is propagated up.
     virtual void install();
 
     /// \brief Clean up memory.

+ 15 - 0
src/lib/datasrc/tests/memory/zone_writer_unittest.cc

@@ -190,6 +190,21 @@ TEST_F(ZoneWriterLocalTest, loadThrows) {
     EXPECT_NO_THROW(writer_->cleanup());
 }
 
+// Check the strong exception guarantee - if it throws, nothing happened
+// to the content.
+TEST_F(ZoneWriterLocalTest, retry) {
+    load_throw_ = true;
+    EXPECT_THROW(writer_->load(), TestException);
+
+    load_called_ = load_throw_ = false;
+    EXPECT_NO_THROW(writer_->load());
+    EXPECT_TRUE(load_called_);
+
+    // The rest still works correctly
+    EXPECT_NO_THROW(writer_->install());
+    EXPECT_NO_THROW(writer_->cleanup());
+}
+
 // Check the writer defends itsefl when load action returns NULL
 TEST_F(ZoneWriterLocalTest, loadNull) {
     load_null_ = true;