Commit 3aa87f68 authored by Yoshitaka Aharen's avatar Yoshitaka Aharen
Browse files

Modified IntervalTimer to accept interval in milliseconds (Trac ticket #452)

Modified the interface of IntervalTimer to accept interval in
milliseconds.
Tests for IntervalTimer are also modified; now it takes 1.4 seconds.
parent ee7acfcc
......@@ -56,7 +56,7 @@
{ "item_name": "statistics-interval",
"item_type": "integer",
"item_optional": true,
"item_default": 60
"item_default": 60000
}
],
"commands": [
......
......@@ -372,7 +372,7 @@ AuthSrv::setStatisticsTimerInterval(uint32_t interval) {
cerr << "[b10-auth] Disabled statistics timer" << endl;
} else {
cerr << "[b10-auth] Set statistics timer to " << interval
<< " seconds" << endl;
<< " milliseconds" << endl;
}
}
}
......
......@@ -308,7 +308,8 @@ public:
/// is shutdown.
void setStatisticsSession(isc::cc::AbstractSession* statistics_session);
/// Return the interval of periodic submission of statistics in seconds.
/// Return the interval of periodic submission of statistics in
/// milliseconds.
///
/// If the statistics submission is disabled, it returns 0.
///
......@@ -318,7 +319,7 @@ public:
/// Set the interval of periodic submission of statistics.
///
/// If the specified value is non 0, the \c AuthSrv object will submit
/// its statistics to the statistics module every \c interval seconds.
/// its statistics to the statistics module every \c interval milliseconds.
/// If it's 0, and \c AuthSrv currently submits statistics, the submission
/// will be disabled.
///
......@@ -326,7 +327,7 @@ public:
/// underlying library routines may involve resource allocation, and
/// when it fails it would result in a corresponding standard exception.
///
/// \param interval The submission interval in seconds if non 0;
/// \param interval The submission interval in milliseconds if non 0;
/// or a value of 0 to disable the submission.
void setStatisticsTimerInterval(uint32_t interval);
......
......@@ -395,7 +395,7 @@ private:
void update();
// a function to call back when timer_ expires
IntervalTimer::Callback cbfunc_;
// interval in seconds
// interval in milliseconds
long interval_;
// asio timer
asio::deadline_timer timer_;
......@@ -438,7 +438,7 @@ IntervalTimerImpl::update() {
}
try {
// Update expire time to (current time + interval_).
timer_.expires_from_now(boost::posix_time::seconds(interval_));
timer_.expires_from_now(boost::posix_time::millisec(interval_));
} catch (const asio::system_error& e) {
isc_throw(isc::Unexpected, "Failed to update timer");
}
......
......@@ -581,7 +581,7 @@ private:
/// \c IntervalTimerImpl::callback() is called by the timer when it expires.
///
/// The function calls the call back function set by \c setup() and updates
/// the timer to expire in (now + interval) seconds.
/// the timer to expire in (now + interval) milliseconds.
/// The type of call back function is \c void(void).
///
/// The call back function will not be called if the instance of this class is
......@@ -595,14 +595,13 @@ private:
/// void function_to_call_back() {
/// // this function will be called periodically
/// }
/// int interval_in_seconds = 1;
/// int interval_in_milliseconds = 1000;
/// IOService io_service;
///
/// IntervalTimer intervalTimer(io_service);
/// intervalTimer.setup(function_to_call_back, interval_in_seconds);
/// intervalTimer.setup(function_to_call_back, interval_in_milliseconds);
/// io_service.run();
/// \endcode
///
class IntervalTimer {
public:
/// \name The type of timer callback function
......@@ -625,7 +624,6 @@ public:
/// This constructor may also throw \c asio::system_error.
///
/// \param io_service A reference to an instance of IOService
///
IntervalTimer(IOService& io_service);
/// \brief The destructor.
......@@ -634,18 +632,17 @@ public:
///
/// On the destruction of this class the timer will be canceled
/// inside \c asio::deadline_timer.
///
~IntervalTimer();
//@}
/// \brief Register timer callback function and interval.
///
/// This function sets callback function and interval in seconds.
/// This function sets callback function and interval in milliseconds.
/// Timer will actually start after calling \c IOService::run().
///
/// \param cbfunc A reference to a function \c void(void) to call back
/// when the timer is expired (should not be an empty functor)
/// \param interval Interval in seconds (greater than 0)
/// \param interval Interval in milliseconds (greater than 0)
///
/// Note: IntervalTimer will not pass \c asio::error_code to
/// call back function. In case the timer is cancelled, the function
......@@ -654,7 +651,6 @@ public:
/// \throw isc::InvalidParameter cbfunc is empty
/// \throw isc::BadValue interval is less than or equal to 0
/// \throw isc::Unexpected ASIO library error
///
void setup(const Callback& cbfunc, const long interval);
/// Cancel the timer.
......@@ -669,14 +665,10 @@ public:
/// Return the timer interval.
///
/// This method returns the timer interval in seconds if it's running;
/// This method returns the timer interval in milliseconds if it's running;
/// if the timer has been canceled it returns 0.
///
/// This method never throws an exception.
///
/// Note: We may want to change the granularity of the timer to
/// milliseconds or even finer. If and when this happens the semantics
/// of the return value of this method will be changed accordingly.
long getInterval() const;
private:
......
......@@ -836,7 +836,7 @@ protected:
// First time of call back.
// Call setup() to update callback function to TimerCallBack.
test_obj_->timer_called_ = false;
timer_.setup(TimerCallBack(test_obj_), 1);
timer_.setup(TimerCallBack(test_obj_), 100);
} else if (count_ == 2) {
// Second time of call back.
// If it reaches here, re-setup() is failed (unexpected).
......@@ -876,27 +876,24 @@ TEST_F(IntervalTimerTest, startIntervalTimer) {
boost::posix_time::ptime start;
start = boost::posix_time::microsec_clock::universal_time();
// setup timer
itimer.setup(TimerCallBack(this), 1);
EXPECT_EQ(1, itimer.getInterval());
itimer.setup(TimerCallBack(this), 100);
EXPECT_EQ(100, itimer.getInterval());
io_service_.run();
// reaches here after timer expired
// delta: difference between elapsed time and 1 second
// delta: difference between elapsed time and 100 milliseconds.
boost::posix_time::time_duration delta =
(boost::posix_time::microsec_clock::universal_time() - start)
- boost::posix_time::seconds(1);
- boost::posix_time::millisec(100);
if (delta.is_negative()) {
delta.invert_sign();
}
// expect TimerCallBack is called; timer_called_ is true
EXPECT_TRUE(timer_called_);
// expect interval is 1 second +/- TIMER_MARGIN_MSEC.
// expect interval is 100 milliseconds +/- TIMER_MARGIN_MSEC.
EXPECT_TRUE(delta < TIMER_MARGIN_MSEC);
}
TEST_F(IntervalTimerTest, destructIntervalTimer) {
// Note: This test currently takes 6 seconds. The timer should have
// finer granularity and timer periods in this test should be shorter
// in the future.
// This code isn't exception safe, but we'd rather keep the code
// simpler and more readable as this is only for tests and if it throws
// the program would immediately terminate anyway.
......@@ -917,24 +914,24 @@ TEST_F(IntervalTimerTest, destructIntervalTimer) {
// if they are same the timer was not called; expected result
// if they are different the timer was called after destructed
//
// 0 1 2 3 4 5 6 (s)
// (A) i-----+--x
// ^
// |destruct itimer_counter
// (B) i--------+--------s
// ^stop io_service
// and test itimer_counter have been stopped
//
// 0 100 200 300 400 500 600 (ms)
// (A) i--------+----x
// ^
// |destruct itimer_counter
// (B) i-------------+--------------s
// ^stop io_service
// and check if itimer_counter have been
// stopped
// itimer_counter will be deleted in TimerCallBackCancelDeleter
IntervalTimer* itimer_counter = new IntervalTimer(io_service_);
IntervalTimer itimer_canceller(io_service_);
timer_cancel_success_ = false;
TimerCallBackCounter callback_canceller(this);
itimer_counter->setup(callback_canceller, 2);
itimer_counter->setup(callback_canceller, 200);
itimer_canceller.setup(
TimerCallBackCancelDeleter(this, itimer_counter, callback_canceller),
3);
300);
io_service_.run();
EXPECT_TRUE(timer_cancel_success_);
}
......@@ -945,8 +942,8 @@ TEST_F(IntervalTimerTest, cancel) {
IntervalTimer itimer_counter(io_service_);
IntervalTimer itimer_watcher(io_service_);
unsigned int counter = 0;
itimer_counter.setup(TimerCallBackCanceller(counter, itimer_counter), 1);
itimer_watcher.setup(TimerCallBack(this), 3);
itimer_counter.setup(TimerCallBackCanceller(counter, itimer_counter), 100);
itimer_watcher.setup(TimerCallBack(this), 200);
io_service_.run();
EXPECT_EQ(1, counter);
EXPECT_EQ(0, itimer_counter.getInterval());
......@@ -956,10 +953,6 @@ TEST_F(IntervalTimerTest, cancel) {
}
TEST_F(IntervalTimerTest, overwriteIntervalTimer) {
// Note: This test currently takes 4 seconds. The timer should have
// finer granularity and timer periods in this test should be shorter
// in the future.
// Calling setup() multiple times updates call back function and interval.
//
// There are two timers:
......@@ -967,23 +960,24 @@ TEST_F(IntervalTimerTest, overwriteIntervalTimer) {
// (Calls TimerCallBackCounter / TimerCallBack)
// - increments internal counter in callback function
// (TimerCallBackCounter)
// interval: 2 seconds
// interval: 300 milliseconds
// - io_service_.stop() (TimerCallBack)
// interval: 1 second
// interval: 100 milliseconds
// itimer_overwriter (B)
// (Calls TimerCallBackOverwriter)
// - first time of callback, it calls setup() to change call back
// function and interval of itimer to TimerCallBack / 1 second
// after 3 + 1 seconds from the beginning of this test,
// function to TimerCallBack and interval of itimer to 100
// milliseconds
// after 300 + 100 milliseconds from the beginning of this test,
// TimerCallBack() will be called and io_service_ stops.
// - second time of callback, it means the test fails.
//
// 0 1 2 3 4 5 6 (s)
// (A) i-----+--C--s
// ^ ^stop io_service
// |change call back function
// (B) i--------+--------S
// ^(stop io_service on fail)
// 0 100 200 300 400 500 600 700 800 (ms)
// (A) i-------------+----C----s
// ^ ^stop io_service
// |change call back function
// (B) i------------------+-------------------S
// ^(stop io_service on fail)
//
IntervalTimer itimer(io_service_);
......@@ -991,22 +985,22 @@ TEST_F(IntervalTimerTest, overwriteIntervalTimer) {
// store start time
boost::posix_time::ptime start;
start = boost::posix_time::microsec_clock::universal_time();
itimer.setup(TimerCallBackCounter(this), 2);
itimer_overwriter.setup(TimerCallBackOverwriter(this, itimer), 3);
itimer.setup(TimerCallBackCounter(this), 300);
itimer_overwriter.setup(TimerCallBackOverwriter(this, itimer), 400);
io_service_.run();
// reaches here after timer expired
// if interval is updated, it takes
// 3 seconds for TimerCallBackOverwriter
// + 1 second for TimerCallBack (stop)
// = 4 seconds.
// 400 milliseconds for TimerCallBackOverwriter
// + 100 milliseconds for TimerCallBack (stop)
// = 500 milliseconds.
// otherwise (test fails), it takes
// 3 seconds for TimerCallBackOverwriter
// + 3 seconds for TimerCallBackOverwriter (stop)
// = 6 seconds.
// delta: difference between elapsed time and 3 + 1 seconds
// 400 milliseconds for TimerCallBackOverwriter
// + 400 milliseconds for TimerCallBackOverwriter (stop)
// = 800 milliseconds.
// delta: difference between elapsed time and 400 + 100 milliseconds
boost::posix_time::time_duration delta =
(boost::posix_time::microsec_clock::universal_time() - start)
- boost::posix_time::seconds(3 + 1);
- boost::posix_time::millisec(400 + 100);
if (delta.is_negative()) {
delta.invert_sign();
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment