aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Austin Clements <amdragon@mit.edu>2014-10-02 15:19:08 -0400
committerGravatar David Bremner <david@tethera.net>2014-10-03 08:58:58 +0200
commitcec601c4dd94d19ce7e27804b6a2adbb9197824d (patch)
tree3e8229b040dc824e0c38d3fd0d9fcf396eb23a4c
parent0d597f6889fe29bf94658a1389b38c100154b72f (diff)
lib: Simplify close and codify aborting atomic section
In Xapian, closing a database implicitly aborts any outstanding transaction and commits changes. For historical reasons, notmuch_database_close had grown to almost, but not quite duplicate this behavior. Before closing the database, it would explicitly (and unnecessarily) commit it. However, if there was an outstanding transaction (ie atomic section), commit would throw a Xapian exception, which notmuch_database_close would unnecessarily print to stderr, even though notmuch_database_close would ultimately abort the transaction anyway when it called close. This patch simplifies notmuch_database_close to explicitly abort any outstanding transaction and then just call Database::close. This works for both read-only and read/write databases, takes care of committing changes, unifies the exception handling path, and codifies aborting outstanding transactions. This is currently the only way to abort an atomic section (and may remain so, since it would be difficult to roll back things we may have cached from rolled-back modifications).
-rw-r--r--lib/database.cc32
-rw-r--r--lib/notmuch.h9
2 files changed, 25 insertions, 16 deletions
diff --git a/lib/database.cc b/lib/database.cc
index a3a7cd30..a47a71d5 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -903,28 +903,30 @@ notmuch_database_close (notmuch_database_t *notmuch)
{
notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;
- try {
- if (notmuch->xapian_db != NULL &&
- notmuch->mode == NOTMUCH_DATABASE_MODE_READ_WRITE)
- (static_cast <Xapian::WritableDatabase *> (notmuch->xapian_db))->flush ();
- } catch (const Xapian::Error &error) {
- status = NOTMUCH_STATUS_XAPIAN_EXCEPTION;
- if (! notmuch->exception_reported) {
- fprintf (stderr, "Error: A Xapian exception occurred flushing database: %s\n",
- error.get_msg().c_str());
- }
- }
-
/* Many Xapian objects (and thus notmuch objects) hold references to
* the database, so merely deleting the database may not suffice to
* close it. Thus, we explicitly close it here. */
if (notmuch->xapian_db != NULL) {
try {
+ /* If there's an outstanding transaction, it's unclear if
+ * closing the Xapian database commits everything up to
+ * that transaction, or may discard committed (but
+ * unflushed) transactions. To be certain, explicitly
+ * cancel any outstanding transaction before closing. */
+ if (notmuch->mode == NOTMUCH_DATABASE_MODE_READ_WRITE &&
+ notmuch->atomic_nesting)
+ (static_cast <Xapian::WritableDatabase *> (notmuch->xapian_db))
+ ->cancel_transaction ();
+
+ /* Close the database. This implicitly flushes
+ * outstanding changes. */
notmuch->xapian_db->close();
} catch (const Xapian::Error &error) {
- /* don't clobber previous error status */
- if (status == NOTMUCH_STATUS_SUCCESS)
- status = NOTMUCH_STATUS_XAPIAN_EXCEPTION;
+ status = NOTMUCH_STATUS_XAPIAN_EXCEPTION;
+ if (! notmuch->exception_reported) {
+ fprintf (stderr, "Error: A Xapian exception occurred closing database: %s\n",
+ error.get_msg().c_str());
+ }
}
}
diff --git a/lib/notmuch.h b/lib/notmuch.h
index fe2340bb..dae04164 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -281,7 +281,7 @@ notmuch_database_open (const char *path,
notmuch_database_t **database);
/**
- * Close the given notmuch database.
+ * Commit changes and close the given notmuch database.
*
* After notmuch_database_close has been called, calls to other
* functions on objects derived from this database may either behave
@@ -292,6 +292,13 @@ notmuch_database_open (const char *path,
* notmuch_database_close can be called multiple times. Later calls
* have no effect.
*
+ * For writable databases, notmuch_database_close commits all changes
+ * to disk before closing the database. If the caller is currently in
+ * an atomic section (there was a notmuch_database_begin_atomic
+ * without a matching notmuch_database_end_atomic), this will discard
+ * changes made in that atomic section (but still commit changes made
+ * prior to entering the atomic section).
+ *
* Return value:
*
* NOTMUCH_STATUS_SUCCESS: Successfully closed the database.