+notmuch_status_t
+notmuch_database_begin_atomic (notmuch_database_t *notmuch)
+{
+ if (notmuch->mode == NOTMUCH_DATABASE_MODE_READ_ONLY ||
+ notmuch->atomic_nesting > 0)
+ goto DONE;
+
+ try {
+ (static_cast <Xapian::WritableDatabase *> (notmuch->xapian_db))->begin_transaction (false);
+ } catch (const Xapian::Error &error) {
+ fprintf (stderr, "A Xapian exception occurred beginning transaction: %s.\n",
+ error.get_msg().c_str());
+ notmuch->exception_reported = TRUE;
+ return NOTMUCH_STATUS_XAPIAN_EXCEPTION;
+ }
+
+DONE:
+ notmuch->atomic_nesting++;
+ return NOTMUCH_STATUS_SUCCESS;
+}
+
+notmuch_status_t
+notmuch_database_end_atomic (notmuch_database_t *notmuch)
+{
+ Xapian::WritableDatabase *db;
+
+ if (notmuch->atomic_nesting == 0)
+ return NOTMUCH_STATUS_UNBALANCED_ATOMIC;
+
+ if (notmuch->mode == NOTMUCH_DATABASE_MODE_READ_ONLY ||
+ notmuch->atomic_nesting > 1)
+ goto DONE;
+
+ db = static_cast <Xapian::WritableDatabase *> (notmuch->xapian_db);
+ try {
+ db->commit_transaction ();
+
+ /* This is a hack for testing. Xapian never flushes on a
+ * non-flushed commit, even if the flush threshold is 1.
+ * However, we rely on flushing to test atomicity. */
+ const char *thresh = getenv ("XAPIAN_FLUSH_THRESHOLD");
+ if (thresh && atoi (thresh) == 1)
+ db->flush ();
+ } catch (const Xapian::Error &error) {
+ fprintf (stderr, "A Xapian exception occurred committing transaction: %s.\n",
+ error.get_msg().c_str());
+ notmuch->exception_reported = TRUE;
+ return NOTMUCH_STATUS_XAPIAN_EXCEPTION;
+ }
+
+DONE:
+ notmuch->atomic_nesting--;
+ return NOTMUCH_STATUS_SUCCESS;
+}
+