Browse Source

[2210] Address review comments

as discussed in the ticket comments
Jelte Jansen 12 years ago
parent
commit
3a5e410f45

+ 31 - 11
src/bin/auth/auth_messages.mes

@@ -75,28 +75,48 @@ exception type is even more unexpected.  This may rather indicate some
 run time failure than program errors, but in any case the server needs
 run time failure than program errors, but in any case the server needs
 to be restarted by hand.
 to be restarted by hand.
 
 
-% AUTH_DATASRC_CLIENTS_BUILDER_RECONFIGURE_CONFIG_ERROR Error in configuration: %1
+% AUTH_DATASRC_CLIENTS_BUILDER_RECONFIGURE_CONFIG_ERROR Error in data source configuration: %1
 The thread for maintaining data source clients has received a command to
 The thread for maintaining data source clients has received a command to
-reconfigure, but the parameter data is not in the expected format, or contains
+reconfigure, but the parameter data contains an error. This data should have
-another error. This data should have been validated, but may still contain
+been validated, but may still contain an error. The system is still running
-an error. The system is still running with the data sources from before
+with the data sources that were previously configured (i.e. as if the
-the reconfigure command, and the configuration data needs to be checked.
+configuration has not changed), and the configuration data needs to be
+checked.
 The specific problem is printed in the log message.
 The specific problem is printed in the log message.
 
 
-% AUTH_DATASRC_CLIENTS_BUILDER_RECONFIGURE_ERROR Error in configuration: %1
+% AUTH_DATASRC_CLIENTS_BUILDER_RECONFIGURE_ERROR Error in data source configuration: %1
 The thread for maintaining data source clients has received a command to
 The thread for maintaining data source clients has received a command to
 reconfigure, but raised an exception while reconfiguring. This is most
 reconfigure, but raised an exception while reconfiguring. This is most
 likely a bug in the data source, but it is probably a good idea to verify
 likely a bug in the data source, but it is probably a good idea to verify
 the configuration itself. The system is still running with the data sources
 the configuration itself. The system is still running with the data sources
-from before the reconfigure command, and the configuration data needs to be
+that were previously configured (i.e. as if the configuration has not
-checked. The specific problem is printed in the log message.
+changed), and the configuration data needs to be checked.
+The specific problem is printed in the log message.
+
+% AUTH_DATASRC_CLIENTS_BUILDER_RECONFIGURE_FORMAT_ERROR Error in data source configuration format: %1
+The thread for maintaining data source clients has received a command to
+reconfigure, but the parameter data is not in the expected format (a list of
+maps). This should have been validated, and this error is most likely to be
+a bug in the system, but it is probably a good idea to verify the
+configuration itself. The system is still running with the data sources that
+were previously configured (i.e. as if the configuration has not changed),
+and the configuration data needs to be checked.
+The specific problem is printed in the log message.
 
 
-% AUTH_DATASRC_CLIENTS_BUILDER_RECONFIGURE_UNKNOWN_ERROR Unknown uncaught exception in reconfigure
+% AUTH_DATASRC_CLIENTS_BUILDER_RECONFIGURE_STARTED data source reconfiguration started
+The thread for maintaining data source clients has received a command to
+reconfigure, and has now started this process.
+
+% AUTH_DATASRC_CLIENTS_BUILDER_RECONFIGURE_SUCCESS data source reconfiguration completed succesfully
+The thread for maintaining data source clients has finished reconfiguring
+the data source clients, and is now running with the new configuration.
+
+% AUTH_DATASRC_CLIENTS_BUILDER_RECONFIGURE_UNKNOWN_ERROR unknown uncaught exception in data source reconfigure
 The thread for maintaining data source clients has received a command to
 The thread for maintaining data source clients has received a command to
 reconfigure, but raised an unknown exception while reconfiguring. This is a
 reconfigure, but raised an unknown exception while reconfiguring. This is a
 bug in the data source. The system is still running with the data sources
 bug in the data source. The system is still running with the data sources
-from before the reconfigure command, and the configuration data needs to be
+that were previously configured (i.e. as if the configuration has not
-checked.
+changed), and the configuration data needs to be checked.
 
 
 % AUTH_DATASRC_CLIENTS_BUILDER_STARTED data source builder thread started
 % AUTH_DATASRC_CLIENTS_BUILDER_STARTED data source builder thread started
 A separate thread for maintaining data source clients has been started.
 A separate thread for maintaining data source clients has been started.

+ 31 - 12
src/bin/auth/datasrc_clients_mgr.h

@@ -47,7 +47,9 @@ namespace datasrc_clientmgr_internal {
 /// \brief ID of commands from the DataSrcClientsMgr to DataSrcClientsBuilder.
 /// \brief ID of commands from the DataSrcClientsMgr to DataSrcClientsBuilder.
 enum CommandID {
 enum CommandID {
     NOOP,         ///< Do nothing.  Only useful for tests; no argument
     NOOP,         ///< Do nothing.  Only useful for tests; no argument
-    RECONFIGURE,  ///< Reconfigure the datasource client lists, configuration argument (TODO: describe here?)
+    RECONFIGURE,  ///< Reconfigure the datasource client lists,
+                  ///  the argument to the command is the full new
+                  ///  datasources configuration.
     SHUTDOWN,     ///< Shutdown the builder; no argument
     SHUTDOWN,     ///< Shutdown the builder; no argument
     NUM_COMMANDS
     NUM_COMMANDS
 };
 };
@@ -167,8 +169,9 @@ private:
     std::list<datasrc_clientmgr_internal::Command> command_queue_;
     std::list<datasrc_clientmgr_internal::Command> command_queue_;
     CondVarType cond_;          // condition variable for queue operations
     CondVarType cond_;          // condition variable for queue operations
     MutexType queue_mutex_;     // mutex to protect the queue
     MutexType queue_mutex_;     // mutex to protect the queue
-    isc::datasrc::DataSrcClientListsPtr clients_map_;
+    datasrc::DataSrcClientListsPtr clients_map_;
-    MutexType map_mutex_;
+                                // map of actual data source client objects
+    MutexType map_mutex_;       // mutex to protect the clients map
 
 
     BuilderType builder_;
     BuilderType builder_;
     ThreadType builder_thread_; // for safety this should be placed last
     ThreadType builder_thread_; // for safety this should be placed last
@@ -204,7 +207,7 @@ public:
     /// \throw None
     /// \throw None
     DataSrcClientsBuilderBase(std::list<Command>* command_queue,
     DataSrcClientsBuilderBase(std::list<Command>* command_queue,
                               CondVarType* cond, MutexType* queue_mutex,
                               CondVarType* cond, MutexType* queue_mutex,
-                              isc::datasrc::DataSrcClientListsPtr* clients_map,
+                              datasrc::DataSrcClientListsPtr* clients_map,
                               MutexType* map_mutex
                               MutexType* map_mutex
         ) :
         ) :
         command_queue_(command_queue), cond_(cond), queue_mutex_(queue_mutex),
         command_queue_(command_queue), cond_(cond), queue_mutex_(queue_mutex),
@@ -229,17 +232,32 @@ private:
     // implementation really does nothing.
     // implementation really does nothing.
     void doNoop() {}
     void doNoop() {}
 
 
-    void doReconfigure(const isc::data::ConstElementPtr& config) {
+    void doReconfigure(const data::ConstElementPtr& config) {
         if (config) {
         if (config) {
+            LOG_INFO(auth_logger,
+                     AUTH_DATASRC_CLIENTS_BUILDER_RECONFIGURE_STARTED);
             try {
             try {
-                isc::datasrc::DataSrcClientListsPtr new_clients_map =
+                // Define new_clients_map outside of the block that
+                // has the lock scope; this way, after the swap,
+                // the lock is guaranteed to be released before
+                // the old data is destroyed, minimizing the lock
+                // duration.
+                datasrc::DataSrcClientListsPtr new_clients_map =
                     configureDataSource(config);
                     configureDataSource(config);
-                typename MutexType::Locker locker(*map_mutex_);
+                {
-                std::swap(new_clients_map, *clients_map_);
+                    typename MutexType::Locker locker(*map_mutex_);
-                // lock is released by leaving scope
+                    new_clients_map.swap(*clients_map_);
-            } catch (const isc::data::TypeError& type_error) {
+                } // lock is released by leaving scope
+                LOG_INFO(auth_logger,
+                         AUTH_DATASRC_CLIENTS_BUILDER_RECONFIGURE_SUCCESS);
+            } catch (const datasrc::ConfigurableClientList::ConfigurationError&
+                     config_error) {
                 LOG_ERROR(auth_logger,
                 LOG_ERROR(auth_logger,
                     AUTH_DATASRC_CLIENTS_BUILDER_RECONFIGURE_CONFIG_ERROR).
                     AUTH_DATASRC_CLIENTS_BUILDER_RECONFIGURE_CONFIG_ERROR).
+                    arg(config_error.what());
+            } catch (const data::TypeError& type_error) {
+                LOG_ERROR(auth_logger,
+                    AUTH_DATASRC_CLIENTS_BUILDER_RECONFIGURE_FORMAT_ERROR).
                     arg(type_error.what());
                     arg(type_error.what());
             } catch (const std::exception& exc) {
             } catch (const std::exception& exc) {
                 LOG_ERROR(auth_logger,
                 LOG_ERROR(auth_logger,
@@ -249,6 +267,7 @@ private:
                 LOG_ERROR(auth_logger,
                 LOG_ERROR(auth_logger,
                     AUTH_DATASRC_CLIENTS_BUILDER_RECONFIGURE_UNKNOWN_ERROR);
                     AUTH_DATASRC_CLIENTS_BUILDER_RECONFIGURE_UNKNOWN_ERROR);
             }
             }
+            // old clients_map_ data is released by leaving scope
         }
         }
     }
     }
 
 
@@ -256,7 +275,7 @@ private:
     std::list<Command>* command_queue_;
     std::list<Command>* command_queue_;
     CondVarType* cond_;
     CondVarType* cond_;
     MutexType* queue_mutex_;
     MutexType* queue_mutex_;
-    isc::datasrc::DataSrcClientListsPtr* clients_map_;
+    datasrc::DataSrcClientListsPtr* clients_map_;
     MutexType* map_mutex_;
     MutexType* map_mutex_;
 };
 };
 
 
@@ -282,7 +301,7 @@ DataSrcClientsBuilderBase<MutexType, CondVarType>::run() {
                 }
                 }
                 current_commands.splice(current_commands.end(),
                 current_commands.splice(current_commands.end(),
                                         *command_queue_);
                                         *command_queue_);
-            } // the lock is release here.
+            } // the lock is released here.
 
 
             while (keep_running && !current_commands.empty()) {
             while (keep_running && !current_commands.empty()) {
                 keep_running = handleCommand(current_commands.front());
                 keep_running = handleCommand(current_commands.front());

+ 2 - 1
src/bin/auth/datasrc_config.h

@@ -48,6 +48,8 @@
 /// \param config The configuration value to parse. It is in the form
 /// \param config The configuration value to parse. It is in the form
 ///     as an update from the config manager.
 ///     as an update from the config manager.
 /// \return A map from RR classes to configured lists.
 /// \return A map from RR classes to configured lists.
+/// \throw ConfigurationError if the config element is not in the expected
+///        format (A map of lists)
 template<class List>
 template<class List>
 boost::shared_ptr<std::map<isc::dns::RRClass,
 boost::shared_ptr<std::map<isc::dns::RRClass,
                            boost::shared_ptr<List> > > // = ListMap below
                            boost::shared_ptr<List> > > // = ListMap below
@@ -58,7 +60,6 @@ configureDataSourceGeneric(const isc::data::ConstElementPtr& config) {
 
 
     boost::shared_ptr<ListMap> new_lists(new ListMap);
     boost::shared_ptr<ListMap> new_lists(new ListMap);
 
 
-    // Go through the configuration and create corresponding list.
     const Map& map(config->mapValue());
     const Map& map(config->mapValue());
     for (Map::const_iterator it(map.begin()); it != map.end(); ++it) {
     for (Map::const_iterator it(map.begin()); it != map.end(); ++it) {
         const isc::dns::RRClass rrclass(it->first);
         const isc::dns::RRClass rrclass(it->first);

+ 21 - 0
src/bin/auth/tests/datasrc_clients_builder_unittest.cc

@@ -117,6 +117,18 @@ TEST_F(DataSrcClientsBuilderTest, reconfigure) {
         "}"
         "}"
     );
     );
 
 
+    // A configuration that is 'correct' in the top-level, but contains
+    // bad data for the type it specifies
+    ConstElementPtr bad_config = isc::data::Element::fromJSON(
+        "{"
+        "\"IN\": [{"
+        "   \"type\": \"MasterFiles\","
+        "   \"params\": { \"foo\": [ 1, 2, 3, 4  ]},"
+        "   \"cache-enable\": true"
+        "}]"
+        "}"
+    );
+
     reconfig_cmd.second = good_config;
     reconfig_cmd.second = good_config;
     EXPECT_TRUE(builder.handleCommand(reconfig_cmd));
     EXPECT_TRUE(builder.handleCommand(reconfig_cmd));
     EXPECT_EQ(1, clients_map->size());
     EXPECT_EQ(1, clients_map->size());
@@ -134,6 +146,15 @@ TEST_F(DataSrcClientsBuilderTest, reconfigure) {
     // Building failed, so map mutex should not have been locked again
     // Building failed, so map mutex should not have been locked again
     EXPECT_EQ(1, map_mutex.lock_count);
     EXPECT_EQ(1, map_mutex.lock_count);
 
 
+    // The same for a configuration that has bad data for the type it
+    // specifies
+    reconfig_cmd.second = bad_config;
+    builder.handleCommand(reconfig_cmd);
+    EXPECT_TRUE(builder.handleCommand(reconfig_cmd));
+    EXPECT_EQ(working_config_clients, clients_map);
+    // Building failed, so map mutex should not have been locked again
+    EXPECT_EQ(1, map_mutex.lock_count);
+
     // The same goes for an empty parameter (it should at least be
     // The same goes for an empty parameter (it should at least be
     // an empty map)
     // an empty map)
     reconfig_cmd.second = ConstElementPtr();
     reconfig_cmd.second = ConstElementPtr();