From: Marcin Siodelski Date: Thu, 10 Sep 2015 14:27:32 +0000 (+0200) Subject: [3973] Update statistics when the lease is reclaimed. X-Git-Tag: trac4065_base^2~4 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=216d4107cbdb37e1831a7652e1db573b435ff101;p=thirdparty%2Fkea.git [3973] Update statistics when the lease is reclaimed. --- diff --git a/src/lib/dhcpsrv/alloc_engine.cc b/src/lib/dhcpsrv/alloc_engine.cc index 4009b1e512..af97beb83f 100644 --- a/src/lib/dhcpsrv/alloc_engine.cc +++ b/src/lib/dhcpsrv/alloc_engine.cc @@ -1314,6 +1314,35 @@ AllocEngine::reclaimExpiredLeases6(const size_t max_leases, const uint16_t timeo boost::bind(&LeaseMgr::updateLease6, &lease_mgr, _1)); + // Update statistics. + + // Decrease number of assigned leases. + if (lease->type_ == Lease::TYPE_NA) { + // IA_NA + StatsMgr::instance().addValue(StatsMgr::generateName("subnet", + lease->subnet_id_, + "assigned-nas"), + int64_t(-1)); + + } else if (lease->type_ == Lease::TYPE_PD) { + // IA_PD + StatsMgr::instance().addValue(StatsMgr::generateName("subnet", + lease->subnet_id_, + "assigned-pds"), + int64_t(-1)); + + } + + // Increase total number of reclaimed leases. + StatsMgr::instance().addValue("reclaimed-leases", int64_t(1)); + + // Increase number of reclaimed leases for a subnet. + StatsMgr::instance().addValue(StatsMgr::generateName("subnet", + lease->subnet_id_, + "reclaimed-leases"), + int64_t(1)); + + } catch (const std::exception& ex) { LOG_ERROR(alloc_engine_logger, ALLOC_ENGINE_V6_LEASE_RECLAMATION_FAILED) .arg(lease->addr_.toText()) @@ -1373,6 +1402,23 @@ AllocEngine::reclaimExpiredLeases4(const size_t max_leases, const uint16_t timeo boost::bind(&LeaseMgr::updateLease4, &lease_mgr, _1)); + // Update statistics. + + // Decrease number of assigned addresses. + StatsMgr::instance().addValue(StatsMgr::generateName("subnet", + lease->subnet_id_, + "assigned-addresses"), + int64_t(-1)); + + // Increase total number of reclaimed leases. + StatsMgr::instance().addValue("reclaimed-leases", int64_t(1)); + + // Increase number of reclaimed leases for a subnet. + StatsMgr::instance().addValue(StatsMgr::generateName("subnet", + lease->subnet_id_, + "reclaimed-leases"), + int64_t(1)); + } catch (const std::exception& ex) { LOG_ERROR(alloc_engine_logger, ALLOC_ENGINE_V4_LEASE_RECLAMATION_FAILED) .arg(lease->addr_.toText()) diff --git a/src/lib/dhcpsrv/tests/alloc_engine_expiration_unittest.cc b/src/lib/dhcpsrv/tests/alloc_engine_expiration_unittest.cc index 2b7077bec8..93ff635367 100644 --- a/src/lib/dhcpsrv/tests/alloc_engine_expiration_unittest.cc +++ b/src/lib/dhcpsrv/tests/alloc_engine_expiration_unittest.cc @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -33,6 +34,7 @@ using namespace isc::asiolink; using namespace isc::dhcp; using namespace isc::dhcp::test; using namespace isc::dhcp_ddns; +using namespace isc::stats; namespace { @@ -158,12 +160,20 @@ public: /// Clears configuration, creates new lease manager and allocation engine /// instances. ExpirationAllocEngineTest(const std::string& lease_mgr_params) { + // Clear configuration. CfgMgr::instance().clear(); + D2ClientConfigPtr cfg(new D2ClientConfig()); + CfgMgr::instance().setD2ClientConfig(cfg); + + // Remove all statistics. + StatsMgr::instance().resetAll(); + + // Create lease manager. LeaseMgrFactory::create(lease_mgr_params); + // Create allocation engine instance. engine_.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100, false)); - } /// @brief Destructor @@ -179,7 +189,15 @@ public: mgr.clearQueue(); } + // Clear configuration. CfgMgr::instance().clear(); + D2ClientConfigPtr cfg(new D2ClientConfig()); + CfgMgr::instance().setD2ClientConfig(cfg); + + // Remove all statistics. + StatsMgr::instance().resetAll(); + + // Kill lease manager. LeaseMgrFactory::destroy(); } @@ -222,6 +240,14 @@ public: /// @param lease_index Index of the lease. virtual LeasePtrType getLease(const unsigned int lease_index) const = 0; + /// @brief Sets subnet id for a lease. + /// + /// It also updates statistics of assigned leases in the stats manager. + /// + /// @param lease_index Lease index. + /// @param id New subnet id. + virtual void setSubnetId(const uint16_t lease_index, const SubnetID& id) = 0; + /// @brief Wrapper method running lease reclamation routine. /// /// @param max_leases Maximum number of leases to be reclaimed. @@ -234,6 +260,30 @@ public: const uint16_t timeout, const bool remove_lease) = 0; + /// @brief Test that statistic manager holds a given value. + /// + /// @param stat_name Statistic name. + /// @param exp_value Expected value. + bool testStatistics(const std::string& stat_name, const int64_t exp_value) const { + try { + ObservationPtr observation = StatsMgr::instance().getObservation(stat_name); + if (observation) { + if (observation->getInteger().first != exp_value) { + ADD_FAILURE() + << "value of the observed statistics '" + << stat_name << "' " << "(" + << observation->getInteger().first << ") " + << "doesn't match expected value (" << exp_value << ")"; + } + return (observation->getInteger().first == exp_value); + } + + } catch (...) { + ; + } + return (false); + } + /// @brief Test selected leases using the specified algorithms. /// /// This function picks leases from the range of 0 thru @@ -698,6 +748,22 @@ public: LeaseMgrFactory::instance().updateLease6(leases_[lease_index]); } + /// @brief Sets subnet id for a lease. + /// + /// It also updates statistics of assigned leases in the stats manager. + /// + /// @param lease_index Lease index. + /// @param id New subnet id. + virtual void setSubnetId(const uint16_t lease_index, const SubnetID& id); + + /// @brief Sets type of a lease. + /// + /// It also updates statistics of assigned leases in the stats manager. + /// + /// @param lease_index Lease index. + /// @param lease_type Lease type. + void setLeaseType(const uint16_t lease_index, const Lease6::Type& lease_type); + /// @brief Retrieves lease from the database. /// /// @param lease_index Index of the lease. @@ -720,6 +786,9 @@ public: engine_->reclaimExpiredLeases6(max_leases, timeout, remove_lease); } + /// @brief Test that statistics is updated when leases are reclaimed. + void testReclaimExpiredLeasesStats(); + }; ExpirationAllocEngine6Test::ExpirationAllocEngine6Test() @@ -747,10 +816,97 @@ ExpirationAllocEngine6Test::createLeases() { generateHostnameForLeaseIndex(i))); leases_.push_back(lease); LeaseMgrFactory::instance().addLease(lease); + + // Note in the statistics that this lease has been added. + StatsMgr& stats_mgr = StatsMgr::instance(); + std::string stat_name = + lease->type_ == Lease::TYPE_NA ? "assigned-nas" : "assigned-pds"; + stats_mgr.addValue(stats_mgr.generateName("subnet", lease->subnet_id_, stat_name), + int64_t(1)); + } +} + +void +ExpirationAllocEngine6Test::setSubnetId(const uint16_t lease_index, const SubnetID& id) { + ASSERT_GT(leases_.size(), lease_index); + if (leases_[lease_index]->subnet_id_ != id) { + StatsMgr& stats_mgr = StatsMgr::instance(); + std::string stats_name = (leases_[lease_index]->type_ == Lease::TYPE_NA ? + "assigned-nas" : "assigned-pds"); + stats_mgr.addValue(stats_mgr.generateName("subnet", id, stats_name), + int64_t(1)); + stats_mgr.addValue(stats_mgr.generateName("subnet", + leases_[lease_index]->subnet_id_, + stats_name), + int64_t(-1)); + leases_[lease_index]->subnet_id_ = id; + ASSERT_NO_THROW(updateLease(lease_index)); + } +} + +void +ExpirationAllocEngine6Test::setLeaseType(const uint16_t lease_index, + const Lease6::Type& lease_type) { + ASSERT_GT(leases_.size(), lease_index); + if (leases_[lease_index]->type_ != lease_type) { + StatsMgr& stats_mgr = StatsMgr::instance(); + std::string stats_name = (lease_type == Lease::TYPE_NA ? + "assigned-nas" : "assigned-pds"); + stats_mgr.addValue(stats_mgr.generateName("subnet", + leases_[lease_index]->subnet_id_, + stats_name), + int64_t(1)); + stats_name = (leases_[lease_index]->type_ == Lease::TYPE_NA ? + "assigned-nas" : "assigned-pds"); + stats_mgr.addValue(stats_mgr.generateName("subnet", + leases_[lease_index]->subnet_id_, + stats_name), + int64_t(-1)); + leases_[lease_index]->type_ = lease_type; + ASSERT_NO_THROW(updateLease(lease_index)); } } +void +ExpirationAllocEngine6Test::testReclaimExpiredLeasesStats() { + // This test requires that the number of leases is an even number. + BOOST_STATIC_ASSERT(TEST_LEASES_NUM % 2 == 0); + + for (int i = 0; i < TEST_LEASES_NUM; ++i) { + // Mark all leaes as expired. The higher the index the less + // expired the lease. + expire(i, 1000 - i); + // Modify subnet ids and lease types for some leases. + if (evenLeaseIndex(i)) { + setSubnetId(i, SubnetID(2)); + setLeaseType(i, Lease::TYPE_PD); + } + } + + // Leases will be reclaimed in groups of 8. + const size_t reclamation_group_size = 8; + for (int i = reclamation_group_size; i < TEST_LEASES_NUM; + i += reclamation_group_size) { + + // Reclaim 8 most expired leases out of TEST_LEASES_NUM. + ASSERT_NO_THROW(reclaimExpiredLeases(reclamation_group_size, + 0, false)); + + // Number of reclaimed leases should increase as we loop. + EXPECT_TRUE(testStatistics("reclaimed-leases", i)); + // Make sure that the number of reclaimed leases is also distributed + // across two subnets. + EXPECT_TRUE(testStatistics("subnet[1].reclaimed-leases", i / 2)); + EXPECT_TRUE(testStatistics("subnet[2].reclaimed-leases", i / 2)); + // Number of assigned leases should decrease as we reclaim them. + EXPECT_TRUE(testStatistics("subnet[1].assigned-nas", + (TEST_LEASES_NUM - i) / 2)); + EXPECT_TRUE(testStatistics("subnet[2].assigned-pds", + (TEST_LEASES_NUM - i) / 2)); + } +} + // This test verifies that the leases can be reclaimed without being removed // from the database. In such case, the leases' state is set to // "expired-reclaimed". @@ -788,6 +944,12 @@ TEST_F(ExpirationAllocEngine6Test, reclaimExpiredLeasesInvalidHostname) { testReclaimExpiredLeasesInvalidHostname(); } +// This test verifies that statistics is correctly updated when the leases +// are reclaimed. +TEST_F(ExpirationAllocEngine6Test, reclaimExpiredLeasesStats) { + testReclaimExpiredLeasesStats(); +} + // ******************************************************* // // DHCPv4 lease reclamation routine tests start here! @@ -829,6 +991,14 @@ public: return (LeaseMgrFactory::instance().getLease4(leases_[lease_index]->addr_)); } + /// @brief Sets subnet id for a lease. + /// + /// It also updates statistics of assigned leases in the stats manager. + /// + /// @param lease_index Lease index. + /// @param id New subnet id. + virtual void setSubnetId(const uint16_t lease_index, const SubnetID& id); + /// @brief Wrapper method running lease reclamation routine. /// /// @param max_leases Maximum number of leases to be reclaimed. @@ -856,6 +1026,10 @@ public: /// @brief Test that DNS updates are properly generated when the /// reclaimed leases contain client identifier. void testReclaimExpiredLeasesWithDDNSAndClientId(); + + /// @brief Test that statistics is updated when leases are reclaimed.. + void testReclaimExpiredLeasesStats(); + }; ExpirationAllocEngine4Test::ExpirationAllocEngine4Test() @@ -886,6 +1060,12 @@ ExpirationAllocEngine4Test::createLeases() { generateHostnameForLeaseIndex(i))); leases_.push_back(lease); LeaseMgrFactory::instance().addLease(lease); + + // Note in the statistics that this lease has been added. + StatsMgr& stats_mgr = StatsMgr::instance(); + std::string stat_name = "assigned-addresses"; + stats_mgr.addValue(stats_mgr.generateName("subnet", lease->subnet_id_, stat_name), + int64_t(1)); } } @@ -900,6 +1080,23 @@ ExpirationAllocEngine4Test::setUniqueClientId(const uint16_t index) { LeaseMgrFactory::instance().updateLease4(leases_[index]); } +void +ExpirationAllocEngine4Test::setSubnetId(const uint16_t lease_index, const SubnetID& id) { + ASSERT_GT(leases_.size(), lease_index); + if (leases_[lease_index]->subnet_id_ != id) { + StatsMgr& stats_mgr = StatsMgr::instance(); + stats_mgr.addValue(stats_mgr.generateName("subnet", id, "assigned-addresses"), + int64_t(1)); + stats_mgr.addValue(stats_mgr.generateName("subnet", + leases_[lease_index]->subnet_id_, + "assigned-addresses"), + int64_t(-1)); + leases_[lease_index]->subnet_id_ = id; + ASSERT_NO_THROW(updateLease(lease_index)); + } +} + + bool ExpirationAllocEngine4Test::dnsUpdateGeneratedFromClientId(const Lease4Ptr& lease) { try { @@ -996,6 +1193,45 @@ ExpirationAllocEngine4Test::testReclaimExpiredLeasesWithDDNSAndClientId() { EXPECT_TRUE(testLeases(&dnsUpdateGeneratedFromHWAddress, &oddLeaseIndex)); } +void +ExpirationAllocEngine4Test::testReclaimExpiredLeasesStats() { + // This test requires that the number of leases is an even number. + BOOST_STATIC_ASSERT(TEST_LEASES_NUM % 2 == 0); + + for (int i = 0; i < TEST_LEASES_NUM; ++i) { + // Mark all leaes as expired. The higher the index the less + // expired the lease. + expire(i, 1000 - i); + // Modify subnet ids of some leases. + if (evenLeaseIndex(i)) { + setSubnetId(i, 2); + } + } + + // Leases will be reclaimed in groups of 8. + const size_t reclamation_group_size = 8; + for (int i = reclamation_group_size; i < TEST_LEASES_NUM; + i += reclamation_group_size) { + + // Reclaim 8 most expired leases out of TEST_LEASES_NUM. + ASSERT_NO_THROW(reclaimExpiredLeases(reclamation_group_size, + 0, false)); + + // Number of reclaimed leases should increase as we loop. + EXPECT_TRUE(testStatistics("reclaimed-leases", i)); + // Make sure that the number of reclaimed leases is also distributed + // across two subnets. + EXPECT_TRUE(testStatistics("subnet[1].reclaimed-leases", i / 2)); + EXPECT_TRUE(testStatistics("subnet[2].reclaimed-leases", i / 2)); + // Number of assigned leases should decrease as we reclaim them. + EXPECT_TRUE(testStatistics("subnet[1].assigned-addresses", + (TEST_LEASES_NUM - i) / 2)); + EXPECT_TRUE(testStatistics("subnet[2].assigned-addresses", + (TEST_LEASES_NUM - i) / 2)); + } +} + + // This test verifies that the leases can be reclaimed without being removed // from the database. In such case, the leases' state is set to // "expired-reclaimed". @@ -1039,4 +1275,10 @@ TEST_F(ExpirationAllocEngine4Test, reclaimExpiredLeasesWithDDNSAndClientId) { testReclaimExpiredLeasesWithDDNSAndClientId(); } +// This test verifies that statistics is correctly updated when the leases +// are reclaimed. +TEST_F(ExpirationAllocEngine4Test, reclaimExpiredLeasesStats) { + testReclaimExpiredLeasesStats(); +} + }; // end of anonymous namespace