BIND 10 trac2541, updated. bc8aae68ec152b7dce35c158758537bd9912688f [2541] Address more comments; add tests and update docs
BIND 10 source code commits
bind10-changes at lists.isc.org
Wed Dec 12 14:15:30 UTC 2012
The branch, trac2541 has been updated
via bc8aae68ec152b7dce35c158758537bd9912688f (commit)
via 8aa69ddf3d2d99fd9050a07c20eb01dd4287de95 (commit)
via eb65b11ca44fb2b2c128b317449272240ce337c3 (commit)
via 5c72873a1145a7bcdc70d8b1f9ddce1198548c3c (commit)
from b193ad87c312d2e6ceb54f0f2746425ba4f59d63 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit bc8aae68ec152b7dce35c158758537bd9912688f
Author: Jelte Jansen <jelte at isc.org>
Date: Wed Dec 12 15:15:01 2012 +0100
[2541] Address more comments; add tests and update docs
commit 8aa69ddf3d2d99fd9050a07c20eb01dd4287de95
Author: Jelte Jansen <jelte at isc.org>
Date: Wed Dec 12 11:43:13 2012 +0100
[2541] Use c++-style doxygen
commit eb65b11ca44fb2b2c128b317449272240ce337c3
Author: Jelte Jansen <jelte at isc.org>
Date: Wed Dec 12 11:30:56 2012 +0100
[2541] Catch and log exception in transaction rollback
commit 5c72873a1145a7bcdc70d8b1f9ddce1198548c3c
Author: Jelte Jansen <jelte at isc.org>
Date: Wed Dec 12 11:12:07 2012 +0100
[2541] Move method implementations in client.h to client.cc
-----------------------------------------------------------------------
Summary of changes:
src/lib/datasrc/Makefile.am | 2 +-
src/lib/datasrc/{exceptions.h => client.cc} | 55 ++---
src/lib/datasrc/client.h | 31 +--
src/lib/datasrc/database.cc | 13 +-
src/lib/datasrc/database.h | 7 +-
src/lib/datasrc/datasrc_messages.mes | 10 +
src/lib/datasrc/sqlite3_accessor.cc | 3 +
src/lib/datasrc/sqlite3_accessor.h | 219 +++++++++-----------
src/lib/datasrc/tests/sqlite3_accessor_unittest.cc | 66 +++++-
9 files changed, 223 insertions(+), 183 deletions(-)
copy src/lib/datasrc/{exceptions.h => client.cc} (50%)
-----------------------------------------------------------------------
diff --git a/src/lib/datasrc/Makefile.am b/src/lib/datasrc/Makefile.am
index f4e768a..911d2f5 100644
--- a/src/lib/datasrc/Makefile.am
+++ b/src/lib/datasrc/Makefile.am
@@ -31,7 +31,7 @@ libb10_datasrc_la_SOURCES += zonetable.h zonetable.cc
libb10_datasrc_la_SOURCES += zone.h zone_finder.cc zone_finder_context.cc
libb10_datasrc_la_SOURCES += result.h
libb10_datasrc_la_SOURCES += logger.h logger.cc
-libb10_datasrc_la_SOURCES += client.h iterator.h
+libb10_datasrc_la_SOURCES += client.h client.cc iterator.h
libb10_datasrc_la_SOURCES += database.h database.cc
libb10_datasrc_la_SOURCES += factory.h factory.cc
libb10_datasrc_la_SOURCES += client_list.h client_list.cc
diff --git a/src/lib/datasrc/client.cc b/src/lib/datasrc/client.cc
new file mode 100644
index 0000000..919e9ab
--- /dev/null
+++ b/src/lib/datasrc/client.cc
@@ -0,0 +1,48 @@
+// Copyright (C) 2012 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.
+
+#include <datasrc/client.h>
+
+#include <exceptions/exceptions.h>
+
+/// This file defines a few default implementations for methods.
+///
+/// While some of the detail of the API are worked out, we define
+/// default implementations to ease development for some of the
+/// more tentative methods (those that are not (yet) pure virtual)
+/// They should all throw NotImplemented
+
+namespace isc {
+namespace datasrc {
+
+ZoneIteratorPtr
+DataSourceClient::getIterator(const isc::dns::Name&, bool) const {
+ isc_throw(isc::NotImplemented,
+ "Data source doesn't support iteration");
+}
+
+unsigned int
+DataSourceClient::getZoneCount() const {
+ isc_throw(isc::NotImplemented,
+ "Data source doesn't support getZoneCount");
+}
+
+bool
+DataSourceClient::createZone(const dns::Name&) {
+ isc_throw(isc::NotImplemented,
+ "Data source doesn't support addZone");
+}
+
+} // end namespace datasrc
+} // end namespace isc
diff --git a/src/lib/datasrc/client.h b/src/lib/datasrc/client.h
index 33d1faa..f65d87d 100644
--- a/src/lib/datasrc/client.h
+++ b/src/lib/datasrc/client.h
@@ -20,8 +20,6 @@
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
-#include <exceptions/exceptions.h>
-
#include <datasrc/zone.h>
/// \file
@@ -225,15 +223,7 @@ public:
/// adjusted to the lowest one found.
/// \return Pointer to the iterator.
virtual ZoneIteratorPtr getIterator(const isc::dns::Name& name,
- bool separate_rrs = false) const {
- // This is here to both document the parameter in doxygen (therefore it
- // needs a name) and avoid unused parameter warning.
- static_cast<void>(name);
- static_cast<void>(separate_rrs);
-
- isc_throw(isc::NotImplemented,
- "Data source doesn't support iteration");
- }
+ bool separate_rrs = false) const;
/// Return an updater to make updates to a specific zone.
///
@@ -368,16 +358,15 @@ public:
/// This is an optional convenience method, currently only implemented
/// by the InMemory datasource. By default, it throws NotImplemented
///
+ /// \note This is a tentative API, and this method is likely to change
+ /// or be removed in the near future. For that reason, it currently
+ /// provides a default implementation that throws NotImplemented.
+ ///
/// \exception NotImplemented Thrown if this method is not supported
/// by the datasource
///
- /// \note This is a tentative API, and this method may likely to be
- /// removed in the near future.
/// \return The number of zones known to this datasource
- virtual unsigned int getZoneCount() const {
- isc_throw(isc::NotImplemented,
- "Data source doesn't support getZoneCount");
- }
+ virtual unsigned int getZoneCount() const;
/// \brief Create a zone in the database
///
@@ -385,7 +374,8 @@ public:
/// can subsequently be filled with data (through getUpdater()).
///
/// \note This is a tentative API, and this method is likely to change
- /// or be removed in the near future.
+ /// or be removed in the near future. For that reason, it currently
+ /// provides a default implementation that throws NotImplemented.
///
/// Apart from the two exceptions mentioned below, in theory this
/// call can throw anything, depending on the implementation of
@@ -397,10 +387,7 @@ public:
/// while creating the zone.
/// \param name The (fully qualified) name of the zone to create
/// \return True if the zone was added, false if it already existed
- virtual bool createZone(const dns::Name&) {
- isc_throw(isc::NotImplemented,
- "Data source doesn't support addZone");
- }
+ virtual bool createZone(const dns::Name& name);
};
}
}
diff --git a/src/lib/datasrc/database.cc b/src/lib/datasrc/database.cc
index b83c401..62da2e0 100644
--- a/src/lib/datasrc/database.cc
+++ b/src/lib/datasrc/database.cc
@@ -55,7 +55,18 @@ public:
}
~TransactionHolder() {
if (!committed_) {
- accessor_.rollback();
+ try {
+ accessor_.rollback();
+ } catch (const DataSourceError& e) {
+ // We generally expect that rollback always succeeds, and
+ // it should in fact succeed in a way we execute it. But
+ // as the public API allows rollback() to fail and
+ // throw, we should expect it. Obviously we cannot re-throw
+ // it. The best we can do is to log it as a critical error.
+ logger.error(DATASRC_DATABASE_TRANSACTION_ROLLBACKFAIL).
+ arg(accessor_.getDBName()).
+ arg(e.what());
+ }
}
}
void commit() {
diff --git a/src/lib/datasrc/database.h b/src/lib/datasrc/database.h
index 8437331..9db8a8f 100644
--- a/src/lib/datasrc/database.h
+++ b/src/lib/datasrc/database.h
@@ -186,8 +186,8 @@ public:
/// responsibility of the caller to do so.
///
/// Callers must also start a transaction before calling this method,
- /// implementations may throw DataSourceError if this has not been done.
- /// Callers should also expect DataSourceErrors for other potential
+ /// implementations should throw DataSourceError if this has not been
+ /// done. Callers should also expect DataSourceErrors for other potential
/// problems.
///
/// \param name The (fully qualified) domain name of the zone to add.
@@ -1399,9 +1399,6 @@ public:
/// does not, creates it, commits, and returns true. If the zone
/// does exist already, it does nothing (except abort the transaction)
/// and returns false.
- ///
- /// \param name The (fully qualified) name of the zone to create
- /// \return True if the zone was added, false if it already existed
virtual bool createZone(const isc::dns::Name& name);
/// \brief Get the zone iterator
diff --git a/src/lib/datasrc/datasrc_messages.mes b/src/lib/datasrc/datasrc_messages.mes
index e7cb9d3..e9b4c90 100644
--- a/src/lib/datasrc/datasrc_messages.mes
+++ b/src/lib/datasrc/datasrc_messages.mes
@@ -216,6 +216,16 @@ to find any invalid data and fix it.
No match (not even a wildcard) was found in the named data source for the given
name/type/class in the data source.
+% DATASRC_DATABASE_TRANSACTION_ROLLBACKFAIL failed to roll back transaction on %1: %2
+A transaction on the database was rolled back without committing the
+changes to the database, but the rollback itself unexpectedly fails.
+The higher level implementation does not expect it to fail, so this means
+either a serious operational error in the underlying data source (such as a
+system failure of a database) or software bug in the underlying data source
+implementation. In either case if this message is logged the administrator
+should carefully examine the underlying data source to see what exactly
+happens and whether the data is still valid.
+
% DATASRC_DATABASE_UPDATER_COMMIT updates committed for '%1/%2' on %3
Debug information. A set of updates to a zone has been successfully
committed to the corresponding database backend. The zone name,
diff --git a/src/lib/datasrc/sqlite3_accessor.cc b/src/lib/datasrc/sqlite3_accessor.cc
index 516cad9..4ef49d0 100644
--- a/src/lib/datasrc/sqlite3_accessor.cc
+++ b/src/lib/datasrc/sqlite3_accessor.cc
@@ -625,6 +625,9 @@ SQLite3Accessor::addZone(const std::string& name) {
}
StatementProcessor proc(*dbparameters_, ADD_ZONE, "add zone");
+ // note: using TRANSIENT here, STATIC would be slightly more
+ // efficient, but TRANSIENT is safer and performance is not
+ // as important in this specific code path.
proc.bindText(1, name.c_str(), SQLITE_TRANSIENT);
proc.bindText(2, class_.c_str(), SQLITE_TRANSIENT);
proc.exec();
diff --git a/src/lib/datasrc/sqlite3_accessor.h b/src/lib/datasrc/sqlite3_accessor.h
index e144d53..e931573 100644
--- a/src/lib/datasrc/sqlite3_accessor.h
+++ b/src/lib/datasrc/sqlite3_accessor.h
@@ -34,13 +34,11 @@ class RRClass;
namespace datasrc {
-/**
- * \brief Low-level database error
- *
- * This exception is thrown when the SQLite library complains about something.
- * It might mean corrupt database file, invalid request or that something is
- * rotten in the library.
- */
+/// \brief Low-level database error
+///
+/// This exception is thrown when the SQLite library complains about something.
+/// It might mean corrupt database file, invalid request or that something is
+/// rotten in the library.
class SQLite3Error : public DataSourceError {
public:
SQLite3Error(const char* file, size_t line, const char* what) :
@@ -53,24 +51,20 @@ public:
isc::Exception(file, line, what) {}
};
-/**
- * \brief Too Much Data
- *
- * Thrown if a query expecting a certain number of rows back returned too
- * many rows.
- */
+/// \brief Too Much Data
+///
+/// Thrown if a query expecting a certain number of rows back returned too
+/// many rows.
class TooMuchData : public DataSourceError {
public:
TooMuchData(const char* file, size_t line, const char* what) :
DataSourceError(file, line, what) {}
};
-/**
- * \brief Too Little Data
- *
- * Thrown if a query expecting a certain number of rows back returned too
- * few rows (including none).
- */
+/// \brief Too Little Data
+///
+/// Thrown if a query expecting a certain number of rows back returned too
+/// few rows (including none).
class TooLittleData : public DataSourceError {
public:
TooLittleData(const char* file, size_t line, const char* what) :
@@ -79,94 +73,83 @@ public:
struct SQLite3Parameters;
-/**
- * \brief Concrete implementation of DatabaseAccessor for SQLite3 databases
- *
- * This opens one database file with our schema and serves data from there.
- * According to the design, it doesn't interpret the data in any way, it just
- * provides unified access to the DB.
- */
+/// \brief Concrete implementation of DatabaseAccessor for SQLite3 databases
+///
+/// This opens one database file with our schema and serves data from there.
+/// According to the design, it doesn't interpret the data in any way, it just
+/// provides unified access to the DB.
class SQLite3Accessor : public DatabaseAccessor,
public boost::enable_shared_from_this<SQLite3Accessor> {
public:
- /**
- * \brief Constructor
- *
- * This opens the database and becomes ready to serve data from there.
- *
- * \exception SQLite3Error will be thrown if the given database file
- * doesn't work (it is broken, doesn't exist and can't be created, etc).
- *
- * \param filename The database file to be used.
- * \param rrclass Textual representation of RR class ("IN", "CH", etc),
- * specifying which class of data it should serve (while the database
- * file can contain multiple classes of data, a single accessor can
- * work with only one class).
- */
+ /// \brief Constructor
+ ///
+ /// This opens the database and becomes ready to serve data from there.
+ ///
+ /// \exception SQLite3Error will be thrown if the given database file
+ /// doesn't work (it is broken, doesn't exist and can't be created, etc).
+ ///
+ /// \param filename The database file to be used.
+ /// \param rrclass Textual representation of RR class ("IN", "CH", etc),
+ /// specifying which class of data it should serve (while the database
+ /// file can contain multiple classes of data, a single accessor can
+ /// work with only one class).
SQLite3Accessor(const std::string& filename, const std::string& rrclass);
- /**
- * \brief Destructor
- *
- * Closes the database.
- */
+ /// \brief Destructor
+ ///
+ /// Closes the database.
~SQLite3Accessor();
/// This implementation internally opens a new sqlite3 database for the
/// same file name specified in the constructor of the original accessor.
virtual boost::shared_ptr<DatabaseAccessor> clone();
- /**
- * \brief Look up a zone
- *
- * This implements the getZone from DatabaseAccessor and looks up a zone
- * in the data. It looks for a zone with the exact given origin and class
- * passed to the constructor.
- *
- * \exception SQLite3Error if something about the database is broken.
- *
- * \param name The (fully qualified) domain name of zone to look up
- * \return The pair contains if the lookup was successful in the first
- * element and the zone id in the second if it was.
- */
+ /// \brief Look up a zone
+ ///
+ /// This implements the getZone from DatabaseAccessor and looks up a zone
+ /// in the data. It looks for a zone with the exact given origin and class
+ /// passed to the constructor.
+ ///
+ /// \exception SQLite3Error if something about the database is broken.
+ ///
+ /// \param name The (fully qualified) domain name of zone to look up
+ /// \return The pair contains if the lookup was successful in the first
+ /// element and the zone id in the second if it was.
virtual std::pair<bool, int> getZone(const std::string& name) const;
- /**
- * \brief Add a zone
- *
- * This implements the addZone from DatabaseAccessor and adds an (empty)
- * zone into the zones table. If the zone exists already, it is still
- * added, so the caller should make sure this does not happen (by making
- * sure the zone does not exist). In the case of duplicate addition,
- * it is undefined which zone id is returned.
- *
- * The class of the newly created zone is the class passed at construction
- * time of the accessor.
- *
- * This method requires a transaction has been started (with
- * \c beginTransaction) by the caller.
- *
- * \exception DataSourceError if no transaction is active, or if there
- * is an SQLite3 error when performing the
- * queries.
- *
- * \param name The origin name of the zone to add
- * \return the id of the zone that has been added
- */
+ /// \brief Add a zone
+ ///
+ /// This implements the addZone from DatabaseAccessor and adds a zone
+ /// into the zones table. If the zone exists already, it is still added,
+ /// so the caller should make sure this does not happen (by making
+ /// sure the zone does not exist). In the case of duplicate addition,
+ /// it is undefined which zone id is returned.
+ ///
+ /// The class of the newly created zone is the class passed at construction
+ /// time of the accessor.
+ ///
+ /// This method requires a transaction has been started (with
+ /// \c beginTransaction) by the caller.
+ ///
+ /// \exception DataSourceError if no transaction is active, or if there
+ /// is an SQLite3 error when performing the
+ /// queries.
+ ///
+ /// \param name The origin name of the zone to add
+ /// \return the id of the zone that has been added
virtual int addZone(const std::string& name);
- /** \brief Look up all resource records for a name
- *
- * This implements the getRecords() method from DatabaseAccessor
- *
- * \exception SQLite3Error if there is an sqlite3 error when performing
- * the query
- *
- * \param name the name to look up
- * \param id the zone id, as returned by getZone()
- * \param subdomains Match subdomains instead of the name.
- * \return Iterator that contains all records with the given name
- */
+ /// \brief Look up all resource records for a name
+ ///
+ /// This implements the getRecords() method from DatabaseAccessor
+ ///
+ /// \exception SQLite3Error if there is an sqlite3 error when performing
+ /// the query
+ ///
+ /// \param name the name to look up
+ /// \param id the zone id, as returned by getZone()
+ /// \param subdomains Match subdomains instead of the name.
+ /// \return Iterator that contains all records with the given name
virtual IteratorContextPtr getRecords(const std::string& name,
int id,
bool subdomains = false) const;
@@ -179,35 +162,33 @@ public:
virtual IteratorContextPtr getNSEC3Records(const std::string& hash,
int id) const;
- /** \brief Look up all resource records for a zone
- *
- * This implements the getRecords() method from DatabaseAccessor
- *
- * \exception SQLite3Error if there is an sqlite3 error when performing
- * the query
- *
- * \param id the zone id, as returned by getZone()
- * \return Iterator that contains all records in the given zone
- */
+ /// \brief Look up all resource records for a zone
+ ///
+ /// This implements the getRecords() method from DatabaseAccessor
+ ///
+ /// \exception SQLite3Error if there is an sqlite3 error when performing
+ /// the query
+ ///
+ /// \param id the zone id, as returned by getZone()
+ /// \return Iterator that contains all records in the given zone
virtual IteratorContextPtr getAllRecords(int id) const;
- /** \brief Creates an iterator context for a set of differences.
- *
- * Implements the getDiffs() method from DatabaseAccessor
- *
- * \exception NoSuchSerial if either of the versions do not exist in
- * the difference table.
- * \exception SQLite3Error if there is an sqlite3 error when performing
- * the query
- *
- * \param id The ID of the zone, returned from getZone().
- * \param start The SOA serial number of the version of the zone from
- * which the difference sequence should start.
- * \param end The SOA serial number of the version of the zone at which
- * the difference sequence should end.
- *
- * \return Iterator containing difference records.
- */
+ /// \brief Creates an iterator context for a set of differences.
+ ///
+ /// Implements the getDiffs() method from DatabaseAccessor
+ ///
+ /// \exception NoSuchSerial if either of the versions do not exist in
+ /// the difference table.
+ /// \exception SQLite3Error if there is an sqlite3 error when performing
+ /// the query
+ ///
+ /// \param id The ID of the zone, returned from getZone().
+ /// \param start The SOA serial number of the version of the zone from
+ /// which the difference sequence should start.
+ /// \param end The SOA serial number of the version of the zone at which
+ /// the difference sequence should end.
+ ///
+ /// \return Iterator containing difference records.
virtual IteratorContextPtr
getDiffs(int id, uint32_t start, uint32_t end) const;
diff --git a/src/lib/datasrc/tests/sqlite3_accessor_unittest.cc b/src/lib/datasrc/tests/sqlite3_accessor_unittest.cc
index c490364..d45d672 100644
--- a/src/lib/datasrc/tests/sqlite3_accessor_unittest.cc
+++ b/src/lib/datasrc/tests/sqlite3_accessor_unittest.cc
@@ -675,11 +675,10 @@ TEST_F(SQLite3Create, addZone) {
new SQLite3Accessor(SQLITE_NEW_DBFILE, "IN"));
const std::string zone_name("example.com");
- const std::pair<bool, int> zone_info(accessor->getZone(zone_name));
- ASSERT_FALSE(zone_info.first);
+ EXPECT_FALSE(accessor->getZone(zone_name).first);
// Calling addZone without transaction should fail
- ASSERT_THROW(accessor->addZone(zone_name), DataSourceError);
+ EXPECT_THROW(accessor->addZone(zone_name), DataSourceError);
// Add the zone. Returns the new zone id
accessor->startTransaction();
@@ -687,17 +686,68 @@ TEST_F(SQLite3Create, addZone) {
accessor->commit();
// Check that it exists now, but has no records at this point
- const std::pair<bool, int> zone_info2(accessor->getZone(zone_name));
- ASSERT_TRUE(zone_info2.first);
- ASSERT_EQ(new_zone_id, zone_info2.second);
+ const std::pair<bool, int> zone_info(accessor->getZone(zone_name));
+ ASSERT_TRUE(zone_info.first);
+ EXPECT_EQ(new_zone_id, zone_info.second);
DatabaseAccessor::IteratorContextPtr context =
- accessor->getAllRecords(zone_info2.second);
+ accessor->getAllRecords(zone_info.second);
string data[DatabaseAccessor::COLUMN_COUNT];
- ASSERT_NE(DatabaseAccessor::IteratorContextPtr(), context);
+ EXPECT_NE(DatabaseAccessor::IteratorContextPtr(), context);
EXPECT_FALSE(context->getNext(data));
}
+// Test addZone does not get confused with different classes
+TEST_F(SQLite3Create, addZoneDifferentClass) {
+ const std::string zone_name("example.com.");
+
+ // Add IN zone
+ boost::shared_ptr<SQLite3Accessor> accessor(
+ new SQLite3Accessor(SQLITE_NEW_DBFILE, "IN"));
+ accessor->startTransaction();
+ const int new_zone_id_IN = accessor->addZone(zone_name);
+ accessor->commit();
+
+ // Add CH zone
+ accessor.reset(new SQLite3Accessor(SQLITE_NEW_DBFILE, "CH"));
+ accessor->startTransaction();
+ const int new_zone_id_CH = accessor->addZone(zone_name);
+ accessor->commit();
+
+ // id's should differ
+ ASSERT_NE(new_zone_id_IN, new_zone_id_CH);
+
+ // Reopen the database for both classes, and make sure
+ // we get the right zone id on searches
+ accessor.reset(new SQLite3Accessor(SQLITE_NEW_DBFILE, "IN"));
+ EXPECT_EQ(new_zone_id_IN, accessor->getZone(zone_name).second);
+ accessor.reset(new SQLite3Accessor(SQLITE_NEW_DBFILE, "CH"));
+ EXPECT_EQ(new_zone_id_CH, accessor->getZone(zone_name).second);
+}
+
+// Test addZone fails correctly if the entire db is locked
+TEST_F(SQLite3Create, addZoneWhileLocked) {
+ const std::string zone_name("example.com.");
+
+ boost::shared_ptr<SQLite3Accessor> accessor(
+ new SQLite3Accessor(SQLITE_NEW_DBFILE, "IN"));
+ accessor->startTransaction();
+
+ // Manually make an exclusive lock
+ sqlite3* db;
+ ASSERT_EQ(SQLITE_OK, sqlite3_open(SQLITE_NEW_DBFILE, &db));
+ sqlite3_exec(db, "BEGIN EXCLUSIVE TRANSACTION", NULL, NULL, NULL);
+
+ // addZone should throw exception that it is locket
+ ASSERT_THROW(accessor->addZone(zone_name), DataSourceError);
+
+ sqlite3_exec(db, "ROLLBACK TRANSACTION", NULL, NULL, NULL);
+
+ // Despite commit, zone should not exist
+ accessor->commit();
+ EXPECT_FALSE(accessor->getZone(zone_name).first);
+}
+
TEST_F(SQLite3Create, emptytest) {
ASSERT_FALSE(isReadable(SQLITE_NEW_DBFILE));
More information about the bind10-changes
mailing list