* [PATCH 1/2] lib: Replace freeze/thaw functionality with single sync function
2012-12-11 6:54 [PATCH 0/2] lib: Allow read-only messages to be synchronized to a writable database Michael Forney
@ 2012-12-11 6:54 ` Michael Forney
2012-12-11 6:54 ` [PATCH 2/2] lib: Allow synchronizing message changes with a separate database connection Michael Forney
2012-12-12 2:19 ` [PATCH 0/2] lib: Allow read-only messages to be synchronized to a writable database Jameson Graef Rollins
2 siblings, 0 replies; 4+ messages in thread
From: Michael Forney @ 2012-12-11 6:54 UTC (permalink / raw)
To: notmuch
In all cases I could find, message tags were being modified with
freeze/thaw. This commit changes the default operation of
notmuch_message_{add_tag,remove_tag,remove_all_tags} to *not* commit
changes until notmuch_message_sync is called.
---
bindings/go/src/notmuch/notmuch.go | 69 ++++------------
bindings/python/docs/source/message.rst | 4 +-
bindings/python/notmuch/__init__.py | 1 -
bindings/python/notmuch/errors.py | 7 --
bindings/python/notmuch/message.py | 139 ++++++++------------------------
bindings/ruby/defs.h | 6 +-
bindings/ruby/init.c | 12 +--
bindings/ruby/message.c | 27 +------
bindings/ruby/status.c | 2 -
contrib/notmuch-deliver/src/main.c | 10 +++
lib/database.cc | 14 ++--
lib/message.cc | 92 +++++----------------
lib/notmuch-private.h | 7 +-
lib/notmuch.h | 87 ++++++--------------
notmuch-new.c | 4 +-
notmuch-tag.c | 4 +-
tag-util.c | 10 +--
17 files changed, 123 insertions(+), 372 deletions(-)
diff --git a/bindings/go/src/notmuch/notmuch.go b/bindings/go/src/notmuch/notmuch.go
index 00bd53a..56eb710 100644
--- a/bindings/go/src/notmuch/notmuch.go
+++ b/bindings/go/src/notmuch/notmuch.go
@@ -26,7 +26,6 @@ const (
STATUS_DUPLICATE_MESSAGE_ID
STATUS_NULL_POINTER
STATUS_TAG_TOO_LONG
- STATUS_UNBALANCED_FREEZE_THAW
STATUS_UNBALANCED_ATOMIC
STATUS_LAST_STATUS
@@ -926,7 +925,7 @@ func (self *Message) RemoveTag(tag string) Status {
/* Remove all tags from the given message.
*
- * See notmuch_message_freeze for an example showing how to safely
+ * See notmuch_message_sync for an example showing how to safely
* replace tag values.
*
* NOTMUCH_STATUS_READ_ONLY_DATABASE: Database was opened in read-only
@@ -939,79 +938,39 @@ func (self *Message) RemoveAllTags() Status {
return Status(C.notmuch_message_remove_all_tags(self.message))
}
-/* Freeze the current state of 'message' within the database.
+/* Synchronize the current state of 'message' into the database.
*
- * This means that changes to the message state, (via
+ * This will commit any changes made to the message state, (via
* notmuch_message_add_tag, notmuch_message_remove_tag, and
- * notmuch_message_remove_all_tags), will not be committed to the
- * database until the message is thawed with notmuch_message_thaw.
+ * notmuch_message_remove_all_tags), to the database.
*
- * Multiple calls to freeze/thaw are valid and these calls will
- * "stack". That is there must be as many calls to thaw as to freeze
- * before a message is actually thawed.
- *
- * The ability to do freeze/thaw allows for safe transactions to
- * change tag values. For example, explicitly setting a message to
- * have a given set of tags might look like this:
- *
- * notmuch_message_freeze (message);
+ * If this method succeeds, the message in the database is guaranteed to
+ * have the full set of changes made to the message committed to the
+ * database. For example, explicitly setting a message to have a given
+ * set of tags might look like this:
*
* notmuch_message_remove_all_tags (message);
*
* for (i = 0; i < NUM_TAGS; i++)
* notmuch_message_add_tag (message, tags[i]);
*
- * notmuch_message_thaw (message);
+ * notmuch_message_sync (message);
*
- * With freeze/thaw used like this, the message in the database is
- * guaranteed to have either the full set of original tag values, or
- * the full set of new tag values, but nothing in between.
- *
- * Imagine the example above without freeze/thaw and the operation
- * somehow getting interrupted. This could result in the message being
- * left with no tags if the interruption happened after
- * notmuch_message_remove_all_tags but before notmuch_message_add_tag.
+ * This method only works if the database associated with 'message' was
+ * opened in read-write mode.
*
* Return value:
*
- * NOTMUCH_STATUS_SUCCESS: Message successfully frozen.
+ * NOTMUCH_STATUS_SUCCESS: Message successfully synchronized.
*
* NOTMUCH_STATUS_READ_ONLY_DATABASE: Database was opened in read-only
* mode so message cannot be modified.
*/
-func (self *Message) Freeze() Status {
- if self.message == nil {
- return STATUS_NULL_POINTER
- }
- return Status(C.notmuch_message_freeze(self.message))
-}
-
-/* Thaw the current 'message', synchronizing any changes that may have
- * occurred while 'message' was frozen into the notmuch database.
- *
- * See notmuch_message_freeze for an example of how to use this
- * function to safely provide tag changes.
- *
- * Multiple calls to freeze/thaw are valid and these calls with
- * "stack". That is there must be as many calls to thaw as to freeze
- * before a message is actually thawed.
- *
- * Return value:
- *
- * NOTMUCH_STATUS_SUCCESS: Message successfully thawed, (or at least
- * its frozen count has successfully been reduced by 1).
- *
- * NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW: An attempt was made to thaw
- * an unfrozen message. That is, there have been an unbalanced
- * number of calls to notmuch_message_freeze and
- * notmuch_message_thaw.
- */
-func (self *Message) Thaw() Status {
+func (self *Message) Sync() Status {
if self.message == nil {
return STATUS_NULL_POINTER
}
-
- return Status(C.notmuch_message_thaw(self.message))
+ return Status(C.notmuch_message_sync(self.message))
}
/* Destroy a notmuch_message_t object.
diff --git a/bindings/python/docs/source/message.rst b/bindings/python/docs/source/message.rst
index 1a6cc3d..d3ada71 100644
--- a/bindings/python/docs/source/message.rst
+++ b/bindings/python/docs/source/message.rst
@@ -43,8 +43,6 @@
.. automethod:: remove_all_tags
- .. automethod:: freeze
-
- .. automethod:: thaw
+ .. automethod:: sync
.. automethod:: __str__
diff --git a/bindings/python/notmuch/__init__.py b/bindings/python/notmuch/__init__.py
index 5561624..edd7cbd 100644
--- a/bindings/python/notmuch/__init__.py
+++ b/bindings/python/notmuch/__init__.py
@@ -72,7 +72,6 @@ from .errors import (
DuplicateMessageIdError,
NullPointerError,
TagTooLongError,
- UnbalancedFreezeThawError,
UnbalancedAtomicError,
NotInitializedError,
)
diff --git a/bindings/python/notmuch/errors.py b/bindings/python/notmuch/errors.py
index f153a9c..cb748d6 100644
--- a/bindings/python/notmuch/errors.py
+++ b/bindings/python/notmuch/errors.py
@@ -54,7 +54,6 @@ STATUS = Status(['SUCCESS',
'DUPLICATE_MESSAGE_ID',
'NULL_POINTER',
'TAG_TOO_LONG',
- 'UNBALANCED_FREEZE_THAW',
'UNBALANCED_ATOMIC',
'NOT_INITIALIZED'])
"""STATUS is a class, whose attributes provide constants that serve as return
@@ -71,7 +70,6 @@ description.
* DUPLICATE_MESSAGE_ID
* NULL_POINTER
* TAG_TOO_LONG
- * UNBALANCED_FREEZE_THAW
* UNBALANCED_ATOMIC
* NOT_INITIALIZED
@@ -99,7 +97,6 @@ class NotmuchError(Exception, Python3StringMixIn):
STATUS.DUPLICATE_MESSAGE_ID: DuplicateMessageIdError,
STATUS.NULL_POINTER: NullPointerError,
STATUS.TAG_TOO_LONG: TagTooLongError,
- STATUS.UNBALANCED_FREEZE_THAW: UnbalancedFreezeThawError,
STATUS.UNBALANCED_ATOMIC: UnbalancedAtomicError,
STATUS.NOT_INITIALIZED: NotInitializedError,
}
@@ -167,10 +164,6 @@ class TagTooLongError(NotmuchError):
status = STATUS.TAG_TOO_LONG
-class UnbalancedFreezeThawError(NotmuchError):
- status = STATUS.UNBALANCED_FREEZE_THAW
-
-
class UnbalancedAtomicError(NotmuchError):
status = STATUS.UNBALANCED_ATOMIC
diff --git a/bindings/python/notmuch/message.py b/bindings/python/notmuch/message.py
index d1c1b58..600c01e 100644
--- a/bindings/python/notmuch/message.py
+++ b/bindings/python/notmuch/message.py
@@ -308,7 +308,7 @@ class Message(Python3StringMixIn):
_add_tag.argtypes = [NotmuchMessageP, c_char_p]
_add_tag.restype = c_uint
- def add_tag(self, tag, sync_maildir_flags=False):
+ def add_tag(self, tag):
"""Adds a tag to the given message
Adds a tag to the current message. The maximal tag length is defined in
@@ -316,14 +316,6 @@ class Message(Python3StringMixIn):
:param tag: String with a 'tag' to be added.
- :param sync_maildir_flags: If notmuch configuration is set to do
- this, add maildir flags corresponding to notmuch tags. See
- underlying method :meth:`tags_to_maildir_flags`. Use False
- if you want to add/remove many tags on a message without
- having to physically rename the file every time. Do note,
- that this will do nothing when a message is frozen, as tag
- changes will not be committed to the database yet.
-
:returns: STATUS.SUCCESS if the tag was successfully added.
Raises an exception otherwise.
:raises: :exc:`NullPointerError` if the `tag` argument is NULL
@@ -342,29 +334,19 @@ class Message(Python3StringMixIn):
# bail out on failure
if status != STATUS.SUCCESS:
raise NotmuchError(status)
-
- if sync_maildir_flags:
- self.tags_to_maildir_flags()
return STATUS.SUCCESS
_remove_tag = nmlib.notmuch_message_remove_tag
_remove_tag.argtypes = [NotmuchMessageP, c_char_p]
_remove_tag.restype = c_uint
- def remove_tag(self, tag, sync_maildir_flags=False):
+ def remove_tag(self, tag):
"""Removes a tag from the given message
If the message has no such tag, this is a non-operation and
will report success anyway.
:param tag: String with a 'tag' to be removed.
- :param sync_maildir_flags: If notmuch configuration is set to do
- this, add maildir flags corresponding to notmuch tags. See
- underlying method :meth:`tags_to_maildir_flags`. Use False
- if you want to add/remove many tags on a message without
- having to physically rename the file every time. Do note,
- that this will do nothing when a message is frozen, as tag
- changes will not be committed to the database yet.
:returns: STATUS.SUCCESS if the tag was successfully removed or if
the message had no such tag.
@@ -385,29 +367,18 @@ class Message(Python3StringMixIn):
if status != STATUS.SUCCESS:
raise NotmuchError(status)
- if sync_maildir_flags:
- self.tags_to_maildir_flags()
return STATUS.SUCCESS
_remove_all_tags = nmlib.notmuch_message_remove_all_tags
_remove_all_tags.argtypes = [NotmuchMessageP]
_remove_all_tags.restype = c_uint
- def remove_all_tags(self, sync_maildir_flags=False):
+ def remove_all_tags(self):
"""Removes all tags from the given message.
- See :meth:`freeze` for an example showing how to safely
+ See :meth:`sync` for an example showing how to safely
replace tag values.
-
- :param sync_maildir_flags: If notmuch configuration is set to do
- this, add maildir flags corresponding to notmuch tags. See
- :meth:`tags_to_maildir_flags`. Use False if you want to
- add/remove many tags on a message without having to
- physically rename the file every time. Do note, that this
- will do nothing when a message is frozen, as tag changes
- will not be committed to the database yet.
-
:returns: STATUS.SUCCESS if the tags were successfully removed.
Raises an exception otherwise.
:raises: :exc:`ReadOnlyDatabaseError` if the database was opened
@@ -424,46 +395,40 @@ class Message(Python3StringMixIn):
if status != STATUS.SUCCESS:
raise NotmuchError(status)
- if sync_maildir_flags:
- self.tags_to_maildir_flags()
return STATUS.SUCCESS
- _freeze = nmlib.notmuch_message_freeze
- _freeze.argtypes = [NotmuchMessageP]
- _freeze.restype = c_uint
-
- def freeze(self):
- """Freezes the current state of 'message' within the database
+ _sync = nmlib.notmuch_message_sync
+ _sync.argtypes = [NotmuchMessageP]
+ _sync.restype = c_uint
- This means that changes to the message state, (via :meth:`add_tag`,
- :meth:`remove_tag`, and :meth:`remove_all_tags`), will not be
- committed to the database until the message is :meth:`thaw` ed.
+ def sync(self, sync_maildir_flags=False):
+ """Synchronize the current state of 'message' into the database.
- Multiple calls to freeze/thaw are valid and these calls will
- "stack". That is there must be as many calls to thaw as to freeze
- before a message is actually thawed.
+ This will commit any changes made to the message state, (via
+ :meth:`add_tag`, :meth:`remove_tag`, and :meth:`remove_all_tags`), to
+ the database.
- The ability to do freeze/thaw allows for safe transactions to
- change tag values. For example, explicitly setting a message to
- have a given set of tags might look like this::
+ If this method succeeds, the message in the database is guaranteed to
+ have the full set of changes made to the message committed to the
+ database. For example, explicitly setting a message to have a given set
+ of tags might look like this:
- msg.freeze()
msg.remove_all_tags(False)
for tag in new_tags:
msg.add_tag(tag, False)
- msg.thaw()
+ msg.sync()
msg.tags_to_maildir_flags()
- With freeze/thaw used like this, the message in the database is
- guaranteed to have either the full set of original tag values, or
- the full set of new tag values, but nothing in between.
+ This method only works if the database associated with 'message' was
+ opened with NOTMUCH_DATABASE_MODE_READ_WRITE.
- Imagine the example above without freeze/thaw and the operation
- somehow getting interrupted. This could result in the message being
- left with no tags if the interruption happened after
- :meth:`remove_all_tags` but before :meth:`add_tag`.
+ :param sync_maildir_flags: If notmuch configuration is set to do
+ this, add maildir flags corresponding to notmuch tags. See
+ :meth:`tags_to_maildir_flags`. Use False if you want to
+ add/remove many tags on a message without having to
+ physically rename the file every time.
- :returns: STATUS.SUCCESS if the message was successfully frozen.
+ :returns: STATUS.SUCCESS if the message was successfully synchronized.
Raises an exception otherwise.
:raises: :exc:`ReadOnlyDatabaseError` if the database was opened
in read-only mode so message cannot be modified
@@ -473,50 +438,14 @@ class Message(Python3StringMixIn):
if not self._msg:
raise NotInitializedError()
- status = self._freeze(self._msg)
-
- if STATUS.SUCCESS == status:
- # return on success
- return status
-
- raise NotmuchError(status)
-
- _thaw = nmlib.notmuch_message_thaw
- _thaw.argtypes = [NotmuchMessageP]
- _thaw.restype = c_uint
-
- def thaw(self):
- """Thaws the current 'message'
+ status = self._sync(self._msg)
- Thaw the current 'message', synchronizing any changes that may have
- occurred while 'message' was frozen into the notmuch database.
-
- See :meth:`freeze` for an example of how to use this
- function to safely provide tag changes.
-
- Multiple calls to freeze/thaw are valid and these calls with
- "stack". That is there must be as many calls to thaw as to freeze
- before a message is actually thawed.
-
- :returns: STATUS.SUCCESS if the message was successfully frozen.
- Raises an exception otherwise.
- :raises: :exc:`UnbalancedFreezeThawError` if an attempt was made
- to thaw an unfrozen message. That is, there have been
- an unbalanced number of calls to :meth:`freeze` and
- :meth:`thaw`.
- :raises: :exc:`NotInitializedError` if message has not been
- initialized
- """
- if not self._msg:
- raise NotInitializedError()
-
- status = self._thaw(self._msg)
-
- if STATUS.SUCCESS == status:
- # return on success
- return status
+ if status != STATUS.SUCCESS:
+ raise NotmuchError(status)
- raise NotmuchError(status)
+ if sync_maildir_flags:
+ self.tags_to_maildir_flags()
+ raise STATUS.SUCCESS
def is_match(self):
"""(Not implemented)"""
@@ -537,9 +466,9 @@ class Message(Python3StringMixIn):
Also, if this filename is in a directory named "new", rename it
to be within the neighboring directory named "cur".
- Do note that calling this method while a message is frozen might
- not work yet, as the modified tags have not been committed yet
- to the database.
+ Do note that calling this method before :meth:`sync` is called
+ might not work yet, as the modified tags have not been committed
+ yet to the database.
:returns: a :class:`STATUS` value. In short, you want to see
notmuch.STATUS.SUCCESS here. See there for details."""
diff --git a/bindings/ruby/defs.h b/bindings/ruby/defs.h
index fe81b3f..de36936 100644
--- a/bindings/ruby/defs.h
+++ b/bindings/ruby/defs.h
@@ -43,7 +43,6 @@ extern VALUE notmuch_rb_eFileError;
extern VALUE notmuch_rb_eFileNotEmailError;
extern VALUE notmuch_rb_eNullPointerError;
extern VALUE notmuch_rb_eTagTooLongError;
-extern VALUE notmuch_rb_eUnbalancedFreezeThawError;
extern VALUE notmuch_rb_eUnbalancedAtomicError;
extern ID ID_call;
@@ -329,10 +328,7 @@ VALUE
notmuch_rb_message_tags_to_maildir_flags (VALUE self);
VALUE
-notmuch_rb_message_freeze (VALUE self);
-
-VALUE
-notmuch_rb_message_thaw (VALUE self);
+notmuch_rb_message_sync (VALUE self);
/* tags.c */
VALUE
diff --git a/bindings/ruby/init.c b/bindings/ruby/init.c
index f4931d3..b7a7456 100644
--- a/bindings/ruby/init.c
+++ b/bindings/ruby/init.c
@@ -39,7 +39,6 @@ VALUE notmuch_rb_eFileError;
VALUE notmuch_rb_eFileNotEmailError;
VALUE notmuch_rb_eNullPointerError;
VALUE notmuch_rb_eTagTooLongError;
-VALUE notmuch_rb_eUnbalancedFreezeThawError;
VALUE notmuch_rb_eUnbalancedAtomicError;
ID ID_call;
@@ -191,14 +190,6 @@ Init_notmuch (void)
*/
notmuch_rb_eTagTooLongError = rb_define_class_under (mod, "TagTooLongError", notmuch_rb_eBaseError);
/*
- * Document-class: Notmuch::UnbalancedFreezeThawError
- *
- * Raised when the notmuch_message_thaw function has been called more times
- * than notmuch_message_freeze.
- */
- notmuch_rb_eUnbalancedFreezeThawError = rb_define_class_under (mod, "UnbalancedFreezeThawError",
- notmuch_rb_eBaseError);
- /*
* Document-class: Notmuch::UnbalancedAtomicError
*
* Raised when notmuch_database_end_atomic has been called more times than
@@ -338,8 +329,7 @@ Init_notmuch (void)
rb_define_method (notmuch_rb_cMessage, "remove_all_tags", notmuch_rb_message_remove_all_tags, 0); /* in message.c */
rb_define_method (notmuch_rb_cMessage, "maildir_flags_to_tags", notmuch_rb_message_maildir_flags_to_tags, 0); /* in message.c */
rb_define_method (notmuch_rb_cMessage, "tags_to_maildir_flags", notmuch_rb_message_tags_to_maildir_flags, 0); /* in message.c */
- rb_define_method (notmuch_rb_cMessage, "freeze", notmuch_rb_message_freeze, 0); /* in message.c */
- rb_define_method (notmuch_rb_cMessage, "thaw", notmuch_rb_message_thaw, 0); /* in message.c */
+ rb_define_method (notmuch_rb_cMessage, "sync", notmuch_rb_message_sync, 0); /* in message.c */
/*
* Document-class: Notmuch::Tags
diff --git a/bindings/ruby/message.c b/bindings/ruby/message.c
index eed4b31..719ca16 100644
--- a/bindings/ruby/message.c
+++ b/bindings/ruby/message.c
@@ -328,38 +328,19 @@ notmuch_rb_message_tags_to_maildir_flags (VALUE self)
}
/*
- * call-seq: MESSAGE.freeze => true
+ * call-seq: MESSAGE.sync => true
*
- * Freeze the 'message'
+ * Sync the 'message' to the database
*/
VALUE
-notmuch_rb_message_freeze (VALUE self)
+notmuch_rb_message_sync (VALUE self)
{
notmuch_status_t ret;
notmuch_message_t *message;
Data_Get_Notmuch_Message (self, message);
- ret = notmuch_message_freeze (message);
- notmuch_rb_status_raise (ret);
-
- return Qtrue;
-}
-
-/*
- * call-seq: MESSAGE.thaw => true
- *
- * Thaw a 'message'
- */
-VALUE
-notmuch_rb_message_thaw (VALUE self)
-{
- notmuch_status_t ret;
- notmuch_message_t *message;
-
- Data_Get_Notmuch_Message (self, message);
-
- ret = notmuch_message_thaw (message);
+ ret = notmuch_message_sync (message);
notmuch_rb_status_raise (ret);
return Qtrue;
diff --git a/bindings/ruby/status.c b/bindings/ruby/status.c
index b11fb9f..8d1390a 100644
--- a/bindings/ruby/status.c
+++ b/bindings/ruby/status.c
@@ -41,8 +41,6 @@ notmuch_rb_status_raise (notmuch_status_t status)
rb_raise (notmuch_rb_eNullPointerError, "null pointer");
case NOTMUCH_STATUS_TAG_TOO_LONG:
rb_raise (notmuch_rb_eTagTooLongError, "tag too long");
- case NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW:
- rb_raise (notmuch_rb_eUnbalancedFreezeThawError, "unbalanced freeze/thaw");
case NOTMUCH_STATUS_UNBALANCED_ATOMIC:
rb_raise (notmuch_rb_eUnbalancedAtomicError, "unbalanced atomic");
default:
diff --git a/contrib/notmuch-deliver/src/main.c b/contrib/notmuch-deliver/src/main.c
index 032b9d6..afe84ff 100644
--- a/contrib/notmuch-deliver/src/main.c
+++ b/contrib/notmuch-deliver/src/main.c
@@ -300,6 +300,11 @@ add_tags(notmuch_message_t *message, char **tags)
tags[i], notmuch_status_to_string(ret));
}
+ ret = notmuch_message_sync(message);
+ if (ret != NOTMUCH_STATUS_SUCCESS)
+ g_warning("Failed to sync changes to database: %s",
+ notmuch_status_to_string(ret));
+
return i;
}
@@ -319,6 +324,11 @@ rm_tags(notmuch_message_t *message, char **tags)
tags[i], notmuch_status_to_string(ret));
}
+ ret = notmuch_message_sync(message);
+ if (ret != NOTMUCH_STATUS_SUCCESS)
+ g_warning("Failed to sync changes to database: %s",
+ notmuch_status_to_string(ret));
+
return i;
}
diff --git a/lib/database.cc b/lib/database.cc
index 91d4329..98ea789 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -264,8 +264,6 @@ notmuch_status_to_string (notmuch_status_t status)
return "Erroneous NULL pointer";
case NOTMUCH_STATUS_TAG_TOO_LONG:
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:
@@ -917,7 +915,7 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
filename = _notmuch_message_talloc_copy_data (message);
if (filename && *filename != '\0') {
_notmuch_message_add_filename (message, filename);
- _notmuch_message_sync (message);
+ notmuch_message_sync (message);
}
talloc_free (filename);
@@ -993,7 +991,7 @@ notmuch_database_upgrade (notmuch_database_t *notmuch,
filename = _notmuch_message_talloc_copy_data (message);
if (filename && *filename != '\0') {
_notmuch_message_clear_data (message);
- _notmuch_message_sync (message);
+ notmuch_message_sync (message);
}
talloc_free (filename);
@@ -1483,7 +1481,7 @@ _merge_threads (notmuch_database_t *notmuch,
_notmuch_message_remove_term (message, "thread", loser_thread_id);
_notmuch_message_add_term (message, "thread", winner_thread_id);
- _notmuch_message_sync (message);
+ notmuch_message_sync (message);
notmuch_message_destroy (message);
message = NULL;
@@ -1601,7 +1599,7 @@ _notmuch_database_link_message_to_children (notmuch_database_t *notmuch,
} else if (strcmp (*thread_id, child_thread_id)) {
_notmuch_message_remove_term (child_message, "reference",
message_id);
- _notmuch_message_sync (child_message);
+ notmuch_message_sync (child_message);
ret = _merge_threads (notmuch, *thread_id, child_thread_id);
if (ret)
goto DONE;
@@ -1828,7 +1826,7 @@ notmuch_database_add_message (notmuch_database_t *notmuch,
ret = NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID;
}
- _notmuch_message_sync (message);
+ notmuch_message_sync (message);
} catch (const Xapian::Error &error) {
fprintf (stderr, "A Xapian exception occurred adding message: %s.\n",
error.get_msg().c_str());
@@ -1873,7 +1871,7 @@ notmuch_database_remove_message (notmuch_database_t *notmuch,
if (status == NOTMUCH_STATUS_SUCCESS)
_notmuch_message_delete (message);
else if (status == NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID)
- _notmuch_message_sync (message);
+ notmuch_message_sync (message);
notmuch_message_destroy (message);
}
diff --git a/lib/message.cc b/lib/message.cc
index 320901f..b7e4bbe 100644
--- a/lib/message.cc
+++ b/lib/message.cc
@@ -28,7 +28,6 @@
struct visible _notmuch_message {
notmuch_database_t *notmuch;
Xapian::docid doc_id;
- int frozen;
char *message_id;
char *thread_id;
char *in_reply_to;
@@ -97,7 +96,6 @@ _notmuch_message_create_for_document (const void *talloc_owner,
message->notmuch = notmuch;
message->doc_id = doc_id;
- message->frozen = 0;
message->flags = 0;
/* Each of these will be lazily created as needed. */
@@ -199,7 +197,7 @@ _notmuch_message_create (const void *talloc_owner,
* returned message contains a newly created document (not yet
* added to the database) and a document ID that is known not to
* exist in the database. The caller can modify the message, and a
- * call to _notmuch_message_sync will add * the document to the
+ * call to notmuch_message_sync will add the document to the
* database.
*
* If an error occurs, this function will return NULL and *status
@@ -476,7 +474,7 @@ notmuch_message_get_replies (notmuch_message_t *message)
/* Add an additional 'filename' for 'message'.
*
* This change will not be reflected in the database until the next
- * call to _notmuch_message_sync. */
+ * call to notmuch_message_sync. */
notmuch_status_t
_notmuch_message_add_filename (notmuch_message_t *message,
const char *filename)
@@ -515,7 +513,7 @@ _notmuch_message_add_filename (notmuch_message_t *message,
/* Remove a particular 'filename' from 'message'.
*
* This change will not be reflected in the database until the next
- * call to _notmuch_message_sync.
+ * call to notmuch_message_sync.
*
* If this message still has other filenames, returns
* NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID.
@@ -831,17 +829,22 @@ _notmuch_message_set_header_values (notmuch_message_t *message,
message->doc.add_value (NOTMUCH_VALUE_SUBJECT, subject);
}
-/* Synchronize changes made to message->doc out into the database. */
-void
-_notmuch_message_sync (notmuch_message_t *message)
+/* Synchronize changes made to message->doc into the given database. */
+notmuch_status_t
+_notmuch_message_sync_to_database (notmuch_message_t *message,
+ notmuch_database_t *notmuch)
{
+ notmuch_status_t status;
Xapian::WritableDatabase *db;
- if (message->notmuch->mode == NOTMUCH_DATABASE_MODE_READ_ONLY)
- return;
+ status = _notmuch_database_ensure_writable(notmuch);
+ if (status)
+ return status;
- db = static_cast <Xapian::WritableDatabase *> (message->notmuch->xapian_db);
+ db = static_cast <Xapian::WritableDatabase *> (notmuch->xapian_db);
db->replace_document (message->doc_id, message->doc);
+
+ return NOTMUCH_STATUS_SUCCESS;
}
/* Delete a message document from the database. */
@@ -879,7 +882,7 @@ _notmuch_message_close (notmuch_message_t *message)
* names to prefix values.
*
* This change will not be reflected in the database until the next
- * call to _notmuch_message_sync. */
+ * call to notmuch_message_sync. */
notmuch_private_status_t
_notmuch_message_add_term (notmuch_message_t *message,
const char *prefix_name,
@@ -940,7 +943,7 @@ _notmuch_message_gen_terms (notmuch_message_t *message,
* names to prefix values.
*
* This change will not be reflected in the database until the next
- * call to _notmuch_message_sync. */
+ * call to notmuch_message_sync. */
notmuch_private_status_t
_notmuch_message_remove_term (notmuch_message_t *message,
const char *prefix_name,
@@ -977,11 +980,6 @@ notmuch_status_t
notmuch_message_add_tag (notmuch_message_t *message, const char *tag)
{
notmuch_private_status_t private_status;
- notmuch_status_t status;
-
- status = _notmuch_database_ensure_writable (message->notmuch);
- if (status)
- return status;
if (tag == NULL)
return NOTMUCH_STATUS_NULL_POINTER;
@@ -995,9 +993,6 @@ notmuch_message_add_tag (notmuch_message_t *message, const char *tag)
private_status);
}
- if (! message->frozen)
- _notmuch_message_sync (message);
-
return NOTMUCH_STATUS_SUCCESS;
}
@@ -1005,11 +1000,6 @@ notmuch_status_t
notmuch_message_remove_tag (notmuch_message_t *message, const char *tag)
{
notmuch_private_status_t private_status;
- notmuch_status_t status;
-
- status = _notmuch_database_ensure_writable (message->notmuch);
- if (status)
- return status;
if (tag == NULL)
return NOTMUCH_STATUS_NULL_POINTER;
@@ -1023,9 +1013,6 @@ notmuch_message_remove_tag (notmuch_message_t *message, const char *tag)
private_status);
}
- if (! message->frozen)
- _notmuch_message_sync (message);
-
return NOTMUCH_STATUS_SUCCESS;
}
@@ -1113,10 +1100,6 @@ notmuch_message_maildir_flags_to_tags (notmuch_message_t *message)
if (! seen_maildir_info)
return NOTMUCH_STATUS_SUCCESS;
- status = notmuch_message_freeze (message);
- if (status)
- return status;
-
for (i = 0; i < ARRAY_SIZE(flag2tag); i++) {
if ((strchr (combined_flags, flag2tag[i].flag) != NULL)
^
@@ -1129,7 +1112,7 @@ notmuch_message_maildir_flags_to_tags (notmuch_message_t *message)
if (status)
return status;
}
- status = notmuch_message_thaw (message);
+ status = notmuch_message_sync (message);
talloc_free (combined_flags);
@@ -1348,7 +1331,7 @@ notmuch_message_tags_to_maildir_flags (notmuch_message_t *message)
continue;
}
- _notmuch_message_sync (message);
+ notmuch_message_sync (message);
}
talloc_free (filename_new);
@@ -1364,14 +1347,9 @@ notmuch_status_t
notmuch_message_remove_all_tags (notmuch_message_t *message)
{
notmuch_private_status_t private_status;
- notmuch_status_t status;
notmuch_tags_t *tags;
const char *tag;
- status = _notmuch_database_ensure_writable (message->notmuch);
- if (status)
- return status;
-
for (tags = notmuch_message_get_tags (message);
notmuch_tags_valid (tags);
notmuch_tags_move_to_next (tags))
@@ -1385,44 +1363,14 @@ notmuch_message_remove_all_tags (notmuch_message_t *message)
}
}
- if (! message->frozen)
- _notmuch_message_sync (message);
-
talloc_free (tags);
return NOTMUCH_STATUS_SUCCESS;
}
notmuch_status_t
-notmuch_message_freeze (notmuch_message_t *message)
+notmuch_message_sync (notmuch_message_t *message)
{
- notmuch_status_t status;
-
- status = _notmuch_database_ensure_writable (message->notmuch);
- if (status)
- return status;
-
- message->frozen++;
-
- return NOTMUCH_STATUS_SUCCESS;
-}
-
-notmuch_status_t
-notmuch_message_thaw (notmuch_message_t *message)
-{
- notmuch_status_t status;
-
- status = _notmuch_database_ensure_writable (message->notmuch);
- if (status)
- return status;
-
- if (message->frozen > 0) {
- message->frozen--;
- if (message->frozen == 0)
- _notmuch_message_sync (message);
- return NOTMUCH_STATUS_SUCCESS;
- } else {
- return NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW;
- }
+ return _notmuch_message_sync_to_database (message, message->notmuch);
}
void
diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h
index 7a409f5..9a43129 100644
--- a/lib/notmuch-private.h
+++ b/lib/notmuch-private.h
@@ -122,7 +122,6 @@ typedef enum _notmuch_private_status {
NOTMUCH_PRIVATE_STATUS_FILE_NOT_EMAIL = NOTMUCH_STATUS_FILE_NOT_EMAIL,
NOTMUCH_PRIVATE_STATUS_NULL_POINTER = NOTMUCH_STATUS_NULL_POINTER,
NOTMUCH_PRIVATE_STATUS_TAG_TOO_LONG = NOTMUCH_STATUS_TAG_TOO_LONG,
- NOTMUCH_PRIVATE_STATUS_UNBALANCED_FREEZE_THAW = NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW,
/* Then add our own private values. */
NOTMUCH_PRIVATE_STATUS_TERM_TOO_LONG = NOTMUCH_STATUS_LAST_STATUS,
@@ -295,8 +294,10 @@ _notmuch_message_set_header_values (notmuch_message_t *message,
const char *date,
const char *from,
const char *subject);
-void
-_notmuch_message_sync (notmuch_message_t *message);
+
+notmuch_status_t
+_notmuch_message_sync_to_database (notmuch_message_t *message,
+ notmuch_database_t *notmuch);
notmuch_status_t
_notmuch_message_delete (notmuch_message_t *message);
diff --git a/lib/notmuch.h b/lib/notmuch.h
index 3633bed..f6962ee 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -78,9 +78,6 @@ typedef int notmuch_bool_t;
* NOTMUCH_STATUS_TAG_TOO_LONG: A tag value is too long (exceeds
* NOTMUCH_TAG_MAX)
*
- * 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.
*
@@ -99,7 +96,6 @@ typedef enum _notmuch_status {
NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID,
NOTMUCH_STATUS_NULL_POINTER,
NOTMUCH_STATUS_TAG_TOO_LONG,
- NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW,
NOTMUCH_STATUS_UNBALANCED_ATOMIC,
NOTMUCH_STATUS_LAST_STATUS
@@ -1043,6 +1039,9 @@ notmuch_message_get_tags (notmuch_message_t *message);
/* Add a tag to the given message.
*
+ * The changes to the message will not be committed into the database
+ * until notmuch_message_sync is called.
+ *
* Return value:
*
* NOTMUCH_STATUS_SUCCESS: Tag successfully added to message
@@ -1051,15 +1050,15 @@ notmuch_message_get_tags (notmuch_message_t *message);
*
* NOTMUCH_STATUS_TAG_TOO_LONG: The length of 'tag' is too long
* (exceeds NOTMUCH_TAG_MAX)
- *
- * NOTMUCH_STATUS_READ_ONLY_DATABASE: Database was opened in read-only
- * mode so message cannot be modified.
*/
notmuch_status_t
notmuch_message_add_tag (notmuch_message_t *message, const char *tag);
/* Remove a tag from the given message.
*
+ * The changes to the message will not be committed into the database
+ * until notmuch_message_sync is called.
+ *
* Return value:
*
* NOTMUCH_STATUS_SUCCESS: Tag successfully removed from message
@@ -1068,17 +1067,14 @@ notmuch_message_add_tag (notmuch_message_t *message, const char *tag);
*
* NOTMUCH_STATUS_TAG_TOO_LONG: The length of 'tag' is too long
* (exceeds NOTMUCH_TAG_MAX)
- *
- * NOTMUCH_STATUS_READ_ONLY_DATABASE: Database was opened in read-only
- * mode so message cannot be modified.
*/
notmuch_status_t
notmuch_message_remove_tag (notmuch_message_t *message, const char *tag);
/* Remove all tags from the given message.
*
- * See notmuch_message_freeze for an example showing how to safely
- * replace tag values.
+ * See notmuch_message_sync for an example showing how to safely replace
+ * tag values.
*
* NOTMUCH_STATUS_READ_ONLY_DATABASE: Database was opened in read-only
* mode so message cannot be modified.
@@ -1148,79 +1144,44 @@ notmuch_message_maildir_flags_to_tags (notmuch_message_t *message);
*
* A client can ensure that maildir filename flags remain synchronized
* with notmuch database tags by calling this function after changing
- * tags, (after calls to notmuch_message_add_tag,
- * notmuch_message_remove_tag, or notmuch_message_freeze/
- * notmuch_message_thaw). See also notmuch_message_maildir_flags_to_tags
- * for synchronizing maildir flag changes back to tags.
+ * tags, (after calls to notmuch_message_sync).
+ *
+ * See also notmuch_message_maildir_flags_to_tags for synchronizing
+ * maildir flag changes back to tags.
*/
notmuch_status_t
notmuch_message_tags_to_maildir_flags (notmuch_message_t *message);
-/* Freeze the current state of 'message' within the database.
+/* Synchronize the current state of 'message' into the database.
*
- * This means that changes to the message state, (via
+ * This will commit any changes made to the message state, (via
* notmuch_message_add_tag, notmuch_message_remove_tag, and
- * notmuch_message_remove_all_tags), will not be committed to the
- * database until the message is thawed with notmuch_message_thaw.
- *
- * Multiple calls to freeze/thaw are valid and these calls will
- * "stack". That is there must be as many calls to thaw as to freeze
- * before a message is actually thawed.
+ * notmuch_message_remove_all_tags), to the database.
*
- * The ability to do freeze/thaw allows for safe transactions to
- * change tag values. For example, explicitly setting a message to
- * have a given set of tags might look like this:
- *
- * notmuch_message_freeze (message);
+ * If this method succeeds, the message in the database is guaranteed to
+ * have the full set of changes made to the message committed to the
+ * database. For example, explicitly setting a message to have a given
+ * set of tags might look like this:
*
* notmuch_message_remove_all_tags (message);
*
* for (i = 0; i < NUM_TAGS; i++)
* notmuch_message_add_tag (message, tags[i]);
*
- * notmuch_message_thaw (message);
- *
- * With freeze/thaw used like this, the message in the database is
- * guaranteed to have either the full set of original tag values, or
- * the full set of new tag values, but nothing in between.
+ * notmuch_message_sync (message);
*
- * Imagine the example above without freeze/thaw and the operation
- * somehow getting interrupted. This could result in the message being
- * left with no tags if the interruption happened after
- * notmuch_message_remove_all_tags but before notmuch_message_add_tag.
+ * This method only works if the database associated with 'message' was
+ * opened in read-write mode.
*
* Return value:
*
- * NOTMUCH_STATUS_SUCCESS: Message successfully frozen.
+ * NOTMUCH_STATUS_SUCCESS: Message successfully synchronized.
*
* NOTMUCH_STATUS_READ_ONLY_DATABASE: Database was opened in read-only
* mode so message cannot be modified.
*/
notmuch_status_t
-notmuch_message_freeze (notmuch_message_t *message);
-
-/* Thaw the current 'message', synchronizing any changes that may have
- * occurred while 'message' was frozen into the notmuch database.
- *
- * See notmuch_message_freeze for an example of how to use this
- * function to safely provide tag changes.
- *
- * Multiple calls to freeze/thaw are valid and these calls with
- * "stack". That is there must be as many calls to thaw as to freeze
- * before a message is actually thawed.
- *
- * Return value:
- *
- * NOTMUCH_STATUS_SUCCESS: Message successfully thawed, (or at least
- * its frozen count has successfully been reduced by 1).
- *
- * NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW: An attempt was made to thaw
- * an unfrozen message. That is, there have been an unbalanced
- * number of calls to notmuch_message_freeze and
- * notmuch_message_thaw.
- */
-notmuch_status_t
-notmuch_message_thaw (notmuch_message_t *message);
+notmuch_message_sync (notmuch_message_t *message);
/* Destroy a notmuch_message_t object.
*
diff --git a/notmuch-new.c b/notmuch-new.c
index feb9c32..644a809 100644
--- a/notmuch-new.c
+++ b/notmuch-new.c
@@ -509,12 +509,11 @@ add_files (notmuch_database_t *notmuch,
/* success */
case NOTMUCH_STATUS_SUCCESS:
state->added_messages++;
- notmuch_message_freeze (message);
for (tag=state->new_tags; *tag != NULL; tag++)
notmuch_message_add_tag (message, *tag);
if (state->synchronize_flags == TRUE)
notmuch_message_maildir_flags_to_tags (message);
- notmuch_message_thaw (message);
+ notmuch_message_sync (message);
break;
/* Non-fatal issues (go on to next file) */
case NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID:
@@ -537,7 +536,6 @@ add_files (notmuch_database_t *notmuch,
case NOTMUCH_STATUS_FILE_ERROR:
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);
diff --git a/notmuch-tag.c b/notmuch-tag.c
index 88d559b..23714c9 100644
--- a/notmuch-tag.c
+++ b/notmuch-tag.c
@@ -145,8 +145,6 @@ tag_query (void *ctx, notmuch_database_t *notmuch, const char *query_string,
notmuch_messages_move_to_next (messages)) {
message = notmuch_messages_get (messages);
- notmuch_message_freeze (message);
-
for (i = 0; tag_ops[i].tag; i++) {
if (tag_ops[i].remove)
notmuch_message_remove_tag (message, tag_ops[i].tag);
@@ -154,7 +152,7 @@ tag_query (void *ctx, notmuch_database_t *notmuch, const char *query_string,
notmuch_message_add_tag (message, tag_ops[i].tag);
}
- notmuch_message_thaw (message);
+ notmuch_message_sync (message);
if (synchronize_flags)
notmuch_message_tags_to_maildir_flags (message);
diff --git a/tag-util.c b/tag-util.c
index eab482f..65db504 100644
--- a/tag-util.c
+++ b/tag-util.c
@@ -228,12 +228,6 @@ tag_op_list_apply (notmuch_message_t *message,
if (! (flags & TAG_FLAG_PRE_OPTIMIZED) && ! makes_changes (message, list, flags))
return NOTMUCH_STATUS_SUCCESS;
- status = notmuch_message_freeze (message);
- if (status) {
- message_error (message, status, "freezing message");
- return status;
- }
-
if (flags & TAG_FLAG_REMOVE_ALL) {
status = notmuch_message_remove_all_tags (message);
if (status) {
@@ -259,9 +253,9 @@ tag_op_list_apply (notmuch_message_t *message,
}
}
- status = notmuch_message_thaw (message);
+ status = notmuch_message_sync (message);
if (status) {
- message_error (message, status, "thawing message");
+ message_error (message, status, "syncing message");
return status;
}
--
1.8.0
^ permalink raw reply related [flat|nested] 4+ messages in thread