// --- multi-threading ------------------------------------------------
dhcp_multi_threading: DHCP_MULTI_THREADING {
- ElementPtr qc(new MapElement(ctx.loc2pos(@1)));
- ctx.stack_.back()->set("multi-threading", qc);
- ctx.stack_.push_back(qc);
+ ElementPtr mt(new MapElement(ctx.loc2pos(@1)));
+ ctx.stack_.back()->set("multi-threading", mt);
+ ctx.stack_.push_back(mt);
ctx.enter(ctx.DHCP_MULTI_THREADING);
} COLON LCURLY_BRACKET multi_threading_params RCURLY_BRACKET {
- // The enable queue parameter is required.
+ // The enable parameter is required.
ctx.require("enable-multi-threading", ctx.loc2pos(@4), ctx.loc2pos(@6));
ctx.stack_.pop_back();
ctx.leave();
};
multi_threading_params: multi_threading_param
- | multi_threading_param COMMA multi_threading_param
+ | multi_threading_params COMMA multi_threading_param
;
multi_threading_param: enable_multi_threading
EXPECT_TRUE(subnet2->getStoreExtendedInfo());
}
+<<<<<<< HEAD
/// This test checks that the statistic-default-sample-count and age
/// global parameters are committed to the stats manager as expected.
TEST_F(Dhcp4ParserTest, statsDefaultLimits) {
util::durationToText(stats_mgr.getMaxSampleAgeDefault(), 0));
}
+// This test checks that adding multi threadding settings works.
+TEST_F(Dhcp4ParserTest, multiThreadingSettings) {
+ std::string config = "{ " + genIfaceConfig() + "," +
+ "\"subnet4\": [ ], "
+ "\"multi-threading\": { "
+ " \"enable-multi-threading\": false,"
+ " \"thread-pool-size\": 0,"
+ " \"packet-queue-size\": 0 }"
+ "}";
+
+ ConstElementPtr json;
+ ASSERT_NO_THROW(json = parseDHCP4(config));
+ extractConfig(config);
+
+ ConstElementPtr status;
+ ASSERT_NO_THROW(status = configureDhcp4Server(*srv_, json));
+ checkResult(status, 0);
+
+ ASSERT_TRUE(CfgMgr::instance().getStagingCfg()->getDHCPMultiThreading());
+ ASSERT_EQ(CfgMgr::instance().getStagingCfg()->getDHCPMultiThreading()->size(), 3);
}
+
+} // namespace
// --- multi-threading ------------------------------------------------
dhcp_multi_threading: DHCP_MULTI_THREADING {
- ElementPtr qc(new MapElement(ctx.loc2pos(@1)));
- ctx.stack_.back()->set("multi-threading", qc);
- ctx.stack_.push_back(qc);
+ ElementPtr mt(new MapElement(ctx.loc2pos(@1)));
+ ctx.stack_.back()->set("multi-threading", mt);
+ ctx.stack_.push_back(mt);
ctx.enter(ctx.DHCP_MULTI_THREADING);
} COLON LCURLY_BRACKET multi_threading_params RCURLY_BRACKET {
- // The enable queue parameter is required.
+ // The enable parameter is required.
ctx.require("enable-multi-threading", ctx.loc2pos(@4), ctx.loc2pos(@6));
ctx.stack_.pop_back();
ctx.leave();
};
multi_threading_params: multi_threading_param
- | multi_threading_param COMMA multi_threading_param
+ | multi_threading_params COMMA multi_threading_param
;
multi_threading_param: enable_multi_threading
EXPECT_TRUE(subnet->getStoreExtendedInfo());
}
+<<<<<<< HEAD
/// This test checks that the statistic-default-sample-count and age
/// global parameters are committed to the stats manager as expected.
TEST_F(Dhcp6ParserTest, statsDefaultLimits) {
util::durationToText(stats_mgr.getMaxSampleAgeDefault(), 0));
}
+// This test checks that adding multi threadding settings works.
+TEST_F(Dhcp6ParserTest, multiThreadingSettings) {
+ std::string config = "{ " + genIfaceConfig() + "," +
+ "\"subnet6\": [ ], "
+ "\"multi-threading\": { "
+ " \"enable-multi-threading\": false,"
+ " \"thread-pool-size\": 0,"
+ " \"packet-queue-size\": 0 }"
+ "}";
+
+ ConstElementPtr json;
+ ASSERT_NO_THROW(json = parseDHCP6(config));
+ extractConfig(config);
+
+ ConstElementPtr status;
+ ASSERT_NO_THROW(status = configureDhcp6Server(srv_, json));
+ checkResult(status, 0);
+
+ ASSERT_TRUE(CfgMgr::instance().getStagingCfg()->getDHCPMultiThreading());
+ ASSERT_EQ(CfgMgr::instance().getStagingCfg()->getDHCPMultiThreading()->size(), 3);
}
+
+} // namespace
isc_throw(DhcpConfigError, "multi-threading is supposed to be a map");
}
+ // enable-multi-threading is mandatory
+ getBoolean(value, "enable-multi-threading");
+
+ // thread-pool-size is not mandatory
if (value->get("thread-pool-size")) {
auto thread_pool_size = getInteger(value, "thread-pool-size");
uint32_t max_size = std::numeric_limits<uint16_t>::max();
}
}
+ // packet-queue-size is not mandatory
if (value->get("packet-queue-size")) {
auto packet_queue_size = getInteger(value, "packet-queue-size");
uint32_t max_size = std::numeric_limits<uint16_t>::max();
libdhcpsrv_unittests_SOURCES += cfg_hosts_unittest.cc
libdhcpsrv_unittests_SOURCES += cfg_iface_unittest.cc
libdhcpsrv_unittests_SOURCES += cfg_mac_source_unittest.cc
+libdhcpsrv_unittests_SOURCES += cfg_multi_threading_unittest.cc
libdhcpsrv_unittests_SOURCES += cfg_option_unittest.cc
libdhcpsrv_unittests_SOURCES += cfg_option_def_unittest.cc
libdhcpsrv_unittests_SOURCES += cfg_rsoo_unittest.cc
libdhcpsrv_unittests_SOURCES += lease_mgr_unittest.cc
libdhcpsrv_unittests_SOURCES += generic_lease_mgr_unittest.cc generic_lease_mgr_unittest.h
libdhcpsrv_unittests_SOURCES += memfile_lease_mgr_unittest.cc
+libdhcpsrv_unittests_SOURCES += multi_threading_config_parser_unittest.cc
libdhcpsrv_unittests_SOURCES += dhcp_parsers_unittest.cc
libdhcpsrv_unittests_SOURCES += ncr_generator_unittest.cc
if HAVE_MYSQL
--- /dev/null
+// Copyright (C) 2020 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <cc/data.h>
+#include <dhcpsrv/cfg_multi_threading.h>
+#include <util/multi_threading_mgr.h>
+
+#include <gtest/gtest.h>
+
+using namespace isc::data;
+using namespace isc::dhcp;
+using namespace isc::util;
+
+namespace {
+
+/// @brief Test fixture class for @c MultiThreadingConfigParser
+class CfgMultiThreadingTest : public ::testing::Test {
+protected:
+
+ /// @brief Setup for each test.
+ ///
+ /// Clears the configuration in the @c MultiThreadingMgr.
+ virtual void SetUp();
+
+ /// @brief Cleans up after each test.
+ ///
+ /// Clears the configuration in the @c MultiThreadingMgr.
+ virtual void TearDown();
+};
+
+void
+CfgMultiThreadingTest::SetUp() {
+ MultiThreadingMgr::instance().apply(false, 0, 0);
+}
+
+void
+CfgMultiThreadingTest::TearDown() {
+ MultiThreadingMgr::instance().apply(false, 0 , 0);
+}
+
+// Verifies that applying multi threading setting works
+TEST_F(CfgMultiThreadingTest, apply) {
+ EXPECT_FALSE(MultiThreadingMgr::instance().getMode());
+ EXPECT_EQ(MultiThreadingMgr::instance().getThreadPoolSize(), 0);
+ EXPECT_EQ(MultiThreadingMgr::instance().getThreadQueueSize(), 0);
+ ElementPtr param = Element::createMap();
+ param->set("enable-multi-threading", Element::create(true));
+ param->set("thread-pool-size", Element::create(4));
+ param->set("packet-queue-size", Element::create(64));
+ CfgMultiThreading::apply(-1, param);
+ EXPECT_TRUE(MultiThreadingMgr::instance().getMode());
+ EXPECT_EQ(MultiThreadingMgr::instance().getThreadPoolSize(), 4);
+ EXPECT_EQ(MultiThreadingMgr::instance().getThreadQueueSize(), 64);
+ CfgMultiThreading::apply(8, param);
+ EXPECT_TRUE(MultiThreadingMgr::instance().getMode());
+ EXPECT_EQ(MultiThreadingMgr::instance().getThreadPoolSize(), 8);
+ EXPECT_EQ(MultiThreadingMgr::instance().getThreadQueueSize(), 0);
+}
+
+} // namespace
--- /dev/null
+// Copyright (C) 2020 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <cc/data.h>
+#include <dhcpsrv/parsers/multi_threading_config_parser.h>
+#include <testutils/test_to_element.h>
+
+#include <gtest/gtest.h>
+
+using namespace isc::data;
+using namespace isc::dhcp;
+using namespace isc::test;
+
+namespace {
+
+/// @brief Test fixture class for @c MultiThreadingConfigParser
+class MultiThreadingConfigParserTest : public ::testing::Test {
+protected:
+
+ /// @brief Setup for each test.
+ virtual void SetUp();
+
+ /// @brief Cleans up after each test.
+ virtual void TearDown();
+};
+
+void
+MultiThreadingConfigParserTest::SetUp() {
+}
+
+void
+MultiThreadingConfigParserTest::TearDown() {
+}
+
+// Verifies that MultiThreadingConfigParser handles
+// expected valid content
+TEST_F(MultiThreadingConfigParserTest, validContent) {
+ struct Scenario {
+ std::string description_;
+ std::string json_;
+ };
+
+ std::vector<Scenario> scenarios = {
+ {
+ "enable-multi-threading disabled",
+ "{ \n"
+ " \"enable-multi-threading\": false \n"
+ "} \n"
+ },
+ {
+ "enable-multi-threading, with thread-pool-size and packet-queue-size",
+ "{ \n"
+ " \"enable-multi-threading\": true, \n"
+ " \"thread-pool-size\": 4, \n"
+ " \"packet-queue-size\": 64 \n"
+ "} \n"
+ }
+ };
+
+ // Iterate over the valid scenarios and verify they succeed.
+ ConstElementPtr config_elems;
+ ConstElementPtr multi_threading_config;
+ for (auto scenario : scenarios) {
+ SCOPED_TRACE(scenario.description_);
+ {
+ // Construct the config JSON
+ ASSERT_NO_THROW(config_elems = Element::fromJSON(scenario.json_))
+ << "invalid JSON, test is broken";
+
+ // Parsing config should succeed.
+ MultiThreadingConfigParser parser;
+ try {
+ multi_threading_config = parser.parse(config_elems);
+ } catch (const std::exception& ex) {
+ ADD_FAILURE() << "parser threw an exception: " << ex.what();
+ }
+
+ // Verify the resultant configuration.
+ ASSERT_TRUE(multi_threading_config);
+
+ // The parser should have created a duplicate of the
+ // configuration elements.
+ ASSERT_TRUE(multi_threading_config.get() != config_elems.get());
+ EXPECT_TRUE(multi_threading_config->equals(*config_elems));
+ }
+ }
+}
+
+// Verifies that MultiThreadingConfigParser correctly catches
+// invalid content
+TEST_F(MultiThreadingConfigParserTest, invalidContent) {
+ struct Scenario {
+ std::string description_;
+ std::string json_;
+ };
+
+ std::vector<Scenario> scenarios = {
+ {
+ "enable-multi-threading not boolean",
+ "{ \n"
+ " \"enable-multi-threading\": \"always\" \n"
+ "} \n"
+ },
+ {
+ "thread-pool-size not integer",
+ "{ \n"
+ " \"thread-pool-size\": true \n"
+ "} \n"
+ },
+ {
+ "thread-pool-size negative",
+ "{ \n"
+ " \"thread-pool-size\": -1 \n"
+ "} \n"
+ },
+ {
+ "thread-pool-size too large",
+ "{ \n"
+ " \"thread-pool-size\": 200000 \n"
+ "} \n"
+ },
+ {
+ "packet-queue-size not integer",
+ "{ \n"
+ " \"packet-queue-size\": true \n"
+ "} \n"
+ },
+ {
+ "packet-queue-size-size negative",
+ "{ \n"
+ " \"packet-queue-size\": -1 \n"
+ "} \n"
+ },
+ {
+ "packet-queue-size too large",
+ "{ \n"
+ " \"packet-queue-size\": 200000 \n"
+ "} \n"
+ }
+ };
+
+ // Iterate over the valid scenarios and verify they succeed.
+ ConstElementPtr config_elems;
+ ConstElementPtr queue_control;
+ for (auto scenario : scenarios) {
+ SCOPED_TRACE(scenario.description_);
+ {
+ // Construct the config JSON
+ ASSERT_NO_THROW(config_elems = Element::fromJSON(scenario.json_))
+ << "invalid JSON, test is broken";
+
+ // Parsing config into a queue control should succeed.
+ MultiThreadingConfigParser parser;
+ EXPECT_THROW(parser.parse(config_elems), DhcpConfigError);
+ }
+ }
+}
+
+} // namespace
#include <dhcpsrv/subnet.h>
#include <process/logging_info.h>
#include <testutils/test_to_element.h>
+
#include <gtest/gtest.h>
using namespace isc::asiolink;
EXPECT_TRUE(params->getHostnameCharReplacement().empty());
}
+// Verifies that adding multi threading settings works
+TEST_F(SrvConfigTest, multiThreadingSettings) {
+ SrvConfig conf(32);
+ ElementPtr param = Element::createMap();
+ param->set("enable-multi-threading", Element::create(true));
+ conf.setDHCPMultiThreading(param);
+ EXPECT_TRUE(isEquivalent(param, conf.getDHCPMultiThreading()));
+}
+
} // end of anonymous namespace