sqlite3_accessor.cc 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170
  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. #include <sqlite3.h>
  15. #include <string>
  16. #include <vector>
  17. #include <boost/foreach.hpp>
  18. #include <datasrc/sqlite3_accessor.h>
  19. #include <datasrc/logger.h>
  20. #include <datasrc/data_source.h>
  21. #include <datasrc/factory.h>
  22. #include <datasrc/database.h>
  23. #include <util/filename.h>
  24. using namespace std;
  25. using namespace isc::data;
  26. #define SQLITE_SCHEMA_VERSION 1
  27. #define CONFIG_ITEM_DATABASE_FILE "database_file"
  28. namespace isc {
  29. namespace datasrc {
  30. // The following enum and char* array define the SQL statements commonly
  31. // used in this implementation. Corresponding prepared statements (of
  32. // type sqlite3_stmt*) are maintained in the statements_ array of the
  33. // SQLite3Parameters structure.
  34. enum StatementID {
  35. ZONE = 0,
  36. ANY = 1,
  37. ANY_SUB = 2,
  38. BEGIN = 3,
  39. COMMIT = 4,
  40. ROLLBACK = 5,
  41. DEL_ZONE_RECORDS = 6,
  42. ADD_RECORD = 7,
  43. DEL_RECORD = 8,
  44. ITERATE = 9,
  45. FIND_PREVIOUS = 10,
  46. ADD_RECORD_DIFF = 11,
  47. GET_RECORD_DIFF = 12, // This is temporary for testing "add diff"
  48. LOW_DIFF_ID = 13,
  49. HIGH_DIFF_ID = 14,
  50. DIFF_RECS = 15,
  51. NUM_STATEMENTS = 16
  52. };
  53. const char* const text_statements[NUM_STATEMENTS] = {
  54. // note for ANY and ITERATE: the order of the SELECT values is
  55. // specifically chosen to match the enum values in RecordColumns
  56. "SELECT id FROM zones WHERE name=?1 AND rdclass = ?2", // ZONE
  57. "SELECT rdtype, ttl, sigtype, rdata FROM records " // ANY
  58. "WHERE zone_id=?1 AND name=?2",
  59. "SELECT rdtype, ttl, sigtype, rdata " // ANY_SUB
  60. "FROM records WHERE zone_id=?1 AND name LIKE (\"%.\" || ?2)",
  61. "BEGIN", // BEGIN
  62. "COMMIT", // COMMIT
  63. "ROLLBACK", // ROLLBACK
  64. "DELETE FROM records WHERE zone_id=?1", // DEL_ZONE_RECORDS
  65. "INSERT INTO records " // ADD_RECORD
  66. "(zone_id, name, rname, ttl, rdtype, sigtype, rdata) "
  67. "VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)",
  68. "DELETE FROM records WHERE zone_id=?1 AND name=?2 " // DEL_RECORD
  69. "AND rdtype=?3 AND rdata=?4",
  70. "SELECT rdtype, ttl, sigtype, rdata, name FROM records " // ITERATE
  71. "WHERE zone_id = ?1 ORDER BY rname, rdtype",
  72. /*
  73. * This one looks for previous name with NSEC record. It is done by
  74. * using the reversed name. The NSEC is checked because we need to
  75. * skip glue data, which don't have the NSEC.
  76. */
  77. "SELECT name FROM records " // FIND_PREVIOUS
  78. "WHERE zone_id=?1 AND rdtype = 'NSEC' AND "
  79. "rname < $2 ORDER BY rname DESC LIMIT 1",
  80. "INSERT INTO diffs " // ADD_RECORD_DIFF
  81. "(zone_id, version, operation, name, rrtype, ttl, rdata) "
  82. "VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)",
  83. "SELECT name, rrtype, ttl, rdata, version, operation " // GET_RECORD_DIFF
  84. "FROM diffs WHERE zone_id = ?1 ORDER BY id, operation",
  85. // Two statements to select the lowest ID and highest ID in a set of
  86. // differences.
  87. "SELECT id FROM diffs " // LOW_DIFF_ID
  88. "WHERE zone_id=?1 AND version=?2 and OPERATION=?3 "
  89. "ORDER BY id ASC LIMIT 1",
  90. "SELECT id FROM diffs " // HIGH_DIFF_ID
  91. "WHERE zone_id=?1 AND version=?2 and OPERATION=?3 "
  92. "ORDER BY id DESC LIMIT 1",
  93. // In the next statement, note the redundant ID. This is to ensure
  94. // that the columns match the column IDs passed to the iterator
  95. "SELECT rrtype, ttl, id, rdata, name FROM diffs " // DIFF_RECS
  96. "WHERE zone_id=?1 AND id>=?2 and id<=?3 "
  97. "ORDER BY id ASC"
  98. };
  99. struct SQLite3Parameters {
  100. SQLite3Parameters() :
  101. db_(NULL), version_(-1), in_transaction(false), updating_zone(false),
  102. updated_zone_id(-1)
  103. {
  104. for (int i = 0; i < NUM_STATEMENTS; ++i) {
  105. statements_[i] = NULL;
  106. }
  107. }
  108. // This method returns the specified ID of SQLITE3 statement. If it's
  109. // not yet prepared it internally creates a new one. This way we can
  110. // avoid preparing unnecessary statements and minimize the overhead.
  111. sqlite3_stmt*
  112. getStatement(int id) {
  113. assert(id < NUM_STATEMENTS);
  114. if (statements_[id] == NULL) {
  115. assert(db_ != NULL);
  116. sqlite3_stmt* prepared = NULL;
  117. if (sqlite3_prepare_v2(db_, text_statements[id], -1, &prepared,
  118. NULL) != SQLITE_OK) {
  119. isc_throw(SQLite3Error, "Could not prepare SQLite statement: "
  120. << text_statements[id] <<
  121. ": " << sqlite3_errmsg(db_));
  122. }
  123. statements_[id] = prepared;
  124. }
  125. return (statements_[id]);
  126. }
  127. void
  128. finalizeStatements() {
  129. for (int i = 0; i < NUM_STATEMENTS; ++i) {
  130. if (statements_[i] != NULL) {
  131. sqlite3_finalize(statements_[i]);
  132. statements_[i] = NULL;
  133. }
  134. }
  135. }
  136. sqlite3* db_;
  137. int version_;
  138. bool in_transaction; // whether or not a transaction has been started
  139. bool updating_zone; // whether or not updating the zone
  140. int updated_zone_id; // valid only when in_transaction is true
  141. private:
  142. // statements_ are private and must be accessed via getStatement() outside
  143. // of this structure.
  144. sqlite3_stmt* statements_[NUM_STATEMENTS];
  145. };
  146. // This is a helper class to encapsulate the code logic of executing
  147. // a specific SQLite3 statement, ensuring the corresponding prepared
  148. // statement is always reset whether the execution is completed successfully
  149. // or it results in an exception.
  150. // Note that an object of this class is intended to be used for "ephemeral"
  151. // statement, which is completed with a single "step" (normally within a
  152. // single call to an SQLite3Database method). In particular, it cannot be
  153. // used for "SELECT" variants, which generally expect multiple matching rows.
  154. class StatementProcessor {
  155. public:
  156. // desc will be used on failure in the what() message of the resulting
  157. // DataSourceError exception.
  158. StatementProcessor(SQLite3Parameters& dbparameters, StatementID stmt_id,
  159. const char* desc) :
  160. dbparameters_(dbparameters), stmt_(dbparameters.getStatement(stmt_id)),
  161. desc_(desc)
  162. {
  163. sqlite3_clear_bindings(stmt_);
  164. }
  165. ~StatementProcessor() {
  166. sqlite3_reset(stmt_);
  167. }
  168. void exec() {
  169. if (sqlite3_step(stmt_) != SQLITE_DONE) {
  170. sqlite3_reset(stmt_);
  171. isc_throw(DataSourceError, "failed to " << desc_ << ": " <<
  172. sqlite3_errmsg(dbparameters_.db_));
  173. }
  174. }
  175. private:
  176. SQLite3Parameters& dbparameters_;
  177. sqlite3_stmt* stmt_;
  178. const char* const desc_;
  179. };
  180. SQLite3Accessor::SQLite3Accessor(const std::string& filename,
  181. const string& rrclass) :
  182. dbparameters_(new SQLite3Parameters),
  183. filename_(filename),
  184. class_(rrclass),
  185. database_name_("sqlite3_" +
  186. isc::util::Filename(filename).nameAndExtension())
  187. {
  188. LOG_DEBUG(logger, DBG_TRACE_BASIC, DATASRC_SQLITE_NEWCONN);
  189. open(filename);
  190. }
  191. boost::shared_ptr<DatabaseAccessor>
  192. SQLite3Accessor::clone() {
  193. return (boost::shared_ptr<DatabaseAccessor>(new SQLite3Accessor(filename_,
  194. class_)));
  195. }
  196. namespace {
  197. // This is a helper class to initialize a Sqlite3 DB safely. An object of
  198. // this class encapsulates all temporary resources that are necessary for
  199. // the initialization, and release them in the destructor. Once everything
  200. // is properly initialized, the move() method moves the allocated resources
  201. // to the main object in an exception free manner. This way, the main code
  202. // for the initialization can be exception safe, and can provide the strong
  203. // exception guarantee.
  204. class Initializer {
  205. public:
  206. ~Initializer() {
  207. if (params_.db_ != NULL) {
  208. sqlite3_close(params_.db_);
  209. }
  210. }
  211. void move(SQLite3Parameters* dst) {
  212. *dst = params_;
  213. params_ = SQLite3Parameters(); // clear everything
  214. }
  215. SQLite3Parameters params_;
  216. };
  217. const char* const SCHEMA_LIST[] = {
  218. "CREATE TABLE schema_version (version INTEGER NOT NULL)",
  219. "INSERT INTO schema_version VALUES (1)",
  220. "CREATE TABLE zones (id INTEGER PRIMARY KEY, "
  221. "name STRING NOT NULL COLLATE NOCASE, "
  222. "rdclass STRING NOT NULL COLLATE NOCASE DEFAULT 'IN', "
  223. "dnssec BOOLEAN NOT NULL DEFAULT 0)",
  224. "CREATE INDEX zones_byname ON zones (name)",
  225. "CREATE TABLE records (id INTEGER PRIMARY KEY, "
  226. "zone_id INTEGER NOT NULL, name STRING NOT NULL COLLATE NOCASE, "
  227. "rname STRING NOT NULL COLLATE NOCASE, ttl INTEGER NOT NULL, "
  228. "rdtype STRING NOT NULL COLLATE NOCASE, sigtype STRING COLLATE NOCASE, "
  229. "rdata STRING NOT NULL)",
  230. "CREATE INDEX records_byname ON records (name)",
  231. "CREATE INDEX records_byrname ON records (rname)",
  232. "CREATE TABLE nsec3 (id INTEGER PRIMARY KEY, zone_id INTEGER NOT NULL, "
  233. "hash STRING NOT NULL COLLATE NOCASE, "
  234. "owner STRING NOT NULL COLLATE NOCASE, "
  235. "ttl INTEGER NOT NULL, rdtype STRING NOT NULL COLLATE NOCASE, "
  236. "rdata STRING NOT NULL)",
  237. "CREATE INDEX nsec3_byhash ON nsec3 (hash)",
  238. "CREATE TABLE diffs (id INTEGER PRIMARY KEY, "
  239. "zone_id INTEGER NOT NULL, "
  240. "version INTEGER NOT NULL, "
  241. "operation INTEGER NOT NULL, "
  242. "name STRING NOT NULL COLLATE NOCASE, "
  243. "rrtype STRING NOT NULL COLLATE NOCASE, "
  244. "ttl INTEGER NOT NULL, "
  245. "rdata STRING NOT NULL)",
  246. NULL
  247. };
  248. sqlite3_stmt*
  249. prepare(sqlite3* const db, const char* const statement) {
  250. sqlite3_stmt* prepared = NULL;
  251. if (sqlite3_prepare_v2(db, statement, -1, &prepared, NULL) != SQLITE_OK) {
  252. isc_throw(SQLite3Error, "Could not prepare SQLite statement: " <<
  253. statement << ": " << sqlite3_errmsg(db));
  254. }
  255. return (prepared);
  256. }
  257. // small function to sleep for 0.1 seconds, needed when waiting for
  258. // exclusive database locks (which should only occur on startup, and only
  259. // when the database has not been created yet)
  260. void doSleep() {
  261. struct timespec req;
  262. req.tv_sec = 0;
  263. req.tv_nsec = 100000000;
  264. nanosleep(&req, NULL);
  265. }
  266. // returns the schema version if the schema version table exists
  267. // returns -1 if it does not
  268. int checkSchemaVersion(sqlite3* db) {
  269. sqlite3_stmt* prepared = NULL;
  270. // At this point in time, the database might be exclusively locked, in
  271. // which case even prepare() will return BUSY, so we may need to try a
  272. // few times
  273. for (size_t i = 0; i < 50; ++i) {
  274. int rc = sqlite3_prepare_v2(db, "SELECT version FROM schema_version",
  275. -1, &prepared, NULL);
  276. if (rc == SQLITE_ERROR) {
  277. // this is the error that is returned when the table does not
  278. // exist
  279. return (-1);
  280. } else if (rc == SQLITE_OK) {
  281. break;
  282. } else if (rc != SQLITE_BUSY || i == 50) {
  283. isc_throw(SQLite3Error, "Unable to prepare version query: "
  284. << rc << " " << sqlite3_errmsg(db));
  285. }
  286. doSleep();
  287. }
  288. if (sqlite3_step(prepared) != SQLITE_ROW) {
  289. isc_throw(SQLite3Error,
  290. "Unable to query version: " << sqlite3_errmsg(db));
  291. }
  292. int version = sqlite3_column_int(prepared, 0);
  293. sqlite3_finalize(prepared);
  294. return (version);
  295. }
  296. // return db version
  297. int create_database(sqlite3* db) {
  298. // try to get an exclusive lock. Once that is obtained, do the version
  299. // check *again*, just in case this process was racing another
  300. //
  301. // try for 5 secs (50*0.1)
  302. int rc;
  303. logger.info(DATASRC_SQLITE_SETUP);
  304. for (size_t i = 0; i < 50; ++i) {
  305. rc = sqlite3_exec(db, "BEGIN EXCLUSIVE TRANSACTION", NULL, NULL,
  306. NULL);
  307. if (rc == SQLITE_OK) {
  308. break;
  309. } else if (rc != SQLITE_BUSY || i == 50) {
  310. isc_throw(SQLite3Error, "Unable to acquire exclusive lock "
  311. "for database creation: " << sqlite3_errmsg(db));
  312. }
  313. doSleep();
  314. }
  315. int schema_version = checkSchemaVersion(db);
  316. if (schema_version == -1) {
  317. for (int i = 0; SCHEMA_LIST[i] != NULL; ++i) {
  318. if (sqlite3_exec(db, SCHEMA_LIST[i], NULL, NULL, NULL) !=
  319. SQLITE_OK) {
  320. isc_throw(SQLite3Error,
  321. "Failed to set up schema " << SCHEMA_LIST[i]);
  322. }
  323. }
  324. sqlite3_exec(db, "COMMIT TRANSACTION", NULL, NULL, NULL);
  325. return (SQLITE_SCHEMA_VERSION);
  326. } else {
  327. return (schema_version);
  328. }
  329. }
  330. void
  331. checkAndSetupSchema(Initializer* initializer) {
  332. sqlite3* const db = initializer->params_.db_;
  333. int schema_version = checkSchemaVersion(db);
  334. if (schema_version != SQLITE_SCHEMA_VERSION) {
  335. schema_version = create_database(db);
  336. }
  337. initializer->params_.version_ = schema_version;
  338. }
  339. }
  340. void
  341. SQLite3Accessor::open(const std::string& name) {
  342. LOG_DEBUG(logger, DBG_TRACE_BASIC, DATASRC_SQLITE_CONNOPEN).arg(name);
  343. if (dbparameters_->db_ != NULL) {
  344. // There shouldn't be a way to trigger this anyway
  345. isc_throw(DataSourceError, "Duplicate SQLite open with " << name);
  346. }
  347. Initializer initializer;
  348. if (sqlite3_open(name.c_str(), &initializer.params_.db_) != 0) {
  349. isc_throw(SQLite3Error, "Cannot open SQLite database file: " << name);
  350. }
  351. checkAndSetupSchema(&initializer);
  352. initializer.move(dbparameters_.get());
  353. }
  354. SQLite3Accessor::~SQLite3Accessor() {
  355. LOG_DEBUG(logger, DBG_TRACE_BASIC, DATASRC_SQLITE_DROPCONN);
  356. if (dbparameters_->db_ != NULL) {
  357. close();
  358. }
  359. }
  360. void
  361. SQLite3Accessor::close(void) {
  362. LOG_DEBUG(logger, DBG_TRACE_BASIC, DATASRC_SQLITE_CONNCLOSE);
  363. if (dbparameters_->db_ == NULL) {
  364. isc_throw(DataSourceError,
  365. "SQLite data source is being closed before open");
  366. }
  367. dbparameters_->finalizeStatements();
  368. sqlite3_close(dbparameters_->db_);
  369. dbparameters_->db_ = NULL;
  370. }
  371. std::pair<bool, int>
  372. SQLite3Accessor::getZone(const std::string& name) const {
  373. int rc;
  374. sqlite3_stmt* const stmt = dbparameters_->getStatement(ZONE);
  375. // Take the statement (simple SELECT id FROM zones WHERE...)
  376. // and prepare it (bind the parameters to it)
  377. sqlite3_reset(stmt);
  378. rc = sqlite3_bind_text(stmt, 1, name.c_str(), -1, SQLITE_STATIC);
  379. if (rc != SQLITE_OK) {
  380. isc_throw(SQLite3Error, "Could not bind " << name <<
  381. " to SQL statement (zone)");
  382. }
  383. rc = sqlite3_bind_text(stmt, 2, class_.c_str(), -1, SQLITE_STATIC);
  384. if (rc != SQLITE_OK) {
  385. isc_throw(SQLite3Error, "Could not bind " << class_ <<
  386. " to SQL statement (zone)");
  387. }
  388. // Get the data there and see if it found anything
  389. rc = sqlite3_step(stmt);
  390. if (rc == SQLITE_ROW) {
  391. const int zone_id = sqlite3_column_int(stmt, 0);
  392. sqlite3_reset(stmt);
  393. return (pair<bool, int>(true, zone_id));
  394. } else if (rc == SQLITE_DONE) {
  395. // Free resources
  396. sqlite3_reset(stmt);
  397. return (pair<bool, int>(false, 0));
  398. }
  399. sqlite3_reset(stmt);
  400. isc_throw(DataSourceError, "Unexpected failure in sqlite3_step: " <<
  401. sqlite3_errmsg(dbparameters_->db_));
  402. // Compilers might not realize isc_throw always throws
  403. return (std::pair<bool, int>(false, 0));
  404. }
  405. namespace {
  406. // Conversion to plain char
  407. const char*
  408. convertToPlainChar(const unsigned char* ucp, sqlite3 *db) {
  409. if (ucp == NULL) {
  410. // The field can really be NULL, in which case we return an
  411. // empty string, or sqlite may have run out of memory, in
  412. // which case we raise an error
  413. if (sqlite3_errcode(db) == SQLITE_NOMEM) {
  414. isc_throw(DataSourceError,
  415. "Sqlite3 backend encountered a memory allocation "
  416. "error in sqlite3_column_text()");
  417. } else {
  418. return ("");
  419. }
  420. }
  421. const void* p = ucp;
  422. return (static_cast<const char*>(p));
  423. }
  424. }
  425. class SQLite3Accessor::Context : public DatabaseAccessor::IteratorContext {
  426. public:
  427. // Construct an iterator for all records. When constructed this
  428. // way, the getNext() call will copy all fields
  429. Context(const boost::shared_ptr<const SQLite3Accessor>& accessor, int id) :
  430. iterator_type_(ITT_ALL),
  431. accessor_(accessor),
  432. statement_(NULL),
  433. name_("")
  434. {
  435. // We create the statement now and then just keep getting data from it
  436. statement_ = prepare(accessor->dbparameters_->db_,
  437. text_statements[ITERATE]);
  438. bindZoneId(id);
  439. }
  440. // Construct an iterator for records with a specific name. When constructed
  441. // this way, the getNext() call will copy all fields except name
  442. Context(const boost::shared_ptr<const SQLite3Accessor>& accessor, int id,
  443. const std::string& name, bool subdomains) :
  444. iterator_type_(ITT_NAME),
  445. accessor_(accessor),
  446. statement_(NULL),
  447. name_(name)
  448. {
  449. // We create the statement now and then just keep getting data from it
  450. statement_ = prepare(accessor->dbparameters_->db_,
  451. subdomains ? text_statements[ANY_SUB] :
  452. text_statements[ANY]);
  453. bindZoneId(id);
  454. bindName(name_);
  455. }
  456. bool getNext(std::string (&data)[COLUMN_COUNT]) {
  457. // If there's another row, get it
  458. // If finalize has been called (e.g. when previous getNext() got
  459. // SQLITE_DONE), directly return false
  460. if (statement_ == NULL) {
  461. return false;
  462. }
  463. const int rc(sqlite3_step(statement_));
  464. if (rc == SQLITE_ROW) {
  465. // For both types, we copy the first four columns
  466. copyColumn(data, TYPE_COLUMN);
  467. copyColumn(data, TTL_COLUMN);
  468. copyColumn(data, SIGTYPE_COLUMN);
  469. copyColumn(data, RDATA_COLUMN);
  470. // Only copy Name if we are iterating over every record
  471. if (iterator_type_ == ITT_ALL) {
  472. copyColumn(data, NAME_COLUMN);
  473. }
  474. return (true);
  475. } else if (rc != SQLITE_DONE) {
  476. isc_throw(DataSourceError,
  477. "Unexpected failure in sqlite3_step: " <<
  478. sqlite3_errmsg(accessor_->dbparameters_->db_));
  479. }
  480. finalize();
  481. return (false);
  482. }
  483. virtual ~Context() {
  484. finalize();
  485. }
  486. private:
  487. // Depending on which constructor is called, behaviour is slightly
  488. // different. We keep track of what to do with the iterator type
  489. // See description of getNext() and the constructors
  490. enum IteratorType {
  491. ITT_ALL,
  492. ITT_NAME
  493. };
  494. void copyColumn(std::string (&data)[COLUMN_COUNT], int column) {
  495. data[column] = convertToPlainChar(sqlite3_column_text(statement_,
  496. column),
  497. accessor_->dbparameters_->db_);
  498. }
  499. void bindZoneId(const int zone_id) {
  500. if (sqlite3_bind_int(statement_, 1, zone_id) != SQLITE_OK) {
  501. finalize();
  502. isc_throw(SQLite3Error, "Could not bind int " << zone_id <<
  503. " to SQL statement: " <<
  504. sqlite3_errmsg(accessor_->dbparameters_->db_));
  505. }
  506. }
  507. void bindName(const std::string& name) {
  508. if (sqlite3_bind_text(statement_, 2, name.c_str(), -1,
  509. SQLITE_TRANSIENT) != SQLITE_OK) {
  510. const char* errmsg = sqlite3_errmsg(accessor_->dbparameters_->db_);
  511. finalize();
  512. isc_throw(SQLite3Error, "Could not bind text '" << name <<
  513. "' to SQL statement: " << errmsg);
  514. }
  515. }
  516. void finalize() {
  517. sqlite3_finalize(statement_);
  518. statement_ = NULL;
  519. }
  520. const IteratorType iterator_type_;
  521. boost::shared_ptr<const SQLite3Accessor> accessor_;
  522. sqlite3_stmt* statement_;
  523. const std::string name_;
  524. };
  525. // Methods to retrieve the various iterators
  526. DatabaseAccessor::IteratorContextPtr
  527. SQLite3Accessor::getRecords(const std::string& name, int id,
  528. bool subdomains) const
  529. {
  530. return (IteratorContextPtr(new Context(shared_from_this(), id, name,
  531. subdomains)));
  532. }
  533. DatabaseAccessor::IteratorContextPtr
  534. SQLite3Accessor::getAllRecords(int id) const {
  535. return (IteratorContextPtr(new Context(shared_from_this(), id)));
  536. }
  537. /// \brief Difference Iterator
  538. ///
  539. /// This iterator is used to search through the differences table for the
  540. /// resouce records making up an IXFR between two versions of a zone.
  541. class SQLite3Accessor::DiffContext : public DatabaseAccessor::IteratorContext {
  542. public:
  543. /// \brief Constructor
  544. ///
  545. /// Constructs the iterator for the difference sequence. It is
  546. /// passed two parameters, the first and last versions in the difference
  547. /// sequence. Note that because of serial number rollover, it may well
  548. /// be that the start serial number is greater than the end one.
  549. ///
  550. /// \param zone_id ID of the zone (in the zone table)
  551. /// \param start Serial number of first version in difference sequence
  552. /// \param end Serial number of last version in difference sequence
  553. ///
  554. /// \exception any A number of exceptions can be expected
  555. DiffContext(const boost::shared_ptr<const SQLite3Accessor>& accessor,
  556. int zone_id, uint32_t start, uint32_t end) :
  557. accessor_(accessor),
  558. last_status_(SQLITE_ROW)
  559. {
  560. try {
  561. int low_id = findIndex(LOW_DIFF_ID, zone_id, start, DIFF_DELETE);
  562. int high_id = findIndex(HIGH_DIFF_ID, zone_id, end, DIFF_ADD);
  563. // Prepare the statement that will return data values
  564. reset(DIFF_RECS);
  565. bindInt(DIFF_RECS, 1, zone_id);
  566. bindInt(DIFF_RECS, 2, low_id);
  567. bindInt(DIFF_RECS, 3, high_id);
  568. } catch (...) {
  569. // Something wrong, clear up everything.
  570. accessor_->dbparameters_->finalizeStatements();
  571. throw;
  572. }
  573. }
  574. /// \brief Destructor
  575. virtual ~DiffContext()
  576. {}
  577. /// \brief Get Next Diff Record
  578. ///
  579. /// Returns the next difference record in the difference sequence.
  580. ///
  581. /// \param data Array of std::strings COLUMN_COUNT long. The results
  582. /// are returned in this.
  583. ///
  584. /// \return bool true if data is returned, false if not.
  585. ///
  586. /// \exceptions any Varied
  587. bool getNext(std::string (&data)[COLUMN_COUNT]) {
  588. if (last_status_ != SQLITE_DONE) {
  589. // Last call (if any) didn't reach end of result set, so we
  590. // can read another row from it.
  591. //
  592. // Get a pointer to the statement for brevity (this does not
  593. // transfer ownership of the statement to this class, so there is
  594. // no need to tidy up after we have finished using it).
  595. sqlite3_stmt* stmt =
  596. accessor_->dbparameters_->getStatement(DIFF_RECS);
  597. const int rc(sqlite3_step(stmt));
  598. if (rc == SQLITE_ROW) {
  599. // Copy the data across to the output array
  600. copyColumn(DIFF_RECS, data, TYPE_COLUMN);
  601. copyColumn(DIFF_RECS, data, TTL_COLUMN);
  602. copyColumn(DIFF_RECS, data, NAME_COLUMN);
  603. copyColumn(DIFF_RECS, data, RDATA_COLUMN);
  604. } else if (rc != SQLITE_DONE) {
  605. isc_throw(DataSourceError,
  606. "Unexpected failure in sqlite3_step: " <<
  607. sqlite3_errmsg(accessor_->dbparameters_->db_));
  608. }
  609. last_status_ = rc;
  610. }
  611. return (last_status_ == SQLITE_ROW);
  612. }
  613. private:
  614. /// \brief Reset prepared statement
  615. ///
  616. /// Sets up the statement so that new parameters can be attached to it and
  617. /// that it can be used to query for another difference sequence.
  618. ///
  619. /// \param stindex Index of prepared statement to which to bind
  620. void reset(int stindex) {
  621. sqlite3_stmt* stmt = accessor_->dbparameters_->getStatement(stindex);
  622. if ((sqlite3_reset(stmt) != SQLITE_OK) ||
  623. (sqlite3_clear_bindings(stmt) != SQLITE_OK)) {
  624. isc_throw(SQLite3Error, "Could not clear statement bindings in '" <<
  625. text_statements[stindex] << "': " <<
  626. sqlite3_errmsg(accessor_->dbparameters_->db_));
  627. }
  628. }
  629. /// \brief Bind Int
  630. ///
  631. /// Binds an integer to a specific variable in a prepared statement.
  632. ///
  633. /// \param stindex Index of prepared statement to which to bind
  634. /// \param varindex Index of variable to which to bind
  635. /// \param value Value of variable to bind
  636. /// \exception SQLite3Error on an error
  637. void bindInt(int stindex, int varindex, sqlite3_int64 value) {
  638. if (sqlite3_bind_int64(accessor_->dbparameters_->getStatement(stindex),
  639. varindex, value) != SQLITE_OK) {
  640. isc_throw(SQLite3Error, "Could not bind value to parameter " <<
  641. varindex << " in statement '" <<
  642. text_statements[stindex] << "': " <<
  643. sqlite3_errmsg(accessor_->dbparameters_->db_));
  644. }
  645. }
  646. ///\brief Get Single Value
  647. ///
  648. /// Executes a prepared statement (which has parameters bound to it)
  649. /// for which the result of a single value is expected.
  650. ///
  651. /// \param stindex Index of prepared statement in statement table.
  652. ///
  653. /// \return Value of SELECT.
  654. ///
  655. /// \exception TooMuchData Multiple rows returned when one expected
  656. /// \exception TooLittleData Zero rows returned when one expected
  657. /// \exception DataSourceError SQLite3-related error
  658. int getSingleValue(StatementID stindex) {
  659. // Get a pointer to the statement for brevity (does not transfer
  660. // resources)
  661. sqlite3_stmt* stmt = accessor_->dbparameters_->getStatement(stindex);
  662. // Execute the data. Should be just one result
  663. int rc = sqlite3_step(stmt);
  664. int result = -1;
  665. if (rc == SQLITE_ROW) {
  666. // Got some data, extract the value
  667. result = sqlite3_column_int(stmt, 0);
  668. rc = sqlite3_step(stmt);
  669. if (rc == SQLITE_DONE) {
  670. // All OK, exit with the value.
  671. return (result);
  672. } else if (rc == SQLITE_ROW) {
  673. isc_throw(TooMuchData, "request to return one value from "
  674. "diffs table returned multiple values");
  675. }
  676. } else if (rc == SQLITE_DONE) {
  677. // No data in the table. A bare exception with no explanation is
  678. // thrown, as it will be replaced by a more informative one by
  679. // the caller.
  680. isc_throw(TooLittleData, "");
  681. }
  682. // We get here on an error.
  683. isc_throw(DataSourceError, "could not get data from diffs table: " <<
  684. sqlite3_errmsg(accessor_->dbparameters_->db_));
  685. // Keep the compiler happy with a return value.
  686. return (result);
  687. }
  688. /// \brief Find index
  689. ///
  690. /// Executes the prepared statement locating the high or low index in
  691. /// the diffs table and returns that index.
  692. ///
  693. /// \param stmt_id Index of the prepared statement to execute
  694. /// \param zone_id ID of the zone for which the index is being sought
  695. /// \param serial Zone serial number for which an index is being sought.
  696. /// \param diff Code to delete record additions or deletions
  697. ///
  698. /// \return int ID of the row in the difss table corresponding to the
  699. /// statement.
  700. ///
  701. /// \exception TooLittleData Internal error, no result returned when one
  702. /// was expected.
  703. /// \exception NoSuchSerial Serial number not found.
  704. /// \exception NoDiffsData No data for this zone found in diffs table
  705. int findIndex(StatementID stindex, int zone_id, uint32_t serial, int diff) {
  706. // Set up the statement
  707. reset(stindex);
  708. bindInt(stindex, 1, zone_id);
  709. bindInt(stindex, 2, serial);
  710. bindInt(stindex, 3, diff);
  711. // Execute the statement
  712. int result = -1;
  713. try {
  714. result = getSingleValue(stindex);
  715. } catch (const TooLittleData&) {
  716. // No data returned but the SQL query succeeded. Only possibility
  717. // is that there is no entry in the differences table for the given
  718. // zone and version.
  719. isc_throw(NoSuchSerial, "No entry in differences table for " <<
  720. " zone ID " << zone_id << ", serial number " << serial);
  721. }
  722. return (result);
  723. }
  724. /// \brief Copy Column to Output
  725. ///
  726. /// Copies the textual data in the result set to the specified column
  727. /// in the output.
  728. ///
  729. /// \param stindex Index of prepared statement used to access data
  730. /// \param data Array of columns passed to getNext
  731. /// \param column Column of output to copy
  732. void copyColumn(StatementID stindex, std::string (&data)[COLUMN_COUNT],
  733. int column) {
  734. // Get a pointer to the statement for brevity (does not transfer
  735. // resources)
  736. sqlite3_stmt* stmt = accessor_->dbparameters_->getStatement(stindex);
  737. data[column] = convertToPlainChar(sqlite3_column_text(stmt,
  738. column),
  739. accessor_->dbparameters_->db_);
  740. }
  741. // Attributes
  742. boost::shared_ptr<const SQLite3Accessor> accessor_; // Accessor object
  743. int last_status_; // Last status received from sqlite3_step
  744. };
  745. // ... and return the iterator
  746. DatabaseAccessor::IteratorContextPtr
  747. SQLite3Accessor::getDiffs(int id, uint32_t start, uint32_t end) const {
  748. return (IteratorContextPtr(new DiffContext(shared_from_this(), id, start,
  749. end)));
  750. }
  751. pair<bool, int>
  752. SQLite3Accessor::startUpdateZone(const string& zone_name, const bool replace) {
  753. if (dbparameters_->updating_zone) {
  754. isc_throw(DataSourceError,
  755. "duplicate zone update on SQLite3 data source");
  756. }
  757. if (dbparameters_->in_transaction) {
  758. isc_throw(DataSourceError,
  759. "zone update attempt in another SQLite3 transaction");
  760. }
  761. const pair<bool, int> zone_info(getZone(zone_name));
  762. if (!zone_info.first) {
  763. return (zone_info);
  764. }
  765. StatementProcessor(*dbparameters_, BEGIN,
  766. "start an SQLite3 update transaction").exec();
  767. if (replace) {
  768. try {
  769. StatementProcessor delzone_exec(*dbparameters_, DEL_ZONE_RECORDS,
  770. "delete zone records");
  771. sqlite3_stmt* stmt = dbparameters_->getStatement(DEL_ZONE_RECORDS);
  772. sqlite3_clear_bindings(stmt);
  773. if (sqlite3_bind_int(stmt, 1, zone_info.second) != SQLITE_OK) {
  774. isc_throw(DataSourceError,
  775. "failed to bind SQLite3 parameter: " <<
  776. sqlite3_errmsg(dbparameters_->db_));
  777. }
  778. delzone_exec.exec();
  779. } catch (const DataSourceError&) {
  780. // Once we start a transaction, if something unexpected happens
  781. // we need to rollback the transaction so that a subsequent update
  782. // is still possible with this accessor.
  783. StatementProcessor(*dbparameters_, ROLLBACK,
  784. "rollback an SQLite3 transaction").exec();
  785. throw;
  786. }
  787. }
  788. dbparameters_->in_transaction = true;
  789. dbparameters_->updating_zone = true;
  790. dbparameters_->updated_zone_id = zone_info.second;
  791. return (zone_info);
  792. }
  793. void
  794. SQLite3Accessor::startTransaction() {
  795. if (dbparameters_->in_transaction) {
  796. isc_throw(DataSourceError,
  797. "duplicate transaction on SQLite3 data source");
  798. }
  799. StatementProcessor(*dbparameters_, BEGIN,
  800. "start an SQLite3 transaction").exec();
  801. dbparameters_->in_transaction = true;
  802. }
  803. void
  804. SQLite3Accessor::commit() {
  805. if (!dbparameters_->in_transaction) {
  806. isc_throw(DataSourceError, "performing commit on SQLite3 "
  807. "data source without transaction");
  808. }
  809. StatementProcessor(*dbparameters_, COMMIT,
  810. "commit an SQLite3 transaction").exec();
  811. dbparameters_->in_transaction = false;
  812. dbparameters_->updated_zone_id = -1;
  813. }
  814. void
  815. SQLite3Accessor::rollback() {
  816. if (!dbparameters_->in_transaction) {
  817. isc_throw(DataSourceError, "performing rollback on SQLite3 "
  818. "data source without transaction");
  819. }
  820. StatementProcessor(*dbparameters_, ROLLBACK,
  821. "rollback an SQLite3 transaction").exec();
  822. dbparameters_->in_transaction = false;
  823. dbparameters_->updated_zone_id = -1;
  824. }
  825. namespace {
  826. // Commonly used code sequence for adding/deleting record
  827. template <typename COLUMNS_TYPE>
  828. void
  829. doUpdate(SQLite3Parameters& dbparams, StatementID stmt_id,
  830. COLUMNS_TYPE update_params, const char* exec_desc)
  831. {
  832. sqlite3_stmt* const stmt = dbparams.getStatement(stmt_id);
  833. StatementProcessor executer(dbparams, stmt_id, exec_desc);
  834. int param_id = 0;
  835. if (sqlite3_bind_int(stmt, ++param_id, dbparams.updated_zone_id)
  836. != SQLITE_OK) {
  837. isc_throw(DataSourceError, "failed to bind SQLite3 parameter: " <<
  838. sqlite3_errmsg(dbparams.db_));
  839. }
  840. const size_t column_count =
  841. sizeof(update_params) / sizeof(update_params[0]);
  842. for (int i = 0; i < column_count; ++i) {
  843. // The old sqlite3 data source API assumes NULL for an empty column.
  844. // We need to provide compatibility at least for now.
  845. if (sqlite3_bind_text(stmt, ++param_id,
  846. update_params[i].empty() ? NULL :
  847. update_params[i].c_str(),
  848. -1, SQLITE_TRANSIENT) != SQLITE_OK) {
  849. isc_throw(DataSourceError, "failed to bind SQLite3 parameter: " <<
  850. sqlite3_errmsg(dbparams.db_));
  851. }
  852. }
  853. executer.exec();
  854. }
  855. }
  856. void
  857. SQLite3Accessor::addRecordToZone(const string (&columns)[ADD_COLUMN_COUNT]) {
  858. if (!dbparameters_->updating_zone) {
  859. isc_throw(DataSourceError, "adding record to SQLite3 "
  860. "data source without transaction");
  861. }
  862. doUpdate<const string (&)[DatabaseAccessor::ADD_COLUMN_COUNT]>(
  863. *dbparameters_, ADD_RECORD, columns, "add record to zone");
  864. }
  865. void
  866. SQLite3Accessor::deleteRecordInZone(const string (&params)[DEL_PARAM_COUNT]) {
  867. if (!dbparameters_->updating_zone) {
  868. isc_throw(DataSourceError, "deleting record in SQLite3 "
  869. "data source without transaction");
  870. }
  871. doUpdate<const string (&)[DatabaseAccessor::DEL_PARAM_COUNT]>(
  872. *dbparameters_, DEL_RECORD, params, "delete record from zone");
  873. }
  874. void
  875. SQLite3Accessor::addRecordDiff(int zone_id, uint32_t serial,
  876. DiffOperation operation,
  877. const std::string (&params)[DIFF_PARAM_COUNT])
  878. {
  879. if (!dbparameters_->updating_zone) {
  880. isc_throw(DataSourceError, "adding record diff without update "
  881. "transaction on " << getDBName());
  882. }
  883. if (zone_id != dbparameters_->updated_zone_id) {
  884. isc_throw(DataSourceError, "bad zone ID for adding record diff on "
  885. << getDBName() << ": " << zone_id << ", must be "
  886. << dbparameters_->updated_zone_id);
  887. }
  888. sqlite3_stmt* const stmt = dbparameters_->getStatement(ADD_RECORD_DIFF);
  889. StatementProcessor executer(*dbparameters_, ADD_RECORD_DIFF,
  890. "add record diff");
  891. int param_id = 0;
  892. if (sqlite3_bind_int(stmt, ++param_id, zone_id)
  893. != SQLITE_OK) {
  894. isc_throw(DataSourceError, "failed to bind SQLite3 parameter: " <<
  895. sqlite3_errmsg(dbparameters_->db_));
  896. }
  897. if (sqlite3_bind_int64(stmt, ++param_id, serial)
  898. != SQLITE_OK) {
  899. isc_throw(DataSourceError, "failed to bind SQLite3 parameter: " <<
  900. sqlite3_errmsg(dbparameters_->db_));
  901. }
  902. if (sqlite3_bind_int(stmt, ++param_id, operation)
  903. != SQLITE_OK) {
  904. isc_throw(DataSourceError, "failed to bind SQLite3 parameter: " <<
  905. sqlite3_errmsg(dbparameters_->db_));
  906. }
  907. for (int i = 0; i < DIFF_PARAM_COUNT; ++i) {
  908. if (sqlite3_bind_text(stmt, ++param_id, params[i].c_str(),
  909. -1, SQLITE_TRANSIENT) != SQLITE_OK) {
  910. isc_throw(DataSourceError, "failed to bind SQLite3 parameter: " <<
  911. sqlite3_errmsg(dbparameters_->db_));
  912. }
  913. }
  914. executer.exec();
  915. }
  916. vector<vector<string> >
  917. SQLite3Accessor::getRecordDiff(int zone_id) {
  918. sqlite3_stmt* const stmt = dbparameters_->getStatement(GET_RECORD_DIFF);
  919. sqlite3_bind_int(stmt, 1, zone_id);
  920. vector<vector<string> > result;
  921. while (sqlite3_step(stmt) == SQLITE_ROW) {
  922. vector<string> row_result;
  923. for (int i = 0; i < 6; ++i) {
  924. row_result.push_back(convertToPlainChar(sqlite3_column_text(stmt,
  925. i),
  926. dbparameters_->db_));
  927. }
  928. result.push_back(row_result);
  929. }
  930. sqlite3_reset(stmt);
  931. return (result);
  932. }
  933. std::string
  934. SQLite3Accessor::findPreviousName(int zone_id, const std::string& rname)
  935. const
  936. {
  937. sqlite3_stmt* const stmt = dbparameters_->getStatement(FIND_PREVIOUS);
  938. sqlite3_reset(stmt);
  939. sqlite3_clear_bindings(stmt);
  940. if (sqlite3_bind_int(stmt, 1, zone_id) != SQLITE_OK) {
  941. isc_throw(SQLite3Error, "Could not bind zone ID " << zone_id <<
  942. " to SQL statement (find previous): " <<
  943. sqlite3_errmsg(dbparameters_->db_));
  944. }
  945. if (sqlite3_bind_text(stmt, 2, rname.c_str(), -1, SQLITE_STATIC) !=
  946. SQLITE_OK) {
  947. isc_throw(SQLite3Error, "Could not bind name " << rname <<
  948. " to SQL statement (find previous): " <<
  949. sqlite3_errmsg(dbparameters_->db_));
  950. }
  951. std::string result;
  952. const int rc = sqlite3_step(stmt);
  953. if (rc == SQLITE_ROW) {
  954. // We found it
  955. result = convertToPlainChar(sqlite3_column_text(stmt, 0),
  956. dbparameters_->db_);
  957. }
  958. sqlite3_reset(stmt);
  959. if (rc == SQLITE_DONE) {
  960. // No NSEC records here, this DB doesn't support DNSSEC or
  961. // we asked before the apex
  962. isc_throw(isc::NotImplemented, "The zone doesn't support DNSSEC or "
  963. "query before apex");
  964. }
  965. if (rc != SQLITE_ROW && rc != SQLITE_DONE) {
  966. // Some kind of error
  967. isc_throw(SQLite3Error, "Could not get data for previous name");
  968. }
  969. return (result);
  970. }
  971. namespace {
  972. void
  973. addError(ElementPtr errors, const std::string& error) {
  974. if (errors != ElementPtr() && errors->getType() == Element::list) {
  975. errors->add(Element::create(error));
  976. }
  977. }
  978. bool
  979. checkConfig(ConstElementPtr config, ElementPtr errors) {
  980. /* Specific configuration is under discussion, right now this accepts
  981. * the 'old' configuration, see header file
  982. */
  983. bool result = true;
  984. if (!config || config->getType() != Element::map) {
  985. addError(errors, "Base config for SQlite3 backend must be a map");
  986. result = false;
  987. } else {
  988. if (!config->contains(CONFIG_ITEM_DATABASE_FILE)) {
  989. addError(errors,
  990. "Config for SQlite3 backend does not contain a '"
  991. CONFIG_ITEM_DATABASE_FILE
  992. "' value");
  993. result = false;
  994. } else if (!config->get(CONFIG_ITEM_DATABASE_FILE) ||
  995. config->get(CONFIG_ITEM_DATABASE_FILE)->getType() !=
  996. Element::string) {
  997. addError(errors, "value of " CONFIG_ITEM_DATABASE_FILE
  998. " in SQLite3 backend is not a string");
  999. result = false;
  1000. } else if (config->get(CONFIG_ITEM_DATABASE_FILE)->stringValue() ==
  1001. "") {
  1002. addError(errors, "value of " CONFIG_ITEM_DATABASE_FILE
  1003. " in SQLite3 backend is empty");
  1004. result = false;
  1005. }
  1006. }
  1007. return (result);
  1008. }
  1009. } // end anonymous namespace
  1010. DataSourceClient *
  1011. createInstance(isc::data::ConstElementPtr config, std::string& error) {
  1012. ElementPtr errors(Element::createList());
  1013. if (!checkConfig(config, errors)) {
  1014. error = "Configuration error: " + errors->str();
  1015. return (NULL);
  1016. }
  1017. std::string dbfile = config->get(CONFIG_ITEM_DATABASE_FILE)->stringValue();
  1018. try {
  1019. boost::shared_ptr<DatabaseAccessor> sqlite3_accessor(
  1020. new SQLite3Accessor(dbfile, "IN")); // XXX: avoid hardcode RR class
  1021. return (new DatabaseClient(isc::dns::RRClass::IN(), sqlite3_accessor));
  1022. } catch (const std::exception& exc) {
  1023. error = std::string("Error creating sqlite3 datasource: ") + exc.what();
  1024. return (NULL);
  1025. } catch (...) {
  1026. error = std::string("Error creating sqlite3 datasource, "
  1027. "unknown exception");
  1028. return (NULL);
  1029. }
  1030. }
  1031. void destroyInstance(DataSourceClient* instance) {
  1032. delete instance;
  1033. }
  1034. } // end of namespace datasrc
  1035. } // end of namespace isc