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.
Showing
4 changed files
with
60 additions
and
46 deletions
... | @@ -106,6 +106,9 @@ struct _amd_data | ... | @@ -106,6 +106,9 @@ struct _amd_data |
106 | 106 | ||
107 | int amd_init_mailbox (mu_mailbox_t mailbox, size_t mhd_size, | 107 | int amd_init_mailbox (mu_mailbox_t mailbox, size_t mhd_size, |
108 | struct _amd_data **pmhd); | 108 | struct _amd_data **pmhd); |
109 | int _amd_message_lookup_or_insert (struct _amd_data *amd, | ||
110 | struct _amd_message *key, | ||
111 | size_t *pindex); | ||
109 | int _amd_message_insert (struct _amd_data *mhd, struct _amd_message *msg); | 112 | int _amd_message_insert (struct _amd_data *mhd, struct _amd_message *msg); |
110 | int amd_message_stream_open (struct _amd_message *mhm); | 113 | int amd_message_stream_open (struct _amd_message *mhm); |
111 | void amd_message_stream_close (struct _amd_message *mhm); | 114 | void amd_message_stream_close (struct _amd_message *mhm); | ... | ... |
... | @@ -1336,27 +1336,48 @@ amd_cleanup (void *arg) | ... | @@ -1336,27 +1336,48 @@ amd_cleanup (void *arg) |
1336 | mu_locker_unlock (mailbox->locker); | 1336 | mu_locker_unlock (mailbox->locker); |
1337 | } | 1337 | } |
1338 | 1338 | ||
1339 | int | ||
1340 | _amd_message_lookup_or_insert (struct _amd_data *amd, | ||
1341 | struct _amd_message *key, | ||
1342 | size_t *pindex) | ||
1343 | { | ||
1344 | int result = 0; | ||
1345 | size_t index; | ||
1346 | if (amd_msg_lookup (amd, key, &index)) | ||
1347 | { | ||
1348 | /* Not found. Index points to the array cell where msg would | ||
1349 | be placed */ | ||
1350 | result = amd_array_expand (amd, index); | ||
1351 | if (result) | ||
1352 | return result; | ||
1353 | else | ||
1354 | result = MU_ERR_NOENT; | ||
1355 | } | ||
1356 | else | ||
1357 | result = 0; | ||
1358 | *pindex = index; | ||
1359 | return result; | ||
1360 | } | ||
1361 | |||
1339 | /* Insert message msg into the message list on the appropriate position */ | 1362 | /* Insert message msg into the message list on the appropriate position */ |
1340 | int | 1363 | int |
1341 | _amd_message_insert (struct _amd_data *amd, struct _amd_message *msg) | 1364 | _amd_message_insert (struct _amd_data *amd, struct _amd_message *msg) |
1342 | { | 1365 | { |
1343 | size_t index; | 1366 | size_t index; |
1367 | int rc = _amd_message_lookup_or_insert (amd, msg, &index); | ||
1344 | 1368 | ||
1345 | if (amd_msg_lookup (amd, msg, &index)) | 1369 | if (rc == MU_ERR_NOENT) |
1346 | { | 1370 | { |
1347 | /* Not found. Index is the index of the array cell where msg | ||
1348 | must be placed */ | ||
1349 | int rc = amd_array_expand (amd, index); | ||
1350 | if (rc) | ||
1351 | return rc; | ||
1352 | amd->msg_array[index] = msg; | 1371 | amd->msg_array[index] = msg; |
1353 | msg->amd = amd; | 1372 | msg->amd = amd; |
1354 | } | 1373 | } |
1355 | else | 1374 | else if (rc == 0) |
1356 | { | 1375 | { |
1357 | /*FIXME: Found? Shouldn't happen */ | 1376 | /*FIXME: Found? Shouldn't happen */ |
1358 | return EEXIST; | 1377 | return EEXIST; |
1359 | } | 1378 | } |
1379 | else | ||
1380 | return rc; | ||
1360 | return 0; | 1381 | return 0; |
1361 | } | 1382 | } |
1362 | 1383 | ... | ... |
... | @@ -164,11 +164,8 @@ maildir_message_cmp (struct _amd_message *a, struct _amd_message *b) | ... | @@ -164,11 +164,8 @@ maildir_message_cmp (struct _amd_message *a, struct _amd_message *b) |
164 | if ((rc = (*name_a - *name_b))) | 164 | if ((rc = (*name_a - *name_b))) |
165 | return rc; | 165 | return rc; |
166 | 166 | ||
167 | if (*name_a == ':' && *name_b == ':') | 167 | if ((*name_a == ':' || *name_a == 0) && (*name_b == ':' || *name_b == 0)) |
168 | { | 168 | return 0; |
169 | name_a++; | ||
170 | name_b++; | ||
171 | } | ||
172 | 169 | ||
173 | return *name_a - *name_b; | 170 | return *name_a - *name_b; |
174 | } | 171 | } |
... | @@ -579,33 +576,14 @@ maildir_deliver_new (struct _amd_data *amd, DIR *dir) | ... | @@ -579,33 +576,14 @@ maildir_deliver_new (struct _amd_data *amd, DIR *dir) |
579 | return 0; | 576 | return 0; |
580 | } | 577 | } |
581 | 578 | ||
582 | static struct _maildir_message * | ||
583 | maildir_message_lookup (struct _amd_data *amd, char *file_name) | ||
584 | { | ||
585 | struct _maildir_message *msg; | ||
586 | char *p = strchr (file_name, ':'); | ||
587 | size_t length = p ? p - file_name : strlen (file_name); | ||
588 | size_t i; | ||
589 | |||
590 | /*FIXME: Replace linear search with binary one! */ | ||
591 | for (i = 0; i < amd->msg_count; i++) | ||
592 | { | ||
593 | msg = (struct _maildir_message *) amd->msg_array[i]; | ||
594 | |||
595 | if (strlen (msg->file_name) <= length | ||
596 | && memcmp (msg->file_name, file_name, length) == 0) | ||
597 | return msg; | ||
598 | } | ||
599 | return NULL; | ||
600 | } | ||
601 | |||
602 | static int | 579 | static int |
603 | maildir_scan_dir (struct _amd_data *amd, DIR *dir, char *dirname) | 580 | maildir_scan_dir (struct _amd_data *amd, DIR *dir, char *dirname) |
604 | { | 581 | { |
605 | struct dirent *entry; | 582 | struct dirent *entry; |
606 | struct _maildir_message *msg; | 583 | struct _maildir_message *msg, key; |
607 | char *p; | 584 | char *p; |
608 | int insert; | 585 | size_t index; |
586 | int rc = 0; | ||
609 | 587 | ||
610 | while ((entry = readdir (dir))) | 588 | while ((entry = readdir (dir))) |
611 | { | 589 | { |
... | @@ -615,18 +593,32 @@ maildir_scan_dir (struct _amd_data *amd, DIR *dir, char *dirname) | ... | @@ -615,18 +593,32 @@ maildir_scan_dir (struct _amd_data *amd, DIR *dir, char *dirname) |
615 | break; | 593 | break; |
616 | 594 | ||
617 | default: | 595 | default: |
618 | msg = maildir_message_lookup (amd, entry->d_name); | 596 | key.file_name = entry->d_name; |
619 | if (msg) | 597 | rc = _amd_message_lookup_or_insert (amd, |
598 | (struct _amd_message *)&key, | ||
599 | &index); | ||
600 | if (rc == MU_ERR_NOENT) | ||
620 | { | 601 | { |
621 | free (msg->file_name); | 602 | /* Message not found. Index pointd to the array cell where it |
622 | insert = 0; | 603 | would be placed */ |
604 | msg = calloc (1, sizeof (*msg)); | ||
605 | if (!msg) | ||
606 | { | ||
607 | rc = ENOMEM; | ||
608 | break; | ||
609 | } | ||
610 | amd->msg_array[index] = (struct _amd_message *)msg; | ||
611 | msg->amd_message.amd = amd; | ||
612 | rc = 0; | ||
623 | } | 613 | } |
624 | else | 614 | else if (rc == 0) |
625 | { | 615 | { |
626 | msg = calloc (1, sizeof(*msg)); | 616 | msg = (struct _maildir_message *)amd->msg_array[index]; |
627 | insert = 1; | 617 | free (msg->file_name); |
628 | } | 618 | } |
629 | 619 | else | |
620 | break; | ||
621 | |||
630 | msg->dir = dirname; | 622 | msg->dir = dirname; |
631 | msg->file_name = strdup (entry->d_name); | 623 | msg->file_name = strdup (entry->d_name); |
632 | 624 | ||
... | @@ -636,11 +628,10 @@ maildir_scan_dir (struct _amd_data *amd, DIR *dir, char *dirname) | ... | @@ -636,11 +628,10 @@ maildir_scan_dir (struct _amd_data *amd, DIR *dir, char *dirname) |
636 | else | 628 | else |
637 | msg->amd_message.attr_flags = 0; | 629 | msg->amd_message.attr_flags = 0; |
638 | msg->amd_message.orig_flags = msg->amd_message.attr_flags; | 630 | msg->amd_message.orig_flags = msg->amd_message.attr_flags; |
639 | if (insert) | ||
640 | _amd_message_insert (amd, (struct _amd_message*) msg); | ||
641 | } | 631 | } |
642 | } | 632 | } |
643 | return 0; | 633 | |
634 | return rc; | ||
644 | } | 635 | } |
645 | 636 | ||
646 | static int | 637 | static int | ... | ... |
... | @@ -37,7 +37,6 @@ lib/tcpwrap.c | ... | @@ -37,7 +37,6 @@ lib/tcpwrap.c |
37 | lib/xmalloc.c | 37 | lib/xmalloc.c |
38 | lib/strexit.c | 38 | lib/strexit.c |
39 | 39 | ||
40 | libmu_argp/auth.c | ||
41 | libmu_argp/cmdline.c | 40 | libmu_argp/cmdline.c |
42 | libmu_argp/common.c | 41 | libmu_argp/common.c |
43 | libmu_argp/mu_argp.c | 42 | libmu_argp/mu_argp.c | ... | ... |
-
Please register or sign in to post a comment