diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2010-12-29 13:22:02 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2010-12-29 13:22:02 +0200 |
commit | b6a162923d3fdfc0c8642dd0169bf870a5ae2868 (patch) | |
tree | 59ad4fa971c7687083f46dec1ca497bb87f962e6 /libmailutils | |
parent | 0cf36c45b0a1a8dada253bc7ab0c6ab6057e7d3e (diff) | |
download | mailutils-b6a162923d3fdfc0c8642dd0169bf870a5ae2868.tar.gz mailutils-b6a162923d3fdfc0c8642dd0169bf870a5ae2868.tar.bz2 |
amd: bugfixes; speed up expunging.
* libmailutils/base/amd.c (_amd_message_delete): Remove.
(amd_array_expand): Fix element size.
(amd_array_shrink): Rewrite.
(amd_expunge): Shrink the array once, after everything has been
expunged.
Generate MU_EVT_MAILBOX_MESSAGE_EXPUNGE for each expunged message.
Diffstat (limited to 'libmailutils')
-rw-r--r-- | libmailutils/base/amd.c | 102 |
1 files changed, 48 insertions, 54 deletions
diff --git a/libmailutils/base/amd.c b/libmailutils/base/amd.c index 0bda6734b..2584f82ef 100644 --- a/libmailutils/base/amd.c +++ b/libmailutils/base/amd.c @@ -100,8 +100,6 @@ static int amd_get_attr_flags (mu_attribute_t attr, int *pflags); static int amd_set_attr_flags (mu_attribute_t attr, int flags); static int amd_unset_attr_flags (mu_attribute_t attr, int flags); -static void _amd_message_delete (struct _amd_data *amd, - struct _amd_message *msg); static int amd_pool_open (struct _amd_message *mhm); static int amd_pool_open_count (struct _amd_data *amd); static void amd_pool_flush (struct _amd_data *amd); @@ -233,7 +231,7 @@ amd_array_expand (struct _amd_data *amd, size_t index) struct _amd_message **p; amd->msg_max += AMD_MSG_INC; /* FIXME: configurable? */ - p = realloc (amd->msg_array, amd->msg_max * amd->msg_size); + p = realloc (amd->msg_array, amd->msg_max * sizeof (amd->msg_array[0])); if (!p) { amd->msg_max -= AMD_MSG_INC; @@ -243,20 +241,21 @@ amd_array_expand (struct _amd_data *amd, size_t index) } if (amd->msg_count > index) memmove (&amd->msg_array[index+1], &amd->msg_array[index], - (amd->msg_count-index) * amd->msg_size); + (amd->msg_count-index) * sizeof (amd->msg_array[0])); amd->msg_count++; return 0; } -/* Shrink the message array by removing element at INDEX-1 and - shifting left by one position all the elements on the right of +/* Shrink the message array by removing element at INDEX-COUNT and + shifting left by COUNT positions all the elements on the right of it. */ int -amd_array_shrink (struct _amd_data *amd, size_t index) +amd_array_shrink (struct _amd_data *amd, size_t index, size_t count) { - memmove (&amd->msg_array[index-1], &amd->msg_array[index], - (amd->msg_count-index) * amd->msg_size); - amd->msg_count--; + if (amd->msg_count-index-1 && index < amd->msg_count) + memmove (&amd->msg_array[index-count+1], &amd->msg_array[index + 1], + (amd->msg_count-index-1) * sizeof (amd->msg_array[0])); + amd->msg_count -= count; return 0; } @@ -1150,6 +1149,7 @@ amd_expunge (mu_mailbox_t mailbox) size_t i; int updated = amd->has_new_msg; size_t expcount = 0; + size_t last_expunged = 0; if (amd == NULL) return EINVAL; @@ -1157,35 +1157,20 @@ amd_expunge (mu_mailbox_t mailbox) if (amd->msg_count == 0) return 0; - /* Find the first dirty(modified) message. */ for (i = 0; i < amd->msg_count; i++) { mhm = amd->msg_array[i]; - if ((mhm->attr_flags & MU_ATTRIBUTE_MODIFIED) || - (mhm->attr_flags & MU_ATTRIBUTE_DELETED) || - (mhm->message && mu_message_is_modified (mhm->message))) - break; - } - - while (i < amd->msg_count) - { - mhm = amd->msg_array[i]; if (mhm->attr_flags & MU_ATTRIBUTE_DELETED) { int rc; + struct _amd_message **pp; if (amd->delete_msg) { - size_t expevt[2] = { i + 1, expcount }; rc = amd->delete_msg (amd, mhm); if (rc) return rc; - - mu_observable_notify (mailbox->observable, - MU_EVT_MAILBOX_MESSAGE_EXPUNGE, - expevt); - ++expcount; } else { @@ -1220,9 +1205,25 @@ amd_expunge (mu_mailbox_t mailbox) free (old_name); free (new_name); } - _amd_message_delete (amd, mhm); + + pp = amd_pool_lookup (mhm); + if (pp) + *pp = NULL; + mu_message_destroy (&mhm->message, mhm); + if (amd->msg_free) + amd->msg_free (mhm); + free (mhm); + amd->msg_array[i] = NULL; + last_expunged = i; updated = 1; - /* Do not increase i! */ + + { + size_t expevt[2] = { i + 1, expcount }; + mu_observable_notify (mailbox->observable, + MU_EVT_MAILBOX_MESSAGE_EXPUNGE, + expevt); + ++expcount; + } } else { @@ -1233,10 +1234,28 @@ amd_expunge (mu_mailbox_t mailbox) _amd_message_save (amd, mhm, 1); updated = 1; } - i++; /* Move to the next message */ } } + if (expcount) + { + last_expunged++; + do + { + size_t j; + + for (j = 1; j < last_expunged && !amd->msg_array[last_expunged-j-1]; + j++) + ; + amd_array_shrink (amd, last_expunged - 1, j); + for (last_expunged -= j; + last_expunged > 0 && amd->msg_array[last_expunged - 1]; + last_expunged--) + ; + } + while (last_expunged); + } + if (updated && !amd->mailbox_size) { mu_off_t size = 0; @@ -1419,31 +1438,6 @@ amd_sort (struct _amd_data *amd) msg_array_comp); } -static void -_amd_message_delete (struct _amd_data *amd, struct _amd_message *msg) -{ - size_t index; - struct _amd_message **pp; - - if (amd_msg_lookup (amd, msg, &index)) - { - /* FIXME: Not found? */ - return; - } - - msg = _amd_get_message (amd, index); - - pp = amd_pool_lookup (msg); - if (pp) - *pp = NULL; - - mu_message_destroy (&msg->message, msg); - if (amd->msg_free) - amd->msg_free (msg); - free (msg); - amd_array_shrink (amd, index); -} - /* Scan given message and fill amd_message_t fields. NOTE: the function assumes mhm->stream != NULL. */ static int |