]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#1277] query filter is not kea thread safe
authorRazvan Becheriu <razvan@isc.org>
Thu, 18 Jun 2020 17:04:04 +0000 (20:04 +0300)
committerRazvan Becheriu <razvan@isc.org>
Fri, 19 Jun 2020 08:22:52 +0000 (08:22 +0000)
src/hooks/dhcp/high_availability/query_filter.cc
src/hooks/dhcp/high_availability/query_filter.h
src/hooks/dhcp/high_availability/tests/query_filter_unittest.cc

index e438b9e1e0d4847b5102c02b54b5b4bd74414f2f..dd9c4689639f4b89fc71e298187703644d2b6b2a 100644 (file)
 #include <dhcp/dhcp6.h>
 #include <dhcp/option.h>
 #include <exceptions/exceptions.h>
+#include <util/multi_threading_mgr.h>
+
 #include <array>
 #include <iostream>
 #include <sstream>
 
 using namespace isc::dhcp;
 using namespace isc::log;
+using namespace isc::util;
 
 namespace {
 
@@ -50,7 +53,8 @@ namespace isc {
 namespace ha {
 
 QueryFilter::QueryFilter(const HAConfigPtr& config)
-    : config_(config), peers_(), scopes_(), active_servers_(0) {
+    : config_(config), peers_(), scopes_(), active_servers_(0),
+      mutex_(new std::mutex) {
 
     // Make sure that the configuration is valid. We make certain
     // assumptions about the availability of the servers' configurations
@@ -101,26 +105,56 @@ QueryFilter::QueryFilter(const HAConfigPtr& config)
 
 void
 QueryFilter::serveScope(const std::string& scope_name) {
+    if (MultiThreadingMgr::instance().getMode()) {
+        std::lock_guard<std::mutex> lock(*mutex_);
+        serveScopeInternal(scope_name);
+    } else {
+        serveScopeInternal(scope_name);
+    }
+}
+
+void
+QueryFilter::serveScopeInternal(const std::string& scope_name) {
     validateScopeName(scope_name);
     scopes_[scope_name] = true;
 }
 
 void
 QueryFilter::serveScopeOnly(const std::string& scope_name) {
+    if (MultiThreadingMgr::instance().getMode()) {
+        std::lock_guard<std::mutex> lock(*mutex_);
+        serveScopeOnlyInternal(scope_name);
+    } else {
+        serveScopeOnlyInternal(scope_name);
+    }
+}
+
+void
+QueryFilter::serveScopeOnlyInternal(const std::string& scope_name) {
     validateScopeName(scope_name);
-    serveNoScopes();
-    serveScope(scope_name);
+    serveNoScopesInternal();
+    serveScopeInternal(scope_name);
 }
 
 void
 QueryFilter::serveScopes(const std::vector<std::string>& scopes) {
+    if (MultiThreadingMgr::instance().getMode()) {
+        std::lock_guard<std::mutex> lock(*mutex_);
+        serveScopesInternal(scopes);
+    } else {
+        serveScopesInternal(scopes);
+    }
+}
+
+void
+QueryFilter::serveScopesInternal(const std::vector<std::string>& scopes) {
     // Remember currently enabled scopes in case we fail to process
     // the provided list of scopes.
     auto current_scopes = scopes_;
     try {
-        serveNoScopes();
+        serveNoScopesInternal();
         for (size_t i = 0; i < scopes.size(); ++i) {
-            serveScope(scopes[i]);
+            serveScopeInternal(scopes[i]);
         }
 
     } catch (...) {
@@ -133,25 +167,45 @@ QueryFilter::serveScopes(const std::vector<std::string>& scopes) {
 
 void
 QueryFilter::serveDefaultScopes() {
+    if (MultiThreadingMgr::instance().getMode()) {
+        std::lock_guard<std::mutex> lock(*mutex_);
+        serveDefaultScopesInternal();
+    } else {
+        serveDefaultScopesInternal();
+    }
+}
+
+void
+QueryFilter::serveDefaultScopesInternal() {
     // Get this server instance configuration.
     HAConfig::PeerConfigPtr my_config = config_->getThisServerConfig();
     HAConfig::PeerConfig::Role my_role = my_config->getRole();
 
     // Clear scopes.
-    serveNoScopes();
+    serveNoScopesInternal();
 
     // If I am primary or secondary, then I am only responsible for my own
     // scope.  If I am standby, I am not responsible for any scope.
     if ((my_role == HAConfig::PeerConfig::PRIMARY) ||
         (my_role == HAConfig::PeerConfig::SECONDARY)) {
-        serveScope(my_config->getName());
+        serveScopeInternal(my_config->getName());
     }
 }
 
 void
 QueryFilter::serveFailoverScopes() {
+    if (MultiThreadingMgr::instance().getMode()) {
+        std::lock_guard<std::mutex> lock(*mutex_);
+        serveFailoverScopesInternal();
+    } else {
+        serveFailoverScopesInternal();
+    }
+}
+
+void
+QueryFilter::serveFailoverScopesInternal() {
     // Clear scopes.
-    serveNoScopes();
+    serveNoScopesInternal();
 
     // Iterate over the roles of all servers to see which scope should
     // be enabled.
@@ -164,13 +218,23 @@ QueryFilter::serveFailoverScopes() {
         // server.
         if (((*peer)->getRole() == HAConfig::PeerConfig::PRIMARY) ||
             ((*peer)->getRole() == HAConfig::PeerConfig::SECONDARY)) {
-            serveScope((*peer)->getName());
+            serveScopeInternal((*peer)->getName());
         }
     }
 }
 
 void
 QueryFilter::serveNoScopes() {
+    if (MultiThreadingMgr::instance().getMode()) {
+        std::lock_guard<std::mutex> lock(*mutex_);
+        serveNoScopesInternal();
+    } else {
+        serveNoScopesInternal();
+    }
+}
+
+void
+QueryFilter::serveNoScopesInternal() {
     scopes_.clear();
 
     // Disable scope for each peer in the configuration.
@@ -181,12 +245,32 @@ QueryFilter::serveNoScopes() {
 
 bool
 QueryFilter::amServingScope(const std::string& scope_name) const {
+    if (MultiThreadingMgr::instance().getMode()) {
+        std::lock_guard<std::mutex> lock(*mutex_);
+        return (amServingScopeInternal(scope_name));
+    } else {
+        return (amServingScopeInternal(scope_name));
+    }
+}
+
+bool
+QueryFilter::amServingScopeInternal(const std::string& scope_name) const {
     auto scope = scopes_.find(scope_name);
     return ((scope == scopes_.end()) || (scope->second));
 }
 
 std::set<std::string>
 QueryFilter::getServedScopes() const {
+    if (MultiThreadingMgr::instance().getMode()) {
+        std::lock_guard<std::mutex> lock(*mutex_);
+        return (getServedScopesInternal());
+    } else {
+        return (getServedScopesInternal());
+    }
+}
+
+std::set<std::string>
+QueryFilter::getServedScopesInternal() const {
     std::set<std::string> scope_set;
     for (auto scope : scopes_) {
         if (scope.second) {
@@ -198,12 +282,22 @@ QueryFilter::getServedScopes() const {
 
 bool
 QueryFilter::inScope(const dhcp::Pkt4Ptr& query4, std::string& scope_class) const {
-    return (inScopeInternal(query4, scope_class));
+    if (MultiThreadingMgr::instance().getMode()) {
+        std::lock_guard<std::mutex> lock(*mutex_);
+        return (inScopeInternal(query4, scope_class));
+    } else {
+        return (inScopeInternal(query4, scope_class));
+    }
 }
 
 bool
 QueryFilter::inScope(const dhcp::Pkt6Ptr& query6, std::string& scope_class) const {
-    return (inScopeInternal(query6, scope_class));
+    if (MultiThreadingMgr::instance().getMode()) {
+        std::lock_guard<std::mutex> lock(*mutex_);
+        return (inScopeInternal(query6, scope_class));
+    } else {
+        return (inScopeInternal(query6, scope_class));
+    }
 }
 
 template<typename QueryPtrType>
@@ -229,7 +323,7 @@ QueryFilter::inScopeInternal(const QueryPtrType& query,
 
     auto scope = peers_[candidate_server]->getName();
     scope_class = makeScopeClass(scope);
-    return ((candidate_server >= 0) && amServingScope(scope));
+    return ((candidate_server >= 0) && amServingScopeInternal(scope));
 }
 
 int
@@ -315,6 +409,5 @@ QueryFilter::makeScopeClass(const std::string& scope_name) const {
     return (std::string("HA_") + scope_name);
 }
 
-
 } // end of namespace isc::ha
 } // end of namespace isc
index 541677fab877625a6ccee78a0c6d5a883282b431..c913a24f028813ffcb7e9dcf9bfb96628f8b2002 100644 (file)
 #include <ha_config.h>
 #include <dhcp/pkt4.h>
 #include <dhcp/pkt6.h>
+
+#include <boost/scoped_ptr.hpp>
+
 #include <cstdint>
 #include <map>
-#include <vector>
+#include <mutex>
 #include <set>
 #include <string>
+#include <vector>
 
 namespace isc {
 namespace ha {
@@ -165,10 +169,82 @@ public:
     bool inScope(const dhcp::Pkt6Ptr& query6, std::string& scope_class) const;
 
 private:
+    /// @brief Enable scope.
+    ///
+    /// Should be called in a thread safe context.
+    ///
+    /// Starts serving queries from the specified scope. It doesn't affect
+    /// other scopes.
+    ///
+    /// @param scope_name name of the scope/server to be enabled.
+    /// @throw BadValue if scope name doesn't match any of the server names.
+    void serveScopeInternal(const std::string& scope_name);
+
+    /// @brief Enable scope and disable all other scopes.
+    ///
+    /// Should be called in a thread safe context.
+    ///
+    /// Starts serving queries from the specified scope. Disable all other
+    /// scopes.
+    ///
+    /// @param scope_name name of the scope/server to be enabled.
+    /// @throw BadValue if scope name doesn't match any of the server names.
+    void serveScopeOnlyInternal(const std::string& scope_name);
+
+    /// @brief Enables selected scopes.
+    ///
+    /// Should be called in a thread safe context.
+    ///
+    /// All non listed scopes are disabled.
+    ///
+    /// @param scopes vector of scope names to be enabled.
+    void serveScopesInternal(const std::vector<std::string>& scopes);
+
+    /// @brief Serve default scopes for the given HA mode.
+    ///
+    /// Should be called in a thread safe context.
+    ///
+    /// If this server is primary or secondary (load balancing), the scope
+    /// of this server is enabled. All other scopes are disabled.
+    void serveDefaultScopesInternal();
+
+    /// @brief Enable scopes required in failover case.
+    ///
+    /// Should be called in a thread safe context.
+    ///
+    /// In the load balancing case, the scopes of the primary and secondary
+    /// servers are enabled (this server will handle the entire traffic).
+    /// In the hot standby case, the primary server's scope is enabled
+    /// (this server will handle the entire traffic normally processed by
+    /// the primary server).
+    void serveFailoverScopesInternal();
+
+    /// @brief Disables all scopes.
+    ///
+    /// Should be called in a thread safe context.
+    void serveNoScopesInternal();
+
+    /// @brief Checks if this server instance is configured to process traffic
+    /// belonging to a particular scope.
+    ///
+    /// Should be called in a thread safe context.
+    ///
+    /// @param scope_name name of the scope/server.
+    /// @return true if the scope is enabled.
+    bool amServingScopeInternal(const std::string& scope_name) const;
+
+    /// @brief Returns served scopes.
+    ///
+    /// Should be called in a thread safe context.
+    ///
+    /// This method is mostly useful for testing purposes.
+    std::set<std::string> getServedScopesInternal() const;
 
     /// @brief Generic implementation of the @c inScope function for DHCPv4
     /// and DHCPv6 queries.
     ///
+    /// Should be called in a thread safe context.
+    ///
     /// @tparam QueryPtrType type of the query, i.e. DHCPv4 or DHCPv6 query.
     /// @param query pointer to the DHCP query instance.
     /// @param [out] scope_class name of the class which corresponds to the
@@ -258,6 +334,9 @@ protected:
 
     /// @brief Number of the active servers in the given HA mode.
     int active_servers_;
+
+    /// @brief Mutex to protect the internal state.
+    boost::scoped_ptr<std::mutex> mutex_;
 };
 
 } // end of namespace isc::ha
index 36e620388180ad0ab7afe89498544e17c16012a9..8ed6ef33b33c626008487234445dd85fba3dbcdf 100644 (file)
@@ -13,6 +13,8 @@
 #include <dhcp/dhcp4.h>
 #include <dhcp/dhcp6.h>
 #include <dhcp/hwaddr.h>
+#include <util/multi_threading_mgr.h>
+
 #include <cstdint>
 #include <string>
 
@@ -21,15 +23,86 @@ using namespace isc::data;
 using namespace isc::dhcp;
 using namespace isc::ha;
 using namespace isc::ha::test;
+using namespace util;
 
 namespace  {
 
 /// @brief Test fixture class for @c QueryFilter class.
-using QueryFilterTest = HATest;
+class QueryFilterTest : public HATest {
+public:
+    /// @brief Constructor.
+    QueryFilterTest() {
+        MultiThreadingMgr::instance().setMode(false);
+    }
 
-// This test verifies the case when load balancing is enabled and
-// this server is primary.
-TEST_F(QueryFilterTest, loadBalancingThisPrimary) {
+    /// @brief Destructor.
+    ~QueryFilterTest() {
+        MultiThreadingMgr::instance().setMode(false);
+    }
+
+    /// @brief This test verifies that client identifier is used for load
+    /// balancing.
+    void loadBalancingClientIdThisPrimary();
+
+    /// @brief This test verifies the case when load balancing is enabled and
+    /// this server is primary.
+    void loadBalancingThisPrimary();
+
+    /// @brief This test verifies the case when load balancing is enabled and
+    /// this server is secondary.
+    void loadBalancingThisSecondary();
+
+    /// @brief This test verifies the case when load balancing is enabled and
+    /// this server is backup.
+    /// @todo Expand these tests once we implement the actual load balancing to
+    /// verify which packets are in scope.
+    void loadBalancingThisBackup();
+
+    /// @brief This test verifies the case when hot-standby is enabled and this
+    /// server is primary.
+    void hotStandbyThisPrimary();
+
+    /// @brief This test verifies the case when hot-standby is enabled and this
+    /// server is standby.
+    void hotStandbyThisSecondary();
+
+    /// @brief This test verifies the case when hot-standby is enabled and this
+    /// server is backup.
+    void hotStandbyThisBackup();
+
+    /// @brief This test verifies the case when load balancing is enabled and
+    /// this server is primary.
+    void loadBalancingThisPrimary6();
+
+    /// @brief This test verifies the case when load balancing is enabled and
+    /// this server is secondary.
+    void loadBalancingThisSecondary6();
+
+    /// @brief This test verifies the case when load balancing is enabled and
+    /// this server is backup.
+    /// @todo Expand these tests once we implement the actual load balancing to
+    /// verify which packets are in scope.
+    void loadBalancingThisBackup6();
+
+    /// @brief This test verifies the case when hot-standby is enabled and this
+    /// server is primary.
+    void hotStandbyThisPrimary6();
+
+    /// @brief This test verifies the case when hot-standby is enabled and this
+    /// server is standby.
+    void hotStandbyThisSecondary6();
+
+    /// @brief This test verifies the case when hot-standby is enabled and this
+    /// server is backup.
+    void hotStandbyThisBackup6();
+
+    /// @brief This test verifies that it is possible to explicitly enable and
+    /// disable certain scopes.
+    void explicitlyServeScopes();
+};
+
+void
+QueryFilterTest::loadBalancingThisPrimary() {
     HAConfigPtr config = createValidConfiguration();
 
     QueryFilter filter(config);
@@ -85,8 +158,8 @@ TEST_F(QueryFilterTest, loadBalancingThisPrimary) {
     EXPECT_FALSE(filter.inScope(query4, scope_class));
 }
 
-// This test verifies that client identifier is used for load balancing.
-TEST_F(QueryFilterTest, loadBalancingClientIdThisPrimary) {
+void
+QueryFilterTest::loadBalancingClientIdThisPrimary() {
     HAConfigPtr config = createValidConfiguration();
 
     QueryFilter filter(config);
@@ -140,9 +213,8 @@ TEST_F(QueryFilterTest, loadBalancingClientIdThisPrimary) {
     }
 }
 
-// This test verifies the case when load balancing is enabled and
-// this server is secondary.
-TEST_F(QueryFilterTest, loadBalancingThisSecondary) {
+void
+QueryFilterTest::loadBalancingThisSecondary() {
     HAConfigPtr config = createValidConfiguration();
 
     // We're now a secondary server.
@@ -196,11 +268,8 @@ TEST_F(QueryFilterTest, loadBalancingThisSecondary) {
     }
 }
 
-// This test verifies the case when load balancing is enabled and
-// this server is backup.
-/// @todo Expand these tests once we implement the actual load balancing to
-/// verify which packets are in scope.
-TEST_F(QueryFilterTest, loadBalancingThisBackup) {
+void
+QueryFilterTest::loadBalancingThisBackup() {
     HAConfigPtr config = createValidConfiguration();
 
     config->setThisServerName("server3");
@@ -241,9 +310,8 @@ TEST_F(QueryFilterTest, loadBalancingThisBackup) {
     }
 }
 
-// This test verifies the case when hot-standby is enabled and this
-// server is primary.
-TEST_F(QueryFilterTest, hotStandbyThisPrimary) {
+void
+QueryFilterTest::hotStandbyThisPrimary() {
     HAConfigPtr config = createValidConfiguration();
 
     config->setHAMode("hot-standby");
@@ -278,9 +346,8 @@ TEST_F(QueryFilterTest, hotStandbyThisPrimary) {
     EXPECT_NE(scope_class, "HA_server2");
 }
 
-// This test verifies the case when hot-standby is enabled and this
-// server is standby.
-TEST_F(QueryFilterTest, hotStandbyThisSecondary) {
+void
+QueryFilterTest::hotStandbyThisSecondary() {
     HAConfigPtr config = createValidConfiguration();
 
     config->setHAMode("hot-standby");
@@ -318,9 +385,8 @@ TEST_F(QueryFilterTest, hotStandbyThisSecondary) {
     EXPECT_NE(scope_class, "HA_server2");
 }
 
-// This test verifies the case when hot-standby is enabled and this
-// server is backup.
-TEST_F(QueryFilterTest, hotStandbyThisBackup) {
+void
+QueryFilterTest::hotStandbyThisBackup() {
     HAConfigPtr config = createValidConfiguration();
 
     config->setHAMode("hot-standby");
@@ -354,9 +420,8 @@ TEST_F(QueryFilterTest, hotStandbyThisBackup) {
     EXPECT_TRUE(filter.inScope(query4, scope_class));
 }
 
-// This test verifies the case when load balancing is enabled and
-// this DHCPv6 server is primary.
-TEST_F(QueryFilterTest, loadBalancingThisPrimary6) {
+void
+QueryFilterTest::loadBalancingThisPrimary6() {
     HAConfigPtr config = createValidConfiguration();
 
     QueryFilter filter(config);
@@ -411,9 +476,8 @@ TEST_F(QueryFilterTest, loadBalancingThisPrimary6) {
     EXPECT_FALSE(filter.inScope(query6, scope_class));
 }
 
-// This test verifies the case when load balancing is enabled and
-// this server is secondary.
-TEST_F(QueryFilterTest, loadBalancingThisSecondary6) {
+void
+QueryFilterTest::loadBalancingThisSecondary6() {
     HAConfigPtr config = createValidConfiguration();
 
     // We're now a secondary server.
@@ -467,11 +531,8 @@ TEST_F(QueryFilterTest, loadBalancingThisSecondary6) {
     }
 }
 
-// This test verifies the case when load balancing is enabled and
-// this server is backup.
-/// @todo Expand these tests once we implement the actual load balancing to
-/// verify which packets are in scope.
-TEST_F(QueryFilterTest, loadBalancingThisBackup6) {
+void
+QueryFilterTest::loadBalancingThisBackup6() {
     HAConfigPtr config = createValidConfiguration();
 
     config->setThisServerName("server3");
@@ -512,9 +573,8 @@ TEST_F(QueryFilterTest, loadBalancingThisBackup6) {
     }
 }
 
-// This test verifies the case when hot-standby is enabled and this
-// server is primary.
-TEST_F(QueryFilterTest, hotStandbyThisPrimary6) {
+void
+QueryFilterTest::hotStandbyThisPrimary6() {
     HAConfigPtr config = createValidConfiguration();
 
     config->setHAMode("hot-standby");
@@ -549,9 +609,8 @@ TEST_F(QueryFilterTest, hotStandbyThisPrimary6) {
     EXPECT_NE(scope_class, "HA_server2");
 }
 
-// This test verifies the case when hot-standby is enabled and this
-// server is standby.
-TEST_F(QueryFilterTest, hotStandbyThisSecondary6) {
+void
+QueryFilterTest::hotStandbyThisSecondary6() {
     HAConfigPtr config = createValidConfiguration();
 
     config->setHAMode("hot-standby");
@@ -589,9 +648,43 @@ TEST_F(QueryFilterTest, hotStandbyThisSecondary6) {
     EXPECT_NE(scope_class, "HA_server2");
 }
 
-// This test verifies that it is possible to explicitly enable and
-// disable certain scopes.
-TEST_F(QueryFilterTest, explicitlyServeScopes) {
+void
+QueryFilterTest::hotStandbyThisBackup6() {
+    HAConfigPtr config = createValidConfiguration();
+
+    config->setHAMode("hot-standby");
+    config->getPeerConfig("server2")->setRole("standby");
+    config->setThisServerName("server3");
+
+    QueryFilter filter(config);
+
+    Pkt6Ptr query6 = createQuery6(randomKey(10));
+
+    // By default the backup server doesn't process any traffic.
+    EXPECT_FALSE(filter.amServingScope("server1"));
+    EXPECT_FALSE(filter.amServingScope("server2"));
+    EXPECT_FALSE(filter.amServingScope("server3"));
+
+    std::string scope_class;
+
+    EXPECT_FALSE(filter.inScope(query6, scope_class));
+
+    // Simulate failover. Although, backup server never starts handling
+    // other server's traffic automatically, it can be manually instructed
+    // to do so. This simulates such scenario.
+    filter.serveFailoverScopes();
+
+    // The backup server now handles the entire traffic, i.e. the traffic
+    // that the primary server handles.
+    EXPECT_TRUE(filter.amServingScope("server1"));
+    EXPECT_FALSE(filter.amServingScope("server2"));
+    EXPECT_FALSE(filter.amServingScope("server3"));
+
+    EXPECT_TRUE(filter.inScope(query6, scope_class));
+}
+
+void
+QueryFilterTest::explicitlyServeScopes() {
     HAConfigPtr config = createValidConfiguration();
 
     QueryFilter filter(config);
@@ -638,4 +731,130 @@ TEST_F(QueryFilterTest, explicitlyServeScopes) {
     EXPECT_THROW(filter.serveScopes({ "server1", "unsupported" }), BadValue);
 }
 
+TEST_F(QueryFilterTest, loadBalancingClientIdThisPrimary) {
+    loadBalancingClientIdThisPrimary();
+}
+
+TEST_F(QueryFilterTest, loadBalancingClientIdThisPrimaryMultiThreading) {
+    MultiThreadingMgr::instance().setMode(true);
+    loadBalancingClientIdThisPrimary();
+}
+
+TEST_F(QueryFilterTest, loadBalancingThisPrimary) {
+    loadBalancingThisPrimary();
+}
+
+TEST_F(QueryFilterTest, loadBalancingThisPrimaryMultiThreading) {
+    MultiThreadingMgr::instance().setMode(true);
+    loadBalancingThisPrimary();
+}
+
+TEST_F(QueryFilterTest, loadBalancingThisSecondary) {
+    loadBalancingThisSecondary();
+}
+
+TEST_F(QueryFilterTest, loadBalancingThisSecondaryMultiThreading) {
+    MultiThreadingMgr::instance().setMode(true);
+    loadBalancingThisSecondary();
+}
+
+TEST_F(QueryFilterTest, loadBalancingThisBackup) {
+    loadBalancingThisBackup();
+}
+
+TEST_F(QueryFilterTest, loadBalancingThisBackupMultiThreading) {
+    MultiThreadingMgr::instance().setMode(true);
+    loadBalancingThisBackup();
+}
+
+TEST_F(QueryFilterTest, hotStandbyThisPrimary) {
+    hotStandbyThisPrimary();
+}
+
+TEST_F(QueryFilterTest, hotStandbyThisPrimaryMultiThreading) {
+    MultiThreadingMgr::instance().setMode(true);
+    hotStandbyThisPrimary();
+}
+
+TEST_F(QueryFilterTest, hotStandbyThisSecondary) {
+    hotStandbyThisSecondary();
+}
+
+TEST_F(QueryFilterTest, hotStandbyThisSecondaryMultiThreading) {
+    MultiThreadingMgr::instance().setMode(true);
+    hotStandbyThisSecondary();
+}
+
+TEST_F(QueryFilterTest, hotStandbyThisBackup) {
+    hotStandbyThisBackup();
+}
+
+TEST_F(QueryFilterTest, hotStandbyThisBackupMultiThreading) {
+    MultiThreadingMgr::instance().setMode(true);
+    hotStandbyThisBackup();
+}
+
+TEST_F(QueryFilterTest, loadBalancingThisPrimary6) {
+    loadBalancingThisPrimary6();
+}
+
+TEST_F(QueryFilterTest, loadBalancingThisPrimary6MultiThreading) {
+    MultiThreadingMgr::instance().setMode(true);
+    loadBalancingThisPrimary6();
+}
+
+TEST_F(QueryFilterTest, loadBalancingThisSecondary6) {
+    loadBalancingThisSecondary6();
+}
+
+TEST_F(QueryFilterTest, loadBalancingThisSecondary6MultiThreading) {
+    MultiThreadingMgr::instance().setMode(true);
+    loadBalancingThisSecondary6();
+}
+
+TEST_F(QueryFilterTest, loadBalancingThisBackup6) {
+    loadBalancingThisBackup6();
+}
+
+TEST_F(QueryFilterTest, loadBalancingThisBackup6MultiThreading) {
+    MultiThreadingMgr::instance().setMode(true);
+    loadBalancingThisBackup6();
+}
+
+TEST_F(QueryFilterTest, hotStandbyThisPrimary6) {
+    hotStandbyThisPrimary6();
+}
+
+TEST_F(QueryFilterTest, hotStandbyThisPrimary6MultiThreading) {
+    MultiThreadingMgr::instance().setMode(true);
+    hotStandbyThisPrimary6();
+}
+
+TEST_F(QueryFilterTest, hotStandbyThisSecondary6) {
+    hotStandbyThisSecondary6();
+}
+
+TEST_F(QueryFilterTest, hotStandbyThisSecondary6MultiThreading) {
+    MultiThreadingMgr::instance().setMode(true);
+    hotStandbyThisSecondary6();
+}
+
+TEST_F(QueryFilterTest, hotStandbyThisBackup6) {
+    hotStandbyThisBackup6();
+}
+
+TEST_F(QueryFilterTest, hotStandbyThisBackup6MultiThreading) {
+    MultiThreadingMgr::instance().setMode(true);
+    hotStandbyThisBackup6();
+}
+
+TEST_F(QueryFilterTest, explicitlyServeScopes) {
+    explicitlyServeScopes();
+}
+
+TEST_F(QueryFilterTest, explicitlyServeScopesMultiThreading) {
+    MultiThreadingMgr::instance().setMode(true);
+    explicitlyServeScopes();
+}
+
 }