sqlite3_accessor.h 12 KB

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