This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "GNU Mailutils".
http://git.savannah.gnu.org/cgit/mailutils.git/commit/?id=d85540094f0df7258af1cae7c61cc6d45c2a4f53 The branch, master has been updated via d85540094f0df7258af1cae7c61cc6d45c2a4f53 (commit) from 42838314448528fd390d93a0b07a0d3d2d9d312f (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit d85540094f0df7258af1cae7c61cc6d45c2a4f53 Author: Sergey Poznyakoff <g...@gnu.org.ua> Date: Tue Dec 28 14:37:37 2010 +0200 mh,maildir: speed up scanning. * include/mailutils/sys/amd.h (_amd_message_append, amd_sort): New protos. * libmailutils/base/amd.c (amd_array_expand): Call memmove only if there is actually something to move. (_amd_message_append, amd_sort): New functions. * libproto/maildir/mbox.c (maildir_scan_dir): Append new messages to the end of the array, and sort it afterwards. This avoids unnecessary memory moves, which improves performance considerably, especially on large mailboxes. * libproto/mh/mbox.c (mh_scan0): Likewise. ----------------------------------------------------------------------- Summary of changes: include/mailutils/sys/amd.h | 2 + libmailutils/base/amd.c | 34 ++++++++++++++++++++++++- libproto/maildir/mbox.c | 38 +++++++++++++---------------- libproto/mh/mbox.c | 56 ++++++++++++++++++++++++++----------------- 4 files changed, 85 insertions(+), 45 deletions(-) diff --git a/include/mailutils/sys/amd.h b/include/mailutils/sys/amd.h index 2bc8dc7..e96e3ca 100644 --- a/include/mailutils/sys/amd.h +++ b/include/mailutils/sys/amd.h @@ -110,6 +110,8 @@ int _amd_message_lookup_or_insert (struct _amd_data *amd, struct _amd_message *key, size_t *pindex); int _amd_message_insert (struct _amd_data *mhd, struct _amd_message *msg); +int _amd_message_append (struct _amd_data *amd, struct _amd_message *msg); +void amd_sort (struct _amd_data *amd); int amd_message_stream_open (struct _amd_message *mhm); void amd_message_stream_close (struct _amd_message *mhm); void amd_cleanup (void *arg); diff --git a/libmailutils/base/amd.c b/libmailutils/base/amd.c index f77cf3a..96d55cc 100644 --- a/libmailutils/base/amd.c +++ b/libmailutils/base/amd.c @@ -241,8 +241,9 @@ amd_array_expand (struct _amd_data *amd, size_t index) } amd->msg_array = p; } - memmove (&amd->msg_array[index+1], &amd->msg_array[index], - (amd->msg_count-index) * amd->msg_size); + 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++; return 0; } @@ -1381,6 +1382,35 @@ _amd_message_insert (struct _amd_data *amd, struct _amd_message *msg) return 0; } +/* Append message to the end of the array, expanding it if necessary */ +int +_amd_message_append (struct _amd_data *amd, struct _amd_message *msg) +{ + size_t index = amd->msg_count; + int rc = amd_array_expand (amd, index); + if (rc) + return rc; + amd->msg_array[index] = msg; + msg->amd = amd; + return 0; +} + +static int +msg_array_comp (const void *a, const void *b) +{ + struct _amd_message **ma = (struct _amd_message **) a; + struct _amd_message **mb = (struct _amd_message **) b; + struct _amd_data *amd = (*ma)->amd; + return amd->msg_cmp (*ma, *mb); +} + +void +amd_sort (struct _amd_data *amd) +{ + qsort (amd->msg_array, amd->msg_count, sizeof (amd->msg_array[0]), + msg_array_comp); +} + static void _amd_message_delete (struct _amd_data *amd, struct _amd_message *msg) { diff --git a/libproto/maildir/mbox.c b/libproto/maildir/mbox.c index 1f245ec..aa66fb4 100644 --- a/libproto/maildir/mbox.c +++ b/libproto/maildir/mbox.c @@ -584,7 +584,8 @@ maildir_scan_dir (struct _amd_data *amd, DIR *dir, char *dirname) char *p; size_t index; int rc = 0; - + int need_sort = 0; + while ((entry = readdir (dir))) { switch (entry->d_name[0]) @@ -593,31 +594,23 @@ maildir_scan_dir (struct _amd_data *amd, DIR *dir, char *dirname) break; default: - key.file_name = entry->d_name; - rc = _amd_message_lookup_or_insert (amd, - (struct _amd_message *)&key, - &index); - if (rc == MU_ERR_NOENT) - { /* Message not found. Index pointd to the array cell where it would be placed */ - msg = calloc (1, sizeof (*msg)); - if (!msg) - { - rc = ENOMEM; - break; - } - amd->msg_array[index] = (struct _amd_message *)msg; - msg->amd_message.amd = amd; - rc = 0; + msg = calloc (1, sizeof (*msg)); + if (!msg) + { + rc = ENOMEM; + break; } - else if (rc == 0) + key.file_name = entry->d_name; + if (!amd_msg_lookup (amd, (struct _amd_message *) &key, &index)) + continue; + rc = _amd_message_append (amd, (struct _amd_message *) msg); + if (rc) { - msg = (struct _maildir_message *)amd->msg_array[index]; - free (msg->file_name); + free (msg); + break; } - else - break; msg->dir = dirname; msg->file_name = strdup (entry->d_name); @@ -628,9 +621,12 @@ maildir_scan_dir (struct _amd_data *amd, DIR *dir, char *dirname) else msg->amd_message.attr_flags = 0; msg->amd_message.orig_flags = msg->amd_message.attr_flags; + need_sort = 1; } } + if (rc == 0 && need_sort) + amd_sort (amd); return rc; } diff --git a/libproto/mh/mbox.c b/libproto/mh/mbox.c index 82d0283..bfa937c 100644 --- a/libproto/mh/mbox.c +++ b/libproto/mh/mbox.c @@ -181,6 +181,7 @@ mh_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, size_t *pcount, struct dirent *entry; int status = 0; struct stat st; + int need_sort = 0; if (amd == NULL) return EINVAL; @@ -235,12 +236,18 @@ mh_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, size_t *pcount, if (!msg) { msg = calloc (1, sizeof(*msg)); + status = _amd_message_append (amd, (struct _amd_message *) msg); + if (status) + { + free (msg); + break; + } msg->seq_number = num; msg->amd_message.attr_flags = attr_flags; msg->amd_message.orig_flags = msg->amd_message.attr_flags; - _amd_message_insert (amd, (struct _amd_message*) msg); + need_sort = 1; } else { @@ -251,38 +258,43 @@ mh_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, size_t *pcount, closedir (dir); - if (do_notify) - { - size_t i; + if (need_sort) + amd_sort (amd); - for (i = 0; i < amd->msg_count; i++) + if (status == 0) + { + if (do_notify) { - DISPATCH_ADD_MSG (mailbox, amd, i); + size_t i; + + for (i = 0; i < amd->msg_count; i++) + { + DISPATCH_ADD_MSG (mailbox, amd, i); + } } - } - if (stat (amd->name, &st) == 0) - amd->mtime = st.st_mtime; + if (stat (amd->name, &st) == 0) + amd->mtime = st.st_mtime; - if (pcount) - *pcount = amd->msg_count; + if (pcount) + *pcount = amd->msg_count; - /* Reset the uidvalidity. */ - if (amd->msg_count > 0) - { - if (amd->uidvalidity == 0) + /* Reset the uidvalidity. */ + if (amd->msg_count > 0) { - amd->uidvalidity = (unsigned long)time (NULL); - /* Tell that we have been modified for expunging. */ - if (amd->msg_count) + if (amd->uidvalidity == 0) { - amd_message_stream_open (amd->msg_array[0]); - amd_message_stream_close (amd->msg_array[0]); - amd->msg_array[0]->attr_flags |= MU_ATTRIBUTE_MODIFIED; + amd->uidvalidity = (unsigned long)time (NULL); + /* Tell that we have been modified for expunging. */ + if (amd->msg_count) + { + amd_message_stream_open (amd->msg_array[0]); + amd_message_stream_close (amd->msg_array[0]); + amd->msg_array[0]->attr_flags |= MU_ATTRIBUTE_MODIFIED; + } } } } - /* Clean up the things */ amd_cleanup (mailbox); hooks/post-receive -- GNU Mailutils _______________________________________________ Commit-mailutils mailing list Commit-mailutils@gnu.org http://lists.gnu.org/mailman/listinfo/commit-mailutils