factory.h 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. // Copyright (C) 2011 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. #ifndef DATA_SOURCE_FACTORY_H
  15. #define DATA_SOURCE_FACTORY_H 1
  16. #include <datasrc/data_source.h>
  17. #include <datasrc/client.h>
  18. #include <cc/data.h>
  19. #include <boost/noncopyable.hpp>
  20. #include <boost/shared_ptr.hpp>
  21. namespace isc {
  22. namespace datasrc {
  23. /// \brief Raised if there is an error loading the datasource implementation
  24. /// library
  25. class DataSourceLibraryError : public DataSourceError {
  26. public:
  27. DataSourceLibraryError(const char* file, size_t line, const char* what) :
  28. DataSourceError(file, line, what) {}
  29. };
  30. /// \brief Raised if there is an error reading a symbol from the datasource
  31. /// implementation library
  32. class DataSourceLibrarySymbolError : public DataSourceError {
  33. public:
  34. DataSourceLibrarySymbolError(const char* file, size_t line,
  35. const char* what) :
  36. DataSourceError(file, line, what) {}
  37. };
  38. typedef DataSourceClient* ds_creator(isc::data::ConstElementPtr config,
  39. std::string& error);
  40. typedef void ds_destructor(DataSourceClient* instance);
  41. /// \brief Container class for dynamically loaded libraries
  42. ///
  43. /// This class is used to dlopen() a library, provides access to dlsym(),
  44. /// and cleans up the dlopened library when the instance of this class is
  45. /// destroyed.
  46. ///
  47. /// Its main function is to provide RAII-style access to dlopen'ed libraries.
  48. ///
  49. /// \note Currently it is Datasource-backend specific. If we have need for this
  50. /// in other places than for dynamically loading datasources, then, apart
  51. /// from moving it to another location, we also need to make the
  52. /// exceptions raised more general.
  53. class LibraryContainer : boost::noncopyable {
  54. public:
  55. /// \brief Constructor
  56. ///
  57. /// \param name The name of the library (.so) file. This file must be in
  58. /// the library path.
  59. ///
  60. /// \exception DataSourceLibraryError If the library cannot be found or
  61. /// cannot be loaded, or if name is an empty string.
  62. LibraryContainer(const std::string& name);
  63. /// \brief Destructor
  64. ///
  65. /// Cleans up the library by calling dlclose()
  66. ~LibraryContainer();
  67. /// \brief Retrieve a symbol
  68. ///
  69. /// This retrieves a symbol from the loaded library.
  70. ///
  71. /// \exception DataSourceLibrarySymbolError if the symbol cannot be found,
  72. /// or if another error (as reported by dlerror() occurs.
  73. ///
  74. /// \param name The name of the symbol to retrieve
  75. /// \return A pointer to the symbol. This may be NULL, and if so, indicates
  76. /// the symbol does indeed exist, but has the value NULL itself.
  77. /// If the symbol does not exist, a DataSourceLibrarySymbolError is
  78. /// raised.
  79. ///
  80. /// \note The argument is a const char* (and not a std::string like the
  81. /// argument in the constructor). This argument is always a fixed
  82. /// string in the code, while the other can be read from
  83. /// configuration, and needs modification
  84. void* getSym(const char* name);
  85. private:
  86. /// Pointer to the dynamically loaded library structure
  87. void *ds_lib_;
  88. };
  89. /// \brief Container for a specific instance of a dynamically loaded
  90. /// DataSourceClient implementation
  91. ///
  92. /// Given a datasource type and a type-specific set of configuration data,
  93. /// the corresponding dynamic library is loaded (if it hadn't been already),
  94. /// and an instance is created. This instance is stored within this structure,
  95. /// and can be accessed through getInstance(). Upon destruction of this
  96. /// container, the stored instance of the DataSourceClient is deleted with
  97. /// the destructor function provided by the loaded library.
  98. ///
  99. /// The 'type' is actually the name of the library, minus the '_ds.so' postfix
  100. /// Datasource implementation libraries therefore have a fixed name, both for
  101. /// easy recognition and to reduce potential mistakes.
  102. /// For example, the sqlite3 implementation has the type 'sqlite3', and the
  103. /// derived filename 'sqlite3_ds.so'
  104. /// The value of type can be a specific loadable library; if it already ends
  105. /// with '.so', the loader will not add '_ds.so'.
  106. /// It may also be an absolute path; if it starts with '/', nothing is
  107. /// prepended. If it does not, the loadable library will be taken from the
  108. /// installation directory, see the value of
  109. /// isc::datasrc::BACKEND_LIBRARY_PATH in datasrc_config.h for the exact path.
  110. ///
  111. /// \note When 'B10_FROM_BUILD' is set in the environment, the build
  112. /// directory is used instead of the install directory.
  113. ///
  114. /// There are of course some demands to an implementation, not all of which
  115. /// can be verified compile-time. It must provide a creator and destructor
  116. /// functions. The creator function must return an instance of a subclass of
  117. /// DataSourceClient. The prototypes of these functions are as follows:
  118. /// \code
  119. /// extern "C" DataSourceClient* createInstance(isc::data::ConstElementPtr cfg);
  120. ///
  121. /// extern "C" void destroyInstance(isc::data::DataSourceClient* instance);
  122. /// \endcode
  123. ///
  124. /// \note This class is relatively recent, and its design is not yet fully
  125. /// formed. We may want to split this into an abstract base container
  126. /// class, and a derived 'dyload' class, and perhaps then add non-dynamic
  127. /// derived classes as well. Currently, the class is actually derived in some
  128. /// of the tests, which is rather unclean (as this class as written is really
  129. /// intended to be used directly).
  130. class DataSourceClientContainer : boost::noncopyable {
  131. public:
  132. /// \brief Constructor
  133. ///
  134. /// \exception DataSourceLibraryError if there is an error loading the
  135. /// backend library
  136. /// \exception DataSourceLibrarySymbolError if the library does not have
  137. /// the needed symbols, or if there is an error reading them
  138. /// \exception DataError if the given config is not correct
  139. /// for the given type, or if there was a problem during
  140. /// initialization
  141. ///
  142. /// \param type The type of the datasource client. Based on the value of
  143. /// type, a specific backend library is used, by appending the
  144. /// string '_ds.so' to the given type, and loading that as the
  145. /// implementation library
  146. /// \param config Type-specific configuration data, see the documentation
  147. /// of the datasource backend type for information on what
  148. /// configuration data to pass.
  149. DataSourceClientContainer(const std::string& type,
  150. isc::data::ConstElementPtr config);
  151. /// \brief Destructor
  152. virtual ~DataSourceClientContainer();
  153. /// \brief Accessor to the instance
  154. ///
  155. /// \return Reference to the DataSourceClient instance contained in this
  156. /// container.
  157. virtual DataSourceClient& getInstance() { return (*instance_); }
  158. private:
  159. DataSourceClient* instance_;
  160. ds_destructor* destructor_;
  161. LibraryContainer ds_lib_;
  162. };
  163. ///
  164. /// Shared pointer type for datasource client containers
  165. ///
  166. typedef boost::shared_ptr<DataSourceClientContainer>
  167. DataSourceClientContainerPtr;
  168. } // end namespace datasrc
  169. } // end namespace isc
  170. #endif // DATA_SOURCE_FACTORY_H
  171. // Local Variables:
  172. // mode: c++
  173. // End: