io_service_signal.cc 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. // Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <asiolink/interval_timer.h>
  15. #include <d2/d2_log.h>
  16. #include <d2/io_service_signal.h>
  17. namespace isc {
  18. namespace d2 {
  19. IOSignal::IOSignal (asiolink::IOService& io_service, int signum,
  20. IOSignalHandler handler)
  21. : sequence_id_(nextSequenceId()), signum_(signum),
  22. timer_(new asiolink::IntervalTimer(io_service)) {
  23. // Valid handler is essential.
  24. if (!handler) {
  25. isc_throw(IOSignalError,
  26. "IOSignal - handler cannot be null");
  27. }
  28. // Set up the timer as a one-shot which expires in 1 ms (intervals of 0
  29. // are invalid). This means that once control returns to IOService::run
  30. // the timer will have expired and its handler will be invoked.
  31. timer_->setup(TimerCallback(sequence_id_, handler), 1,
  32. asiolink::IntervalTimer::ONE_SHOT);
  33. }
  34. IOSignal::~IOSignal() {
  35. if (timer_) {
  36. // In the unlikely event that the timer hasn't expired cancel it.
  37. timer_->cancel();
  38. }
  39. }
  40. IOSignal::
  41. TimerCallback::TimerCallback(IOSignalId sequence_id, IOSignalHandler handler)
  42. : sequence_id_(sequence_id), handler_(handler) {
  43. if (!handler) {
  44. isc_throw(IOSignalError,
  45. "IOSignal::TimerCallback - handler cannot be null");
  46. }
  47. }
  48. void
  49. IOSignal::TimerCallback::operator()() {
  50. try {
  51. handler_(sequence_id_);
  52. } catch (const std::exception& ex) {
  53. // We log it and swallow it so we don't undermine IOService::run.
  54. LOG_ERROR(dctl_logger, DHCP_DDNS_SIGNAL_ERROR)
  55. .arg(sequence_id_).arg(ex.what());
  56. }
  57. return;
  58. }
  59. IOSignalQueue::IOSignalQueue(IOServicePtr& io_service)
  60. : io_service_(io_service), signals_() {
  61. if (!io_service_) {
  62. isc_throw(IOSignalError, "IOSignalQueue - io_serivce cannot be NULL");
  63. }
  64. }
  65. IOSignalQueue::~IOSignalQueue() {
  66. clear();
  67. }
  68. IOSignalId
  69. IOSignalQueue::pushSignal(int signum, IOSignalHandler handler) {
  70. // Create the new signal.
  71. IOSignalPtr signal(new IOSignal(*io_service_, signum, handler));
  72. // Make sure the sequence_id isn't already in the queue.
  73. IOSignalId sequence_id = signal->getSequenceId();
  74. IOSignalMap::iterator it = signals_.find(sequence_id);
  75. if (it != signals_.end()) {
  76. // This really shouldn't happen unless we are in the weeds.
  77. isc_throw (IOSignalError, "pushSignal - "
  78. "signal already exists for sequence_id: " << sequence_id);
  79. }
  80. // Add the signal to the queue.
  81. signals_[sequence_id] = signal;
  82. return (sequence_id);
  83. }
  84. IOSignalPtr
  85. IOSignalQueue::popSignal(IOSignalId sequence_id) {
  86. // Look for the signal in the queue.
  87. IOSignalMap::iterator it = signals_.find(sequence_id);
  88. if (it == signals_.end()) {
  89. // This really shouldn't happen unless we are in the weeds.
  90. isc_throw (IOSignalError, "popSignal - "
  91. "signal not found for sequence_id: " << sequence_id);
  92. }
  93. // Save the siganl so we can return it.
  94. IOSignalPtr signal = ((*it).second);
  95. // Delete it fromt the queue.
  96. signals_.erase(it);
  97. // Return the signal.
  98. return (signal);
  99. }
  100. void
  101. IOSignalQueue::clear() {
  102. signals_.clear();
  103. }
  104. }; // end of isc::d2 namespace
  105. }; // end of isc namespace