Pool capacities have been promoted in code from uint64_t to uint128_t.
Bigint is modelled as an int128_t in statistics, following the precedent of
signed integer of int64_t from statistics.
- "total-nas" is extended to 128 bits as requested in the issue.
- "total-pds" has the same risk of overflowing so it has been extended
as well.
- "total-addresses" always fits in 64 bits, but certain code forces a
128 bit value on it. See Pool::getCapacity(), Subnet::getPoolCapacity(),
Subnet::sumPoolCapacity(). It could have been truncated to a 64 bit value,
but that seems like an unnecessary complication.
Because of the disparity in signedness there is some truncation that can
happen when pool capacity values are passed on to statistics. That only happens
for the last half of the value range, so for prefix ranges larger than /1.
}
- /// @brief Checks the value of statistic for a given subnet.
+ /// @brief Checks the value of an integer statistic for a given subnet.
///
- /// @param subnet_id Identifier of a subnet for which statistics should be
- /// @param name statistic name (e.g. "assigned-addresses", "total-addresses" ...)
+ /// @param subnet_id identifier of a subnet for which the statistic should be checked
+ /// @param name statistic name (e.g. "assigned-addresses", "total-addresses", ...)
/// @param exp_value expected value of the statistic
+ ///
/// @return Number of assigned addresses for a subnet.
void checkSubnetStat(const SubnetID& subnet_id, const std::string& name, int64_t exp_value) const {
// Retrieve statistics name, e.g. subnet[1234].assigned-addresses.
ASSERT_TRUE(obs) << "cannot find: " << stats_name;
EXPECT_EQ(exp_value, obs->getInteger().first);
}
+
+ /// @brief Checks the value of a big integer statistic for a given subnet.
+ ///
+ /// @param subnet_id identifier of a subnet for which the statistic should be checked
+ /// @param name statistic name (e.g. "total-nas", "total-pds", ...)
+ /// @param exp_value expected value of the statistic
+ ///
+ /// @return Number of assigned addresses for a subnet.
+ void checkBigSubnetStat(const SubnetID& subnet_id, const std::string& name, int64_t exp_value) const {
+ // Retrieve statistics name, e.g. subnet[1234].assigned-addresses.
+ const std::string stats_name = StatsMgr::generateName("subnet", subnet_id, name);
+ ObservationPtr obs = StatsMgr::instance().getObservation(stats_name);
+ ASSERT_TRUE(obs) << "cannot find: " << stats_name;
+ EXPECT_EQ(exp_value, obs->getBigInteger().first);
+ }
};
// Tests the following scenario:
-// Copyright (C) 2018-2022 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2018-2023 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
void addValueRow6(ElementPtr value_rows, const SubnetID &subnet_id,
int64_t assigned, int64_t declined, int64_t assigned_pds);
- /// @brief Fetches a single statistic for a subnet from StatsMgr
+ /// @brief Fetches a single integer statistic for a subnet from StatsMgr.
///
/// Uses the given id and name to query the StatsMgr for the desired value.
///
- /// @param subnet_id id of the desired subnet
- /// @param name name of the desired statistic
+ /// @param subnet_id the subnet ID for the desired statistic
+ /// @param name the name of the desired statistic
int64_t getSubnetStat(const SubnetID& subnet_id, const std::string& name);
+
+ /// @brief Fetches a single bigint statistic for a subnet from StatsMgr.
+ ///
+ /// Uses the given id and name to query the StatsMgr for the desired value.
+ ///
+ /// @param subnet_id the subnet ID for the desired statistic
+ /// @param name the name of the desired statistic
+ int128_t getBigSubnetStat(const SubnetID& subnet_id, const std::string& name);
};
int
void
LeaseStatCmdsImpl::addValueRow4(ElementPtr value_rows, const SubnetID &subnet_id,
- int64_t assigned, int64_t declined) {
+ int64_t assigned, int64_t declined) {
ElementPtr row = Element::createList();
row->add(Element::create(static_cast<int64_t>(subnet_id)));
row->add(Element::create(getSubnetStat(subnet_id, "total-addresses")));
void
LeaseStatCmdsImpl::addValueRow6(ElementPtr value_rows, const SubnetID &subnet_id,
- int64_t assigned, int64_t declined, int64_t assigned_pds) {
+ int64_t assigned, int64_t declined, int64_t assigned_pds) {
ElementPtr row = Element::createList();
row->add(Element::create(static_cast<int64_t>(subnet_id)));
- row->add(Element::create(getSubnetStat(subnet_id, "total-nas")));
+ row->add(Element::create(getBigSubnetStat(subnet_id, "total-nas")));
row->add(Element::create(getSubnetStat(subnet_id, "cumulative-assigned-nas")));
row->add(Element::create(assigned));
row->add(Element::create(declined));
- row->add(Element::create(getSubnetStat(subnet_id, "total-pds")));
+ row->add(Element::create(getBigSubnetStat(subnet_id, "total-pds")));
row->add(Element::create(getSubnetStat(subnet_id, "cumulative-assigned-pds")));
row->add(Element::create(assigned_pds));
value_rows->add(row);
return (0);
}
+int128_t
+LeaseStatCmdsImpl::getBigSubnetStat(const SubnetID& subnet_id, const std::string& name) {
+ ObservationPtr stat = StatsMgr::instance().
+ getObservation(StatsMgr::generateName("subnet", subnet_id, name));
+ if (stat) {
+ return (stat->getBigInteger().first);
+ }
+
+ return (0);
+}
+
// Using a critical section to avoid any changes in parallel.
int
using namespace isc;
using namespace isc::asiolink;
+using namespace isc::util;
namespace {
return (IOAddress(x));
}
-uint64_t
+uint128_t
addrsInRange(const IOAddress& min, const IOAddress& max) {
if (min.getFamily() != max.getFamily()) {
isc_throw(BadValue, "Both addresses have to be the same family");
}
}
-uint64_t prefixesInRange(const uint8_t pool_len, const uint8_t delegated_len) {
+uint128_t prefixesInRange(const uint8_t pool_len, const uint8_t delegated_len) {
if (delegated_len < pool_len) {
return (0);
}
- uint64_t count = delegated_len - pool_len;
-
- if (count == 0) {
- // If we want to delegate /64 out of /64 pool, we have only
- // one prefix.
- return (1);
- } else if (count >= 64) {
- // If the difference is greater than or equal 64, e.g. we want to
- // delegate /96 out of /16 pool, the number is bigger than we can
- // express, so we'll stick with maximum value of uint64_t.
- return (std::numeric_limits<uint64_t>::max());
- } else {
- // Now count specifies the exponent (e.g. if the difference between the
- // delegated and pool length is 4, we have 16 prefixes), so we need
- // to calculate 2^(count - 1)
- return ((static_cast<uint64_t>(2)) << (count - 1));
+ uint8_t const count(delegated_len - pool_len);
+
+ if (count == 128) {
+ // One off is the best we can do, unless we promote to uint256_t.
+ return uint128_t(-1);
}
+
+ return (uint128_t(1) << count);
}
IOAddress offsetAddress(const IOAddress& addr, uint64_t offset) {
#define ADDR_UTILITIES_H
#include <asiolink/io_address.h>
+#include <util/bigints.h>
namespace isc {
namespace asiolink {
/// @param min the first address in range
/// @param max the last address in range
/// @return number of addresses in range
-uint64_t addrsInRange(const IOAddress& min, const IOAddress& max);
+isc::util::uint128_t addrsInRange(const IOAddress& min, const IOAddress& max);
/// @brief Returns prefix length from the specified range (min - max).
///
/// @param pool_len length of the pool in bits
/// @param delegated_len length of the prefixes to be delegated from the pool
/// @return number of prefixes in range
-uint64_t prefixesInRange(const uint8_t pool_len, const uint8_t delegated_len);
+isc::util::uint128_t prefixesInRange(const uint8_t pool_len, const uint8_t delegated_len);
/// @brief Finds the address increased by offset.
///
/// @return address being offset greater than the input address
IOAddress offsetAddress(const IOAddress& addr, uint64_t offset);
-};
-};
+} // namespace asiolink
+} // namespace isc
#endif // ADDR_UTILITIES_H
#include <asiolink/addr_utilities.h>
#include <exceptions/exceptions.h>
+#include <util/bigints.h>
#include <gtest/gtest.h>
using namespace std;
using namespace isc::asiolink;
+using namespace isc::util;
namespace {
EXPECT_EQ(uint64_t(9223372036854775808ull), prefixesInRange(64, 127));
// How many /128 prefixes are in /64 pool?
- EXPECT_EQ(std::numeric_limits<uint64_t>::max(),
- prefixesInRange(64, 128));
+ EXPECT_EQ(uint128_t(1) << 64, prefixesInRange(64, 128));
// Let's go overboard again. How many IPv6 addresses are there?
- EXPECT_EQ(std::numeric_limits<uint64_t>::max(),
- prefixesInRange(0, 128));
+ EXPECT_EQ(uint128_t(1) << 127, prefixesInRange(1, 128));
+ // Let's go overboard again. How many IPv6 addresses are there?
+ EXPECT_EQ(uint128_t(-1), prefixesInRange(0, 128));
}
// Checks the function which finds an IPv4 address from input address and offset.
#include <boost/make_shared.hpp>
#include <algorithm>
-#include <limits>
#include <sstream>
#include <stdint.h>
#include <string.h>
namespace isc {
namespace dhcp {
-AllocEngine::AllocEngine(uint64_t attempts)
+AllocEngine::AllocEngine(uint128_t const& attempts)
: attempts_(attempts), incomplete_v4_reclamations_(0),
incomplete_v6_reclamations_(0) {
// - we find a free address
// - we find an address for which the lease has expired
// - we exhaust number of tries
- uint64_t possible_attempts = subnet->getPoolCapacity(ctx.currentIA().type_,
- classes,
- prefix_length_match,
- hint_prefix_length);
+ uint128_t const possible_attempts =
+ subnet->getPoolCapacity(ctx.currentIA().type_,
+ classes,
+ prefix_length_match,
+ hint_prefix_length);
// If the number of tries specified in the allocation engine constructor
// is set to 0 (unlimited) or the pools capacity is lower than that number,
// let's use the pools capacity as the maximum number of tries. Trying
// more than the actual pools capacity is a waste of time. If the specified
// number of tries is lower than the pools capacity, use that number.
- uint64_t max_attempts = ((attempts_ == 0) || (possible_attempts < attempts_)) ? possible_attempts : attempts_;
+ uint128_t const max_attempts =
+ (attempts_ == 0 || possible_attempts < attempts_) ?
+ possible_attempts :
+ attempts_;
if (max_attempts > 0) {
// If max_attempts is greater than 0, there are some pools in this subnet
Subnet4Ptr original_subnet = subnet;
- uint64_t total_attempts = 0;
+ uint128_t total_attempts = 0;
// The following counter tracks the number of subnets with matching client
// classes from which the allocation engine attempted to assign leases.
client_id = ctx.clientid_;
}
- uint64_t possible_attempts =
+ uint128_t const possible_attempts =
subnet->getPoolCapacity(Lease::TYPE_V4, classes);
// If the number of tries specified in the allocation engine constructor
// let's use the pools capacity as the maximum number of tries. Trying
// more than the actual pools capacity is a waste of time. If the specified
// number of tries is lower than the pools capacity, use that number.
- uint64_t max_attempts = ((attempts_ == 0 || possible_attempts < attempts_) ? possible_attempts : attempts_);
+ uint128_t const max_attempts =
+ (attempts_ == 0 || possible_attempts < attempts_) ?
+ possible_attempts :
+ attempts_;
if (max_attempts > 0) {
// If max_attempts is greater than 0, there are some pools in this subnet
CalloutHandle::CalloutNextStep callout_status = CalloutHandle::NEXT_STEP_CONTINUE;
- for (uint64_t i = 0; i < max_attempts; ++i) {
+ for (uint128_t i = 0; i < max_attempts; ++i) {
++total_attempts;
///
/// @param attempts number of attempts for each lease allocation before
/// we give up (0 means unlimited)
- AllocEngine(uint64_t attempts);
+ AllocEngine(isc::util::uint128_t const& attempts);
/// @brief Destructor.
virtual ~AllocEngine() { }
private:
/// @brief number of attempts before we give up lease allocation (0=unlimited)
- uint64_t attempts_;
+ isc::util::uint128_t attempts_;
/// @brief Hook name indexes (used in hooks callouts)
int hook_index_lease4_select_; ///< index for lease4_select hook
#include <exceptions/exceptions.h>
#include <boost/shared_ptr.hpp>
+#include <limits>
#include <vector>
namespace isc {
stats_mgr.setValue(StatsMgr::
generateName("subnet", subnet_id, "total-addresses"),
- static_cast<int64_t>
- (subnet4->getPoolCapacity(Lease::TYPE_V4)));
+ int64_t(subnet4->getPoolCapacity(Lease::TYPE_V4)));
std::string name =
StatsMgr::generateName("subnet", subnet_id, "cumulative-assigned-addresses");
if (!stats_mgr.getObservation(name)) {
stats_mgr.setValue(StatsMgr::generateName("subnet", subnet_id,
"total-nas"),
- static_cast<int64_t>
- (subnet6->getPoolCapacity(Lease::TYPE_NA)));
+ subnet6->getPoolCapacity(Lease::TYPE_NA));
stats_mgr.setValue(StatsMgr::generateName("subnet", subnet_id,
"total-pds"),
- static_cast<int64_t>
- (subnet6->getPoolCapacity(Lease::TYPE_PD)));
+ subnet6->getPoolCapacity(Lease::TYPE_PD));
const std::string& name_nas =
StatsMgr::generateName("subnet", subnet_id, "cumulative-assigned-nas");
-// Copyright (C) 2015-2022 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2015-2023 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
#include <boost/algorithm/string.hpp>
#include <boost/foreach.hpp>
-#include <boost/scoped_ptr.hpp>
#include <algorithm>
#include <iostream>
#include <database/database_connection.h>
#include <dhcpsrv/base_host_data_source.h>
#include <exceptions/exceptions.h>
-#include <boost/scoped_ptr.hpp>
#include <functional>
#include <string>
#include <algorithm>
#include <iostream>
#include <iterator>
+#include <limits>
#include <map>
#include <sstream>
#include <string>
#include <boost/make_shared.hpp>
#include <boost/scoped_ptr.hpp>
+#include <limits>
#include <map>
#include <string>
#include <vector>
#include <exceptions/exceptions.h>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
-#include <limits>
+
#include <string>
using namespace isc::data;
#include <dhcpsrv/parsers/multi_threading_config_parser.h>
#include <util/multi_threading_mgr.h>
+#include <limits>
+
using namespace isc::data;
using namespace isc::util;
-// Copyright (C) 2012-2022 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2023 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
#include <dhcpsrv/cfg_option.h>
#include <dhcpsrv/lease.h>
#include <dhcpsrv/ip_range_permutation.h>
+#include <util/bigints.h>
#include <boost/shared_ptr.hpp>
/// Note that this is the upper bound, assuming that no leases are used
/// and there are no host reservations. This is just a theoretical calculation.
/// @return number of possible leases in this pool
- uint64_t getCapacity() const {
+ isc::util::uint128_t getCapacity() const {
return (capacity_);
}
/// involved, so it is more efficient to calculate it once and just store
/// the result. Note that for very large pools, the number is capped at
/// max value of uint64_t.
- uint64_t capacity_;
+ isc::util::uint128_t capacity_;
/// @brief Pointer to the option data configuration for this pool.
CfgOptionPtr cfg_option_;
#include <boost/make_shared.hpp>
#include <algorithm>
+#include <limits>
#include <sstream>
using namespace isc::asiolink;
using namespace isc::dhcp;
using namespace isc::util;
+using namespace std;
+
namespace {
/// @brief Function used in calls to std::upper_bound to check
return (tmp.str());
}
-uint64_t
+uint128_t
Subnet::getPoolCapacity(Lease::Type type) const {
switch (type) {
case Lease::TYPE_V4:
}
}
-uint64_t
+uint128_t
Subnet::getPoolCapacity(Lease::Type type,
const ClientClasses& client_classes) const {
switch (type) {
}
}
-uint64_t
+uint128_t
Subnet::getPoolCapacity(Lease::Type type,
const ClientClasses& client_classes,
Allocator::PrefixLenMatchType prefix_length_match,
}
}
-uint64_t
+uint128_t
Subnet::sumPoolCapacity(const PoolCollection& pools) const {
- uint64_t sum = 0;
+ uint128_t sum(0);
for (auto const& p : pools) {
- uint64_t x = p->getCapacity();
+ uint128_t const c(p->getCapacity());
- // Check if we can add it. If sum + x > uint64::max, then we would have
+ // Check if we can add it. If sum + c > UINT128_MAX, then we would have
// overflown if we tried to add it.
- if (x > std::numeric_limits<uint64_t>::max() - sum) {
- return (std::numeric_limits<uint64_t>::max());
+ if (c > numeric_limits<uint128_t>::max() - sum) {
+ return (numeric_limits<uint128_t>::max());
}
- sum += x;
+ sum += c;
}
return (sum);
}
-uint64_t
+uint128_t
Subnet::sumPoolCapacity(const PoolCollection& pools,
const ClientClasses& client_classes) const {
- uint64_t sum = 0;
+ uint128_t sum(0);
for (auto const& p : pools) {
if (!p->clientSupported(client_classes)) {
continue;
}
- uint64_t x = p->getCapacity();
- // Check if we can add it. If sum + x > uint64::max, then we would have
+ uint128_t const c(p->getCapacity());
+
+ // Check if we can add it. If sum + c > UINT128_MAX, then we would have
// overflown if we tried to add it.
- if (x > std::numeric_limits<uint64_t>::max() - sum) {
- return (std::numeric_limits<uint64_t>::max());
+ if (c > numeric_limits<uint128_t>::max() - sum) {
+ return (numeric_limits<uint128_t>::max());
}
- sum += x;
+ sum += c;
}
return (sum);
}
-uint64_t
+uint128_t
Subnet::sumPoolCapacity(const PoolCollection& pools,
const ClientClasses& client_classes,
Allocator::PrefixLenMatchType prefix_length_match,
uint8_t hint_prefix_length) const {
- uint64_t sum = 0;
+ uint128_t sum(0);
for (auto const& p : pools) {
if (!p->clientSupported(client_classes)) {
continue;
continue;
}
- uint64_t x = p->getCapacity();
+ uint128_t const c(p->getCapacity());
- // Check if we can add it. If sum + x > uint64::max, then we would have
+ // Check if we can add it. If sum + c > UINT128_MAX, then we would have
// overflown if we tried to add it.
- if (x > std::numeric_limits<uint64_t>::max() - sum) {
- return (std::numeric_limits<uint64_t>::max());
+ if (c > numeric_limits<uint128_t>::max() - sum) {
+ return (numeric_limits<uint128_t>::max());
}
- sum += x;
+ sum += c;
}
return (sum);
#include <dhcpsrv/network.h>
#include <dhcpsrv/pool.h>
#include <dhcpsrv/subnet_id.h>
+#include <util/bigints.h>
#include <util/dhcp_space.h>
#include <util/triplet.h>
#include <boost/multi_index_container.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/pointer_cast.hpp>
-#include <boost/scoped_ptr.hpp>
#include <boost/shared_ptr.hpp>
#include <cstdint>
/// @brief Returns the number of possible leases for specified lease type.
///
/// @param type type of the lease
- uint64_t getPoolCapacity(Lease::Type type) const;
+ isc::util::uint128_t getPoolCapacity(Lease::Type type) const;
/// @brief Returns the number of possible leases for specified lease type
/// allowed for a client which belongs to classes.
/// @param type type of the lease
/// @param client_classes list of classes the client belongs to
/// @return number of leases matching lease type and classes
- uint64_t getPoolCapacity(Lease::Type type,
- const ClientClasses& client_classes) const;
+ isc::util::uint128_t getPoolCapacity(Lease::Type type,
+ const ClientClasses& client_classes) const;
/// @brief Returns the number of possible leases for specified lease type
/// allowed for a client which belongs to classes and matching selection
/// @param hint_prefix_length the hint prefix length that the client
/// provided
/// @return number of leases matching lease type and classes
- uint64_t getPoolCapacity(Lease::Type type,
- const ClientClasses& client_classes,
- Allocator::PrefixLenMatchType prefix_length_match,
- uint8_t hint_prefix_length) const;
+ isc::util::uint128_t getPoolCapacity(Lease::Type type,
+ const ClientClasses& client_classes,
+ Allocator::PrefixLenMatchType prefix_length_match,
+ uint8_t hint_prefix_length) const;
/// @brief Returns textual representation of the subnet (e.g.
/// "2001:db8::/64").
///
/// @param pools list of pools
/// @return sum of possible leases
- uint64_t sumPoolCapacity(const PoolCollection& pools) const;
+ isc::util::uint128_t sumPoolCapacity(const PoolCollection& pools) const;
/// @brief Returns a sum of possible leases in all pools allowing classes.
///
/// @param pools list of pools
/// @param client_classes list of classes
/// @return sum of possible/allowed leases
- uint64_t sumPoolCapacity(const PoolCollection& pools,
- const ClientClasses& client_classes) const;
+ isc::util::uint128_t sumPoolCapacity(const PoolCollection& pools,
+ const ClientClasses& client_classes) const;
/// @brief Returns a sum of possible leases in all pools allowing classes
/// and matching selection criteria relative to provided hint prefix length.
/// @param hint_prefix_length the hint prefix length that the client
/// provided
/// @return sum of possible/allowed leases
- uint64_t sumPoolCapacity(const PoolCollection& pools,
- const ClientClasses& client_classes,
- Allocator::PrefixLenMatchType prefix_length_match,
- uint8_t hint_prefix_length) const;
+ isc::util::uint128_t sumPoolCapacity(const PoolCollection& pools,
+ const ClientClasses& client_classes,
+ Allocator::PrefixLenMatchType prefix_length_match,
+ uint8_t hint_prefix_length) const;
/// @brief Checks if the specified pool overlaps with an existing pool.
///
StatsMgr::generateName("subnet", subnet_id,
"total-nas"));
ASSERT_TRUE(observation);
- ASSERT_EQ(0, observation->getInteger().first);
+ ASSERT_EQ(0, observation->getBigInteger().first);
observation = StatsMgr::instance().getObservation(
StatsMgr::generateName("subnet", subnet_id,
"total-pds"));
ASSERT_TRUE(observation);
- ASSERT_EQ(0, observation->getInteger().first);
+ ASSERT_EQ(0, observation->getBigInteger().first);
observation = StatsMgr::instance().getObservation(
StatsMgr::generateName("subnet", subnet_id,
StatsMgr::instance().setValue(
StatsMgr::generateName("subnet", subnet_id,
"total-nas"),
- int64_t(0));
+ int128_t(0));
observation = StatsMgr::instance().getObservation(
StatsMgr::generateName("subnet", subnet_id,
"total-nas"));
ASSERT_TRUE(observation);
- ASSERT_EQ(0, observation->getInteger().first);
+ ASSERT_EQ(0, observation->getBigInteger().first);
StatsMgr::instance().setValue(
StatsMgr::generateName("subnet", subnet_id,
"total-pds"),
- int64_t(0));
+ int128_t(0));
observation = StatsMgr::instance().getObservation(
StatsMgr::generateName("subnet", subnet_id,
"total-pds"));
ASSERT_TRUE(observation);
- ASSERT_EQ(0, observation->getInteger().first);
+ ASSERT_EQ(0, observation->getBigInteger().first);
StatsMgr::instance().setValue(
StatsMgr::generateName("subnet", subnet_id,
-// Copyright (C) 2012-2022 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2023 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
#include <stats/stats_mgr.h>
#include <util/chrono_time_utils.h>
-#include <boost/scoped_ptr.hpp>
-
#include <gtest/gtest.h>
#include <iostream>
using namespace isc::process;
using namespace isc;
-// don't import the entire boost namespace. It will unexpectedly hide uint8_t
-// for some systems.
-using boost::scoped_ptr;
-
namespace {
template <typename Storage>
CfgSubnets4Ptr subnets = cfg_mgr.getStagingCfg()->getCfgSubnets4();
subnets->add(subnet1);
cfg_mgr.commit();
- stats_mgr.addValue("subnet[123].total-addresses", static_cast<int64_t>(256));
+ stats_mgr.addValue("subnet[123].total-addresses", int64_t(256));
stats_mgr.setValue("subnet[123].assigned-addresses", static_cast<int64_t>(150));
// Now, let's change the configuration to something new.
CfgSubnets4Ptr subnets = cfg_mgr.getStagingCfg()->getCfgSubnets4();
subnets->add(subnet1);
cfg_mgr.commit();
- stats_mgr.addValue("subnet[123].total-addresses", static_cast<int64_t>(256));
+ stats_mgr.addValue("subnet[123].total-addresses", int64_t(256));
stats_mgr.setValue("subnet[123].assigned-addresses", static_cast<int64_t>(150));
// There should be no stats for subnet 42 at this point.
CfgSubnets4Ptr subnets = cfg_mgr.getStagingCfg()->getCfgSubnets4();
subnets->add(subnet1);
cfg_mgr.commit();
- stats_mgr.addValue("subnet[123].total-addresses", static_cast<int64_t>(256));
+ stats_mgr.addValue("subnet[123].total-addresses", int64_t(256));
stats_mgr.setValue("subnet[123].assigned-addresses", static_cast<int64_t>(150));
// The stats should be there.
CfgSubnets6Ptr subnets = cfg_mgr.getStagingCfg()->getCfgSubnets6();
subnets->add(subnet1);
cfg_mgr.commit();
- stats_mgr.addValue("subnet[123].total-nas", static_cast<int64_t>(256));
+ stats_mgr.addValue("subnet[123].total-nas", int128_t(256));
stats_mgr.setValue("subnet[123].assigned-nas", static_cast<int64_t>(150));
- stats_mgr.addValue("subnet[123].total-pds", static_cast<int64_t>(256));
+ stats_mgr.addValue("subnet[123].total-pds", int128_t(256));
stats_mgr.setValue("subnet[123].assigned-pds", static_cast<int64_t>(150));
// Now, let's change the configuration to something new.
ObservationPtr total_addrs;
EXPECT_NO_THROW(total_addrs = stats_mgr.getObservation("subnet[42].total-nas"));
ASSERT_TRUE(total_addrs);
- EXPECT_EQ(128, total_addrs->getInteger().first);
+ EXPECT_EQ(128, total_addrs->getBigInteger().first);
EXPECT_TRUE(total_addrs->getMaxSampleCount().first);
EXPECT_EQ(14, total_addrs->getMaxSampleCount().second);
EXPECT_FALSE(total_addrs->getMaxSampleAge().first);
ObservationPtr total_prfx;
EXPECT_NO_THROW(total_prfx = stats_mgr.getObservation("subnet[42].total-pds"));
ASSERT_TRUE(total_prfx);
- EXPECT_EQ(65536, total_prfx->getInteger().first);
+ EXPECT_EQ(65536, total_prfx->getBigInteger().first);
EXPECT_TRUE(total_prfx->getMaxSampleCount().first);
EXPECT_EQ(14, total_prfx->getMaxSampleCount().second);
EXPECT_FALSE(total_prfx->getMaxSampleAge().first);
ObservationPtr total_addrs;
EXPECT_NO_THROW(total_addrs = stats_mgr.getObservation("subnet[42].total-nas"));
ASSERT_TRUE(total_addrs);
- EXPECT_EQ(128, total_addrs->getInteger().first);
+ EXPECT_EQ(128, total_addrs->getBigInteger().first);
EXPECT_NO_THROW(total_addrs = stats_mgr.getObservation("subnet[42].total-pds"));
ASSERT_TRUE(total_addrs);
- EXPECT_EQ(65536, total_addrs->getInteger().first);
+ EXPECT_EQ(65536, total_addrs->getBigInteger().first);
}
// This test verifies that once the configuration is cleared, the v6 statistics
#include <gtest/gtest.h>
#include <boost/foreach.hpp>
#include <boost/pointer_cast.hpp>
-#include <boost/scoped_ptr.hpp>
#include <map>
#include <string>
#include <dhcpsrv/testutils/test_utils.h>
#include <exceptions/exceptions.h>
#include <stats/stats_mgr.h>
+#include <stats/testutils/stats_test_utils.h>
#include <testutils/gtest_utils.h>
+#include <util/bigints.h>
#include <boost/foreach.hpp>
#include <boost/scoped_ptr.hpp>
using namespace isc::asiolink;
using namespace isc::data;
using namespace isc::db;
+using namespace isc::stats;
+using namespace isc::util;
+
+using isc::stats::test::checkStat;
+
namespace ph = std::placeholders;
namespace isc {
/// a template
leasetype6_.push_back(LEASETYPE6[i]);
}
+
+ // Clear all subnets defined in previous tests.
+ for (Subnet4Ptr const& subnet : *CfgMgr::instance().getStagingCfg()->getCfgSubnets4()->getAll()) {
+ CfgMgr::instance().getStagingCfg()->getCfgSubnets4()->del(subnet);
+ }
+ for (Subnet6Ptr const& subnet : *CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->getAll()) {
+ CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->del(subnet);
+ }
+
+ // Clear all stats.
+ StatsMgr::instance().removeAll();
}
GenericLeaseMgrTest::~GenericLeaseMgrTest() {
}
}
-void
-GenericLeaseMgrTest::checkStat(const std::string& name,
- const int64_t expected_value) {
- stats::ObservationPtr obs =
- stats::StatsMgr::instance().getObservation(name);
-
- ASSERT_TRUE(obs) << " stat: " << name << " not found ";
- ASSERT_EQ(expected_value, obs->getInteger().first)
- << " stat: " << name << " value wrong";
-}
-
void
GenericLeaseMgrTest::checkLeaseStats(const StatValMapList& expectedStats) {
// Global accumulators
ASSERT_NO_FATAL_FAILURE(checkLeaseStats(expectedStats));
}
-
void
GenericLeaseMgrTest::testRecountLeaseStats6() {
using namespace stats;
EXPECT_TRUE(logs_.empty());
}
+void
+GenericLeaseMgrTest::testBigStats() {
+ StatValMapList expected_stats(1);
+
+ // Create the largest possible subnet with the largest possible IPv4 pool.
+ Subnet4Ptr subnet4(new Subnet4(IOAddress("0.0.0.0"), 1, 1, 2, 3, 1));
+ subnet4->addPool(Pool4Ptr(new Pool4(IOAddress("0.0.0.0"), 1)));
+ expected_stats[0]["total-addresses"] = 2147483648;
+
+ // Create the largest possible subnet with the largest possible IA_NA pool.
+ Subnet6Ptr subnet6(new Subnet6(IOAddress("::"), 1, 1, 2, 3, 4, 1));
+ subnet6->addPool(Pool6Ptr(new Pool6(Lease::TYPE_NA, IOAddress("::"), 1)));
+
+ // Add the largest possible IA_PD pool.
+ subnet6->addPool(Pool6Ptr(new Pool6(Lease::TYPE_PD, IOAddress("8000::"), 1)));
+
+ // Commit the subnets to the configurations.
+ CfgMgr::instance().getStagingCfg()->getCfgSubnets4()->add(subnet4);
+ CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet6);
+ ASSERT_NO_THROW(CfgMgr::instance().commit());
+
+ // Create the expected stats list. At this point, the only stats
+ // that should be non-zero are total-addresses, total-nas, total-pds.
+ expected_stats[0]["assigned-nas"] = 0;
+ expected_stats[0]["declined-addresses"] = 0;
+ expected_stats[0]["reclaimed-declined-addresses"] = 0;
+ expected_stats[0]["assigned-pds"] = 0;
+ expected_stats[0]["reclaimed-leases"] = 0;
+
+ // Make sure stats are as expected.
+ ASSERT_NO_THROW(checkLeaseStats(expected_stats));
+
+ // Check the big integers separately.
+ int128_t const two_to_the_power_of_127(int128_t(1) << 127);
+ checkStat(StatsMgr::generateName("subnet", 1, "total-nas"), two_to_the_power_of_127);
+ checkStat(StatsMgr::generateName("subnet", 1, "total-pds"), two_to_the_power_of_127);
+}
+
} // namespace test
} // namespace dhcp
} // namespace isc
/// @return vector<Lease6Ptr> Vector of pointers to leases
std::vector<Lease6Ptr> createLeases6();
- /// @brief Compares a StatsMgr statistic to an expected value
- ///
- /// Attempt to fetch the named statistic from the StatsMgr and if
- /// found, compare its observed value to the given value.
- /// Fails if the stat is not found or if the values do not match.
- ///
- /// @param name StatsMgr name for the statistic to check
- /// @param expected_value expected value of the statistic
- void checkStat(const std::string& name, const int64_t expected_value);
-
/// @brief Compares StatsMgr statistics against an expected list of values
///
/// Iterates over a list of statistic names and expected values, attempting
/// lease manager.
void testRecreateWithoutCallbacks(const std::string& access);
+ /// @brief Checks that statistic with big integer values are handled correctly.
+ void testBigStats();
+
/// @brief String forms of IPv4 addresses
std::vector<std::string> straddress4_;
testRecreateWithoutCallbacks(getConfigString(V4));
}
+TEST_F(MemfileLeaseMgrTest, bigStats) {
+ startBackend(V4);
+ testBigStats();
+}
+
} // namespace
testRecreateWithoutCallbacks(validMySQLConnectionString());
}
+TEST_F(MySqlLeaseMgrTest, bigStats) {
+ testBigStats();
+}
+
} // namespace
testRecreateWithoutCallbacks(validPgSQLConnectionString());
}
+TEST_F(PgSqlLeaseMgrTest, bigStats) {
+ testBigStats();
+}
} // namespace
#include <dhcpsrv/pool.h>
#include <testutils/test_to_element.h>
-#include <boost/scoped_ptr.hpp>
-
#include <gtest/gtest.h>
#include <iostream>
#include <vector>
#include <sstream>
-using boost::scoped_ptr;
using namespace isc;
using namespace isc::dhcp;
using namespace isc::data;
#include <exceptions/exceptions.h>
#include <boost/pointer_cast.hpp>
-#include <boost/scoped_ptr.hpp>
-#include <gtest/gtest.h>
-#include <limits>
-// don't import the entire boost namespace. It will unexpectedly hide uint8_t
-// for some systems.
-using boost::scoped_ptr;
+#include <gtest/gtest.h>
using namespace isc;
using namespace isc::dhcp;
// This is 2^64.
PoolPtr pool4(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:4::"), 48, 112));
subnet->addPool(pool4);
- EXPECT_EQ(std::numeric_limits<uint64_t>::max(),
+ EXPECT_EQ(65536 + 4294967296ull + 4294967296ull + (int128_t(1) << 64),
subnet->getPoolCapacity(Lease::TYPE_PD));
PoolPtr pool5(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:5::"), 48, 112));
subnet->addPool(pool5);
- EXPECT_EQ(std::numeric_limits<uint64_t>::max(),
+ EXPECT_EQ(65536 + 4294967296ull + 4294967296ull + (int128_t(1) << 64) + (int128_t(1) << 64),
subnet->getPoolCapacity(Lease::TYPE_PD));
}
#include <stats/observation.h>
#include <util/chrono_time_utils.h>
#include <cc/data.h>
+
#include <chrono>
#include <utility>
using namespace std;
using namespace std::chrono;
using namespace isc::data;
+using namespace isc::util;
namespace isc {
namespace stats {
setValue(value);
}
+Observation::Observation(const std::string& name, const int128_t& value) :
+ name_(name), type_(STAT_BIG_INTEGER),
+ max_sample_count_(default_max_sample_count_),
+ max_sample_age_(default_max_sample_age_) {
+ setValue(value);
+}
+
Observation::Observation(const std::string& name, const double value) :
name_(name), type_(STAT_FLOAT),
max_sample_count_(default_max_sample_count_),
setMaxSampleAgeInternal(integer_samples_, duration, STAT_INTEGER);
return;
}
+ case STAT_BIG_INTEGER: {
+ setMaxSampleAgeInternal(big_integer_samples_, duration, STAT_BIG_INTEGER);
+ return;
+ }
case STAT_FLOAT: {
setMaxSampleAgeInternal(float_samples_, duration, STAT_FLOAT);
return;
setMaxSampleCountInternal(integer_samples_, max_samples, STAT_INTEGER);
return;
}
+ case STAT_BIG_INTEGER: {
+ setMaxSampleCountInternal(big_integer_samples_, max_samples, STAT_BIG_INTEGER);
+ return;
+ }
case STAT_FLOAT: {
setMaxSampleCountInternal(float_samples_, max_samples, STAT_FLOAT);
return;
setValue(current.first + value);
}
+void Observation::addValue(const int128_t& value) {
+ BigIntegerSample current = getBigInteger();
+ setValue(current.first + value);
+}
+
void Observation::addValue(const double value) {
FloatSample current = getFloat();
setValue(current.first + value);
setValueInternal(value, integer_samples_, STAT_INTEGER);
}
+void Observation::setValue(const int128_t& value) {
+ setValueInternal(value, big_integer_samples_, STAT_BIG_INTEGER);
+}
+
void Observation::setValue(const double value) {
setValueInternal(value, float_samples_, STAT_FLOAT);
}
size = getSizeInternal(integer_samples_, STAT_INTEGER);
return (size);
}
+ case STAT_BIG_INTEGER: {
+ size = getSizeInternal(big_integer_samples_, STAT_BIG_INTEGER);
+ return (size);
+ }
case STAT_FLOAT: {
size = getSizeInternal(float_samples_, STAT_FLOAT);
return (size);
return (getValueInternal<IntegerSample>(integer_samples_, STAT_INTEGER));
}
+BigIntegerSample Observation::getBigInteger() const {
+ return (getValueInternal<BigIntegerSample>(big_integer_samples_, STAT_BIG_INTEGER));
+}
+
FloatSample Observation::getFloat() const {
return (getValueInternal<FloatSample>(float_samples_, STAT_FLOAT));
}
return (getValuesInternal<IntegerSample>(integer_samples_, STAT_INTEGER));
}
+std::list<BigIntegerSample> Observation::getBigIntegers() const {
+ return (getValuesInternal<BigIntegerSample>(big_integer_samples_, STAT_BIG_INTEGER));
+}
+
std::list<FloatSample> Observation::getFloats() const {
return (getValuesInternal<FloatSample>(float_samples_, STAT_FLOAT));
}
case STAT_INTEGER:
tmp << "integer";
break;
+ case STAT_BIG_INTEGER:
+ tmp << "big integer";
+ break;
case STAT_FLOAT:
tmp << "float";
break;
}
break;
}
+ case STAT_BIG_INTEGER: {
+ std::list<BigIntegerSample> const& samples(getBigIntegers());
+
+ // Iterate over all elements in the list and alternately add
+ // value and timestamp to the entry.
+ for (BigIntegerSample const& i : samples) {
+ entry = isc::data::Element::createList();
+ value = isc::data::Element::create(i.first);
+ timestamp = isc::data::Element::create(isc::util::clockToText(i.second));
+
+ entry->add(value);
+ entry->add(timestamp);
+
+ list->add(entry);
+ }
+ break;
+ }
case STAT_FLOAT: {
std::list<FloatSample> s = getFloats();
setValue(static_cast<int64_t>(0));
return;
}
+ case STAT_BIG_INTEGER: {
+ big_integer_samples_.clear();
+ setValue(int128_t(0));
+ return;
+ }
case STAT_FLOAT: {
float_samples_.clear();
setValue(0.0);
#include <cc/data.h>
#include <exceptions/exceptions.h>
+#include <util/bigints.h>
+
#include <boost/shared_ptr.hpp>
+
#include <chrono>
#include <list>
+
#include <stdint.h>
namespace isc {
/// @brief Integer (implemented as signed 64-bit integer)
typedef std::pair<int64_t, SampleClock::time_point> IntegerSample;
+/// @brief BigInteger (implemented as signed 128-bit integer)
+typedef std::pair<isc::util::int128_t, SampleClock::time_point> BigIntegerSample;
+
/// @brief Float (implemented as double precision)
typedef std::pair<double, SampleClock::time_point> FloatSample;
/// int64_t and double. If convincing use cases appear to change them
/// to something else, we may change the underlying type.
enum Type {
- STAT_INTEGER, ///< this statistic is unsigned 64-bit integer value
- STAT_FLOAT, ///< this statistic is a floating point value
- STAT_DURATION,///< this statistic represents time duration
- STAT_STRING ///< this statistic represents a string
+ STAT_INTEGER, ///< this statistic is signed 64-bit integer value
+ STAT_BIG_INTEGER, ///< this statistic is signed 128-bit integer value
+ STAT_FLOAT, ///< this statistic is a floating point value
+ STAT_DURATION, ///< this statistic represents time duration
+ STAT_STRING ///< this statistic represents a string
};
/// @brief Constructor for integer observations
/// @param value integer value observed.
Observation(const std::string& name, const int64_t value);
+ /// @brief Constructor for big integer observations
+ ///
+ /// @param name observation name
+ /// @param value integer value observed.
+ Observation(const std::string& name, const isc::util::int128_t& value);
+
/// @brief Constructor for floating point observations
///
/// @param name observation name
/// @throw InvalidStatType if statistic is not integer
void setValue(const int64_t value);
+ /// @brief Records big integer observation
+ ///
+ /// @param value integer value observed
+ /// @throw InvalidStatType if statistic is not integer
+ void setValue(const isc::util::int128_t& value);
+
/// @brief Records absolute floating point observation
///
/// @param value floating point value observed
/// @throw InvalidStatType if statistic is not integer
void addValue(const int64_t value);
+ /// @brief Records incremental integer observation
+ ///
+ /// @param value integer value observed
+ /// @throw InvalidStatType if statistic is not integer
+ void addValue(const isc::util::int128_t& value);
+
/// @brief Records incremental floating point observation
///
/// @param value floating point value observed
/// @throw InvalidStatType if statistic is not integer
IntegerSample getInteger() const;
+ /// @brief Returns observed integer sample
+ /// @return observed sample (value + timestamp)
+ /// @throw InvalidStatType if statistic is not integer
+ BigIntegerSample getBigInteger() const;
+
/// @brief Returns observed float sample
/// @return observed sample (value + timestamp)
/// @throw InvalidStatType if statistic is not fp
/// @throw InvalidStatType if statistic is not integer
std::list<IntegerSample> getIntegers() const;
+ /// @brief Returns observed big-integer samples
+ /// @return list of observed samples (value + timestamp)
+ /// @throw InvalidStatType if statistic is not integer
+ std::list<BigIntegerSample> getBigIntegers() const;
+
/// @brief Returns observed float samples
/// @return list of observed samples (value + timestamp)
/// @throw InvalidStatType if statistic is not fp
/// @brief Storage for integer samples
std::list<IntegerSample> integer_samples_;
+ /// @brief Storage for big integer samples
+ std::list<BigIntegerSample> big_integer_samples_;
+
/// @brief Storage for floating point samples
std::list<FloatSample> float_samples_;
#include <cc/data.h>
#include <cc/command_interpreter.h>
#include <util/multi_threading_mgr.h>
+#include <util/bigints.h>
+
#include <boost/make_shared.hpp>
+
#include <chrono>
using namespace std;
void
StatsMgr::setValue(const string& name, const int64_t value) {
- if (MultiThreadingMgr::instance().getMode()) {
- lock_guard<mutex> lock(*mutex_);
- setValueInternal(name, value);
- } else {
- setValueInternal(name, value);
- }
+ MultiThreadingLock lock(*mutex_);
+ setValueInternal(name, value);
+}
+
+void
+StatsMgr::setValue(const string& name, const int128_t& value) {
+ MultiThreadingLock lock(*mutex_);
+ setValueInternal(name, value);
}
void
StatsMgr::setValue(const string& name, const double value) {
- if (MultiThreadingMgr::instance().getMode()) {
- lock_guard<mutex> lock(*mutex_);
- setValueInternal(name, value);
- } else {
- setValueInternal(name, value);
- }
+ MultiThreadingLock lock(*mutex_);
+ setValueInternal(name, value);
}
void
StatsMgr::setValue(const string& name, const StatsDuration& value) {
- if (MultiThreadingMgr::instance().getMode()) {
- lock_guard<mutex> lock(*mutex_);
- setValueInternal(name, value);
- } else {
- setValueInternal(name, value);
- }
+ MultiThreadingLock lock(*mutex_);
+ setValueInternal(name, value);
}
void
StatsMgr::setValue(const string& name, const string& value) {
- if (MultiThreadingMgr::instance().getMode()) {
- lock_guard<mutex> lock(*mutex_);
- setValueInternal(name, value);
- } else {
- setValueInternal(name, value);
- }
+ MultiThreadingLock lock(*mutex_);
+ setValueInternal(name, value);
}
void
StatsMgr::addValue(const string& name, const int64_t value) {
- if (MultiThreadingMgr::instance().getMode()) {
- lock_guard<mutex> lock(*mutex_);
- addValueInternal(name, value);
- } else {
- addValueInternal(name, value);
- }
+ MultiThreadingLock lock(*mutex_);
+ addValueInternal(name, value);
+}
+
+void
+StatsMgr::addValue(const string& name, const int128_t& value) {
+ MultiThreadingLock lock(*mutex_);
+ addValueInternal(name, value);
}
void
StatsMgr::addValue(const string& name, const double value) {
- if (MultiThreadingMgr::instance().getMode()) {
- lock_guard<mutex> lock(*mutex_);
- addValueInternal(name, value);
- } else {
- addValueInternal(name, value);
- }
+ MultiThreadingLock lock(*mutex_);
+ addValueInternal(name, value);
}
void
StatsMgr::addValue(const string& name, const StatsDuration& value) {
- if (MultiThreadingMgr::instance().getMode()) {
- lock_guard<mutex> lock(*mutex_);
- addValueInternal(name, value);
- } else {
- addValueInternal(name, value);
- }
+ MultiThreadingLock lock(*mutex_);
+ addValueInternal(name, value);
}
void
StatsMgr::addValue(const string& name, const string& value) {
- if (MultiThreadingMgr::instance().getMode()) {
- lock_guard<mutex> lock(*mutex_);
- addValueInternal(name, value);
- } else {
- addValueInternal(name, value);
- }
+ MultiThreadingLock lock(*mutex_);
+ addValueInternal(name, value);
}
ObservationPtr
StatsMgr::getObservation(const string& name) const {
- if (MultiThreadingMgr::instance().getMode()) {
- lock_guard<mutex> lock(*mutex_);
- return (getObservationInternal(name));
- } else {
- return (getObservationInternal(name));
- }
+ MultiThreadingLock lock(*mutex_);
+ return (getObservationInternal(name));
}
ObservationPtr
void
StatsMgr::addObservation(const ObservationPtr& stat) {
- if (MultiThreadingMgr::instance().getMode()) {
- lock_guard<mutex> lock(*mutex_);
- addObservationInternal(stat);
- } else {
- addObservationInternal(stat);
- }
+ MultiThreadingLock lock(*mutex_);
+ addObservationInternal(stat);
}
void
bool
StatsMgr::deleteObservation(const string& name) {
- if (MultiThreadingMgr::instance().getMode()) {
- lock_guard<mutex> lock(*mutex_);
- return (deleteObservationInternal(name));
- } else {
- return (deleteObservationInternal(name));
- }
+ MultiThreadingLock lock(*mutex_);
+ return (deleteObservationInternal(name));
}
bool
bool
StatsMgr::setMaxSampleAge(const string& name, const StatsDuration& duration) {
- if (MultiThreadingMgr::instance().getMode()) {
- lock_guard<mutex> lock(*mutex_);
- return (setMaxSampleAgeInternal(name, duration));
- } else {
- return (setMaxSampleAgeInternal(name, duration));
- }
+ MultiThreadingLock lock(*mutex_);
+ return (setMaxSampleAgeInternal(name, duration));
}
bool
bool
StatsMgr::setMaxSampleCount(const string& name, uint32_t max_samples) {
- if (MultiThreadingMgr::instance().getMode()) {
- lock_guard<mutex> lock(*mutex_);
- return (setMaxSampleCountInternal(name, max_samples));
- } else {
- return (setMaxSampleCountInternal(name, max_samples));
- }
+ MultiThreadingLock lock(*mutex_);
+ return (setMaxSampleCountInternal(name, max_samples));
}
bool
void
StatsMgr::setMaxSampleAgeAll(const StatsDuration& duration) {
- if (MultiThreadingMgr::instance().getMode()) {
- lock_guard<mutex> lock(*mutex_);
- setMaxSampleAgeAllInternal(duration);
- } else {
- setMaxSampleAgeAllInternal(duration);
- }
+ MultiThreadingLock lock(*mutex_);
+ setMaxSampleAgeAllInternal(duration);
}
void
void
StatsMgr::setMaxSampleCountAll(uint32_t max_samples) {
- if (MultiThreadingMgr::instance().getMode()) {
- lock_guard<mutex> lock(*mutex_);
- setMaxSampleCountAllInternal(max_samples);
- } else {
- setMaxSampleCountAllInternal(max_samples);
- }
+ MultiThreadingLock lock(*mutex_);
+ setMaxSampleCountAllInternal(max_samples);
}
void
void
StatsMgr::setMaxSampleAgeDefault(const StatsDuration& duration) {
- if (MultiThreadingMgr::instance().getMode()) {
- lock_guard<mutex> lock(*mutex_);
- setMaxSampleAgeDefaultInternal(duration);
- } else {
- setMaxSampleAgeDefaultInternal(duration);
- }
+ MultiThreadingLock lock(*mutex_);
+ setMaxSampleAgeDefaultInternal(duration);
}
void
void
StatsMgr::setMaxSampleCountDefault(uint32_t max_samples) {
- if (MultiThreadingMgr::instance().getMode()) {
- lock_guard<mutex> lock(*mutex_);
- setMaxSampleCountDefaultInternal(max_samples);
- } else {
- setMaxSampleCountDefaultInternal(max_samples);
- }
+ MultiThreadingLock lock(*mutex_);
+ setMaxSampleCountDefaultInternal(max_samples);
}
void
const StatsDuration&
StatsMgr::getMaxSampleAgeDefault() const {
- if (MultiThreadingMgr::instance().getMode()) {
- lock_guard<mutex> lock(*mutex_);
- return (getMaxSampleAgeDefaultInternal());
- } else {
- return (getMaxSampleAgeDefaultInternal());
- }
+ MultiThreadingLock lock(*mutex_);
+ return (getMaxSampleAgeDefaultInternal());
}
const StatsDuration&
uint32_t
StatsMgr::getMaxSampleCountDefault() const {
- if (MultiThreadingMgr::instance().getMode()) {
- lock_guard<mutex> lock(*mutex_);
- return (getMaxSampleCountDefaultInternal());
- } else {
- return (getMaxSampleCountDefaultInternal());
- }
+ MultiThreadingLock lock(*mutex_);
+ return (getMaxSampleCountDefaultInternal());
}
uint32_t
bool
StatsMgr::reset(const string& name) {
- if (MultiThreadingMgr::instance().getMode()) {
- lock_guard<mutex> lock(*mutex_);
- return (resetInternal(name));
- } else {
- return (resetInternal(name));
- }
+ MultiThreadingLock lock(*mutex_);
+ return (resetInternal(name));
}
bool
bool
StatsMgr::del(const string& name) {
- if (MultiThreadingMgr::instance().getMode()) {
- lock_guard<mutex> lock(*mutex_);
- return (delInternal(name));
- } else {
- return (delInternal(name));
- }
+ MultiThreadingLock lock(*mutex_);
+ return (delInternal(name));
}
bool
void
StatsMgr::removeAll() {
- if (MultiThreadingMgr::instance().getMode()) {
- lock_guard<mutex> lock(*mutex_);
- removeAllInternal();
- } else {
- removeAllInternal();
- }
+ MultiThreadingLock lock(*mutex_);
+ removeAllInternal();
}
void
ConstElementPtr
StatsMgr::get(const string& name) const {
- if (MultiThreadingMgr::instance().getMode()) {
- lock_guard<mutex> lock(*mutex_);
- return (getInternal(name));
- } else {
- return (getInternal(name));
- }
+ MultiThreadingLock lock(*mutex_);
+ return (getInternal(name));
}
ConstElementPtr
ConstElementPtr
StatsMgr::getAll() const {
- if (MultiThreadingMgr::instance().getMode()) {
- lock_guard<mutex> lock(*mutex_);
- return (getAllInternal());
- } else {
- return (getAllInternal());
- }
+ MultiThreadingLock lock(*mutex_);
+ return (getAllInternal());
}
ConstElementPtr
void
StatsMgr::resetAll() {
- if (MultiThreadingMgr::instance().getMode()) {
- lock_guard<mutex> lock(*mutex_);
- resetAllInternal();
- } else {
- resetAllInternal();
- }
+ MultiThreadingLock lock(*mutex_);
+ resetAllInternal();
}
void
size_t
StatsMgr::getSize(const string& name) const {
- if (MultiThreadingMgr::instance().getMode()) {
- lock_guard<mutex> lock(*mutex_);
- return (getSizeInternal(name));
- } else {
- return (getSizeInternal(name));
- }
+ MultiThreadingLock lock(*mutex_);
+ return (getSizeInternal(name));
}
size_t
size_t
StatsMgr::count() const {
- if (MultiThreadingMgr::instance().getMode()) {
- lock_guard<mutex> lock(*mutex_);
- return (countInternal());
- } else {
- return (countInternal());
- }
+ MultiThreadingLock lock(*mutex_);
+ return (countInternal());
}
size_t
if (!StatsMgr::getStatDuration(params, duration, error)) {
return (createAnswer(CONTROL_RESULT_ERROR, error));
}
- if (MultiThreadingMgr::instance().getMode()) {
- lock_guard<mutex> lock(*mutex_);
- StatsMgr::instance().setMaxSampleCountDefaultInternal(0);
- StatsMgr::instance().setMaxSampleAgeDefaultInternal(duration);
- StatsMgr::instance().setMaxSampleAgeAllInternal(duration);
- } else {
- StatsMgr::instance().setMaxSampleCountDefaultInternal(0);
- StatsMgr::instance().setMaxSampleAgeDefaultInternal(duration);
- StatsMgr::instance().setMaxSampleAgeAllInternal(duration);
- }
+ MultiThreadingLock lock(*mutex_);
+ StatsMgr::instance().setMaxSampleCountDefaultInternal(0);
+ StatsMgr::instance().setMaxSampleAgeDefaultInternal(duration);
+ StatsMgr::instance().setMaxSampleAgeAllInternal(duration);
return (createAnswer(CONTROL_RESULT_SUCCESS,
"All statistics duration limit are set."));
}
error = "'max-samples' parameter must not be zero";
return (createAnswer(CONTROL_RESULT_ERROR, error));
}
- if (MultiThreadingMgr::instance().getMode()) {
- lock_guard<mutex> lock(*mutex_);
- StatsMgr::instance().setMaxSampleCountDefaultInternal(max_samples);
- StatsMgr::instance().setMaxSampleCountAllInternal(max_samples);
- } else {
- StatsMgr::instance().setMaxSampleCountDefaultInternal(max_samples);
- StatsMgr::instance().setMaxSampleCountAllInternal(max_samples);
- }
+ MultiThreadingLock lock(*mutex_);
+ StatsMgr::instance().setMaxSampleCountDefaultInternal(max_samples);
+ StatsMgr::instance().setMaxSampleCountAllInternal(max_samples);
return (createAnswer(CONTROL_RESULT_SUCCESS,
"All statistics count limit are set."));
}
#include <stats/observation.h>
#include <stats/context.h>
+#include <util/bigints.h>
+
#include <boost/noncopyable.hpp>
#include <boost/scoped_ptr.hpp>
/// @throw InvalidStatType if statistic is not integer
void setValue(const std::string& name, const int64_t value);
+ /// @brief Records an absolute big integer observation.
+ ///
+ /// @param name name of the observation
+ /// @param value integer value observed
+ /// @throw InvalidStatType if statistic is not integer
+ void setValue(const std::string& name, const isc::util::int128_t& value);
+
/// @brief Records absolute floating point observation.
///
/// @param name name of the observation
/// @throw InvalidStatType if statistic is not integer
void addValue(const std::string& name, const int64_t value);
+ /// @brief Records an incremental big integer observation.
+ ///
+ /// @param name name of the observation
+ /// @param value integer value observed
+ /// @throw InvalidStatType if statistic is not integer
+ void addValue(const std::string& name, const isc::util::int128_t& value);
+
/// @brief Records incremental floating point observation.
///
/// @param name name of the observation
#include <config.h>
-#include <stats/observation.h>
#include <exceptions/exceptions.h>
+#include <stats/observation.h>
#include <util/chrono_time_utils.h>
+#include <util/bigints.h>
+
#include <boost/shared_ptr.hpp>
+
#include <gtest/gtest.h>
#include <iostream>
using namespace isc;
using namespace isc::stats;
+using namespace isc::util;
using namespace std::chrono;
namespace {
a("alpha", static_cast<int64_t>(1234)), // integer
b("beta", 12.34), // float
c("gamma", dur1234), // duration
- d("delta", "1234") { // string
+ d("delta", "1234"), // string
+ e("epsilon", int128_t(12e34)) { // big integer
}
Observation a;
Observation b;
Observation c;
Observation d;
+ Observation e;
};
// Basic tests for the Observation constructors. This test checks whether
EXPECT_EQ(Observation::STAT_FLOAT, b.getType());
EXPECT_EQ(Observation::STAT_DURATION, c.getType());
EXPECT_EQ(Observation::STAT_STRING, d.getType());
+ EXPECT_EQ(Observation::STAT_BIG_INTEGER, e.getType());
EXPECT_EQ(1234, a.getInteger().first);
EXPECT_EQ(12.34, b.getFloat().first);
EXPECT_EQ(dur1234, c.getDuration().first);
EXPECT_EQ("1234", d.getString().first);
+ EXPECT_EQ(int128_t(12e34), e.getBigInteger().first);
// Let's check that attempting to get a different type
// than used will cause an exception.
EXPECT_THROW(a.getFloat(), InvalidStatType);
EXPECT_THROW(a.getDuration(), InvalidStatType);
EXPECT_THROW(a.getString(), InvalidStatType);
+ EXPECT_THROW(a.getBigInteger(), InvalidStatType);
EXPECT_THROW(b.getInteger(), InvalidStatType);
EXPECT_THROW(b.getDuration(), InvalidStatType);
EXPECT_THROW(b.getString(), InvalidStatType);
+ EXPECT_THROW(b.getBigInteger(), InvalidStatType);
EXPECT_THROW(c.getInteger(), InvalidStatType);
EXPECT_THROW(c.getFloat(), InvalidStatType);
EXPECT_THROW(c.getString(), InvalidStatType);
+ EXPECT_THROW(c.getBigInteger(), InvalidStatType);
EXPECT_THROW(d.getInteger(), InvalidStatType);
EXPECT_THROW(d.getFloat(), InvalidStatType);
EXPECT_THROW(d.getDuration(), InvalidStatType);
+ EXPECT_THROW(d.getBigInteger(), InvalidStatType);
+
+ EXPECT_THROW(e.getInteger(), InvalidStatType);
+ EXPECT_THROW(e.getFloat(), InvalidStatType);
+ EXPECT_THROW(e.getDuration(), InvalidStatType);
+ EXPECT_THROW(e.getString(), InvalidStatType);
}
// This test checks whether it is possible to set to an absolute value for all
EXPECT_NO_THROW(b.setValue(56e+78));
EXPECT_NO_THROW(c.setValue(dur5678));
EXPECT_NO_THROW(d.setValue("fiveSixSevenEight"));
-
+ EXPECT_NO_THROW(e.setValue(int128_t(43e21)));
EXPECT_EQ(5678, a.getInteger().first);
EXPECT_EQ(56e+78, b.getFloat().first);
EXPECT_EQ(dur5678, c.getDuration().first);
EXPECT_EQ("fiveSixSevenEight", d.getString().first);
+ EXPECT_EQ(int128_t(43e21), e.getBigInteger().first);
// Now check whether setting value to a different type does
// throw an exception
EXPECT_THROW(a.setValue(56e+78), InvalidStatType);
EXPECT_THROW(a.setValue(dur5678), InvalidStatType);
EXPECT_THROW(a.setValue("fiveSixSevenEight"), InvalidStatType);
+ EXPECT_THROW(a.setValue(int128_t(43e21)), InvalidStatType);
EXPECT_THROW(b.setValue(static_cast<int64_t>(5678)), InvalidStatType);
EXPECT_THROW(b.setValue(dur5678), InvalidStatType);
EXPECT_THROW(b.setValue("fiveSixSevenEight"), InvalidStatType);
+ EXPECT_THROW(b.setValue(int128_t(43e21)), InvalidStatType);
EXPECT_THROW(c.setValue(static_cast<int64_t>(5678)), InvalidStatType);
EXPECT_THROW(c.setValue(56e+78), InvalidStatType);
EXPECT_THROW(c.setValue("fiveSixSevenEight"), InvalidStatType);
+ EXPECT_THROW(c.setValue(int128_t(43e21)), InvalidStatType);
EXPECT_THROW(d.setValue(static_cast<int64_t>(5678)), InvalidStatType);
EXPECT_THROW(d.setValue(56e+78), InvalidStatType);
EXPECT_THROW(d.setValue(dur5678), InvalidStatType);
+ EXPECT_THROW(d.setValue(int128_t(43e21)), InvalidStatType);
+
+ EXPECT_THROW(e.setValue(int64_t(5678)), InvalidStatType);
+ EXPECT_THROW(e.setValue(56e+78), InvalidStatType);
+ EXPECT_THROW(e.setValue(dur5678), InvalidStatType);
+ EXPECT_THROW(e.setValue("fiveSixSevenEight"), InvalidStatType);
}
// This test checks whether it is possible to add value to existing
EXPECT_NO_THROW(b.addValue(56.78));
EXPECT_NO_THROW(c.addValue(dur5678));
EXPECT_NO_THROW(d.addValue("fiveSixSevenEight"));
+ EXPECT_NO_THROW(e.addValue(int128_t(43e21)));
EXPECT_EQ(6912, a.getInteger().first);
EXPECT_EQ(69.12, b.getFloat().first);
EXPECT_EQ(dur681012, c.getDuration().first);
EXPECT_EQ("1234fiveSixSevenEight", d.getString().first);
+ EXPECT_EQ(int128_t(12e34) + int128_t(43e21), e.getBigInteger().first);
ASSERT_EQ(a.getSize(), 2);
ASSERT_EQ(b.getSize(), 2);
ASSERT_EQ(c.getSize(), 2);
ASSERT_EQ(d.getSize(), 2);
+ ASSERT_EQ(e.getSize(), 2);
}
// This test checks if collecting more than one sample
// Arrays of 4 types of samples
int64_t int_samples[3] = {1234, 6912, 5678};
double float_samples[3] = {12.34, 69.12, 56e+78};
- StatsDuration duration_samples[3] = {dur1234,
- dur681012, dur5678};
+ StatsDuration duration_samples[3] = {dur1234, dur681012, dur5678};
std::string string_samples[3] = {"1234", "1234fiveSixSevenEight", "fiveSixSevenEight"};
+ int128_t bigint_samples[3] = {int128_t(12e34), int128_t(12e34) + int128_t(43e21),
+ int128_t(43e21)};
EXPECT_NO_THROW(a.addValue(static_cast<int64_t>(5678)));
EXPECT_NO_THROW(b.addValue(56.78));
EXPECT_NO_THROW(c.addValue(dur5678));
EXPECT_NO_THROW(d.addValue("fiveSixSevenEight"));
+ EXPECT_NO_THROW(e.addValue(int128_t(43e21)));
EXPECT_NO_THROW(a.setValue(static_cast<int64_t>(5678)));
EXPECT_NO_THROW(b.setValue(56e+78));
EXPECT_NO_THROW(c.setValue(dur5678));
EXPECT_NO_THROW(d.setValue("fiveSixSevenEight"));
+ EXPECT_NO_THROW(e.setValue(int128_t(43e21)));
ASSERT_EQ(a.getSize(), 3);
ASSERT_EQ(b.getSize(), 3);
ASSERT_EQ(c.getSize(), 3);
ASSERT_EQ(d.getSize(), 3);
+ ASSERT_EQ(e.getSize(), 3);
ASSERT_NO_THROW(a.getIntegers());
ASSERT_NO_THROW(b.getFloats());
ASSERT_NO_THROW(c.getDurations());
ASSERT_NO_THROW(d.getStrings());
+ ASSERT_NO_THROW(e.getBigIntegers());
std::list<IntegerSample> samples_int = a.getIntegers(); // List of all integer samples
std::list<FloatSample> samples_float = b.getFloats(); // List of all float samples
std::list<DurationSample> samples_dur = c.getDurations(); // List of all duration samples
std::list<StringSample> samples_str = d.getStrings(); // List of all string samples
+ std::list<BigIntegerSample> samples_bigint = e.getBigIntegers(); // List of all big integer samples
uint32_t i = 2; // Index pointed to the end of array of samples
-
for (std::list<IntegerSample>::iterator it = samples_int.begin(); it != samples_int.end(); ++it) {
EXPECT_EQ(int_samples[i], static_cast<int64_t>((*it).first));
--i;
EXPECT_EQ(string_samples[i], (*it).first);
--i;
}
+ i = 2;
+ for (BigIntegerSample const& sample : samples_bigint) {
+ EXPECT_EQ(bigint_samples[i], sample.first);
+ --i;
+ }
}
// This test checks whether the size of storage
ASSERT_EQ(b.getSize(), 1);
ASSERT_EQ(c.getSize(), 1);
ASSERT_EQ(d.getSize(), 1);
+ ASSERT_EQ(e.getSize(), 1);
a.addValue(static_cast<int64_t>(5678));
b.addValue(56.78);
c.addValue(dur5678);
d.addValue("fiveSixSevenEight");
+ e.addValue(int128_t(43e21));
EXPECT_NO_THROW(a.getSize());
EXPECT_NO_THROW(b.getSize());
EXPECT_NO_THROW(c.getSize());
EXPECT_NO_THROW(d.getSize());
+ EXPECT_NO_THROW(e.getSize());
// Check if size of storages is equal to 2
ASSERT_EQ(a.getSize(), 2);
ASSERT_EQ(b.getSize(), 2);
ASSERT_EQ(c.getSize(), 2);
ASSERT_EQ(d.getSize(), 2);
+ ASSERT_EQ(e.getSize(), 2);
a.setValue(static_cast<int64_t>(5678));
b.setValue(56e+78);
c.setValue(dur5678);
d.setValue("fiveSixSevenEight");
+ e.setValue(int128_t(43e21));
EXPECT_NO_THROW(a.getSize());
EXPECT_NO_THROW(b.getSize());
ASSERT_EQ(b.getSize(), 3);
ASSERT_EQ(c.getSize(), 3);
ASSERT_EQ(d.getSize(), 3);
+ ASSERT_EQ(e.getSize(), 3);
}
// Checks whether setting amount limits works properly
for (uint32_t i = 0; i < 21; ++i) {
d.setValue(string_samples[i]);
}
+ for (uint32_t i = 0; i < 21; ++i) {
+ e.setValue(int128_t(int_samples[i]));
+ }
// Getting all 4 types of samples after inserting 21 values
std::list<IntegerSample> samples_int = a.getIntegers();
std::list<FloatSample> samples_float = b.getFloats();
std::list<DurationSample> samples_duration = c.getDurations();
std::list<StringSample> samples_string = d.getStrings();
+ std::list<BigIntegerSample> samples_bigint = e.getBigIntegers();
// Check if size of storages is equal to 20
ASSERT_EQ(a.getSize(), 20);
ASSERT_EQ(b.getSize(), 20);
ASSERT_EQ(c.getSize(), 20);
ASSERT_EQ(d.getSize(), 20);
+ ASSERT_EQ(e.getSize(), 20);
// And whether stored values are correct
uint32_t i = 20; // index of the last element in array of test's samples
EXPECT_EQ((*it).first, string_samples[i]);
--i;
}
+ i = 20; // index of last element in array of test's samples
+ for (BigIntegerSample const& sample : samples_bigint) {
+ EXPECT_EQ(sample.first, int_samples[i]);
+ --i;
+ }
// Change size of storage to smaller one
ASSERT_NO_THROW(a.setMaxSampleCount(10));
ASSERT_NO_THROW(b.setMaxSampleCount(10));
ASSERT_NO_THROW(c.setMaxSampleCount(10));
ASSERT_NO_THROW(d.setMaxSampleCount(10));
+ ASSERT_NO_THROW(e.setMaxSampleCount(10));
samples_int = a.getIntegers();
samples_float = b.getFloats();
samples_duration = c.getDurations();
samples_string = d.getStrings();
+ samples_bigint = e.getBigIntegers();
// Check if size of storages is equal to 10
ASSERT_EQ(a.getSize(), 10);
ASSERT_EQ(b.getSize(), 10);
ASSERT_EQ(c.getSize(), 10);
ASSERT_EQ(d.getSize(), 10);
+ ASSERT_EQ(e.getSize(), 10);
// And whether storages contain only the 10 newest values
i = 20; // index of last element in array of test's samples
EXPECT_EQ((*it).first, string_samples[i]);
--i;
}
+ i = 20; // index of last element in array of test's samples
+ for (BigIntegerSample const& sample : samples_bigint) {
+ EXPECT_EQ(sample.first, int_samples[i]);
+ --i;
+ }
// Resize max_sample_count to greater
ASSERT_NO_THROW(a.setMaxSampleCount(50));
ASSERT_NO_THROW(b.setMaxSampleCount(50));
ASSERT_NO_THROW(c.setMaxSampleCount(50));
ASSERT_NO_THROW(d.setMaxSampleCount(50));
+ ASSERT_NO_THROW(e.setMaxSampleCount(50));
// Check if size of storages did not change without adding new value
ASSERT_EQ(a.getSize(), 10);
ASSERT_EQ(b.getSize(), 10);
ASSERT_EQ(c.getSize(), 10);
ASSERT_EQ(d.getSize(), 10);
+ ASSERT_EQ(e.getSize(), 10);
// Add new values to each type of Observation
a.setValue(static_cast<int64_t>(21));
b.setValue(21.0);
c.setValue(milliseconds(21));
d.setValue("v");
+ e.setValue(int128_t(21));
samples_int = a.getIntegers();
samples_float = b.getFloats();
samples_duration = c.getDurations();
samples_string = d.getStrings();
+ samples_bigint = e.getBigIntegers();
ASSERT_EQ(a.getSize(), 11);
ASSERT_EQ(b.getSize(), 11);
ASSERT_EQ(c.getSize(), 11);
ASSERT_EQ(d.getSize(), 11);
+ ASSERT_EQ(e.getSize(), 11);
i = 21; // index of last element in array of test's samples
for (std::list<IntegerSample>::iterator it = samples_int.begin(); it != samples_int.end(); ++it) {
EXPECT_EQ((*it).first, string_samples[i]);
--i;
}
-
+ i = 21; // index of last element in array of test's samples
+ for (BigIntegerSample const& sample : samples_bigint) {
+ EXPECT_EQ(sample.first, int_samples[i]);
+ --i;
+ }
}
// Checks whether setting age limits works properly
EXPECT_EQ(b.getMaxSampleAge().first, false);
EXPECT_EQ(c.getMaxSampleAge().first, false);
EXPECT_EQ(d.getMaxSampleAge().first, false);
+ EXPECT_EQ(e.getMaxSampleAge().first, false);
EXPECT_EQ(a.getMaxSampleCount().first, true);
EXPECT_EQ(b.getMaxSampleCount().first, true);
EXPECT_EQ(c.getMaxSampleCount().first, true);
EXPECT_EQ(d.getMaxSampleCount().first, true);
+ EXPECT_EQ(e.getMaxSampleCount().first, true);
EXPECT_EQ(a.getMaxSampleCount().second, 20);
EXPECT_EQ(b.getMaxSampleCount().second, 20);
EXPECT_EQ(c.getMaxSampleCount().second, 20);
EXPECT_EQ(d.getMaxSampleCount().second, 20);
+ EXPECT_EQ(e.getMaxSampleCount().second, 20);
// change limit to time duration
ASSERT_NO_THROW(a.setMaxSampleAge(dur453));
ASSERT_NO_THROW(b.setMaxSampleAge(dur453));
ASSERT_NO_THROW(c.setMaxSampleAge(dur453));
ASSERT_NO_THROW(d.setMaxSampleAge(dur453));
+ ASSERT_NO_THROW(e.setMaxSampleAge(dur453));
EXPECT_EQ(a.getMaxSampleAge().first, true);
EXPECT_EQ(b.getMaxSampleAge().first, true);
EXPECT_EQ(c.getMaxSampleAge().first, true);
EXPECT_EQ(d.getMaxSampleAge().first, true);
+ EXPECT_EQ(e.getMaxSampleAge().first, true);
EXPECT_EQ(a.getMaxSampleAge().second, dur453);
EXPECT_EQ(b.getMaxSampleAge().second, dur453);
EXPECT_EQ(c.getMaxSampleAge().second, dur453);
EXPECT_EQ(d.getMaxSampleAge().second, dur453);
+ EXPECT_EQ(e.getMaxSampleAge().second, dur453);
EXPECT_EQ(a.getMaxSampleCount().first, false);
EXPECT_EQ(b.getMaxSampleCount().first, false);
EXPECT_EQ(c.getMaxSampleCount().first, false);
EXPECT_EQ(d.getMaxSampleCount().first, false);
+ EXPECT_EQ(e.getMaxSampleCount().first, false);
EXPECT_EQ(a.getMaxSampleCount().second, 20);
EXPECT_EQ(b.getMaxSampleCount().second, 20);
EXPECT_EQ(c.getMaxSampleCount().second, 20);
EXPECT_EQ(d.getMaxSampleCount().second, 20);
+ EXPECT_EQ(e.getMaxSampleCount().second, 20);
}
// limit defaults are tested with StatsMgr.
std::string exp = "[ [ 1234, \"" +
isc::util::clockToText(a.getInteger().second) + "\" ]" + first_sample;
- std::cout << a.getJSON()->str() << std::endl;
EXPECT_EQ(exp, a.getJSON()->str());
}
std::string exp = "[ [ 1234.5, \"" +
isc::util::clockToText(b.getFloat().second) + "\" ]" + first_sample;
- std::cout << b.getJSON()->str() << std::endl;
EXPECT_EQ(exp, b.getJSON()->str());
}
std::string exp = "[ [ \"01:02:03.004000\", \"" +
isc::util::clockToText(c.getDuration().second) + "\" ]" + first_sample;
- std::cout << c.getJSON()->str() << std::endl;
EXPECT_EQ(exp, c.getJSON()->str());
}
std::string exp = "[ [ \"Lorem ipsum dolor sit amet\", \"" +
isc::util::clockToText(d.getString().second) + "\" ]" + first_sample;
- std::cout << d.getJSON()->str() << std::endl;
EXPECT_EQ(exp, d.getJSON()->str());
}
+// Checks whether a big integer statistic can generate proper JSON structures.
+// See https://gitlab.isc.org/isc-projects/kea/wikis/designs/Stats-design
+// for details.
+TEST_F(ObservationTest, bigIntegerToJSON) {
+ // String which contains first added sample
+ std::string first_sample = ", [ 120000000000000007304085773727301632, \"" +
+ isc::util::clockToText(e.getBigInteger().second) + "\" ] ]";
+
+ e.setValue(int128_t(43e21));
+
+ std::string exp = "[ [ 43000000000000002097152, \"" +
+ isc::util::clockToText(e.getBigInteger().second) + "\" ]" + first_sample;
+
+ EXPECT_EQ(exp, e.getJSON()->str());
+}
+
// Checks whether reset() resets the statistics properly.
TEST_F(ObservationTest, reset) {
EXPECT_NO_THROW(a.addValue(static_cast<int64_t>(5678)));
EXPECT_NO_THROW(b.addValue(56.78));
EXPECT_NO_THROW(c.addValue(dur5678));
EXPECT_NO_THROW(d.addValue("fiveSixSevenEight"));
+ EXPECT_NO_THROW(e.addValue(int128_t(43e21)));
a.reset(); // integer
b.reset(); // float
c.reset(); // duration
d.reset(); // string
+ e.reset(); // big integer
EXPECT_EQ(0, a.getInteger().first);
EXPECT_EQ(0.0, b.getFloat().first);
EXPECT_EQ(StatsDuration::zero(), c.getDuration().first);
EXPECT_EQ("", d.getString().first);
+ EXPECT_EQ(0, e.getBigInteger().first);
ASSERT_EQ(a.getSize(), 1);
ASSERT_EQ(b.getSize(), 1);
ASSERT_EQ(c.getSize(), 1);
ASSERT_EQ(d.getSize(), 1);
+ ASSERT_EQ(e.getSize(), 1);
}
// Checks whether an observation can keep its name.
EXPECT_EQ("beta", b.getName());
EXPECT_EQ("gamma", c.getName());
EXPECT_EQ("delta", d.getName());
+ EXPECT_EQ("epsilon", e.getName());
}
-}
+} // namespace
///
/// @param name StatsMgr name for the statistic to check.
/// @param expected_value expected value of the statistic.
-inline void checkStat(const std::string& name, const int64_t expected_value) {
- using namespace isc::stats;
- ObservationPtr obs = StatsMgr::instance().getObservation(name);
- ASSERT_TRUE(obs) << " stat: " << name << " not found ";
- ASSERT_EQ(expected_value, obs->getInteger().first)
- << " stat: " << name << " value wrong";
+inline void checkStat(const std::string& name,
+ const isc::util::int128_t expected_value) {
+ ObservationPtr const obs(isc::stats::StatsMgr::instance().getObservation(name));
+
+ ASSERT_TRUE(obs) << "stat " << name << " not found ";
+ if (obs->getType() == Observation::STAT_INTEGER) {
+ EXPECT_EQ(expected_value, obs->getInteger().first)
+ << " wrong value for stat " << name;
+ } else if (obs->getType() == Observation::STAT_BIG_INTEGER) {
+ EXPECT_EQ(expected_value, obs->getBigInteger().first)
+ << " wrong value for stat " << name;
+ } else {
+ GTEST_FAIL() << "unexpected statistic type: "
+ << Observation::typeToText(obs->getType());
+ }
}
/// @brief Check if a statistic does not exists.