Kea  1.5.0
rate_control.cc
Go to the documentation of this file.
1 // Copyright (C) 2013-2015 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #include <config.h>
8 
10 #include "rate_control.h"
11 
12 namespace isc {
13 namespace perfdhcp {
14 
15 using namespace boost::posix_time;
16 
18  : send_due_(currentTime()), last_sent_(currentTime()),
19  aggressivity_(1), rate_(0), late_sent_(false) {
20 }
21 
22 RateControl::RateControl(const int rate, const int aggressivity)
23  : send_due_(currentTime()), last_sent_(currentTime()),
24  aggressivity_(aggressivity), rate_(rate), late_sent_(false) {
25  if (aggressivity_ < 1) {
26  isc_throw(isc::BadValue, "invalid value of aggressivity "
27  << aggressivity << ", expected value is greater than 0");
28  }
29  if (rate_ < 0) {
30  isc_throw(isc::BadValue, "invalid value of rate " << rate
31  << ", expected non-negative value");
32  }
33 }
34 
35 uint64_t
37 
38  // We need calculate the due time for sending next set of messages.
39  updateSendDue();
40 
41  // Get current time. If we are behind due time, we have to calculate
42  // how many messages to send to catch up with the rate.
43  ptime now = currentTime();
44  if (now >= send_due_) {
45  // Reset number of exchanges.
46  uint64_t due_exchanges = 0;
47  // If rate is specified from the command line we have to
48  // synchronize with it.
49  if (getRate() != 0) {
50  time_period period(send_due_, now);
51  time_duration duration = period.length();
52  // due_factor indicates the number of seconds that
53  // sending next chunk of packets will take.
54  double due_factor =
55  static_cast<double>(duration.fractional_seconds()) /
56  static_cast<double>(time_duration::ticks_per_second());
57  due_factor += static_cast<double>(duration.total_seconds());
58  // Multiplying due_factor by expected rate gives the number
59  // of exchanges to be initiated.
60  due_exchanges = static_cast<uint64_t>(due_factor * getRate());
61  // We want to make sure that at least one packet goes out.
62  if (due_exchanges == 0) {
63  due_exchanges = 1;
64  }
65  // We should not exceed aggressivity as it could have been
66  // restricted from command line.
67  if (due_exchanges > getAggressivity()) {
68  due_exchanges = getAggressivity();
69  }
70  } else {
71  // Rate is not specified so we rely on aggressivity
72  // which is the number of packets to be sent in
73  // one chunk.
74  due_exchanges = getAggressivity();
75  }
76  return (due_exchanges);
77  }
78  return (0);
79 }
80 
81 boost::posix_time::ptime
83  return (microsec_clock::universal_time());
84 }
85 
86 void
88  // There is no sense to update due time if the current due time is in the
89  // future. The due time is calculated as a duration between the moment
90  // when the last message of the given type was sent and the time when
91  // next one is supposed to be sent based on a given rate. The former value
92  // will not change until we send the next message, which we don't do
93  // until we reach the due time.
94  if (send_due_ > currentTime()) {
95  return;
96  }
97  // This is initialized in the class constructor, so if it is not initialized
98  // it is a programmatic error.
99  if (last_sent_.is_not_a_date_time()) {
100  isc_throw(isc::Unexpected, "timestamp of the last sent packet not"
101  " initialized");
102  }
103  // If rate was not specified we will wait just one clock tick to
104  // send next packet. This simulates best effort conditions.
105  long duration = 1;
106  if (getRate() != 0) {
107  // We use number of ticks instead of nanoseconds because
108  // nanosecond resolution may not be available on some
109  // machines. Number of ticks guarantees the highest possible
110  // timer resolution.
111  duration = time_duration::ticks_per_second() / getRate();
112  }
113  // Calculate due time to initiate next chunk of exchanges.
114  send_due_ = last_sent_ + time_duration(0, 0, 0, duration);
115  if (send_due_ > currentTime()) {
116  late_sent_ = true;
117  } else {
118  late_sent_ = false;
119  }
120 }
121 
122 void
123 RateControl::setAggressivity(const int aggressivity) {
124  if (aggressivity < 1) {
125  isc_throw(isc::BadValue, "invalid value of aggressivity "
126  << aggressivity << ", expected value is greater than 0");
127  }
128  aggressivity_ = aggressivity;
129 }
130 
131 void
132 RateControl::setRate(const int rate) {
133  if (rate < 0) {
134  isc_throw(isc::BadValue, "invalid value of rate " << rate
135  << ", expected non-negative value");
136  }
137  rate_ = rate;
138 }
139 
140 void
141 RateControl::setRelativeDue(const int offset) {
142  send_due_ = offset > 0 ?
143  currentTime() + seconds(abs(offset)) :
144  currentTime() - seconds(abs(offset));
145 }
146 
147 void
150 }
151 
152 } // namespace perfdhcp
153 } // namespace isc
static boost::posix_time::ptime currentTime()
Convenience function returning current time.
Definition: rate_control.cc:82
RateControl()
Default constructor.
Definition: rate_control.cc:17
int getRate() const
Returns the rate.
Definition: rate_control.h:94
boost::posix_time::ptime last_sent_
Holds a timestamp when the last message was sent.
Definition: rate_control.h:155
void setRelativeDue(const int offset)
Sets the value of the due time.
void updateSendDue()
Calculates the send due.
Definition: rate_control.cc:87
int aggressivity_
Holds an aggressivity value.
Definition: rate_control.h:158
uint64_t getOutboundMessageCount()
Returns number of messages to be sent "now".
Definition: rate_control.cc:36
void updateSendTime()
Sets the timestamp of the last sent message to current time.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
void setRate(const int rate)
Sets the new rate.
bool late_sent_
A flag which indicates that the calculated due time is in the past.
Definition: rate_control.h:165
A generic exception that is thrown when an unexpected error condition occurs.
int rate_
Holds a desired rate value.
Definition: rate_control.h:161
int getAggressivity() const
Returns the value of aggressivity.
Definition: rate_control.h:51
void setAggressivity(const int aggressivity)
Sets the value of aggressivity.
Defines the logger used by the top-level component of kea-dhcp-ddns.
string currentTime()
Create Time.
boost::posix_time::ptime send_due_
Holds a timestamp when the next message should be sent.
Definition: rate_control.h:152