Parcourir la source

made AuthSrv::updateConfig and setDbFile exception safe.
also hid setDbFile in the implementation class because it's currently only
used internally, and it made the exception handling simpler.


git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@1270 e5f2f494-b856-4b98-b285-d166d9295462

JINMEI Tatuya il y a 15 ans
Parent
commit
82ec5fcf5d
2 fichiers modifiés avec 40 ajouts et 35 suppressions
  1. 40 34
      src/bin/auth/auth_srv.cc
  2. 0 1
      src/bin/auth/auth_srv.h

+ 40 - 34
src/bin/auth/auth_srv.cc

@@ -62,6 +62,9 @@ private:
     AuthSrvImpl& operator=(const AuthSrvImpl& source);
 public:
     AuthSrvImpl();
+
+    isc::data::ElementPtr setDbFile(const isc::data::ElementPtr config);
+
     std::string db_file_;
     isc::auth::MetaDataSrc data_sources_;
     /// We keep a pointer to the currently running sqlite datasource
@@ -131,50 +134,53 @@ AuthSrv::processMessage(InputBuffer& request_buffer,
 }
 
 ElementPtr
-AuthSrv::setDbFile(const isc::data::ElementPtr config) {
+AuthSrvImpl::setDbFile(const isc::data::ElementPtr config) {
     if (config) {
-        impl_->db_file_ = config->get("database_file")->stringValue();
-        cout << "[AuthSrv] Data source database file: " << impl_->db_file_
-             << endl;
+        db_file_ = config->get("database_file")->stringValue();
+        cout << "[AuthSrv] Data source database file: " << db_file_ << endl;
     }
 
-    try {
-        // create SQL data source
-        // config may be empty here; in that case it will load the default
-        // database file
-        Sqlite3DataSrc* sd = new Sqlite3DataSrc;
-        sd->init(config);
-
-        if (impl_->cur_datasrc_) {
-            impl_->data_sources_.removeDataSrc(impl_->cur_datasrc_);
-        }
-
-        ConstDataSrcPtr csd = ConstDataSrcPtr(sd);
-        impl_->data_sources_.addDataSrc(csd);
-        impl_->cur_datasrc_ = csd;
+    // create SQL data source
+    // config may be empty here; in that case it will load the default
+    // database file
+    // Note: the following step is tricky to be exception-safe and to ensure
+    // exception guarantee: We first need to perform all operations that can
+    // fail, while acquiring resources in the RAII manner.  We then perform
+    // delete and swap operations which should not fail.
+    DataSrcPtr datasrc_ptr(DataSrcPtr(new Sqlite3DataSrc));
+    datasrc_ptr->init(config);
+    ElementPtr answer = isc::config::createAnswer(0);
+    data_sources_.addDataSrc(datasrc_ptr);
 
-        return isc::config::createAnswer(0);
-    } catch (isc::Exception error) {
-        cout << "[AuthSrv] error: " << error.what() << endl;
-        return isc::config::createAnswer(1, error.what());
+    // The following code should be exception free.
+    if (cur_datasrc_ != NULL) {
+        data_sources_.removeDataSrc(cur_datasrc_);
     }
+    cur_datasrc_ = datasrc_ptr;
+
+    return answer;
 }
 
 ElementPtr
 AuthSrv::updateConfig(isc::data::ElementPtr new_config) {
-    ElementPtr answer = isc::config::createAnswer(0);
-    if (new_config) {
-        // the ModuleCCSession has already checked if we have
-        // the correct ElementPtr type as specified in our .spec file
-        if (new_config->contains("database_file")) {
-            answer = setDbFile(new_config);
+    try {
+        ElementPtr answer = isc::config::createAnswer(0);
+        if (new_config != NULL) {
+            // the ModuleCCSession has already checked if we have
+            // the correct ElementPtr type as specified in our .spec file
+            if (new_config->contains("database_file")) {
+                answer = impl_->setDbFile(new_config);
+            }
         }
-    }
 
-    // if we have no sqlite3 data source, use the default
-    if (impl_->cur_datasrc_ == NULL) {
-        setDbFile(ElementPtr());
-    }
+        // if we have no sqlite3 data source, use the default
+        if (impl_->cur_datasrc_ == NULL) {
+            impl_->setDbFile(ElementPtr());
+        }
     
-    return answer;
+        return answer;
+    } catch (const isc::Exception& error) {
+        cout << "[AuthSrv] error: " << error.what() << endl;
+        return isc::config::createAnswer(1, error.what());
+    }
 }

+ 0 - 1
src/bin/auth/auth_srv.h

@@ -50,7 +50,6 @@ public:
                        isc::dns::MessageRenderer& response_renderer,
                        bool udp_buffer, bool verbose_mode);
     void serve(std::string zone_name);
-    isc::data::ElementPtr setDbFile(const isc::data::ElementPtr config);
     isc::data::ElementPtr updateConfig(isc::data::ElementPtr config);
 private:
     AuthSrvImpl* impl_;