mirror of
https://git.notmuchmail.org/git/notmuch
synced 2024-11-21 18:38:08 +01:00
tag-util: optimization of tag application
The idea is not to bother with restore operations if they don't change the set of tags. This is actually a relatively common case. In order to avoid fancy datastructures, this method is quadratic in the number of tags; at least on my mail database this doesn't seem to be a big problem.
This commit is contained in:
parent
60cd3b9a06
commit
5c7990f251
1 changed files with 68 additions and 0 deletions
68
tag-util.c
68
tag-util.c
|
@ -151,6 +151,71 @@ message_error (notmuch_message_t *message,
|
|||
fprintf (stderr, "Status: %s\n", notmuch_status_to_string (status));
|
||||
}
|
||||
|
||||
static int
|
||||
makes_changes (notmuch_message_t *message,
|
||||
tag_op_list_t *list,
|
||||
tag_op_flag_t flags)
|
||||
{
|
||||
|
||||
size_t i;
|
||||
|
||||
notmuch_tags_t *tags;
|
||||
notmuch_bool_t changes = FALSE;
|
||||
|
||||
/* First, do we delete an existing tag? */
|
||||
changes = FALSE;
|
||||
for (tags = notmuch_message_get_tags (message);
|
||||
! changes && notmuch_tags_valid (tags);
|
||||
notmuch_tags_move_to_next (tags)) {
|
||||
const char *cur_tag = notmuch_tags_get (tags);
|
||||
int last_op = (flags & TAG_FLAG_REMOVE_ALL) ? -1 : 0;
|
||||
|
||||
/* scan backwards to get last operation */
|
||||
i = list->count;
|
||||
while (i > 0) {
|
||||
i--;
|
||||
if (strcmp (cur_tag, list->ops[i].tag) == 0) {
|
||||
last_op = list->ops[i].remove ? -1 : 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
changes = (last_op == -1);
|
||||
}
|
||||
notmuch_tags_destroy (tags);
|
||||
|
||||
if (changes)
|
||||
return TRUE;
|
||||
|
||||
/* Now check for adding new tags */
|
||||
for (i = 0; i < list->count; i++) {
|
||||
notmuch_bool_t exists = FALSE;
|
||||
|
||||
if (list->ops[i].remove)
|
||||
continue;
|
||||
|
||||
for (tags = notmuch_message_get_tags (message);
|
||||
notmuch_tags_valid (tags);
|
||||
notmuch_tags_move_to_next (tags)) {
|
||||
const char *cur_tag = notmuch_tags_get (tags);
|
||||
if (strcmp (cur_tag, list->ops[i].tag) == 0) {
|
||||
exists = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
notmuch_tags_destroy (tags);
|
||||
|
||||
/* the following test is conservative,
|
||||
* in the sense it ignores cases like +foo ... -foo
|
||||
* but this is OK from a correctness point of view
|
||||
*/
|
||||
if (! exists)
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
|
||||
notmuch_status_t
|
||||
tag_op_list_apply (notmuch_message_t *message,
|
||||
tag_op_list_t *list,
|
||||
|
@ -160,6 +225,9 @@ tag_op_list_apply (notmuch_message_t *message,
|
|||
notmuch_status_t status = 0;
|
||||
tag_operation_t *tag_ops = list->ops;
|
||||
|
||||
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");
|
||||
|
|
Loading…
Reference in a new issue