lib: Add support for nested atomic sections.
authorAustin Clements <amdragon@mit.edu>
Sat, 11 Jun 2011 03:35:06 +0000 (23:35 -0400)
committerDavid Bremner <bremner@debian.org>
Sat, 24 Sep 2011 01:50:38 +0000 (21:50 -0400)
notmuch_database_t now keeps a nesting count and we only start a
transaction or commit for the outermost atomic section.

Introduces a new error, NOTMUCH_STATUS_UNBALANCED_ATOMIC.

lib/database-private.h
lib/database.cc
lib/notmuch.h
notmuch-new.c

index f7050097bbccc3054b8a42a536eff6756eb0072e..88532d511a8e395b7c5aa475ad7a403a6722777d 100644 (file)
@@ -43,6 +43,7 @@ struct _notmuch_database {
 
     notmuch_bool_t needs_upgrade;
     notmuch_database_mode_t mode;
+    int atomic_nesting;
     Xapian::Database *xapian_db;
 
     unsigned int last_doc_id;
index 48abbe8e7c72bf01e0e46b00c36b89775b29b942..92c3c4e0a7f03088f9a8337233fc35056605e9fc 100644 (file)
@@ -273,6 +273,8 @@ notmuch_status_to_string (notmuch_status_t status)
        return "Tag value is too long (exceeds NOTMUCH_TAG_MAX)";
     case NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW:
        return "Unbalanced number of calls to notmuch_message_freeze/thaw";
+    case NOTMUCH_STATUS_UNBALANCED_ATOMIC:
+       return "Unbalanced number of calls to notmuch_database_begin_atomic/end_atomic";
     default:
     case NOTMUCH_STATUS_LAST_STATUS:
        return "Unknown error status value";
@@ -611,6 +613,7 @@ notmuch_database_open (const char *path,
 
     notmuch->needs_upgrade = FALSE;
     notmuch->mode = mode;
+    notmuch->atomic_nesting = 0;
     try {
        string last_thread_id;
 
@@ -977,8 +980,9 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
 notmuch_status_t
 notmuch_database_begin_atomic (notmuch_database_t *notmuch)
 {
-    if (notmuch->mode == NOTMUCH_DATABASE_MODE_READ_ONLY)
-       return NOTMUCH_STATUS_SUCCESS;
+    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);
@@ -988,6 +992,9 @@ notmuch_database_begin_atomic (notmuch_database_t *notmuch)
        notmuch->exception_reported = TRUE;
        return NOTMUCH_STATUS_XAPIAN_EXCEPTION;
     }
+
+DONE:
+    notmuch->atomic_nesting++;
     return NOTMUCH_STATUS_SUCCESS;
 }
 
@@ -996,8 +1003,12 @@ notmuch_database_end_atomic (notmuch_database_t *notmuch)
 {
     Xapian::WritableDatabase *db;
 
-    if (notmuch->mode == NOTMUCH_DATABASE_MODE_READ_ONLY)
-       return NOTMUCH_STATUS_SUCCESS;
+    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 {
@@ -1015,6 +1026,9 @@ notmuch_database_end_atomic (notmuch_database_t *notmuch)
        notmuch->exception_reported = TRUE;
        return NOTMUCH_STATUS_XAPIAN_EXCEPTION;
     }
+
+DONE:
+    notmuch->atomic_nesting--;
     return NOTMUCH_STATUS_SUCCESS;
 }
 
index 0c306bb5ee2fd11e1ef576db367c6d97e2583c11..bfa2ced88a3f3893bc43b63ec495ce68fb41cd29 100644 (file)
@@ -81,6 +81,9 @@ typedef int notmuch_bool_t;
  * NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW: The notmuch_message_thaw
  *     function has been called more times than notmuch_message_freeze.
  *
+ * NOTMUCH_STATUS_UNBALANCED_ATOMIC: notmuch_database_end_atomic has
+ *     been called more times than notmuch_database_begin_atomic.
+ *
  * And finally:
  *
  * NOTMUCH_STATUS_LAST_STATUS: Not an actual status value. Just a way
@@ -97,6 +100,7 @@ typedef enum _notmuch_status {
     NOTMUCH_STATUS_NULL_POINTER,
     NOTMUCH_STATUS_TAG_TOO_LONG,
     NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW,
+    NOTMUCH_STATUS_UNBALANCED_ATOMIC,
 
     NOTMUCH_STATUS_LAST_STATUS
 } notmuch_status_t;
@@ -222,6 +226,9 @@ notmuch_database_upgrade (notmuch_database_t *database,
  * only ensures atomicity, not durability; neither begin nor end
  * necessarily flush modifications to disk.
  *
+ * Atomic sections may be nested.  begin_atomic and end_atomic must
+ * always be called in pairs.
+ *
  * Return value:
  *
  * NOTMUCH_STATUS_SUCCESS: Successfully entered atomic section.
@@ -240,6 +247,9 @@ notmuch_database_begin_atomic (notmuch_database_t *notmuch);
  *
  * NOTMUCH_STATUS_XAPIAN_EXCEPTION: A Xapian exception occurred;
  *     atomic section not ended.
+ *
+ * NOTMUCH_STATUS_UNBALANCED_ATOMIC: The database is not currently in
+ *     an atomic section.
  */
 notmuch_status_t
 notmuch_database_end_atomic (notmuch_database_t *notmuch);
index fb59d90c15f4646a9046cceab0bcecc661608ab3..82e2d3582a0fe85d51e02a7f766121b3b42d9190 100644 (file)
@@ -488,6 +488,7 @@ add_files_recursive (notmuch_database_t *notmuch,
        case NOTMUCH_STATUS_NULL_POINTER:
        case NOTMUCH_STATUS_TAG_TOO_LONG:
        case NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW:
+       case NOTMUCH_STATUS_UNBALANCED_ATOMIC:
        case NOTMUCH_STATUS_LAST_STATUS:
            INTERNAL_ERROR ("add_message returned unexpected value: %d",  status);
            goto DONE;