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 ...@@ -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
......