Commit 7980a6c8 authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

[1068] one missing point: have the DatabaseUpdater's destructor catch

catch exception in rollback explicitly.  added a test case for that.
parent 9c62a36b
......@@ -627,9 +627,20 @@ public:
virtual ~DatabaseUpdater() {
if (!committed_) {
try {
} 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 rollbackUpdateZone() 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.
......@@ -608,6 +608,19 @@ the changes. The intermediate changes made through the updater won't
be applied to the underlying database. The zone name, its class, and
the underlying database name are shown in the log message.
%DATASRC_DATABASE_UPDATER_ROLLBACKFAIL failed to roll back zone updates for '%1/%2' on %3: %4
A zone updater is being destroyed without committing the changes to
the database, and attempts to rollback incomplete updates, but it
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. The zone name, its class, and the
underlying database name as well as the error message thrown from the
database module are shown in the log message.
% 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,
......@@ -111,8 +111,7 @@ public:
void exec() {
if (sqlite3_step(dbparameters_.statements_[stmt_id_]) !=
if (sqlite3_step(dbparameters_.statements_[stmt_id_]) != SQLITE_DONE) {
isc_throw(DataSourceError, "failed to " << desc_ << ": " <<
......@@ -328,6 +328,13 @@ public:
*readonly_records_ = *update_records_;
virtual void rollbackUpdateZone() {
// Special hook: if something with a name of ""
// has been added, trigger an imaginary unexpected event with an
// exception.
if (update_records_->count("") > 0) {
isc_throw(DataSourceError, "unexpected failure in rollback");
rollbacked_ = true;
virtual void addRecordToZone(const string (&columns)[ADD_COLUMN_COUNT]) {
......@@ -1572,6 +1579,19 @@ TEST_F(DatabaseClientTest, updateCancel) {
EXPECT_EQ(ZoneFinder::SUCCESS, finder->find(qname_, qtype_).code);
TEST_F(DatabaseClientTest, exceptionFromRollback) {
updater_ = client_->getUpdater(zname_, true);
rrset_.reset(new RRset(Name(""), qclass_, qtype_,
rrset_->getClass(), ""));
// destruct without commit. The added name will result in an exception
// in the MockAccessor's rollback method. It shouldn't be propagated.
TEST_F(DatabaseClientTest, duplicateCommit) {
// duplicate commit. should result in exception.
updater_ = client_->getUpdater(zname_, true);
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment