BIND 10 trac1958, updated. 2175b280a686cc4aec2cf72c21f7ce839bf609ee [1958] Added optional packets archiving and unit test for printing stats.
BIND 10 source code commits
bind10-changes at lists.isc.org
Mon Jul 30 19:53:34 UTC 2012
The branch, trac1958 has been updated
via 2175b280a686cc4aec2cf72c21f7ce839bf609ee (commit)
via 0ef001aacb7a9da735d418504168420ddac0c3df (commit)
via 731fac5042e88fa7611b0f99feace1e1b05fe4a0 (commit)
via 3b17dac1ab05a635f39f73316be62f4783a0182f (commit)
via 0048a810b5641bb7b35f7ccf790846cee6f89697 (commit)
via f40e523668cd8332238b7369470403e8b66b6f35 (commit)
via e1491225037840283b198a6042d90939d52906fe (commit)
via 793457876fc93510db9814cd70c4ab2cc8a918b6 (commit)
via 16e49803425ea35550a9787987215e5344ffe528 (commit)
from 48755af6bfc85aa10e5eea2da1bde9478914e8df (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 2175b280a686cc4aec2cf72c21f7ce839bf609ee
Author: Marcin Siodelski <marcin at isc.org>
Date: Mon Jul 30 21:52:47 2012 +0200
[1958] Added optional packets archiving and unit test for printing stats.
commit 0ef001aacb7a9da735d418504168420ddac0c3df
Author: Marcin Siodelski <marcin at isc.org>
Date: Mon Jul 30 15:15:27 2012 +0200
[1958] Use EXPECT_DOUBLE_EQ for doubles.
commit 731fac5042e88fa7611b0f99feace1e1b05fe4a0
Author: Marcin Siodelski <marcin at isc.org>
Date: Mon Jul 30 15:10:02 2012 +0200
[1958] Renamed member to next_sent_ to reflect the purpose of it.
commit 3b17dac1ab05a635f39f73316be62f4783a0182f
Author: Marcin Siodelski <marcin at isc.org>
Date: Mon Jul 30 14:57:05 2012 +0200
[1958] Better documentation if multi_index_container, removed redundant index.
commit 0048a810b5641bb7b35f7ccf790846cee6f89697
Author: Marcin Siodelski <marcin at isc.org>
Date: Mon Jul 30 13:26:53 2012 +0200
[1958] Improved presentation of statistics counters.
commit f40e523668cd8332238b7369470403e8b66b6f35
Author: Marcin Siodelski <marcin at isc.org>
Date: Mon Jul 30 12:21:24 2012 +0200
[1958] Code cleanup: naming, getters layout and return statements.
commit e1491225037840283b198a6042d90939d52906fe
Author: Marcin Siodelski <marcin at isc.org>
Date: Mon Jul 30 12:04:39 2012 +0200
[1958] Replaced unsigned long long with uin64_t
commit 793457876fc93510db9814cd70c4ab2cc8a918b6
Author: Marcin Siodelski <marcin at isc.org>
Date: Mon Jul 30 12:02:28 2012 +0200
[1958] Replaced printf with cout.
commit 16e49803425ea35550a9787987215e5344ffe528
Author: Marcin Siodelski <marcin at isc.org>
Date: Mon Jul 30 11:11:23 2012 +0200
[1958] Make packet types const and passing them by reference.
-----------------------------------------------------------------------
Summary of changes:
tests/tools/perfdhcp/stats_mgr.h | 529 ++++++++++++++--------
tests/tools/perfdhcp/tests/stats_mgr_unittest.cc | 40 +-
2 files changed, 377 insertions(+), 192 deletions(-)
-----------------------------------------------------------------------
diff --git a/tests/tools/perfdhcp/stats_mgr.h b/tests/tools/perfdhcp/stats_mgr.h
index 6a36149..4ca2576 100644
--- a/tests/tools/perfdhcp/stats_mgr.h
+++ b/tests/tools/perfdhcp/stats_mgr.h
@@ -73,14 +73,14 @@ public:
/// \brief Increment operator.
const CustomCounter& operator++() {
++counter_;
- return *this;
+ return(*this);
}
/// \brief Increment operator.
const CustomCounter& operator++(int) {
CustomCounter& this_counter(*this);
operator++();
- return this_counter;
+ return(this_counter);
}
/// \brief Return counter value.
@@ -88,18 +88,14 @@ public:
/// Method returns counter value.
///
/// \return counter value.
- unsigned long long getValue() const {
- return counter_;
- }
+ uint64_t getValue() const { return counter_; }
/// \brief Return counter name.
///
/// Method returns counter name.
///
/// \return counter name.
- const std::string& getName() const {
- return name_;
- }
+ const std::string& getName() const { return name_; }
private:
/// \brief Default constructor.
///
@@ -108,7 +104,7 @@ public:
/// counter's name.
CustomCounter() { };
- unsigned long long counter_; ///< Counter's value.
+ uint64_t counter_; ///< Counter's value.
std::string name_; ///< Counter's name.
};
@@ -142,35 +138,91 @@ public:
/// \param packet packet which transaction id is to be hashed.
/// \throw isc::BadValue if packet is null.
/// \return transaction id hash.
- static uint32_t hashTransid(const boost::shared_ptr<T> packet) {
+ static uint32_t hashTransid(const boost::shared_ptr<const T>& packet) {
if (!packet) {
isc_throw(BadValue, "Packet is null");
}
- return packet->getTransid() & 1023;
+ return(packet->getTransid() & 1023);
}
/// \brief List of packets (sent or received).
///
/// List of packets based on multi index container allows efficient
/// search of packets based on their sequence (order in which they
- /// were inserted) as well as based on packet transaction id.
+ /// were inserted) as well as based on their hashed transaction id.
+ /// The first index (sequenced) provides the way to use container
+ /// as a regular list (including iterators, removal of elements from
+ /// the middle of the collection etc.). This index is meant to be used
+ /// more frequently than the latter one and it is based on the
+ /// assumption that responses from the DHCP server are received in
+ /// order. In this case, when next packet is received it can be
+ /// matched with next packet on the list of sent packets. This
+ /// prevents intensive searches on the list of sent packets every
+ /// time new packet arrives. In many cases however packets can be
+ /// dropped by the server or may be sent out of order and we still
+ /// want to have ability to search packets using transaction id.
+ /// The second index can be used for this purpose. This index is
+ /// hashing transaction ids using custom function \ref hashTransid.
+ /// Note that other possibility would be to simply specify index
+ /// that uses transaction id directly (instead of hashing with
+ /// \ref hashTransid). In this case however we have chosen to use
+ /// hashing function because it shortens the index size to just
+ /// 1023 values maximum. Search operation on this index generally
+ /// returns the range of packets that have the same transaction id
+ /// hash assigned but most often these ranges will be short so further
+ /// search within a range to find a packet with pacrticular transaction
+ /// id will not be intensive.
+ ///
+ /// Example 1: Add elements to the list
+ /// \code
+ /// PktList packets_collection();
+ /// boost::shared_ptr<Pkt4> pkt1(new Pkt4(...));
+ /// boost::shared_ptr<Pkt4> pkt2(new Pkt4(...));
+ /// // Add new packet to the container, it will be available through
+ /// // both indexes
+ /// packets_collection.push_back(pkt1);
+ /// // Here is another way to add packet to the container. The result
+ /// // is exactly the same as previously.
+ /// packets_collection.template get<0>().push_back(pkt2);
+ /// \endcode
+ ///
+ /// Example 2: Access elements through sequencial index
+ /// \code
+ /// PktList packets_collection();
+ /// ... # Add elements to the container
+ /// for (PktListIterator it = packets_collection.begin();
+ /// it != packets_collection.end();
+ /// ++it) {
+ /// boost::shared_ptr<Pkt4> pkt = *it;
+ /// # Do something with packet;
+ /// }
+ /// \endcode
+ ///
+ /// Example 3: Access elements through hashed index
+ /// \code
+ /// // Get the instance of the second search index.
+ /// PktListTransidHashIndex& idx = sent_packets_.template get<1>();
+ /// // Get the range (bucket) of packets sharing the same transaction
+ /// // id hash.
+ /// std::pair<PktListTransidHashIterator,PktListTransidHashIterator> p =
+ /// idx.equal_range(hashTransid(rcvd_packet));
+ /// // Iterate through the returned bucket.
+ /// for (PktListTransidHashIterator it = p.first; it != p.second;
+ /// ++it) {
+ /// boost::shared_ptr pkt = *it;
+ /// ... # Do something with the packet (e.g. check transaction id)
+ /// }
+ /// \endcode
typedef boost::multi_index_container<
- boost::shared_ptr<T>,
+ boost::shared_ptr<const T>,
boost::multi_index::indexed_by<
boost::multi_index::sequenced<>,
boost::multi_index::hashed_non_unique<
boost::multi_index::global_fun<
- boost::shared_ptr<T>,
+ const boost::shared_ptr<const T>&,
uint32_t,
&ExchangeStats::hashTransid
>
- >,
- boost::multi_index::hashed_non_unique<
- boost::multi_index::const_mem_fun<
- T,
- uint32_t,
- &T::getTransid
- >
>
>
> PktList;
@@ -183,29 +235,27 @@ public:
/// Packet list iterator to access packets using transaction id hash.
typedef typename PktListTransidHashIndex::const_iterator
PktListTransidHashIterator;
- /// Packet list index to search packets using transaction id.
- typedef typename PktList::template nth_index<2>::type
- PktListTransidIndex;
- /// Packet list iterator to access packets using transaction id.
- typedef typename PktListTransidIndex::const_iterator
- PktListTransidIterator;
/// \brief Constructor
///
/// \param xchg_type exchange type
- ExchangeStats(const ExchangeType xchg_type)
+ ExchangeStats(const ExchangeType xchg_type, const bool archive_enabled)
: xchg_type_(xchg_type),
min_delay_(std::numeric_limits<double>::max()),
max_delay_(0.),
sum_delay_(0.),
orphans_(0),
- square_sum_delay_(0.),
+ sum_delay_squared_(0.),
ordered_lookups_(0),
unordered_lookup_size_sum_(0),
unordered_lookups_(0),
sent_packets_num_(0),
- rcvd_packets_num_(0) {
- sent_packets_cache_ = sent_packets_.begin();
+ rcvd_packets_num_(0),
+ sent_packets_(),
+ rcvd_packets_(),
+ archived_packets_(),
+ archive_enabled_(archive_enabled) {
+ next_sent_ = sent_packets_.begin();
}
/// \brief Add new packet to list of sent packets.
@@ -214,7 +264,7 @@ public:
///
/// \param packet packet object to be added.
/// \throw isc::BadValue if packet is null.
- void appendSent(const boost::shared_ptr<T> packet) {
+ void appendSent(const boost::shared_ptr<const T>& packet) {
if (!packet) {
isc_throw(BadValue, "Packet is null");
}
@@ -228,11 +278,10 @@ public:
///
/// \param packet packet object to be added.
/// \throw isc::BadValue if packet is null.
- void appendRcvd(const boost::shared_ptr<T> packet) {
+ void appendRcvd(const boost::shared_ptr<const T>& packet) {
if (!packet) {
isc_throw(BadValue, "Packet is null");
}
- ++rcvd_packets_num_;
rcvd_packets_.push_back(packet);
}
@@ -245,8 +294,8 @@ public:
/// \param rcvd_packet received packet
/// \throw isc::BadValue if sent or received packet is null.
/// \throw isc::Unexpected if failed to calculate timestamps
- void updateDelays(const boost::shared_ptr<const T> sent_packet,
- const boost::shared_ptr<const T> rcvd_packet) {
+ void updateDelays(const boost::shared_ptr<const T>& sent_packet,
+ const boost::shared_ptr<const T>& rcvd_packet) {
if (!sent_packet) {
isc_throw(BadValue, "Sent packet is null");
}
@@ -286,7 +335,7 @@ public:
// Update delay sum and square sum. That will be used to calculate
// mean delays.
sum_delay_ += delta;
- square_sum_delay_ += delta * delta;
+ sum_delay_squared_ += delta * delta;
}
/// \brief Find packet on the list of sent packets.
@@ -304,7 +353,7 @@ public:
/// \throw isc::BadValue if received packet is null.
/// \return packet having specified transaction or NULL if packet
/// not found
- boost::shared_ptr<T> findSent(const boost::shared_ptr<T> rcvd_packet) {
+ boost::shared_ptr<const T> findSent(const boost::shared_ptr<const T>& rcvd_packet) {
if (!rcvd_packet) {
isc_throw(BadValue, "Received packet is null");
}
@@ -315,12 +364,12 @@ public:
// that the received packet we got has no corresponding
// sent packet so orphans counter has to be updated.
++orphans_;
- return boost::shared_ptr<T>();
- } else if (sent_packets_cache_ == sent_packets_.end()) {
+ return(boost::shared_ptr<const T>());
+ } else if (next_sent_ == sent_packets_.end()) {
// Even if there are still many unmatched packets on the
// list we might hit the end of it because of unordered
- // lookups. The next logical step is to reset cache.
- sent_packets_cache_ = sent_packets_.begin();
+ // lookups. The next logical step is to reset iterator.
+ next_sent_ = sent_packets_.begin();
}
// With this variable we will be signalling success or failure
@@ -332,7 +381,7 @@ public:
// incoming packet. We are successful if there is no
// packet drop or out of order packets sent. This is actually
// the fastest way to look for packets.
- if ((*sent_packets_cache_)->getTransid() == rcvd_packet->getTransid()) {
+ if ((*next_sent_)->getTransid() == rcvd_packet->getTransid()) {
++ordered_lookups_;
packet_found = true;
} else {
@@ -363,7 +412,7 @@ public:
++it) {
if ((*it)->getTransid() == rcvd_packet->getTransid()) {
packet_found = true;
- sent_packets_cache_ =
+ next_sent_ =
sent_packets_.template project<0>(it);
break;
}
@@ -374,15 +423,16 @@ public:
// If we are here, it means that both ordered lookup and
// unordered lookup failed. Searched packet is not on the list.
++orphans_;
- return boost::shared_ptr<T>();
+ return(boost::shared_ptr<const T>());
}
- boost::shared_ptr<T> sent_packet(*sent_packets_cache_);
+ ++rcvd_packets_num_;
+ boost::shared_ptr<const T> sent_packet(*next_sent_);
// If packet was found, we assume it will be never searched
// again. We want to delete this packet from the list to
// improve performance of future searches.
- sent_packets_cache_ = eraseSent(sent_packets_cache_);
- return sent_packet;
+ next_sent_ = eraseSent(next_sent_);
+ return(sent_packet);
}
/// \brief Return minumum delay between sent and received packet.
@@ -390,14 +440,14 @@ public:
/// Method returns minimum delay between sent and received packet.
///
/// \return minimum delay between packets.
- double getMinDelay() const { return min_delay_; }
+ double getMinDelay() const { return(min_delay_); }
/// \brief Return maxmimum delay between sent and received packet.
///
/// Method returns maximum delay between sent and received packet.
///
/// \return maximum delay between packets.
- double getMaxDelay() const { return max_delay_; }
+ double getMaxDelay() const { return(max_delay_); }
/// \brief Return avarage packet delay.
///
@@ -409,10 +459,10 @@ public:
/// have been received yet.
/// \return average packet delay.
double getAvgDelay() const {
- if (sum_delay_ == 0) {
+ if (rcvd_packets_num_ == 0) {
isc_throw(InvalidOperation, "no packets received");
}
- return sum_delay_ / rcvd_packets_num_;
+ return(sum_delay_ / rcvd_packets_num_);
}
/// \brief Return standard deviation of packet delay.
@@ -429,8 +479,8 @@ public:
if (rcvd_packets_num_ == 0) {
isc_throw(InvalidOperation, "no packets received");
}
- return sqrt(square_sum_delay_ / rcvd_packets_num_ -
- getAvgDelay() * getAvgDelay());
+ return(sqrt(sum_delay_squared_ / rcvd_packets_num_ -
+ getAvgDelay() * getAvgDelay()));
}
/// \brief Return number of orphant packets.
@@ -440,7 +490,7 @@ public:
/// for us.
///
/// \return number of orphant received packets.
- unsigned long long getOrphans() const { return orphans_; }
+ uint64_t getOrphans() const { return(orphans_); }
/// \brief Return average unordered lookup set size.
///
@@ -455,8 +505,8 @@ public:
if (unordered_lookups_ == 0) {
isc_throw(InvalidOperation, "no unordered lookups");
}
- return static_cast<double>(unordered_lookup_size_sum_) /
- static_cast<double>(unordered_lookups_);
+ return(static_cast<double>(unordered_lookup_size_sum_) /
+ static_cast<double>(unordered_lookups_));
}
/// \brief Return number of unordered sent packets lookups
@@ -467,7 +517,7 @@ public:
/// packet does not match transaction id of next sent packet.
///
/// \return number of unordered lookups.
- unsigned long long getUnorderedLookups() const { return unordered_lookups_; }
+ uint64_t getUnorderedLookups() const { return(unordered_lookups_); }
/// \brief Return number of ordered sent packets lookups
///
@@ -478,70 +528,119 @@ public:
/// function will use unordered lookup (with hash table).
///
/// \return number of ordered lookups.
- unsigned long long getOrderedLookups() const { return ordered_lookups_; }
+ uint64_t getOrderedLookups() const { return(ordered_lookups_); }
/// \brief Return total number of sent packets
///
/// Method returns total number of sent packets.
///
/// \return number of sent packets.
- unsigned long long getSentPacketsNum() const {
- return sent_packets_num_;
- }
+ uint64_t getSentPacketsNum() const { return(sent_packets_num_); }
/// \brief Return total number of received packets
///
/// Method returns total number of received packets.
///
/// \return number of received packets.
- unsigned long long getRcvdPacketsNum() const {
- return rcvd_packets_num_;
+ uint64_t getRcvdPacketsNum() const { return(rcvd_packets_num_); }
+
+ /// \brief Print main statistics for packet exchange.
+ ///
+ /// Method prints main statistics for particular exchange.
+ /// Statistics includes: number of sent and received packets,
+ /// number of dropped packets and number of orphans.
+ void printMainStats() const {
+ using namespace std;
+ uint64_t drops = getRcvdPacketsNum() - getSentPacketsNum();
+ cout << "sent packets: " << getSentPacketsNum() << endl
+ << "received packets: " << getRcvdPacketsNum() << endl
+ << "drops: " << drops << endl
+ << "orphans: " << getOrphans() << endl;
+ }
+
+ /// \brief Print round trip time packets statistics.
+ ///
+ /// Method prints round trip time packets statistics. Statistics
+ /// includes minimum packet delay, maximum packet delay, average
+ /// packet delay and standard deviation of delays. Packet delay
+ /// is a duration between sending a packet to server and receiving
+ /// response from server.
+ void printRTTStats() const {
+ using namespace std;
+ try {
+ cout << fixed << setprecision(3)
+ << "min delay: " << getMinDelay() * 1e3 << " ms" << endl
+ << "avg delay: " << getAvgDelay() * 1e3 << " ms" << endl
+ << "max delay: " << getMaxDelay() * 1e3 << " ms" << endl
+ << "std deviation: " << getStdDevDelay() * 1e3 << " ms"
+ << endl;
+ } catch (const Exception& e) {
+ cout << "Unavailable! No packets received." << endl;
+ }
}
//// \brief Print timestamps for sent and received packets.
///
/// Method prints timestamps for all sent and received packets for
- /// packet exchange.
+ /// packet exchange. In order to run this method the packets
+ /// archiving mode has to be enabled during object constructions.
+ /// Otherwise sent packets are not stored during tests execution
+ /// and this method has no ability to get and print their timestamps.
///
- /// \throw isc::InvalidOperation if found packet with no timestamp set.
+ /// \throw isc::InvalidOperation if found packet with no timestamp or
+ /// if packets archive mode is disabled.
void printTimestamps() {
+ // If archive mode is disabled there is no sense to proceed
+ // because we don't have packets and their timestamps.
+ if (!archive_enabled_) {
+ isc_throw(isc::InvalidOperation,
+ "packets archive mode is disabled");
+ }
+ if (rcvd_packets_num_ == 0) {
+ std::cout << "Unavailable! No packets received." << std::endl;
+ }
+ // We will be using boost::posix_time extensivelly here
+ using namespace boost::posix_time;
+
// Iterate through all received packets.
for (PktListIterator it = rcvd_packets_.begin();
it != rcvd_packets_.end();
++it) {
- boost::shared_ptr<T> rcvd_packet = *it;
- // Search for corresponding sent packet using transaction id
- // of received packet.
- PktListTransidIndex& idx = archived_packets_.template get<2>();
- PktListTransidIterator it_archived =
- idx.find(rcvd_packet->getTransid());
- // This should not happen that there is no corresponding
- // sent packet. If it does however, we just drop the packet.
- if (it_archived != idx.end()) {
- boost::shared_ptr<T> sent_packet = *it_archived;
- // Get sent and received packet times.
- boost::posix_time::ptime sent_time =
- sent_packet->getTimestamp();
- boost::posix_time::ptime rcvd_time =
- rcvd_packet->getTimestamp();
- // All sent and received packets should have timestamps
- // set but if there is a bug somewhere and packet does
- // not have timestamp we want to catch this here.
- if (sent_time.is_not_a_date_time() ||
- rcvd_time.is_not_a_date_time()) {
- isc_throw(InvalidOperation, "packet time is not set");
+ boost::shared_ptr<const T> rcvd_packet = *it;
+ PktListTransidHashIndex& idx =
+ archived_packets_.template get<1>();
+ std::pair<PktListTransidHashIterator,
+ PktListTransidHashIterator> p =
+ idx.equal_range(hashTransid(rcvd_packet));
+ for (PktListTransidHashIterator it_archived = p.first;
+ it_archived != p.second;
+ ++it) {
+ if ((*it_archived)->getTransid() ==
+ rcvd_packet->getTransid()) {
+ boost::shared_ptr<const T> sent_packet = *it_archived;
+ // Get sent and received packet times.
+ ptime sent_time = sent_packet->getTimestamp();
+ ptime rcvd_time = rcvd_packet->getTimestamp();
+ // All sent and received packets should have timestamps
+ // set but if there is a bug somewhere and packet does
+ // not have timestamp we want to catch this here.
+ if (sent_time.is_not_a_date_time() ||
+ rcvd_time.is_not_a_date_time()) {
+ isc_throw(InvalidOperation,
+ "packet time is not set");
+ }
+ // Calculate durations of packets from beginning of epoch.
+ ptime epoch_time(min_date_time);
+ time_period sent_period(epoch_time, sent_time);
+ time_period rcvd_period(epoch_time, rcvd_time);
+ // Print timestamps for sent and received packet.
+ std::cout << "sent / received: "
+ << to_iso_string(sent_period.length())
+ << " / "
+ << to_iso_string(rcvd_period.length())
+ << std::endl;
+ break;
}
- // Calculate durations of packets from beginning of epoch.
- boost::posix_time::ptime
- epoch_time(boost::posix_time::min_date_time);
- boost::posix_time::time_period
- sent_period(epoch_time, sent_time);
- boost::posix_time::time_period
- rcvd_period(epoch_time, rcvd_time);
- // Print timestamps for sent and received packet.
- printf("sent/received times: %s / %s\n",
- boost::posix_time::to_iso_string(sent_period.length()).c_str(),
- boost::posix_time::to_iso_string(rcvd_period.length()).c_str());
}
}
}
@@ -562,14 +661,18 @@ public:
/// \return iterator pointing to packet following erased
/// packet or sent_packets_.end() if packet not found.
PktListIterator eraseSent(const PktListIterator it) {
- // We don't want to keep list of all sent packets
- // because it will affect packet lookup performance.
- // If packet is matched with received packet we
- // move it to list of archived packets. List of
- // archived packets may be used for diagnostics
- // when test is completed.
- archived_packets_.push_back(*it);
- return sent_packets_.template get<0>().erase(it);
+ if (archive_enabled_) {
+ // We don't want to keep list of all sent packets
+ // because it will affect packet lookup performance.
+ // If packet is matched with received packet we
+ // move it to list of archived packets. List of
+ // archived packets may be used for diagnostics
+ // when test is completed.
+ archived_packets_.push_back(*it);
+ }
+ // get<0>() template returns sequencial index to
+ // container.
+ return(sent_packets_.template get<0>().erase(it));
}
ExchangeType xchg_type_; ///< Packet exchange type.
@@ -578,7 +681,7 @@ public:
/// Iterator pointing to the packet on sent list which will most
/// likely match next received packet. This is based on the
/// assumption that server responds in order to incoming packets.
- PktListIterator sent_packets_cache_;
+ PktListIterator next_sent_;
PktList rcvd_packets_; ///< List of received packets.
@@ -587,31 +690,44 @@ public:
/// list for diagnostics purposes.
PktList archived_packets_;
+ /// Indicates all packets have to be preserved after matching.
+ /// By default this is disabled which means that when received
+ /// packet is matched with sent packet both are deleted. This
+ /// is important when test is executed for extended period of
+ /// time and high memory usage might be the issue.
+ /// When timestamps listing is specified from the command line
+ /// (using diagnostics selector), all packets have to be preserved
+ /// so as the printing method may read their timestamps and
+ /// print it to user. In such usage model it will be rare to
+ /// run test for extended period of time so it should be fine
+ /// to keep all packets archived throughout the test.
+ bool archive_enabled_;
+
double min_delay_; ///< Minimum delay between sent
///< and received packets.
double max_delay_; ///< Maximum delay between sent
///< and received packets.
double sum_delay_; ///< Sum of delays between sent
///< and received packets.
- double square_sum_delay_; ///< Square sum of delays between
+ double sum_delay_squared_; ///< Squared sum of delays between
///< sent and recived packets.
- unsigned long long orphans_; ///< Number of orphant received packets.
+ uint64_t orphans_; ///< Number of orphant received packets.
/// Sum of unordered lookup sets. Needed to calculate mean size of
/// lookup set. It is desired that number of unordered lookups is
/// minimal for performance reasons. Tracking number of lookups and
/// mean size of the lookup set should give idea of packets serach
/// complexity.
- unsigned long long unordered_lookup_size_sum_;
+ uint64_t unordered_lookup_size_sum_;
- unsigned long long unordered_lookups_; ///< Number of unordered sent packets
+ uint64_t unordered_lookups_; ///< Number of unordered sent packets
///< lookups.
- unsigned long long ordered_lookups_; ///< Number of ordered sent packets
+ uint64_t ordered_lookups_; ///< Number of ordered sent packets
///< lookups.
- unsigned long long sent_packets_num_; ///< Total number of sent packets.
- unsigned long long rcvd_packets_num_; ///< Total number of received packets.
+ uint64_t sent_packets_num_; ///< Total number of sent packets.
+ uint64_t rcvd_packets_num_; ///< Total number of received packets.
};
/// Pointer to ExchangeStats.
@@ -625,10 +741,32 @@ public:
/// Iterator for \ref CustomCountersMap.
typedef typename CustomCountersMap::const_iterator CustomCountersMapIterator;
+ /// \brief Default constructor.
+ ///
+ /// This constructor by default disables packets archiving mode.
+ /// In this mode all packets from the list of sent packets are
+ /// moved to list of archived packets once they have been matched
+ /// with received packets. This is required if it has been selected
+ /// from the command line to print timestamps for all packets after
+ /// the test. If this is not selected archiving should be disabled
+ /// for performance reasons and to avoid waste of memory for storing
+ /// large list of archived packets.
+ StatsMgr() :
+ exchanges_(),
+ custom_counters_(),
+ archive_enabled_(false) {
+ }
+
/// \brief Constructor.
- StatsMgr()
- : exchanges_(),
- custom_counters_() {
+ ///
+ /// Use this constructor to set packets archive mode.
+ ///
+ /// \param archive_enabled true indicates that packets
+ /// archive mode is enabled.
+ StatsMgr(const bool archive_enabled) :
+ exchanges_(),
+ custom_counters_(),
+ archive_enabled_(archive_enabled) {
}
/// \brief Specify new exchange type.
@@ -643,7 +781,8 @@ public:
if (exchanges_.find(xchg_type) != exchanges_.end()) {
isc_throw(BadValue, "Exchange of specified type already added.");
}
- exchanges_[xchg_type] = ExchangeStatsPtr(new ExchangeStats(xchg_type));
+ exchanges_[xchg_type] =
+ ExchangeStatsPtr(new ExchangeStats(xchg_type, archive_enabled_));
}
/// \brief Add named custom uint64 counter.
@@ -668,6 +807,7 @@ public:
/// Method returns specified counter.
///
/// \param counter_key key poiting to the counter in the counters map.
+ /// The short counter name has to be used to access counter.
/// \return pointer to specified counter object.
CustomCounterPtr getCounter(const std::string& counter_key) {
CustomCountersMapIterator it = custom_counters_.find(counter_key);
@@ -675,7 +815,7 @@ public:
isc_throw(BadValue,
"Custom counter " << counter_key << "does not exist");
}
- return it->second;
+ return(it->second);
}
/// \brief Increment specified counter.
@@ -686,7 +826,7 @@ public:
/// \return pointer to specified counter after incrementation.
const CustomCounter& IncrementCounter(const std::string& counter_key) {
CustomCounterPtr counter = getCounter(counter_key);
- return ++(*counter);
+ return(++(*counter));
}
/// \brief Adds new packet to the sent packets list.
@@ -700,7 +840,7 @@ public:
/// \throw isc::BadValue if invalid exchange type specified or
/// packet is null.
void passSentPacket(const ExchangeType xchg_type,
- const boost::shared_ptr<T> packet) {
+ const boost::shared_ptr<const T>& packet) {
ExchangeStatsPtr xchg_stats = getExchangeStats(xchg_type);
xchg_stats->appendSent(packet);
}
@@ -719,14 +859,16 @@ public:
/// \throw isc::Unexpected if corresponding packet was not
/// found on the list of sent packets.
void passRcvdPacket(const ExchangeType xchg_type,
- const boost::shared_ptr<T> packet) {
+ const boost::shared_ptr<const T>& packet) {
ExchangeStatsPtr xchg_stats = getExchangeStats(xchg_type);
- boost::shared_ptr<T> sent_packet
+ boost::shared_ptr<const T> sent_packet
= xchg_stats->findSent(packet);
if (sent_packet) {
xchg_stats->updateDelays(sent_packet, packet);
- xchg_stats->appendRcvd(packet);
+ if (archive_enabled_) {
+ xchg_stats->appendRcvd(packet);
+ }
}
}
@@ -740,7 +882,7 @@ public:
/// \return minimum delay between packets.
double getMinDelay(const ExchangeType xchg_type) const {
ExchangeStatsPtr xchg_stats = getExchangeStats(xchg_type);
- return xchg_stats->getMinDelay();
+ return(xchg_stats->getMinDelay());
}
/// \brief Return maxmimum delay between sent and received packet.
@@ -753,7 +895,7 @@ public:
/// \return maximum delay between packets.
double getMaxDelay(const ExchangeType xchg_type) const {
ExchangeStatsPtr xchg_stats = getExchangeStats(xchg_type);
- return xchg_stats->getMaxDelay();
+ return(xchg_stats->getMaxDelay());
}
/// \brief Return avarage packet delay.
@@ -764,7 +906,7 @@ public:
/// \return average packet delay.
double getAvgDelay(const ExchangeType xchg_type) const {
ExchangeStatsPtr xchg_stats = getExchangeStats(xchg_type);
- return xchg_stats->getAvgDelay();
+ return(xchg_stats->getAvgDelay());
}
/// \brief Return standard deviation of packet delay.
@@ -775,7 +917,7 @@ public:
/// \return standard deviation of packet delay.
double getStdDevDelay(const ExchangeType xchg_type) const {
ExchangeStatsPtr xchg_stats = getExchangeStats(xchg_type);
- return xchg_stats->getStdDevDelay();
+ return(xchg_stats->getStdDevDelay());
}
/// \brief Return number of orphant packets.
@@ -786,9 +928,9 @@ public:
/// \param xchg_type exchange type.
/// \throw isc::BadValue if invalid exchange type specified.
/// \return number of orphant packets so far.
- unsigned long long getOrphans(const ExchangeType xchg_type) const {
+ uint64_t getOrphans(const ExchangeType xchg_type) const {
ExchangeStatsPtr xchg_stats = getExchangeStats(xchg_type);
- return xchg_stats->getOrphans();
+ return(xchg_stats->getOrphans());
}
/// \brief Return average unordered lookup set size.
@@ -802,7 +944,7 @@ public:
/// \return average unordered lookup set size.
double getAvgUnorderedLookupSetSize(const ExchangeType xchg_type) const {
ExchangeStatsPtr xchg_stats = getExchangeStats(xchg_type);
- return xchg_stats->getAvgUnorderedLookupSetSize();
+ return(xchg_stats->getAvgUnorderedLookupSetSize());
}
/// \brief Return number of unordered sent packets lookups
@@ -815,9 +957,9 @@ public:
/// \param xchg_type exchange type.
/// \throw isc::BadValue if invalid exchange type specified.
/// \return number of unordered lookups.
- unsigned long long getUnorderedLookups(const ExchangeType xchg_type) const {
+ uint64_t getUnorderedLookups(const ExchangeType xchg_type) const {
ExchangeStatsPtr xchg_stats = getExchangeStats(xchg_type);
- return xchg_stats->getUnorderedLookups();
+ return(xchg_stats->getUnorderedLookups());
}
/// \brief Return number of ordered sent packets lookups
@@ -831,9 +973,9 @@ public:
/// \param xchg_type exchange type.
/// \throw isc::BadValue if invalid exchange type specified.
/// \return number of ordered lookups.
- unsigned long long getOrderedLookups(const ExchangeType xchg_type) const {
+ uint64_t getOrderedLookups(const ExchangeType xchg_type) const {
ExchangeStatsPtr xchg_stats = getExchangeStats(xchg_type);
- return xchg_stats->getOrderedLookups();
+ return(xchg_stats->getOrderedLookups());
}
/// \brief Return total number of sent packets
@@ -844,9 +986,9 @@ public:
/// \param xchg_type exchange type.
/// \throw isc::BadValue if invalid exchange type specified.
/// \return number of sent packets.
- unsigned long long getSentPacketsNum(const ExchangeType xchg_type) const {
+ uint64_t getSentPacketsNum(const ExchangeType xchg_type) const {
ExchangeStatsPtr xchg_stats = getExchangeStats(xchg_type);
- return xchg_stats->getSentPacketsNum();
+ return(xchg_stats->getSentPacketsNum());
}
/// \brief Return total number of received packets
@@ -857,9 +999,9 @@ public:
/// \param xchg_type exchange type.
/// \throw isc::BadValue if invalid exchange type specified.
/// \return number of received packets.
- unsigned long long getRcvdPacketsNum(const ExchangeType xchg_type) const {
+ uint64_t getRcvdPacketsNum(const ExchangeType xchg_type) const {
ExchangeStatsPtr xchg_stats = getExchangeStats(xchg_type);
- return xchg_stats->getRcvdPacketsNum();
+ return(xchg_stats->getRcvdPacketsNum());
}
/// \brief Return name of the exchange.
@@ -872,62 +1014,46 @@ public:
std::string exchangeToString(ExchangeType xchg_type) const {
switch(xchg_type) {
case XCHG_DO:
- return "DISCOVER-OFFER";
+ return("DISCOVER-OFFER");
case XCHG_RA:
- return "REQUEST-ACK";
+ return("REQUEST-ACK");
case XCHG_SA:
- return "SOLICIT-ADVERTISE";
+ return("SOLICIT-ADVERTISE");
case XCHG_RR:
- return "REQUEST-REPLY";
+ return("REQUEST-REPLY");
default:
- return "Unknown exchange type";
+ return("Unknown exchange type");
}
}
- /// \brief Print main statistics for all exchange types.
+ /// \brief Print statistics counters for all exchange types.
///
- /// Method prints main statistics for all exchange types.
- /// Statistics includes: number of sent and received packets,
- /// number of dropped packets and number of orphans.
- void printMainStats() const {
- for (ExchangesMapIterator it = exchanges_.begin();
- it != exchanges_.end();
- ++it) {
- ExchangeStatsPtr xchg_stats = it->second;
- printf("***Statistics for packet exchange %s***\n"
- "sent: %llu, received: %llu\n"
- "drops: %lld, orphans: %llu\n\n",
- exchangeToString(it->first).c_str(),
- xchg_stats->getSentPacketsNum(),
- xchg_stats->getRcvdPacketsNum(),
- xchg_stats->getRcvdPacketsNum()
- - xchg_stats->getSentPacketsNum(),
- xchg_stats->getOrphans());
- }
- }
-
- /// \brief Print round trip time packets statistics.
+ /// Method prints statistics for all exchange types.
+ /// Statistics includes:
+ /// - number of sent and received packets
+ /// - number of dropped packets and number of orphans
+ /// - minimum packets delay,
+ /// - average packets delay,
+ /// - maximum packets delay,
+ /// - standard deviation of packets delay.
///
- /// Method prints round trip time packets statistics. Statistics
- /// includes minimum packet delay, maximum packet delay, average
- /// packet delay and standard deviation of delays. Packet delay
- /// is a duration between sending a packet to server and receiving
- /// response from server.
- void printRTTStats() const {
+ /// \throw isc::InvalidOperation if no exchange type added to
+ /// track statistics.
+ void printStats() const {
+ if (exchanges_.size() == 0) {
+ isc_throw(isc::InvalidOperation,
+ "no exchange type added for tracking");
+ }
for (ExchangesMapIterator it = exchanges_.begin();
it != exchanges_.end();
++it) {
ExchangeStatsPtr xchg_stats = it->second;
- printf("***Round trip time Statistics for packet exchange %s***\n"
- "min delay: %.3f\n"
- "avg delay: %.3f\n"
- "max delay: %.3f\n"
- "std deviation: %.3f\n",
- exchangeToString(it->first).c_str(),
- xchg_stats->getMinDelay(),
- xchg_stats->getAvgDelay(),
- xchg_stats->getMaxDelay(),
- xchg_stats->getStdDevDelay());
+ std::cout << "***Statistics for: " << exchangeToString(it->first)
+ << "***" << std::endl;
+ xchg_stats->printMainStats();
+ std::cout << std::endl;
+ xchg_stats->printRTTStats();
+ std::cout << std::endl;
}
}
@@ -937,15 +1063,25 @@ public:
/// packets for all defined exchange types.
///
/// \throw isc::InvalidOperation if one of the packets has
- /// no timestamp value set.
+ /// no timestamp value set or if packets archive mode is
+ /// disabled.
+ ///
+ /// \throw isc::InvalidOperation if no exchange type added to
+ /// track statistics or packets archive mode is disabled.
void printTimestamps() const {
+ if (exchanges_.size() == 0) {
+ isc_throw(isc::InvalidOperation,
+ "no exchange type added for tracking");
+ }
for (ExchangesMapIterator it = exchanges_.begin();
it != exchanges_.end();
++it) {
ExchangeStatsPtr xchg_stats = it->second;
- printf("***Timestamps for packets in exchange %s***\n",
- exchangeToString(it->first).c_str());
+ std::cout << "***Timestamps for packets: "
+ << exchangeToString(it->first)
+ << "***" << std::endl;
xchg_stats->printTimestamps();
+ std::cout << std::endl;
}
}
@@ -953,20 +1089,23 @@ public:
///
/// Method prints names and values of custom counters. Custom counters
/// are defined by client class for tracking different statistics.
+ ///
+ /// \throw isc::InvalidOperation if no custom counters added for tracking.
void printCustomCounters() const {
- if (custom_counters_.size() > 0) {
- printf("***Various statistics counters***\n");
+ if (custom_counters_.size() == 0) {
+ isc_throw(isc::InvalidOperation, "no custom counters specified");
}
for (CustomCountersMapIterator it = custom_counters_.begin();
it != custom_counters_.end();
++it) {
CustomCounterPtr counter = it->second;
- printf("%s: %llu\n", counter->getName().c_str(),
- counter->getValue());
+ std::cout << counter->getName() << ": " << counter->getValue()
+ << std::endl;
}
}
private:
+
/// \brief Return exchange stats object for given exchange type
///
/// Method returns exchange stats object for given exchange type.
@@ -980,11 +1119,21 @@ private:
isc_throw(BadValue, "Packets exchange not specified");
}
ExchangeStatsPtr xchg_stats = it->second;
- return xchg_stats;
+ return(xchg_stats);
}
ExchangesMap exchanges_; ///< Map of exchange types.
CustomCountersMap custom_counters_; ///< Map with custom counters.
+
+ /// Indicates that packets from list of sent packets should be
+ /// archived (moved to list of archived packets) once they are
+ /// matched with received packets. This is required when it has
+ /// been selected from the command line to print packets'
+ /// timestamps after test. This may affect performance and
+ /// consume large amount of memory when the test is running
+ /// for extended period of time and many packets have to be
+ /// archived.
+ bool archive_enabled_;
};
} // namespace perfdhcp
diff --git a/tests/tools/perfdhcp/tests/stats_mgr_unittest.cc b/tests/tools/perfdhcp/tests/stats_mgr_unittest.cc
index dad544e..2233847 100644
--- a/tests/tools/perfdhcp/tests/stats_mgr_unittest.cc
+++ b/tests/tools/perfdhcp/tests/stats_mgr_unittest.cc
@@ -156,11 +156,11 @@ public:
TEST_F(StatsMgrTest, Constructor) {
boost::scoped_ptr<StatsMgr4> stats_mgr(new StatsMgr4());
stats_mgr->addExchangeStats(StatsMgr4::XCHG_DO);
- EXPECT_EQ(
+ EXPECT_DOUBLE_EQ(
std::numeric_limits<double>::max(),
stats_mgr->getMinDelay(StatsMgr4::XCHG_DO)
);
- EXPECT_EQ(0, stats_mgr->getMaxDelay(StatsMgr4::XCHG_DO));
+ EXPECT_DOUBLE_EQ(0, stats_mgr->getMaxDelay(StatsMgr4::XCHG_DO));
EXPECT_EQ(0, stats_mgr->getOrphans(StatsMgr4::XCHG_DO));
EXPECT_EQ(0, stats_mgr->getOrderedLookups(StatsMgr4::XCHG_DO));
EXPECT_EQ(0, stats_mgr->getUnorderedLookups(StatsMgr4::XCHG_DO));
@@ -410,5 +410,41 @@ TEST_F(StatsMgrTest, CustomCounters) {
}
+TEST_F(StatsMgrTest, PrintStats) {
+ std::cout << "This unit test is checking statistics printing "
+ << "capabilities. It is expected that some counters "
+ << "will be printed during this test. It may also "
+ << "cause spurious errors." << std::endl;
+ boost::shared_ptr<StatsMgr6> stats_mgr(new StatsMgr6());
+ stats_mgr->addExchangeStats(StatsMgr6::XCHG_SA);
+
+ // Simulate sending and receiving one packet. Otherwise printing
+ // functions will complain about lack of packets.
+ const int packets_num = 1;
+ passMultiplePackets6(stats_mgr, StatsMgr6::XCHG_SA, DHCPV6_SOLICIT,
+ packets_num);
+ passMultiplePackets6(stats_mgr, StatsMgr6::XCHG_SA, DHCPV6_ADVERTISE,
+ packets_num, true);
+
+ // This function will print statistics even if packets are not
+ // archived because it relies on counters. There is at least one
+ // exchange needed to count the average delay and std deviation.
+ EXPECT_NO_THROW(stats_mgr->printStats());
+
+ // Printing timestamps is expected to fail because by default we
+ // disable packets archiving mode. Without packets we can't get
+ // timestamps.
+ EXPECT_THROW(stats_mgr->printTimestamps(), isc::InvalidOperation);
+
+ // Now, we create another statistics manager instance and enable
+ // packets archiving mode.
+ const bool archive_packets = true;
+ boost::shared_ptr<StatsMgr6> stats_mgr2(new StatsMgr6(archive_packets));
+ stats_mgr2->addExchangeStats(StatsMgr6::XCHG_SA);
+
+ // Timestamps should now get printed because packets have been preserved.
+ EXPECT_NO_THROW(stats_mgr2->printTimestamps());
+}
+
}
More information about the bind10-changes
mailing list