library_manager.h 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. // Copyright (C) 2013-2015 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. #ifndef LIBRARY_MANAGER_H
  7. #define LIBRARY_MANAGER_H
  8. #include <exceptions/exceptions.h>
  9. #include <boost/shared_ptr.hpp>
  10. #include <string>
  11. namespace isc {
  12. namespace hooks {
  13. /// @brief No Callout Manager
  14. ///
  15. /// Thrown if a library manager is instantiated by an external agency without
  16. /// specifying a CalloutManager object.
  17. class NoCalloutManager : public Exception {
  18. public:
  19. NoCalloutManager(const char* file, size_t line, const char* what) :
  20. isc::Exception(file, line, what) {}
  21. };
  22. class CalloutManager;
  23. class LibraryHandle;
  24. class LibraryManager;
  25. /// @brief Library manager
  26. ///
  27. /// This class handles the loading and unloading of a specific library. It also
  28. /// provides a static method for checking that a library is valid (this is used
  29. /// in configuration parsing).
  30. ///
  31. /// On loading, it opens the library using dlopen and checks the version (set
  32. /// with the "version" method. If all is OK, it iterates through the list of
  33. /// known hooks and locates their symbols, registering each callout as it does
  34. /// so. Finally it locates the "load" function (if present) and calls it.
  35. ///
  36. /// On unload, it calls the "unload" method if present, clears the callouts on
  37. /// all hooks, and closes the library.
  38. ///
  39. /// @note Caution needs to be exercised when using the unload method. During
  40. /// normal use, data will pass between the server and the library. In
  41. /// this process, the library may allocate memory and pass it back to the
  42. /// server. This could happen by the server setting arguments or context
  43. /// in the CalloutHandle object, or by the library modifying the content
  44. /// of pointed-to data. If the library is unloaded, this memory may lie
  45. /// in the virtual address space deleted in that process. (The word "may"
  46. /// is used, as this could be operating-system specific.) Should this
  47. /// happen, any reference to the memory will cause a segmentation fault.
  48. /// This can occur in a quite obscure place, for example in the middle of
  49. /// a destructor of an STL class when it is deleting memory allocated
  50. /// when the data structure was extended by a function in the library.
  51. ///
  52. /// @note The only safe way to run the "unload" function is to ensure that all
  53. /// possible references to it are removed first. This means that all
  54. /// CalloutHandles must be destroyed, as must any data items that were
  55. /// passed to the callouts. In practice, it could mean that a server
  56. /// suspends processing of new requests until all existing ones have
  57. /// been serviced and all packet/context structures destroyed before
  58. /// reloading the libraries.
  59. ///
  60. /// When validating a library, only the fact that the library can be opened and
  61. /// version() exists and returns the correct number is checked. The library
  62. /// is closed after the validation.
  63. class LibraryManager {
  64. public:
  65. /// @brief Constructor
  66. ///
  67. /// This constructor is used by external agencies (i.e. the
  68. /// LibraryManagerCollection) when instantiating a LibraryManager. It
  69. /// stores the library name - the actual actual loading is done in
  70. /// loadLibrary().
  71. ///
  72. /// @param name Name of the library to load. This should be an absolute
  73. /// path name.
  74. /// @param index Index of this library
  75. /// @param manager CalloutManager object
  76. ///
  77. /// @throw NoCalloutManager Thrown if the manager argument is NULL.
  78. LibraryManager(const std::string& name, int index,
  79. const boost::shared_ptr<CalloutManager>& manager);
  80. /// @brief Destructor
  81. ///
  82. /// If the library is open, closes it. This is principally a safety
  83. /// feature to ensure closure in the case of an exception destroying this
  84. /// object. However, see the caveat in the class header about when it is
  85. /// safe to unload libraries.
  86. ~LibraryManager();
  87. /// @brief Validate library
  88. ///
  89. /// A static method that is used to validate a library. Validation checks
  90. /// that the library can be opened, that "version" exists, and that it
  91. /// returns the right number.
  92. ///
  93. /// @param name Name of the library to validate
  94. ///
  95. /// @return true if the library validated, false if not. If the library
  96. /// fails to validate, the reason for the failure is logged.
  97. static bool validateLibrary(const std::string& name);
  98. /// @brief Loads a library
  99. ///
  100. /// Open the library and check the version. If all is OK, load all standard
  101. /// symbols then call "load" if present.
  102. ///
  103. /// It also calls the @c isc::log::MessageInitializer::loadDictionary, prior
  104. /// to invoking the @c version function of the library, to update the global
  105. /// logging dictionary with the log messages registered by the loaded library.
  106. ///
  107. /// @return true if the library loaded successfully, false otherwise. In the
  108. /// latter case, the library will be unloaded if possible.
  109. bool loadLibrary();
  110. /// @brief Unloads a library
  111. ///
  112. /// Calls the libraries "unload" function if present, the closes the
  113. /// library.
  114. ///
  115. /// However, see the caveat in the class header about when it is safe to
  116. /// unload libraries.
  117. ///
  118. /// @return true if the library unloaded successfully, false if an error
  119. /// occurred in the process (most likely the unload() function
  120. /// (if present) returned an error). Even if an error did occur,
  121. /// the library is closed if possible.
  122. bool unloadLibrary();
  123. /// @brief Return library name
  124. ///
  125. /// @return Name of this library
  126. std::string getName() const {
  127. return (library_name_);
  128. }
  129. protected:
  130. // The following methods are protected as they are accessed in testing.
  131. /// @brief Open library
  132. ///
  133. /// Opens the library associated with this LibraryManager. A message is
  134. /// logged on an error.
  135. ///
  136. /// @return true if the library opened successfully, false otherwise.
  137. bool openLibrary();
  138. /// @brief Close library
  139. ///
  140. /// Closes the library associated with this LibraryManager. A message is
  141. /// logged on an error.
  142. ///
  143. /// @return true if the library closed successfully, false otherwise. "true"
  144. /// is also returned if the library were already closed when this
  145. /// method was called.
  146. bool closeLibrary();
  147. /// @brief Check library version
  148. ///
  149. /// With the library open, accesses the "version()" function and, if
  150. /// present, checks the returned value against the hooks version symbol
  151. /// for the currently running Kea. The "version()" function is
  152. /// mandatory and must be present (and return the correct value) for the
  153. /// library to load.
  154. ///
  155. /// If there is no version() function, or if there is a mismatch in
  156. /// version number, a message logged.
  157. ///
  158. /// @return bool true if the check succeeded
  159. bool checkVersion() const;
  160. /// @brief Register standard callouts
  161. ///
  162. /// Loops through the list of hook names and searches the library for
  163. /// functions with those names. Any that are found are registered as
  164. /// callouts for that hook.
  165. void registerStandardCallouts();
  166. /// @brief Run the load function if present
  167. ///
  168. /// Searches for the "load" framework function and, if present, runs it.
  169. ///
  170. /// @return bool true if not found or found and run successfully,
  171. /// false on an error. In this case, an error message will
  172. /// have been output.
  173. bool runLoad();
  174. /// @brief Run the unload function if present
  175. ///
  176. /// Searches for the "unload" framework function and, if present, runs it.
  177. ///
  178. /// @return bool true if not found or found and run successfully,
  179. /// false on an error. In this case, an error message will
  180. /// have been output.
  181. bool runUnload();
  182. private:
  183. /// @brief Validating constructor
  184. ///
  185. /// Constructor used when the LibraryManager is instantiated to validate
  186. /// a library (i.e. by the "validateLibrary" static method).
  187. ///
  188. /// @param name Name of the library to load. This should be an absolute
  189. /// path name.
  190. LibraryManager(const std::string& name);
  191. // Member variables
  192. void* dl_handle_; ///< Handle returned by dlopen
  193. int index_; ///< Index associated with this library
  194. boost::shared_ptr<CalloutManager> manager_;
  195. ///< Callout manager for registration
  196. std::string library_name_; ///< Name of the library
  197. };
  198. } // namespace hooks
  199. } // namespace isc
  200. #endif // LIBRARY_MANAGER_H