sqlite3_accessor.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  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 __DATASRC_SQLITE3_ACCESSOR_H
  15. #define __DATASRC_SQLITE3_ACCESSOR_H
  16. #include <datasrc/database.h>
  17. #include <datasrc/data_source.h>
  18. #include <exceptions/exceptions.h>
  19. #include <boost/enable_shared_from_this.hpp>
  20. #include <boost/scoped_ptr.hpp>
  21. #include <string>
  22. #include <cc/data.h>
  23. namespace isc {
  24. namespace dns {
  25. class RRClass;
  26. }
  27. namespace datasrc {
  28. /**
  29. * \brief Low-level database error
  30. *
  31. * This exception is thrown when the SQLite library complains about something.
  32. * It might mean corrupt database file, invalid request or that something is
  33. * rotten in the library.
  34. */
  35. class SQLite3Error : public DataSourceError {
  36. public:
  37. SQLite3Error(const char* file, size_t line, const char* what) :
  38. DataSourceError(file, line, what) {}
  39. };
  40. /**
  41. * \brief Too Much Data
  42. *
  43. * Thrown if a query expecting a certain number of rows back returned too
  44. * many rows.
  45. */
  46. class TooMuchData : public DataSourceError {
  47. public:
  48. TooMuchData(const char* file, size_t line, const char* what) :
  49. DataSourceError(file, line, what) {}
  50. };
  51. /**
  52. * \brief Too Little Data
  53. *
  54. * Thrown if a query expecting a certain number of rows back returned too
  55. * few rows (including none).
  56. */
  57. class TooLittleData : public DataSourceError {
  58. public:
  59. TooLittleData(const char* file, size_t line, const char* what) :
  60. DataSourceError(file, line, what) {}
  61. };
  62. struct SQLite3Parameters;
  63. /**
  64. * \brief Concrete implementation of DatabaseAccessor for SQLite3 databases
  65. *
  66. * This opens one database file with our schema and serves data from there.
  67. * According to the design, it doesn't interpret the data in any way, it just
  68. * provides unified access to the DB.
  69. */
  70. class SQLite3Accessor : public DatabaseAccessor,
  71. public boost::enable_shared_from_this<SQLite3Accessor> {
  72. public:
  73. /**
  74. * \brief Constructor
  75. *
  76. * This opens the database and becomes ready to serve data from there.
  77. *
  78. * \exception SQLite3Error will be thrown if the given database file
  79. * doesn't work (it is broken, doesn't exist and can't be created, etc).
  80. *
  81. * \param filename The database file to be used.
  82. * \param rrclass Textual representation of RR class ("IN", "CH", etc),
  83. * specifying which class of data it should serve (while the database
  84. * file can contain multiple classes of data, a single accessor can
  85. * work with only one class).
  86. */
  87. SQLite3Accessor(const std::string& filename, const std::string& rrclass);
  88. /**
  89. * \brief Destructor
  90. *
  91. * Closes the database.
  92. */
  93. ~SQLite3Accessor();
  94. /// This implementation internally opens a new sqlite3 database for the
  95. /// same file name specified in the constructor of the original accessor.
  96. virtual boost::shared_ptr<DatabaseAccessor> clone();
  97. /**
  98. * \brief Look up a zone
  99. *
  100. * This implements the getZone from DatabaseAccessor and looks up a zone
  101. * in the data. It looks for a zone with the exact given origin and class
  102. * passed to the constructor.
  103. *
  104. * \exception SQLite3Error if something about the database is broken.
  105. *
  106. * \param name The (fully qualified) domain name of zone to look up
  107. * \return The pair contains if the lookup was successful in the first
  108. * element and the zone id in the second if it was.
  109. */
  110. virtual std::pair<bool, int> getZone(const std::string& name) const;
  111. /** \brief Look up all resource records for a name
  112. *
  113. * This implements the getRecords() method from DatabaseAccessor
  114. *
  115. * \exception SQLite3Error if there is an sqlite3 error when performing
  116. * the query
  117. *
  118. * \param name the name to look up
  119. * \param id the zone id, as returned by getZone()
  120. * \param subdomains Match subdomains instead of the name.
  121. * \return Iterator that contains all records with the given name
  122. */
  123. virtual IteratorContextPtr getRecords(const std::string& name,
  124. int id,
  125. bool subdomains = false) const;
  126. /** \brief Look up all resource records for a zone
  127. *
  128. * This implements the getRecords() method from DatabaseAccessor
  129. *
  130. * \exception SQLite3Error if there is an sqlite3 error when performing
  131. * the query
  132. *
  133. * \param id the zone id, as returned by getZone()
  134. * \return Iterator that contains all records in the given zone
  135. */
  136. virtual IteratorContextPtr getAllRecords(int id) const;
  137. /** \brief Creates an iterator context for a set of differences.
  138. *
  139. * Implements the getDiffs() method from DatabaseAccessor
  140. *
  141. * \exception NoSuchSerial if either of the versions do not exist in
  142. * the difference table.
  143. * \exception SQLite3Error if there is an sqlite3 error when performing
  144. * the query
  145. *
  146. * \param id The ID of the zone, returned from getZone().
  147. * \param start The SOA serial number of the version of the zone from
  148. * which the difference sequence should start.
  149. * \param end The SOA serial number of the version of the zone at which
  150. * the difference sequence should end.
  151. *
  152. * \return Iterator containing difference records.
  153. */
  154. virtual IteratorContextPtr
  155. getDiffs(int id, uint32_t start, uint32_t end) const;
  156. virtual std::pair<bool, int> startUpdateZone(const std::string& zone_name,
  157. bool replace);
  158. virtual void startTransaction();
  159. /// \note we are quite impatient here: it's quite possible that the COMMIT
  160. /// fails due to other process performing SELECT on the same database
  161. /// (consider the case where COMMIT is done by xfrin or dynamic update
  162. /// server while an authoritative server is busy reading the DB).
  163. /// In a future version we should probably need to introduce some retry
  164. /// attempt and/or increase timeout before giving up the COMMIT, even
  165. /// if it still doesn't guarantee 100% success. Right now this
  166. /// implementation throws a \c DataSourceError exception in such a case.
  167. virtual void commit();
  168. /// \note In SQLite3 rollback can fail if there's another unfinished
  169. /// statement is performed for the same database structure.
  170. /// Although it's not expected to happen in our expected usage, it's not
  171. /// guaranteed to be prevented at the API level. If it ever happens, this
  172. /// method throws a \c DataSourceError exception. It should be
  173. /// considered a bug of the higher level application program.
  174. virtual void rollback();
  175. virtual void addRecordToZone(
  176. const std::string (&columns)[ADD_COLUMN_COUNT]);
  177. virtual void deleteRecordInZone(
  178. const std::string (&params)[DEL_PARAM_COUNT]);
  179. /// This derived version of the method prepares an SQLite3 statement
  180. /// for adding the diff first time it's called, and if it fails throws
  181. // an \c SQLite3Error exception.
  182. virtual void addRecordDiff(
  183. int zone_id, uint32_t serial, DiffOperation operation,
  184. const std::string (&params)[DIFF_PARAM_COUNT]);
  185. // A short term method for tests until we implement more complete
  186. // API to retrieve diffs (#1330). It returns all records of the diffs
  187. // table whose zone_id column is identical to the given value.
  188. // Since this is a short term workaround, it ignores some corner cases
  189. // (such as an SQLite3 execution failure) and is not very efficient,
  190. // in favor of brevity. Once #1330 is completed, this method must be
  191. // removed, and the tests using this method must be rewritten using the
  192. // official API.
  193. std::vector<std::vector<std::string> > getRecordDiff(int zone_id);
  194. /// The SQLite3 implementation of this method returns a string starting
  195. /// with a fixed prefix of "sqlite3_" followed by the DB file name
  196. /// removing any path name. For example, for the DB file
  197. /// /somewhere/in/the/system/bind10.sqlite3, this method will return
  198. /// "sqlite3_bind10.sqlite3".
  199. virtual const std::string& getDBName() const { return (database_name_); }
  200. /// \brief Concrete implementation of the pure virtual method
  201. virtual std::string findPreviousName(int zone_id, const std::string& rname)
  202. const;
  203. private:
  204. /// \brief Private database data
  205. boost::scoped_ptr<SQLite3Parameters> dbparameters_;
  206. /// \brief The filename of the DB (necessary for clone())
  207. const std::string filename_;
  208. /// \brief The class for which the queries are done
  209. const std::string class_;
  210. /// \brief Database name
  211. const std::string database_name_;
  212. /// \brief Opens the database
  213. void open(const std::string& filename);
  214. /// \brief Closes the database
  215. void close();
  216. /// \brief SQLite3 implementation of IteratorContext for all records
  217. class Context;
  218. friend class Context;
  219. /// \brief SQLite3 implementation of IteratorContext for differences
  220. class DiffContext;
  221. friend class DiffContext;
  222. };
  223. /// \brief Creates an instance of the SQlite3 datasource client
  224. ///
  225. /// Currently the configuration passed here must be a MapElement, containing
  226. /// one item called "database_file", whose value is a string
  227. ///
  228. /// This configuration setup is currently under discussion and will change in
  229. /// the near future.
  230. ///
  231. /// \param config The configuration for the datasource instance
  232. /// \param error This string will be set to an error message if an error occurs
  233. /// during initialization
  234. /// \return An instance of the sqlite3 datasource client, or NULL if there was
  235. /// an error
  236. extern "C" DataSourceClient* createInstance(isc::data::ConstElementPtr config,
  237. std::string& error);
  238. /// \brief Destroy the instance created by createInstance()
  239. extern "C" void destroyInstance(DataSourceClient* instance);
  240. }
  241. }
  242. #endif // __DATASRC_SQLITE3_CONNECTION_H
  243. // Local Variables:
  244. // mode: c++
  245. // End: