lib: Add support for nested atomic sections.

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.
This commit is contained in:
Austin Clements 2011-06-10 23:35:06 -04:00 committed by David Bremner
parent 957f1ba3fc
commit e59cc0031f
4 changed files with 30 additions and 4 deletions

View file

@ -43,6 +43,7 @@ struct _notmuch_database {
notmuch_bool_t needs_upgrade; notmuch_bool_t needs_upgrade;
notmuch_database_mode_t mode; notmuch_database_mode_t mode;
int atomic_nesting;
Xapian::Database *xapian_db; Xapian::Database *xapian_db;
unsigned int last_doc_id; unsigned int last_doc_id;

View file

@ -273,6 +273,8 @@ notmuch_status_to_string (notmuch_status_t status)
return "Tag value is too long (exceeds NOTMUCH_TAG_MAX)"; return "Tag value is too long (exceeds NOTMUCH_TAG_MAX)";
case NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW: case NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW:
return "Unbalanced number of calls to notmuch_message_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: default:
case NOTMUCH_STATUS_LAST_STATUS: case NOTMUCH_STATUS_LAST_STATUS:
return "Unknown error status value"; return "Unknown error status value";
@ -611,6 +613,7 @@ notmuch_database_open (const char *path,
notmuch->needs_upgrade = FALSE; notmuch->needs_upgrade = FALSE;
notmuch->mode = mode; notmuch->mode = mode;
notmuch->atomic_nesting = 0;
try { try {
string last_thread_id; string last_thread_id;
@ -977,8 +980,9 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
notmuch_status_t notmuch_status_t
notmuch_database_begin_atomic (notmuch_database_t *notmuch) notmuch_database_begin_atomic (notmuch_database_t *notmuch)
{ {
if (notmuch->mode == NOTMUCH_DATABASE_MODE_READ_ONLY) if (notmuch->mode == NOTMUCH_DATABASE_MODE_READ_ONLY ||
return NOTMUCH_STATUS_SUCCESS; notmuch->atomic_nesting > 0)
goto DONE;
try { try {
(static_cast <Xapian::WritableDatabase *> (notmuch->xapian_db))->begin_transaction (false); (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; notmuch->exception_reported = TRUE;
return NOTMUCH_STATUS_XAPIAN_EXCEPTION; return NOTMUCH_STATUS_XAPIAN_EXCEPTION;
} }
DONE:
notmuch->atomic_nesting++;
return NOTMUCH_STATUS_SUCCESS; return NOTMUCH_STATUS_SUCCESS;
} }
@ -996,8 +1003,12 @@ notmuch_database_end_atomic (notmuch_database_t *notmuch)
{ {
Xapian::WritableDatabase *db; Xapian::WritableDatabase *db;
if (notmuch->mode == NOTMUCH_DATABASE_MODE_READ_ONLY) if (notmuch->atomic_nesting == 0)
return NOTMUCH_STATUS_SUCCESS; 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); db = static_cast <Xapian::WritableDatabase *> (notmuch->xapian_db);
try { try {
@ -1015,6 +1026,9 @@ notmuch_database_end_atomic (notmuch_database_t *notmuch)
notmuch->exception_reported = TRUE; notmuch->exception_reported = TRUE;
return NOTMUCH_STATUS_XAPIAN_EXCEPTION; return NOTMUCH_STATUS_XAPIAN_EXCEPTION;
} }
DONE:
notmuch->atomic_nesting--;
return NOTMUCH_STATUS_SUCCESS; return NOTMUCH_STATUS_SUCCESS;
} }

View file

@ -81,6 +81,9 @@ typedef int notmuch_bool_t;
* NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW: The notmuch_message_thaw * NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW: The notmuch_message_thaw
* function has been called more times than notmuch_message_freeze. * 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: * And finally:
* *
* NOTMUCH_STATUS_LAST_STATUS: Not an actual status value. Just a way * 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_NULL_POINTER,
NOTMUCH_STATUS_TAG_TOO_LONG, NOTMUCH_STATUS_TAG_TOO_LONG,
NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW, NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW,
NOTMUCH_STATUS_UNBALANCED_ATOMIC,
NOTMUCH_STATUS_LAST_STATUS NOTMUCH_STATUS_LAST_STATUS
} notmuch_status_t; } notmuch_status_t;
@ -222,6 +226,9 @@ notmuch_database_upgrade (notmuch_database_t *database,
* only ensures atomicity, not durability; neither begin nor end * only ensures atomicity, not durability; neither begin nor end
* necessarily flush modifications to disk. * necessarily flush modifications to disk.
* *
* Atomic sections may be nested. begin_atomic and end_atomic must
* always be called in pairs.
*
* Return value: * Return value:
* *
* NOTMUCH_STATUS_SUCCESS: Successfully entered atomic section. * 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; * NOTMUCH_STATUS_XAPIAN_EXCEPTION: A Xapian exception occurred;
* atomic section not ended. * atomic section not ended.
*
* NOTMUCH_STATUS_UNBALANCED_ATOMIC: The database is not currently in
* an atomic section.
*/ */
notmuch_status_t notmuch_status_t
notmuch_database_end_atomic (notmuch_database_t *notmuch); notmuch_database_end_atomic (notmuch_database_t *notmuch);

View file

@ -488,6 +488,7 @@ add_files_recursive (notmuch_database_t *notmuch,
case NOTMUCH_STATUS_NULL_POINTER: case NOTMUCH_STATUS_NULL_POINTER:
case NOTMUCH_STATUS_TAG_TOO_LONG: case NOTMUCH_STATUS_TAG_TOO_LONG:
case NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW: case NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW:
case NOTMUCH_STATUS_UNBALANCED_ATOMIC:
case NOTMUCH_STATUS_LAST_STATUS: case NOTMUCH_STATUS_LAST_STATUS:
INTERNAL_ERROR ("add_message returned unexpected value: %d", status); INTERNAL_ERROR ("add_message returned unexpected value: %d", status);
goto DONE; goto DONE;