callout_manager.cc 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // Copyright (C) 2013 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 <util/hooks/callout_handle.h>
  15. #include <util/hooks/callout_manager.h>
  16. #include <algorithm>
  17. #include <functional>
  18. #include <utility>
  19. using namespace std;
  20. using namespace isc::util;
  21. namespace isc {
  22. namespace util {
  23. // Register a callout for a particular library.
  24. void
  25. CalloutManager::registerCallout(int libindex, const std::string& name,
  26. CalloutPtr callout) {
  27. // Get the index associated with this hook (validating the name in the
  28. // process).
  29. int hook_index = hooks_->getIndex(name);
  30. // Iterate through the callout vector for the hook from start to end,
  31. // looking for the first entry where the library index is greater than
  32. // the present index.
  33. for (CalloutVector::iterator i = hook_vector_[hook_index].begin();
  34. i != hook_vector_[hook_index].end(); ++i) {
  35. if (i->first > libindex) {
  36. // Found an element whose library number is greater than ours,
  37. // so insert the new element ahead of this one.
  38. hook_vector_[hook_index].insert(i,
  39. std::make_pair(libindex, callout));
  40. return;
  41. }
  42. }
  43. // Reach the end of the vector, so no element in the (possibly empty)
  44. // set of callouts with a library index greater that the one related to
  45. // this callout, insert at the end.
  46. hook_vector_[hook_index].push_back(std::make_pair(libindex, callout));
  47. }
  48. // Check if callouts are present for a given hook index.
  49. bool
  50. CalloutManager::calloutsPresent(int hook_index) const {
  51. // Validate the hook index.
  52. checkHookIndex(hook_index);
  53. // Valid, so are there any callouts associated with that hook?
  54. return (!hook_vector_[hook_index].empty());
  55. }
  56. // Call all the callouts for a given hook.
  57. int
  58. CalloutManager::callCallouts(int hook_index, CalloutHandle& callout_handle) {
  59. // Validate the hook index.
  60. checkHookIndex(hook_index);
  61. // Clear the "skip" flag so we don't carry state from a previous
  62. // call.
  63. callout_handle.setSkip(false);
  64. // Call all the callouts, stopping if the "skip" flag is set or if a
  65. // non-zero status is returned.
  66. int status = 0;
  67. for (CalloutVector::const_iterator i = hook_vector_[hook_index].begin();
  68. i != hook_vector_[hook_index].end() && (status == 0); ++i) {
  69. status = (*i->second)(callout_handle);
  70. }
  71. return (status);
  72. }
  73. // Deregister a callout registered by a library on a particular hook.
  74. bool
  75. CalloutManager::deregisterCallout(int library_index, const std::string& name,
  76. CalloutPtr callout) {
  77. // Get the index associated with this hook (validating the name in the
  78. // process).
  79. int hook_index = hooks_->getIndex(name);
  80. /// Construct a CalloutEntry matching the specified library and the callout
  81. /// we want to remove.
  82. CalloutEntry target(library_index, callout);
  83. /// To decide if any entries were removed, we'll record the initial size
  84. /// of the callout vector for the hook, and compare it with the size after
  85. /// the removal.
  86. size_t initial_size = hook_vector_[hook_index].size();
  87. // The next bit is standard STL (see "Item 33" in "Effective STL" by
  88. // Scott Meyers).
  89. //
  90. // remove_if reorders the hook vector so that all items not matching
  91. // the predicate are at the start of the vector and returns a pointer
  92. // to the next element. (In this case, the predicate is that the item
  93. // is equal to the value of the passed callout.) The erase() call
  94. // removes everything from that element to the end of the vector, i.e.
  95. // all the matching elements.
  96. hook_vector_[hook_index].erase(remove_if(hook_vector_[hook_index].begin(),
  97. hook_vector_[hook_index].end(),
  98. bind1st(equal_to<CalloutEntry>(),
  99. target)),
  100. hook_vector_[hook_index].end());
  101. // Return an indication of whether anything was removed.
  102. return (initial_size != hook_vector_[hook_index].size());
  103. }
  104. // Deregister all callouts on a given hook.
  105. bool
  106. CalloutManager::deregisterAllCallouts(int library_index,
  107. const std::string& name) {
  108. // Get the index associated with this hook (validating the name in the
  109. // process).
  110. int hook_index = hooks_->getIndex(name);
  111. /// Construct a CalloutEntry matching the specified library we want to
  112. /// remove (the callout pointer is NULL as we are not checking that).
  113. CalloutEntry target(library_index, NULL);
  114. /// To decide if any entries were removed, we'll record the initial size
  115. /// of the callout vector for the hook, and compare it with the size after
  116. /// the removal.
  117. size_t initial_size = hook_vector_[hook_index].size();
  118. // Remove all callouts matching this library.
  119. hook_vector_[hook_index].erase(remove_if(hook_vector_[hook_index].begin(),
  120. hook_vector_[hook_index].end(),
  121. bind1st(CalloutLibraryEqual(),
  122. target)),
  123. hook_vector_[hook_index].end());
  124. // Return an indication of whether anything was removed.
  125. return (initial_size != hook_vector_[hook_index].size());
  126. }
  127. // CalloutManager methods.
  128. // Return pointer to the current library handle.
  129. boost::shared_ptr<LibraryHandle>
  130. CalloutManager::createHandle() {
  131. // Index is equal to the size of the current collection of handles
  132. // (guarantees that every handle has a unique index, and that index
  133. // is a pointer to the handle in the collection of handles.)
  134. boost::shared_ptr<LibraryHandle> handle(new LibraryHandle(handles_.size(),
  135. this));
  136. // Add to the current collection of handles.
  137. handles_.push_back(handle);
  138. return (handle);
  139. }
  140. } // namespace util
  141. } // namespace isc