123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- // Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
- //
- // Permission to use, copy, modify, and/or distribute this software for any
- // purpose with or without fee is hereby granted, provided that the above
- // copyright notice and this permission notice appear in all copies.
- //
- // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
- // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
- // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- // PERFORMANCE OF THIS SOFTWARE.
- #ifndef DATA_SOURCE_FACTORY_H
- #define DATA_SOURCE_FACTORY_H 1
- #include <datasrc/exceptions.h>
- #include <datasrc/client.h>
- #include <cc/data.h>
- #include <boost/noncopyable.hpp>
- #include <boost/shared_ptr.hpp>
- namespace isc {
- namespace datasrc {
- /// \brief Raised if there is an error in the datasource implementation
- /// library
- class DataSourceLibraryError : public DataSourceError {
- public:
- DataSourceLibraryError(const char* file, size_t line, const char* what) :
- DataSourceError(file, line, what) {}
- };
- /// \brief Raised if there is an error opening the the datasource
- /// implementation library
- class DataSourceLibraryOpenError : public DataSourceLibraryError {
- public:
- DataSourceLibraryOpenError(const char* file, size_t line,
- const char* what) :
- DataSourceLibraryError(file, line, what) {}
- };
- /// \brief Raised if there is an error reading a symbol from the datasource
- /// implementation library
- class DataSourceLibrarySymbolError : public DataSourceLibraryError {
- public:
- DataSourceLibrarySymbolError(const char* file, size_t line,
- const char* what) :
- DataSourceLibraryError(file, line, what) {}
- };
- typedef DataSourceClient* ds_creator(isc::data::ConstElementPtr config,
- std::string& error);
- typedef void ds_destructor(DataSourceClient* instance);
- /// \brief Container class for dynamically loaded libraries
- ///
- /// This class is used to dlopen() a library, provides access to dlsym(),
- /// and cleans up the dlopened library when the instance of this class is
- /// destroyed.
- ///
- /// Its main function is to provide RAII-style access to dlopen'ed libraries.
- ///
- /// \note Currently it is Datasource-backend specific. If we have need for this
- /// in other places than for dynamically loading datasources, then, apart
- /// from moving it to another location, we also need to make the
- /// exceptions raised more general.
- class LibraryContainer : boost::noncopyable {
- public:
- /// \brief Constructor
- ///
- /// \param name The name of the library (.so) file. This file must be in
- /// the library path.
- ///
- /// \exception DataSourceLibraryError If the library cannot be found or
- /// cannot be loaded, or if name is an empty string.
- LibraryContainer(const std::string& name);
- /// \brief Destructor
- ///
- /// Cleans up the library by calling dlclose()
- ~LibraryContainer();
- /// \brief Retrieve a symbol
- ///
- /// This retrieves a symbol from the loaded library.
- ///
- /// \exception DataSourceLibrarySymbolError if the symbol cannot be found,
- /// or if another error (as reported by dlerror() occurs.
- ///
- /// \param name The name of the symbol to retrieve
- /// \return A pointer to the symbol. This may be NULL, and if so, indicates
- /// the symbol does indeed exist, but has the value NULL itself.
- /// If the symbol does not exist, a DataSourceLibrarySymbolError is
- /// raised.
- ///
- /// \note The argument is a const char* (and not a std::string like the
- /// argument in the constructor). This argument is always a fixed
- /// string in the code, while the other can be read from
- /// configuration, and needs modification
- void* getSym(const char* name);
- private:
- /// Pointer to the dynamically loaded library structure
- void *ds_lib_;
- };
- /// \brief Container for a specific instance of a dynamically loaded
- /// DataSourceClient implementation
- ///
- /// Given a datasource type and a type-specific set of configuration data,
- /// the corresponding dynamic library is loaded (if it hadn't been already),
- /// and an instance is created. This instance is stored within this structure,
- /// and can be accessed through getInstance(). Upon destruction of this
- /// container, the stored instance of the DataSourceClient is deleted with
- /// the destructor function provided by the loaded library.
- ///
- /// The 'type' is actually the name of the library, minus the '_ds.so' postfix
- /// Datasource implementation libraries therefore have a fixed name, both for
- /// easy recognition and to reduce potential mistakes.
- /// For example, the sqlite3 implementation has the type 'sqlite3', and the
- /// derived filename 'sqlite3_ds.so'
- /// The value of type can be a specific loadable library; if it already ends
- /// with '.so', the loader will not add '_ds.so'.
- /// It may also be an absolute path; if it starts with '/', nothing is
- /// prepended. If it does not, the loadable library will be taken from the
- /// installation directory, see the value of
- /// isc::datasrc::BACKEND_LIBRARY_PATH in datasrc_config.h for the exact path.
- ///
- /// \note When 'B10_FROM_BUILD' is set in the environment, the build
- /// directory is used instead of the install directory.
- ///
- /// There are of course some demands to an implementation, not all of which
- /// can be verified compile-time. It must provide a creator and destructor
- /// functions. The creator function must return an instance of a subclass of
- /// DataSourceClient. The prototypes of these functions are as follows:
- /// \code
- /// extern "C" DataSourceClient* createInstance(isc::data::ConstElementPtr cfg);
- ///
- /// extern "C" void destroyInstance(isc::data::DataSourceClient* instance);
- /// \endcode
- ///
- /// \note This class is relatively recent, and its design is not yet fully
- /// formed. We may want to split this into an abstract base container
- /// class, and a derived 'dyload' class, and perhaps then add non-dynamic
- /// derived classes as well. Currently, the class is actually derived in some
- /// of the tests, which is rather unclean (as this class as written is really
- /// intended to be used directly).
- class DataSourceClientContainer : boost::noncopyable {
- public:
- /// \brief Constructor
- ///
- /// \exception DataSourceLibraryError if there is an error loading the
- /// backend library
- /// \exception DataSourceLibrarySymbolError if the library does not have
- /// the needed symbols, or if there is an error reading them
- /// \exception DataError if the given config is not correct
- /// for the given type, or if there was a problem during
- /// initialization
- ///
- /// \param type The type of the datasource client. Based on the value of
- /// type, a specific backend library is used, by appending the
- /// string '_ds.so' to the given type, and loading that as the
- /// implementation library
- /// \param config Type-specific configuration data, see the documentation
- /// of the datasource backend type for information on what
- /// configuration data to pass.
- DataSourceClientContainer(const std::string& type,
- isc::data::ConstElementPtr config);
- /// \brief Destructor
- virtual ~DataSourceClientContainer();
- /// \brief Accessor to the instance
- ///
- /// \return Reference to the DataSourceClient instance contained in this
- /// container.
- virtual DataSourceClient& getInstance() { return (*instance_); }
- private:
- DataSourceClient* instance_;
- ds_destructor* destructor_;
- LibraryContainer ds_lib_;
- };
- ///
- /// Shared pointer type for datasource client containers
- ///
- typedef boost::shared_ptr<DataSourceClientContainer>
- DataSourceClientContainerPtr;
- } // end namespace datasrc
- } // end namespace isc
- #endif // DATA_SOURCE_FACTORY_H
- // Local Variables:
- // mode: c++
- // End:
|