Kea 1.5.0
timer_mgr.cc
Go to the documentation of this file.
1// Copyright (C) 2016-2018 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>
10#include <dhcpsrv/dhcpsrv_log.h>
11#include <dhcpsrv/timer_mgr.h>
13
14#include <boost/bind.hpp>
15
16#include <utility>
17
18using namespace isc;
19using namespace isc::asiolink;
20
21namespace {
22
28struct TimerInfo {
30 asiolink::IntervalTimer interval_timer_;
31
35
37 long interval_;
38
40 asiolink::IntervalTimer::Mode scheduling_mode_;
41
50 TimerInfo(asiolink::IOService& io_service,
51 const asiolink::IntervalTimer::Callback& user_callback,
52 const long interval,
54 : interval_timer_(io_service),
55 user_callback_(user_callback),
56 interval_(interval),
57 scheduling_mode_(mode) { };
58};
59
60}
61
62namespace isc {
63namespace dhcp {
64
66typedef boost::shared_ptr<TimerInfo> TimerInfoPtr;
67
69typedef std::map<std::string, TimerInfoPtr> TimerInfoMap;
70
71
74public:
75
78
82 void setIOService(const IOServicePtr& io_service);
83
95 void registerTimer(const std::string& timer_name,
97 const long interval,
98 const asiolink::IntervalTimer::Mode& scheduling_mode);
99
100
109 void unregisterTimer(const std::string& timer_name);
110
115 void unregisterTimers();
116
122 bool isTimerRegistered(const std::string& timer_name);
123
125 size_t timersCount() const;
126
139 void setup(const std::string& timer_name);
140
146 void cancel(const std::string& timer_name);
147
148private:
149
154 void timerCallback(const std::string& timer_name);
155
157 asiolink::IOServicePtr io_service_;
158
161 TimerInfoMap registered_timers_;
162};
163
165 io_service_(new IOService()), registered_timers_() {
166}
167
168void
170 if (!io_service) {
171 isc_throw(BadValue, "IO service object must not be null for TimerMgr");
172 }
173 io_service_ = io_service;
174}
175
176void
177TimerMgrImpl::registerTimer(const std::string& timer_name,
178 const IntervalTimer::Callback& callback,
179 const long interval,
180 const IntervalTimer::Mode& scheduling_mode) {
181
182 // Timer name must not be empty.
183 if (timer_name.empty()) {
184 isc_throw(BadValue, "registered timer name must not be empty");
185 }
186
187 // Must not register two timers under the same name.
188 if (registered_timers_.find(timer_name) != registered_timers_.end()) {
189 isc_throw(BadValue, "trying to register duplicate timer '"
190 << timer_name << "'");
191 }
192
193 // Create a structure holding the configuration for the timer. It will
194 // create the instance if the IntervalTimer. It will also hold the
195 // callback, interval and scheduling mode parameters.
196 TimerInfoPtr timer_info(new TimerInfo(*io_service_, callback,
197 interval, scheduling_mode));
198
199 // Actually register the timer.
200 registered_timers_.insert(std::pair<std::string, TimerInfoPtr>(timer_name,
201 timer_info));
202}
203
204void
205TimerMgrImpl::unregisterTimer(const std::string& timer_name) {
206
207 // Find the timer with specified name.
208 TimerInfoMap::iterator timer_info_it = registered_timers_.find(timer_name);
209
210 // Check if the timer has been registered.
211 if (timer_info_it == registered_timers_.end()) {
212 isc_throw(BadValue, "unable to unregister non existing timer '"
213 << timer_name << "'");
214 }
215
216 // Cancel any pending asynchronous operation and stop the timer.
217 cancel(timer_name);
218
219 // Remove the timer.
220 registered_timers_.erase(timer_info_it);
221}
222
223void
225 // Copy the map holding timers configuration. This is required so as
226 // we don't cut the branch which we're sitting on when we will be
227 // erasing the timers. We're going to iterate over the register timers
228 // and remove them with the call to unregisterTimer function. But this
229 // function will remove them from the register_timers_ map. If we
230 // didn't work on the copy here, our iterator would invalidate. The
231 // TimerInfo structure is copyable and since it is using the shared
232 // pointers the copy is not expensive. Also this function is called when
233 // the process terminates so it is not critical for performance.
234 TimerInfoMap registered_timers_copy(registered_timers_);
235
236 // Iterate over the existing timers and unregister them.
237 for (TimerInfoMap::iterator timer_info_it = registered_timers_copy.begin();
238 timer_info_it != registered_timers_copy.end(); ++timer_info_it) {
239 unregisterTimer(timer_info_it->first);
240 }
241}
242
243bool
244TimerMgrImpl::isTimerRegistered(const std::string& timer_name) {
245 return (registered_timers_.find(timer_name) != registered_timers_.end());
246}
247
248size_t
250 return (registered_timers_.size());
251}
252
253void
254TimerMgrImpl::setup(const std::string& timer_name) {
255
256 // Check if the specified timer exists.
257 TimerInfoMap::const_iterator timer_info_it = registered_timers_.find(timer_name);
258 if (timer_info_it == registered_timers_.end()) {
259 isc_throw(BadValue, "unable to setup timer '" << timer_name << "': "
260 "no such timer registered");
261 }
262
263 // Schedule the execution of the timer using the parameters supplied
264 // during the registration.
265 const TimerInfoPtr& timer_info = timer_info_it->second;
266 IntervalTimer::Callback cb = boost::bind(&TimerMgrImpl::timerCallback, this,
267 timer_name);
268 timer_info->interval_timer_.setup(cb, timer_info->interval_,
269 timer_info->scheduling_mode_);
270}
271
272void
273TimerMgrImpl::cancel(const std::string& timer_name) {
274
275 // Find the timer of our interest.
276 TimerInfoMap::const_iterator timer_info_it = registered_timers_.find(timer_name);
277 if (timer_info_it == registered_timers_.end()) {
278 isc_throw(BadValue, "unable to cancel timer '" << timer_name << "': "
279 "no such timer registered");
280 }
281 // Cancel the timer.
282 timer_info_it->second->interval_timer_.cancel();
283}
284
285void
286TimerMgrImpl::timerCallback(const std::string& timer_name) {
287 // Find the specified timer setup.
288 TimerInfoMap::iterator timer_info_it = registered_timers_.find(timer_name);
289 if (timer_info_it != registered_timers_.end()) {
290
291 // Running user-defined operation for the timer. Logging it
292 // on the slightly lower debug level as there may be many
293 // such traces.
295 DHCPSRV_TIMERMGR_RUN_TIMER_OPERATION)
296 .arg(timer_info_it->first);
297
298 std::string error_string;
299 try {
300 timer_info_it->second->user_callback_();
301
302 } catch (const std::exception& ex){
303 error_string = ex.what();
304
305 } catch (...) {
306 error_string = "unknown reason";
307 }
308
309 // Exception was thrown. Log an error.
310 if (!error_string.empty()) {
311 LOG_ERROR(dhcpsrv_logger, DHCPSRV_TIMERMGR_CALLBACK_FAILED)
312 .arg(timer_info_it->first)
313 .arg(error_string);
314 }
315 }
316}
317
318const TimerMgrPtr&
320 static TimerMgrPtr timer_mgr(new TimerMgr());
321 return (timer_mgr);
322}
323
324TimerMgr::TimerMgr()
325 : impl_(new TimerMgrImpl()) {
326}
327
329 impl_->unregisterTimers();
330 delete impl_;
331}
332
333void
334TimerMgr::registerTimer(const std::string& timer_name,
335 const IntervalTimer::Callback& callback,
336 const long interval,
337 const IntervalTimer::Mode& scheduling_mode) {
338
340 DHCPSRV_TIMERMGR_REGISTER_TIMER)
341 .arg(timer_name)
342 .arg(interval);
343
344 impl_->registerTimer(timer_name, callback, interval, scheduling_mode);
345}
346
347void
348TimerMgr::unregisterTimer(const std::string& timer_name) {
349
351 DHCPSRV_TIMERMGR_UNREGISTER_TIMER)
352 .arg(timer_name);
353
354 impl_->unregisterTimer(timer_name);
355}
356
357void
359
361 DHCPSRV_TIMERMGR_UNREGISTER_ALL_TIMERS);
362
363 impl_->unregisterTimers();
364}
365
366bool
367TimerMgr::isTimerRegistered(const std::string& timer_name) {
368 return (impl_->isTimerRegistered(timer_name));
369}
370
371size_t
373 return (impl_->timersCount());
374}
375
376void
377TimerMgr::setup(const std::string& timer_name) {
378
380 DHCPSRV_TIMERMGR_START_TIMER)
381 .arg(timer_name);
382
383 impl_->setup(timer_name);
384}
385
386void
387TimerMgr::cancel(const std::string& timer_name) {
388
390 DHCPSRV_TIMERMGR_STOP_TIMER)
391 .arg(timer_name);
392
393 impl_->cancel(timer_name);
394}
395
396void
398 impl_->setIOService(io_service);
399}
400
401
402} // end of namespace isc::dhcp
403} // end of namespace isc
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
Implementation of the TimerMgr.
Definition: timer_mgr.cc:73
void unregisterTimers()
Unregisters all timers.
Definition: timer_mgr.cc:224
size_t timersCount() const
Returns the number of registered timers.
Definition: timer_mgr.cc:249
void cancel(const std::string &timer_name)
Cancels the execution of the interval timer.
Definition: timer_mgr.cc:273
void registerTimer(const std::string &timer_name, const asiolink::IntervalTimer::Callback &callback, const long interval, const asiolink::IntervalTimer::Mode &scheduling_mode)
Registers new timer in the TimerMgr.
Definition: timer_mgr.cc:177
void unregisterTimer(const std::string &timer_name)
Unregisters specified timer.
Definition: timer_mgr.cc:205
void setup(const std::string &timer_name)
Schedules the execution of the interval timer.
Definition: timer_mgr.cc:254
void setIOService(const IOServicePtr &io_service)
Sets IO service to be used by the Timer Manager.
Definition: timer_mgr.cc:169
TimerMgrImpl()
Constructor.
Definition: timer_mgr.cc:164
bool isTimerRegistered(const std::string &timer_name)
Checks if the timer with a specified name has been registered.
Definition: timer_mgr.cc:244
Manages a pool of asynchronous interval timers.
Definition: timer_mgr.h:54
bool isTimerRegistered(const std::string &timer_name)
Checks if the timer with a specified name has been registered.
Definition: timer_mgr.cc:367
~TimerMgr()
Destructor.
Definition: timer_mgr.cc:328
void setIOService(const asiolink::IOServicePtr &io_service)
Sets IO service to be used by the Timer Manager.
Definition: timer_mgr.cc:397
void setup(const std::string &timer_name)
Schedules the execution of the interval timer.
Definition: timer_mgr.cc:377
size_t timersCount() const
Returns the number of registered timers.
Definition: timer_mgr.cc:372
void unregisterTimers()
Unregisters all timers.
Definition: timer_mgr.cc:358
void cancel(const std::string &timer_name)
Cancels the execution of the interval timer.
Definition: timer_mgr.cc:387
void registerTimer(const std::string &timer_name, const asiolink::IntervalTimer::Callback &callback, const long interval, const asiolink::IntervalTimer::Mode &scheduling_mode)
Registers new timer in the TimerMgr.
Definition: timer_mgr.cc:334
void unregisterTimer(const std::string &timer_name)
Unregisters specified timer.
Definition: timer_mgr.cc:348
static const TimerMgrPtr & instance()
Returns pointer to the sole instance of the TimerMgr.
Definition: timer_mgr.cc:319
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition: macros.h:32
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition: macros.h:14
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
Definition: dhcpsrv_log.h:56
boost::shared_ptr< TimerMgr > TimerMgrPtr
Type definition of the shared pointer to TimerMgr.
Definition: timer_mgr.h:25
std::map< std::string, TimerInfoPtr > TimerInfoMap
A type definition for the map holding timers configuration.
Definition: timer_mgr.cc:69
const int DHCPSRV_DBG_TRACE_DETAIL
Additional information.
Definition: dhcpsrv_log.h:38
boost::shared_ptr< TimerInfo > TimerInfoPtr
A type definition for the pointer to TimerInfo structure.
Definition: timer_mgr.cc:66
const int DHCPSRV_DBG_TRACE
DHCP server library logging levels.
Definition: dhcpsrv_log.h:26
Defines the logger used by the top-level component of kea-dhcp-ddns.