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