Commit 68d83f0d 68d83f0d247aaa3331bf8e4a29b89687c9b2e6ea by Sergey Poznyakoff

maildir: speed up mailbox scanning

* include/mailutils/sys/amd.h (_amd_message_lookup_or_insert): New proto.
* libmailutils/base/amd.c (_amd_message_lookup_or_insert): New function.
(_amd_message_insert): Rewrite using _amd_message_lookup_or_insert.
* libproto/maildir/mbox.c (maildir_message_cmp): Stop comparison on
':'.
(maildir_message_lookup): Remove.
(maildir_scan_dir): Use _amd_message_lookup_or_insert.

* po/POTFILES.in: Update.
1 parent 094f5d94
......@@ -106,6 +106,9 @@ struct _amd_data
int amd_init_mailbox (mu_mailbox_t mailbox, size_t mhd_size,
struct _amd_data **pmhd);
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_stream_open (struct _amd_message *mhm);
void amd_message_stream_close (struct _amd_message *mhm);
......
......@@ -1336,27 +1336,48 @@ amd_cleanup (void *arg)
mu_locker_unlock (mailbox->locker);
}
int
_amd_message_lookup_or_insert (struct _amd_data *amd,
struct _amd_message *key,
size_t *pindex)
{
int result = 0;
size_t index;
if (amd_msg_lookup (amd, key, &index))
{
/* Not found. Index points to the array cell where msg would
be placed */
result = amd_array_expand (amd, index);
if (result)
return result;
else
result = MU_ERR_NOENT;
}
else
result = 0;
*pindex = index;
return result;
}
/* Insert message msg into the message list on the appropriate position */
int
_amd_message_insert (struct _amd_data *amd, struct _amd_message *msg)
{
size_t index;
int rc = _amd_message_lookup_or_insert (amd, msg, &index);
if (amd_msg_lookup (amd, msg, &index))
if (rc == MU_ERR_NOENT)
{
/* Not found. Index is the index of the array cell where msg
must be placed */
int rc = amd_array_expand (amd, index);
if (rc)
return rc;
amd->msg_array[index] = msg;
msg->amd = amd;
}
else
else if (rc == 0)
{
/*FIXME: Found? Shouldn't happen */
return EEXIST;
}
else
return rc;
return 0;
}
......
......@@ -164,11 +164,8 @@ maildir_message_cmp (struct _amd_message *a, struct _amd_message *b)
if ((rc = (*name_a - *name_b)))
return rc;
if (*name_a == ':' && *name_b == ':')
{
name_a++;
name_b++;
}
if ((*name_a == ':' || *name_a == 0) && (*name_b == ':' || *name_b == 0))
return 0;
return *name_a - *name_b;
}
......@@ -579,33 +576,14 @@ maildir_deliver_new (struct _amd_data *amd, DIR *dir)
return 0;
}
static struct _maildir_message *
maildir_message_lookup (struct _amd_data *amd, char *file_name)
{
struct _maildir_message *msg;
char *p = strchr (file_name, ':');
size_t length = p ? p - file_name : strlen (file_name);
size_t i;
/*FIXME: Replace linear search with binary one! */
for (i = 0; i < amd->msg_count; i++)
{
msg = (struct _maildir_message *) amd->msg_array[i];
if (strlen (msg->file_name) <= length
&& memcmp (msg->file_name, file_name, length) == 0)
return msg;
}
return NULL;
}
static int
maildir_scan_dir (struct _amd_data *amd, DIR *dir, char *dirname)
{
struct dirent *entry;
struct _maildir_message *msg;
struct _maildir_message *msg, key;
char *p;
int insert;
size_t index;
int rc = 0;
while ((entry = readdir (dir)))
{
......@@ -615,18 +593,32 @@ maildir_scan_dir (struct _amd_data *amd, DIR *dir, char *dirname)
break;
default:
msg = maildir_message_lookup (amd, entry->d_name);
if (msg)
key.file_name = entry->d_name;
rc = _amd_message_lookup_or_insert (amd,
(struct _amd_message *)&key,
&index);
if (rc == MU_ERR_NOENT)
{
free (msg->file_name);
insert = 0;
/* 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;
}
else
else if (rc == 0)
{
msg = calloc (1, sizeof(*msg));
insert = 1;
msg = (struct _maildir_message *)amd->msg_array[index];
free (msg->file_name);
}
else
break;
msg->dir = dirname;
msg->file_name = strdup (entry->d_name);
......@@ -636,11 +628,10 @@ 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;
if (insert)
_amd_message_insert (amd, (struct _amd_message*) msg);
}
}
return 0;
return rc;
}
static int
......
......@@ -37,7 +37,6 @@ lib/tcpwrap.c
lib/xmalloc.c
lib/strexit.c
libmu_argp/auth.c
libmu_argp/cmdline.c
libmu_argp/common.c
libmu_argp/mu_argp.c
......