Browse Source

[2211] added reconfigure() for DataSrcClientsMgr

JINMEI Tatuya 12 years ago
parent
commit
eb90dff94f

+ 18 - 0
src/bin/auth/datasrc_clients_mgr.h

@@ -142,6 +142,24 @@ public:
         cleanup();              // see below
         cleanup();              // see below
     }
     }
 
 
+    /// \brief Handle new full configuration for data source clients.
+    ///
+    /// This method simply passes the new configuration to the builder
+    /// and immediately returns.  This method is basically exception free
+    /// as long as the caller a non NULL value for \c config_arg; it doesn't
+    /// validate the argument further.
+    ///
+    /// \brief isc::InvalidParameter config_arg is NULL.
+    /// \brief std::bad_alloc
+    ///
+    /// \param config_arg The new data source configuration.  Must not be NULL.
+    void reconfigure(data::ConstElementPtr config_arg) {
+        if (!config_arg) {
+            isc_throw(InvalidParameter, "Invalid null config argument");
+        }
+        sendCommand(datasrc_clientmgr_internal::RECONFIGURE, config_arg);
+    }
+
 private:
 private:
     // This is expected to be called at the end of the destructor.  It
     // This is expected to be called at the end of the destructor.  It
     // actually does nothing, but provides a customization point for
     // actually does nothing, but provides a customization point for

+ 65 - 0
src/bin/auth/tests/datasrc_clients_mgr_unittest.cc

@@ -12,6 +12,8 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 // PERFORMANCE OF THIS SOFTWARE.
 
 
+#include <exceptions/exceptions.h>
+
 #include <cc/data.h>
 #include <cc/data.h>
 
 
 #include <auth/datasrc_clients_mgr.h>
 #include <auth/datasrc_clients_mgr.h>
@@ -21,6 +23,7 @@
 
 
 #include <boost/function.hpp>
 #include <boost/function.hpp>
 
 
+using namespace isc::data;
 using namespace isc::auth;
 using namespace isc::auth;
 using namespace isc::auth::datasrc_clientmgr_internal;
 using namespace isc::auth::datasrc_clientmgr_internal;
 
 
@@ -41,6 +44,30 @@ shutdownCheck() {
     EXPECT_TRUE(FakeDataSrcClientsBuilder::thread_waited);
     EXPECT_TRUE(FakeDataSrcClientsBuilder::thread_waited);
 }
 }
 
 
+// Commonly used patter of checking member variables shared between the
+// manager and builder.
+void
+checkSharedMembers(size_t expected_queue_lock_count,
+                   size_t expected_queue_unlock_count,
+                   size_t expected_map_lock_count,
+                   size_t expected_map_unlock_count,
+                   size_t expected_cond_signal_count,
+                   size_t expected_command_queue_size)
+{
+    EXPECT_EQ(expected_queue_lock_count,
+              FakeDataSrcClientsBuilder::queue_mutex->lock_count);
+    EXPECT_EQ(expected_queue_unlock_count,
+              FakeDataSrcClientsBuilder::queue_mutex->unlock_count);
+    EXPECT_EQ(expected_map_lock_count,
+              FakeDataSrcClientsBuilder::map_mutex->lock_count);
+    EXPECT_EQ(expected_map_unlock_count,
+              FakeDataSrcClientsBuilder::map_mutex->unlock_count);
+    EXPECT_EQ(expected_cond_signal_count,
+              FakeDataSrcClientsBuilder::cond->signal_count);
+    EXPECT_EQ(expected_command_queue_size,
+              FakeDataSrcClientsBuilder::command_queue->size());
+}
+
 TEST(DataSrcClientsMgrTest, start) {
 TEST(DataSrcClientsMgrTest, start) {
     // When we create a manager, builder's run() method should be called.
     // When we create a manager, builder's run() method should be called.
     FakeDataSrcClientsBuilder::started = false;
     FakeDataSrcClientsBuilder::started = false;
@@ -77,6 +104,44 @@ TEST(DataSrcClientsMgrTest, shutdownWithException) {
         });
         });
 }
 }
 
 
+TEST(DataSrcClientsMgrTest, reconfigure) {
+    TestDataSrcClientsMgr mgr;
+
+    // Check pre-command condition
+    checkSharedMembers(0, 0, 0, 0, 0, 0);
+
+    // A valid reconfigure argument
+    ConstElementPtr reconfigure_arg = Element::fromJSON(
+        "{" "\"IN\": [{\"type\": \"MasterFiles\", \"params\": {},"
+        "              \"cache-enable\": true}]}");
+
+    // On reconfigure(), it just send the RECONFIGURE command to the builder
+    // thread with the given argument intact.
+    mgr.reconfigure(reconfigure_arg);
+
+    // The manager should have acquired the queue lock, send RECONFIGURE
+    // command with the arg, wake up the builder thread by signal.  It doesn't
+    // touch or refer to the map, so it shouldn't acquire the map lock.
+    checkSharedMembers(1, 1, 0, 0, 1, 1);
+    const Command& cmd1 = FakeDataSrcClientsBuilder::command_queue->front();
+    EXPECT_EQ(RECONFIGURE, cmd1.first);
+    EXPECT_EQ(reconfigure_arg, cmd1.second);
+
+    // Non-null, but semantically invalid argument.  The manager doesn't do
+    // this check, so it should result in the same effect.
+    FakeDataSrcClientsBuilder::command_queue->clear();
+    reconfigure_arg = isc::data::Element::create("{ \"foo\": \"bar\" }");
+    mgr.reconfigure(reconfigure_arg);
+    checkSharedMembers(2, 2, 0, 0, 2, 1);
+    const Command& cmd2 = FakeDataSrcClientsBuilder::command_queue->front();
+    EXPECT_EQ(RECONFIGURE, cmd2.first);
+    EXPECT_EQ(reconfigure_arg, cmd2.second);
+
+    // Passing NULL argument is immediately rejected
+    EXPECT_THROW(mgr.reconfigure(ConstElementPtr()), isc::InvalidParameter);
+    checkSharedMembers(2, 2, 0, 0, 2, 1); // no state change
+}
+
 TEST(DataSrcClientsMgrTest, realThread) {
 TEST(DataSrcClientsMgrTest, realThread) {
     // Using the non-test definition with a real thread.  Just checking
     // Using the non-test definition with a real thread.  Just checking
     // no disruption happens.
     // no disruption happens.