lib: Only sync modified message documents
authorAustin Clements <amdragon@mit.edu>
Fri, 5 Jun 2015 17:28:33 +0000 (19:28 +0200)
committerDavid Bremner <david@tethera.net>
Tue, 4 Aug 2015 06:54:46 +0000 (08:54 +0200)
Previously, we updated the database copy of a message on every call to
_notmuch_message_sync, even if nothing had changed.  In particular,
this always happens on a thaw, so a freeze/thaw pair with no
modifications between still caused a database update.

We only modify message documents in a handful of places, so keep track
of whether the document has been modified and only sync it when
necessary.  This will be particularly important when we add message
revision tracking.

lib/message.cc

index 5bc7aff1386a4a7e09a461f98f7e37f86e5a3f58..1ddce3c692bebdc94fa22023a7b80d05345d69c4 100644 (file)
@@ -43,6 +43,9 @@ struct visible _notmuch_message {
      * if each flag has been initialized. */
     unsigned long lazy_flags;
 
+    /* Message document modified since last sync */
+    notmuch_bool_t modified;
+
     Xapian::Document doc;
     Xapian::termcount termpos;
 };
@@ -539,6 +542,7 @@ _notmuch_message_remove_terms (notmuch_message_t *message, const char *prefix)
 
        try {
            message->doc.remove_term ((*i));
+           message->modified = TRUE;
        } catch (const Xapian::InvalidArgumentError) {
            /* Ignore failure to remove non-existent term. */
        }
@@ -793,6 +797,7 @@ void
 _notmuch_message_clear_data (notmuch_message_t *message)
 {
     message->doc.set_data ("");
+    message->modified = TRUE;
 }
 
 static void
@@ -990,6 +995,7 @@ _notmuch_message_set_header_values (notmuch_message_t *message,
                            Xapian::sortable_serialise (time_value));
     message->doc.add_value (NOTMUCH_VALUE_FROM, from);
     message->doc.add_value (NOTMUCH_VALUE_SUBJECT, subject);
+    message->modified = TRUE;
 }
 
 /* Synchronize changes made to message->doc out into the database. */
@@ -1001,8 +1007,12 @@ _notmuch_message_sync (notmuch_message_t *message)
     if (message->notmuch->mode == NOTMUCH_DATABASE_MODE_READ_ONLY)
        return;
 
+    if (! message->modified)
+       return;
+
     db = static_cast <Xapian::WritableDatabase *> (message->notmuch->xapian_db);
     db->replace_document (message->doc_id, message->doc);
+    message->modified = FALSE;
 }
 
 /* Delete a message document from the database. */
@@ -1077,6 +1087,7 @@ _notmuch_message_add_term (notmuch_message_t *message,
        return NOTMUCH_PRIVATE_STATUS_TERM_TOO_LONG;
 
     message->doc.add_term (term, 0);
+    message->modified = TRUE;
 
     talloc_free (term);
 
@@ -1145,6 +1156,7 @@ _notmuch_message_remove_term (notmuch_message_t *message,
 
     try {
        message->doc.remove_term (term);
+       message->modified = TRUE;
     } catch (const Xapian::InvalidArgumentError) {
        /* We'll let the philosopher's try to wrestle with the
         * question of whether failing to remove that which was not