library_manager_collection.cc 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. // Copyright (C) 2013-2017 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. #include <hooks/callout_manager.h>
  7. #include <hooks/hooks_manager.h>
  8. #include <hooks/library_manager.h>
  9. #include <hooks/library_manager_collection.h>
  10. namespace isc {
  11. namespace hooks {
  12. // Return callout manager for the loaded libraries. This call is only valid
  13. // after one has been created for the loaded libraries (which includes the
  14. // case of no loaded libraries).
  15. //
  16. // Note that there is no real connection between the callout manager and the
  17. // libraries, other than it knows the number of libraries so can do sanity
  18. // checks on values passed to it. However, this may change in the future,
  19. // so the hooks framework is written such that a callout manager is used only
  20. // with the LibraryManagerCollection that created it. It is also the reason
  21. // why each LibraryManager contains a pointer to this CalloutManager.
  22. boost::shared_ptr<CalloutManager>
  23. LibraryManagerCollection::getCalloutManager() const {
  24. // Only return a pointer if we have a CalloutManager created.
  25. if (! callout_manager_) {
  26. isc_throw(LoadLibrariesNotCalled, "must load hooks libraries before "
  27. "attempting to retrieve a CalloutManager for them");
  28. }
  29. return (callout_manager_);
  30. }
  31. LibraryManagerCollection::LibraryManagerCollection(const HookLibsCollection& libraries)
  32. :library_info_(libraries) {
  33. // We need to split hook libs into library names and library parameters.
  34. for (HookLibsCollection::const_iterator it = libraries.begin();
  35. it != libraries.end(); ++it) {
  36. library_names_.push_back(it->first);
  37. }
  38. }
  39. // Load a set of libraries
  40. bool
  41. LibraryManagerCollection::loadLibraries() {
  42. // Unload libraries if any are loaded.
  43. static_cast<void>(unloadLibraries());
  44. // Create the callout manager. A pointer to this is maintained by
  45. // each library. Note that the callout manager does not hold any memory
  46. // allocated by a library: although a library registers a callout (and so
  47. // causes the creation of an entry in the CalloutManager's callout list),
  48. // that creation is done by the CalloutManager itself. The CalloutManager
  49. // is created within the server.
  50. //
  51. // The upshot of this is that it is therefore safe for the CalloutManager
  52. // to be deleted after all associated libraries are deleted, hence this
  53. // link (LibraryManager -> CalloutManager) is safe.
  54. //
  55. // To survive reloads an attempt to re-use the shared manager
  56. // is performed when the list of library names is empty.
  57. if (library_names_.empty()) {
  58. callout_manager_ = HooksManager::getSharedCalloutManager();
  59. }
  60. if (!library_names_.empty() || !callout_manager_) {
  61. callout_manager_.reset(new CalloutManager(library_names_.size()));
  62. }
  63. // Now iterate through the libraries are load them one by one. We'll
  64. for (size_t i = 0; i < library_names_.size(); ++i) {
  65. // Create a pointer to the new library manager. The index of this
  66. // library is determined by the number of library managers currently
  67. // loaded: note that the library indexes run from 1 to (number of loaded
  68. // libraries).
  69. boost::shared_ptr<LibraryManager> manager(
  70. new LibraryManager(library_names_[i], lib_managers_.size() + 1,
  71. callout_manager_));
  72. // Load the library. On success, add it to the list of loaded
  73. // libraries. On failure, unload all currently loaded libraries,
  74. // leaving the object in the state it was in before loadLibraries was
  75. // called.
  76. if (manager->loadLibrary()) {
  77. lib_managers_.push_back(manager);
  78. } else {
  79. static_cast<void>(unloadLibraries());
  80. return (false);
  81. }
  82. }
  83. return (true);
  84. }
  85. // Unload the libraries.
  86. void
  87. LibraryManagerCollection::unloadLibraries() {
  88. // Delete the library managers in the reverse order to which they were
  89. // created, then clear the library manager vector.
  90. for (int i = lib_managers_.size() - 1; i >= 0; --i) {
  91. lib_managers_[i].reset();
  92. }
  93. lib_managers_.clear();
  94. // Get rid of the callout manager. (The other member, the list of library
  95. // names, was cleared when the libraries were loaded.)
  96. callout_manager_.reset();
  97. }
  98. // Return number of loaded libraries.
  99. int
  100. LibraryManagerCollection::getLoadedLibraryCount() const {
  101. return (lib_managers_.size());
  102. }
  103. // Validate the libraries.
  104. std::vector<std::string>
  105. LibraryManagerCollection::validateLibraries(
  106. const std::vector<std::string>& libraries) {
  107. std::vector<std::string> failures;
  108. for (size_t i = 0; i < libraries.size(); ++i) {
  109. if (!LibraryManager::validateLibrary(libraries[i])) {
  110. failures.push_back(libraries[i]);
  111. }
  112. }
  113. return (failures);
  114. }
  115. } // namespace hooks
  116. } // namespace isc