Commit 84c33414 84c334143ef6fbe6220e3d889c32375f63c8e8e2 by Sergey Poznyakoff

Use sorted message array with binary

searches/inserts. This speeds up the mh/maildir
operations considerably. Testing on a MH  folder
with 6000 messages shows the following data:

               Time of execution
            List       Array+Bsearch     %    Speedup (times)
scan        24.795     7.526          30.3    3.294
refile (to) 10.915     0.068           0.6    160.514
rmm         10.893     0.105             1    103.742
1 parent 801152df
...@@ -111,8 +111,132 @@ static int amd_envelope_date __P((envelope_t envelope, char *buf, size_t len, ...@@ -111,8 +111,132 @@ static int amd_envelope_date __P((envelope_t envelope, char *buf, size_t len,
111 static int amd_envelope_sender __P((envelope_t envelope, char *buf, size_t len, 111 static int amd_envelope_sender __P((envelope_t envelope, char *buf, size_t len,
112 size_t *psize)); 112 size_t *psize));
113 113
114 /* Should be in other header file. */ 114 /* Operations on message array */
115 extern int amd_message_number __P ((message_t msg, size_t *pnum)); 115
116 /* Perform binary search for message MSG on a segment of message array
117 of AMD between the indexes FIRST and LAST inclusively.
118 If found, return 0 and store index of the located entry in the
119 variable PRET. Otherwise, return 1 and place into PRET index of
120 the nearest array element that is less than MSG (in the sense of
121 amd->msg_cmp)
122 Indexes are zero-based. */
123
124 static int
125 amd_msg_bsearch (struct _amd_data *amd, off_t first, off_t last,
126 struct _amd_message *msg,
127 off_t *pret)
128 {
129 off_t mid;
130 int rc;
131
132 if (last < first)
133 return 1;
134
135 mid = (first + last) / 2;
136 rc = amd->msg_cmp (amd->msg_array[mid], msg);
137 if (rc > 0)
138 return amd_msg_bsearch (amd, first, mid-1, msg, pret);
139 *pret = mid;
140 if (rc < 0)
141 return amd_msg_bsearch (amd, mid+1, last, msg, pret);
142 /* else */
143 return 0;
144 }
145
146 /* Search for message MSG in the message array of AMD.
147 If found, return 0 and store index of the located entry in the
148 variable PRET. Otherwise, return 1 and place into PRET index of
149 the array element that is less than MSG (in the sense of
150 amd->msg_cmp)
151 Index returned in PRET is 1-based, so *PRET == 0 means that MSG
152 is less than the very first element of the message array.
153
154 In other words, when amd_msg_lookup() returns 1, the value in *PRET
155 can be regarded as a 0-based index of the array slot where MSG can
156 be inserted */
157
158 int
159 amd_msg_lookup (struct _amd_data *amd, struct _amd_message *msg,
160 size_t *pret)
161 {
162 int rc;
163 off_t i;
164
165 if (!amd->msg_array)
166 {
167 *pret = 0;
168 return 1;
169 }
170
171 rc = amd->msg_cmp (msg, amd->msg_array[0]);
172 if (rc < 0)
173 {
174 *pret = 0;
175 return 1;
176 }
177 else if (rc == 0)
178 {
179 *pret = 1;
180 return 0;
181 }
182
183 rc = amd->msg_cmp (msg, amd->msg_array[amd->msg_count - 1]);
184 if (rc > 0)
185 {
186 *pret = amd->msg_count;
187 return 1;
188 }
189 else if (rc == 0)
190 {
191 *pret = amd->msg_count;
192 return 0;
193 }
194
195 rc = amd_msg_bsearch (amd, 0, amd->msg_count - 1, msg, &i);
196 *pret = i + 1;
197 return rc;
198 }
199
200 #define AMD_MSG_INC 64
201
202 /* Prepare the message array for insertion of a new message
203 at position INDEX (zero based), by moving its contents
204 one slot to the right. If necessary, expand the array by
205 AMD_MSG_INC */
206 int
207 amd_array_expand (struct _amd_data *amd, size_t index)
208 {
209 if (amd->msg_count == amd->msg_max)
210 {
211 struct _amd_message **p;
212
213 amd->msg_max += AMD_MSG_INC; /* FIXME: configurable? */
214 p = realloc (amd->msg_array, amd->msg_max * amd->msg_size);
215 if (!p)
216 {
217 amd->msg_max -= AMD_MSG_INC;
218 return ENOMEM;
219 }
220 amd->msg_array = p;
221 }
222 memmove (&amd->msg_array[index+1], &amd->msg_array[index],
223 (amd->msg_count-index) * amd->msg_size);
224 amd->msg_count++;
225 return 0;
226 }
227
228 /* Shrink the message array by removing element at INDEX-1 and
229 shifting left by one position all the elements on the right of
230 it. */
231 int
232 amd_array_shrink (struct _amd_data *amd, size_t index)
233 {
234 memmove (&amd->msg_array[index-1], &amd->msg_array[index],
235 (amd->msg_count-index) * amd->msg_size);
236 amd->msg_count--;
237 return 0;
238 }
239
116 240
117 int 241 int
118 amd_init_mailbox (mailbox_t mailbox, size_t amd_size, struct _amd_data **pamd) 242 amd_init_mailbox (mailbox_t mailbox, size_t amd_size, struct _amd_data **pamd)
...@@ -171,20 +295,18 @@ static void ...@@ -171,20 +295,18 @@ static void
171 amd_destroy (mailbox_t mailbox) 295 amd_destroy (mailbox_t mailbox)
172 { 296 {
173 struct _amd_data *amd = mailbox->data; 297 struct _amd_data *amd = mailbox->data;
174 struct _amd_message *msg, *next; 298 size_t i;
175 299
176 if (!amd) 300 if (!amd)
177 return; 301 return;
178 302
179 monitor_wrlock (mailbox->monitor); 303 monitor_wrlock (mailbox->monitor);
180 msg = amd->msg_head; 304 for (i = 0; i < amd->msg_count; i++)
181 while (msg)
182 { 305 {
183 next = msg->next; 306 message_destroy (&amd->msg_array[i]->message, amd->msg_array[i]);
184 message_destroy (&msg->message, msg); 307 free (amd->msg_array[i]);
185 free (msg);
186 msg = next;
187 } 308 }
309 free (amd->msg_array);
188 310
189 if (amd->name) 311 if (amd->name)
190 free (amd->name); 312 free (amd->name);
...@@ -220,16 +342,13 @@ amd_close (mailbox_t mailbox) ...@@ -220,16 +342,13 @@ amd_close (mailbox_t mailbox)
220 return 0; 342 return 0;
221 } 343 }
222 344
223 static struct _amd_message * 345 struct _amd_message *
224 _amd_get_message (struct _amd_data *amd, size_t msgno) 346 _amd_get_message (struct _amd_data *amd, size_t msgno)
225 { 347 {
226 size_t n; 348 msgno--;
227 struct _amd_message *msg; 349 if (msgno >= amd->msg_count)
228 350 return NULL;
229 for (n = 1, msg = amd->msg_head; msg && n < msgno; n++, msg = msg->next) 351 return amd->msg_array[msgno];
230 ;
231
232 return msg;
233 } 352 }
234 353
235 static int 354 static int
...@@ -440,7 +559,7 @@ _amd_message_save (struct _amd_data *amd, struct _amd_message *mhm, int expunge) ...@@ -440,7 +559,7 @@ _amd_message_save (struct _amd_data *amd, struct _amd_message *mhm, int expunge)
440 559
441 /* Add imapbase */ 560 /* Add imapbase */
442 if (amd->next_uid 561 if (amd->next_uid
443 && (!amd->msg_head || (amd->msg_head == mhm))) /*FIXME*/ 562 && (!amd->msg_array || (amd->msg_array[0] == mhm))) /*FIXME*/
444 { 563 {
445 nbytes += fprintf (fp, "X-IMAPbase: %lu %u\n", 564 nbytes += fprintf (fp, "X-IMAPbase: %lu %u\n",
446 (unsigned long) amd->uidvalidity, 565 (unsigned long) amd->uidvalidity,
...@@ -556,7 +675,12 @@ amd_append_message (mailbox_t mailbox, message_t msg) ...@@ -556,7 +675,12 @@ amd_append_message (mailbox_t mailbox, message_t msg)
556 status = _amd_message_save (amd, mhm, 0); 675 status = _amd_message_save (amd, mhm, 0);
557 mhm->message = NULL; 676 mhm->message = NULL;
558 /* Insert and re-scan the message */ 677 /* Insert and re-scan the message */
559 _amd_message_insert (amd, mhm); 678 status = _amd_message_insert (amd, mhm);
679 if (status)
680 {
681 free (mhm);
682 return status;
683 }
560 684
561 if (amd->msg_finish_delivery) 685 if (amd->msg_finish_delivery)
562 amd->msg_finish_delivery (amd, mhm); 686 amd->msg_finish_delivery (amd, mhm);
...@@ -588,8 +712,7 @@ static int ...@@ -588,8 +712,7 @@ static int
588 amd_messages_recent (mailbox_t mailbox, size_t *pcount) 712 amd_messages_recent (mailbox_t mailbox, size_t *pcount)
589 { 713 {
590 struct _amd_data *amd = mailbox->data; 714 struct _amd_data *amd = mailbox->data;
591 struct _amd_message *mhm; 715 size_t count, i;
592 size_t count;
593 716
594 /* If we did not start a scanning yet do it now. */ 717 /* If we did not start a scanning yet do it now. */
595 if (amd->msg_count == 0) 718 if (amd->msg_count == 0)
...@@ -599,9 +722,9 @@ amd_messages_recent (mailbox_t mailbox, size_t *pcount) ...@@ -599,9 +722,9 @@ amd_messages_recent (mailbox_t mailbox, size_t *pcount)
599 return status; 722 return status;
600 } 723 }
601 count = 0; 724 count = 0;
602 for (mhm = amd->msg_head; mhm; mhm = mhm->next) 725 for (i = 0; i < amd->msg_count; i++)
603 { 726 {
604 if (MU_ATTRIBUTE_IS_UNSEEN(mhm->attr_flags)) 727 if (MU_ATTRIBUTE_IS_UNSEEN(amd->msg_array[i]->attr_flags))
605 count++; 728 count++;
606 } 729 }
607 *pcount = count; 730 *pcount = count;
...@@ -613,8 +736,7 @@ static int ...@@ -613,8 +736,7 @@ static int
613 amd_message_unseen (mailbox_t mailbox, size_t *pmsgno) 736 amd_message_unseen (mailbox_t mailbox, size_t *pmsgno)
614 { 737 {
615 struct _amd_data *amd = mailbox->data; 738 struct _amd_data *amd = mailbox->data;
616 struct _amd_message *mhm; 739 size_t i;
617 size_t i, unseen;
618 740
619 /* If we did not start a scanning yet do it now. */ 741 /* If we did not start a scanning yet do it now. */
620 if (amd->msg_count == 0) 742 if (amd->msg_count == 0)
...@@ -623,15 +745,15 @@ amd_message_unseen (mailbox_t mailbox, size_t *pmsgno) ...@@ -623,15 +745,15 @@ amd_message_unseen (mailbox_t mailbox, size_t *pmsgno)
623 if (status != 0) 745 if (status != 0)
624 return status; 746 return status;
625 } 747 }
626 for (unseen = i = 1, mhm = amd->msg_head; mhm; i++, mhm = mhm->next) 748
749 for (i = 0; i < amd->msg_count; i++)
627 { 750 {
628 if (MU_ATTRIBUTE_IS_UNREAD(mhm->attr_flags)) 751 if (MU_ATTRIBUTE_IS_UNREAD(amd->msg_array[0]->attr_flags))
629 { 752 {
630 unseen = i; 753 *pmsgno = i + 1;
631 break; 754 break;
632 } 755 }
633 } 756 }
634 *pmsgno = unseen;
635 return 0; 757 return 0;
636 } 758 }
637 759
...@@ -640,6 +762,7 @@ amd_expunge (mailbox_t mailbox) ...@@ -640,6 +762,7 @@ amd_expunge (mailbox_t mailbox)
640 { 762 {
641 struct _amd_data *amd = mailbox->data; 763 struct _amd_data *amd = mailbox->data;
642 struct _amd_message *mhm; 764 struct _amd_message *mhm;
765 size_t i;
643 766
644 if (amd == NULL) 767 if (amd == NULL)
645 return EINVAL; 768 return EINVAL;
...@@ -648,20 +771,18 @@ amd_expunge (mailbox_t mailbox) ...@@ -648,20 +771,18 @@ amd_expunge (mailbox_t mailbox)
648 return 0; 771 return 0;
649 772
650 /* Find the first dirty(modified) message. */ 773 /* Find the first dirty(modified) message. */
651 for (mhm = amd->msg_head; mhm; mhm = mhm->next) 774 for (i = 0; i < amd->msg_count; i++)
652 { 775 {
776 mhm = amd->msg_array[i];
653 if ((mhm->attr_flags & MU_ATTRIBUTE_MODIFIED) || 777 if ((mhm->attr_flags & MU_ATTRIBUTE_MODIFIED) ||
654 (mhm->attr_flags & MU_ATTRIBUTE_DELETED) || 778 (mhm->attr_flags & MU_ATTRIBUTE_DELETED) ||
655 (mhm->message && message_is_modified (mhm->message))) 779 (mhm->message && message_is_modified (mhm->message)))
656 break; 780 break;
657 } 781 }
658 782
659 if (!mhm) 783 while (i < amd->msg_count)
660 return 0; /* Nothing changed, just return. */
661
662 while (mhm)
663 { 784 {
664 struct _amd_message *next = mhm->next; 785 mhm = amd->msg_array[i];
665 786
666 if (mhm->attr_flags & MU_ATTRIBUTE_DELETED) 787 if (mhm->attr_flags & MU_ATTRIBUTE_DELETED)
667 { 788 {
...@@ -676,15 +797,19 @@ amd_expunge (mailbox_t mailbox) ...@@ -676,15 +797,19 @@ amd_expunge (mailbox_t mailbox)
676 free (new_name); 797 free (new_name);
677 } 798 }
678 _amd_message_delete (amd, mhm); 799 _amd_message_delete (amd, mhm);
800 /* Do not increase i! */
679 } 801 }
680 else if ((mhm->attr_flags & MU_ATTRIBUTE_MODIFIED) 802 else
803 {
804 if ((mhm->attr_flags & MU_ATTRIBUTE_MODIFIED)
681 || (mhm->message && message_is_modified (mhm->message))) 805 || (mhm->message && message_is_modified (mhm->message)))
682 { 806 {
683 _amd_attach_message (mailbox, mhm, NULL); 807 _amd_attach_message (mailbox, mhm, NULL);
684 mhm->deleted = mhm->attr_flags & MU_ATTRIBUTE_DELETED; 808 mhm->deleted = mhm->attr_flags & MU_ATTRIBUTE_DELETED;
685 _amd_message_save (amd, mhm, 1); 809 _amd_message_save (amd, mhm, 1);
686 } 810 }
687 mhm = next; 811 i++; /* Move to the next message */
812 }
688 } 813 }
689 814
690 return 0; 815 return 0;
...@@ -695,6 +820,7 @@ amd_save_attributes (mailbox_t mailbox) ...@@ -695,6 +820,7 @@ amd_save_attributes (mailbox_t mailbox)
695 { 820 {
696 struct _amd_data *amd = mailbox->data; 821 struct _amd_data *amd = mailbox->data;
697 struct _amd_message *mhm; 822 struct _amd_message *mhm;
823 size_t i;
698 824
699 if (amd == NULL) 825 if (amd == NULL)
700 return EINVAL; 826 return EINVAL;
...@@ -703,19 +829,17 @@ amd_save_attributes (mailbox_t mailbox) ...@@ -703,19 +829,17 @@ amd_save_attributes (mailbox_t mailbox)
703 return 0; 829 return 0;
704 830
705 /* Find the first dirty(modified) message. */ 831 /* Find the first dirty(modified) message. */
706 for (mhm = amd->msg_head; mhm; mhm = mhm->next) 832 for (i = 0; i < amd->msg_count; i++)
707 { 833 {
834 mhm = amd->msg_array[i];
708 if ((mhm->attr_flags & MU_ATTRIBUTE_MODIFIED) 835 if ((mhm->attr_flags & MU_ATTRIBUTE_MODIFIED)
709 || (mhm->message && message_is_modified (mhm->message))) 836 || (mhm->message && message_is_modified (mhm->message)))
710 break; 837 break;
711 } 838 }
712 839
713 if (!mhm) 840 for ( ; i < amd->msg_count; i++)
714 return 0; /* Nothing changed, just return. */
715
716 while (mhm)
717 { 841 {
718 struct _amd_message *next = mhm->next; 842 mhm = amd->msg_array[i];
719 843
720 if ((mhm->attr_flags & MU_ATTRIBUTE_MODIFIED) 844 if ((mhm->attr_flags & MU_ATTRIBUTE_MODIFIED)
721 || (mhm->message && message_is_modified (mhm->message))) 845 || (mhm->message && message_is_modified (mhm->message)))
...@@ -724,7 +848,6 @@ amd_save_attributes (mailbox_t mailbox) ...@@ -724,7 +848,6 @@ amd_save_attributes (mailbox_t mailbox)
724 mhm->deleted = mhm->attr_flags & MU_ATTRIBUTE_DELETED; 848 mhm->deleted = mhm->attr_flags & MU_ATTRIBUTE_DELETED;
725 _amd_message_save (amd, mhm, 0); 849 _amd_message_save (amd, mhm, 0);
726 } 850 }
727 mhm = next;
728 } 851 }
729 852
730 return 0; 853 return 0;
...@@ -782,61 +905,52 @@ amd_cleanup (void *arg) ...@@ -782,61 +905,52 @@ amd_cleanup (void *arg)
782 } 905 }
783 906
784 /* Insert message msg into the message list on the appropriate position */ 907 /* Insert message msg into the message list on the appropriate position */
785 void 908 int
786 _amd_message_insert (struct _amd_data *amd, struct _amd_message *msg) 909 _amd_message_insert (struct _amd_data *amd, struct _amd_message *msg)
787 { 910 {
788 struct _amd_message *p; 911 size_t index;
789 struct _amd_message *prev;
790
791 for (p = amd->msg_head; p && amd->msg_cmp (p, msg) < 0; p = p->next)
792 ;
793 912
794 if (!p) 913 if (amd_msg_lookup (amd, msg, &index))
795 { 914 {
796 msg->next = NULL; 915 /* Not found. Index is the index of the array cell where msg
797 msg->prev = amd->msg_tail; 916 must be placed */
798 amd->msg_tail = msg; 917 int rc = amd_array_expand (amd, index);
799 if (!amd->msg_head) 918 if (rc)
800 amd->msg_head = msg; 919 return rc;
920 amd->msg_array[index] = msg;
921 msg->amd = amd;
801 } 922 }
802 else 923 else
803 { 924 {
804 msg->next = p; 925 /*FIXME: Found? Shouldn't happen */
805 msg->prev = p->prev; 926 return EEXIST;
806 p->prev = msg;
807 } 927 }
808 if ((prev = msg->prev) != NULL) 928 return 0;
809 prev->next = msg;
810 else
811 amd->msg_head = msg;
812 msg->amd = amd;
813 amd->msg_count++;
814 } 929 }
815 930
816 static void 931 static void
817 _amd_message_delete (struct _amd_data *amd, struct _amd_message *msg) 932 _amd_message_delete (struct _amd_data *amd, struct _amd_message *msg)
818 { 933 {
819 struct _amd_message *p; 934 size_t index;
820 struct _amd_message **pp = amd_pool_lookup (msg); 935 struct _amd_message **pp;
821 936
822 if (pp) 937 if (amd_msg_lookup (amd, msg, &index))
823 *pp = NULL; 938 {
939 /* FIXME: Not found? */
940 return;
941 }
824 942
825 if ((p = msg->next) != NULL) 943 msg = _amd_get_message (amd, index);
826 p->prev = msg->prev;
827 else
828 amd->msg_tail = msg->prev;
829 944
830 if ((p = msg->prev) != NULL) 945 pp = amd_pool_lookup (msg);
831 p->next = msg->next; 946 if (pp)
832 else 947 *pp = NULL;
833 amd->msg_head = msg->next;
834 948
835 message_destroy (&msg->message, msg); 949 message_destroy (&msg->message, msg);
836 if (amd->msg_free) 950 if (amd->msg_free)
837 amd->msg_free (msg); 951 amd->msg_free (msg);
838 free (msg); 952 free (msg);
839 amd->msg_count--; 953 amd_array_shrink (amd, index);
840 } 954 }
841 955
842 /* Scan given message and fill amd_message_t fields. 956 /* Scan given message and fill amd_message_t fields.
...@@ -935,7 +1049,7 @@ amd_is_updated (mailbox_t mailbox) ...@@ -935,7 +1049,7 @@ amd_is_updated (mailbox_t mailbox)
935 struct stat st; 1049 struct stat st;
936 struct _amd_data *amd = mailbox->data; 1050 struct _amd_data *amd = mailbox->data;
937 1051
938 if (!amd->msg_head) 1052 if (amd->msg_count == 0)
939 return 0; 1053 return 0;
940 1054
941 if (stat (amd->name, &st) < 0) 1055 if (stat (amd->name, &st) < 0)
......
...@@ -39,9 +39,6 @@ do \ ...@@ -39,9 +39,6 @@ do \
39 struct _amd_data; 39 struct _amd_data;
40 struct _amd_message 40 struct _amd_message
41 { 41 {
42 struct _amd_message *next;
43 struct _amd_message *prev;
44
45 stream_t stream; /* Associated file stream */ 42 stream_t stream; /* Associated file stream */
46 off_t body_start; /* Offset of body start in the message file */ 43 off_t body_start; /* Offset of body start in the message file */
47 off_t body_end; /* Offset of body end (size of file, effectively)*/ 44 off_t body_end; /* Offset of body end (size of file, effectively)*/
...@@ -72,8 +69,8 @@ struct _amd_data ...@@ -72,8 +69,8 @@ struct _amd_data
72 69
73 /* List of messages: */ 70 /* List of messages: */
74 size_t msg_count; /* number of messages in the list */ 71 size_t msg_count; /* number of messages in the list */
75 struct _amd_message *msg_head; /* First */ 72 size_t msg_max; /* maximum message buffer capacity */
76 struct _amd_message *msg_tail; /* Last */ 73 struct _amd_message **msg_array;
77 74
78 unsigned long uidvalidity; 75 unsigned long uidvalidity;
79 76
...@@ -92,9 +89,13 @@ struct _amd_data ...@@ -92,9 +89,13 @@ struct _amd_data
92 89
93 int amd_init_mailbox __P((mailbox_t mailbox, size_t mhd_size, 90 int amd_init_mailbox __P((mailbox_t mailbox, size_t mhd_size,
94 struct _amd_data **pmhd)); 91 struct _amd_data **pmhd));
95 void _amd_message_insert __P((struct _amd_data *mhd, 92 int _amd_message_insert __P((struct _amd_data *mhd,
96 struct _amd_message *msg)); 93 struct _amd_message *msg));
97 int amd_message_stream_open __P((struct _amd_message *mhm)); 94 int amd_message_stream_open __P((struct _amd_message *mhm));
98 void amd_message_stream_close __P((struct _amd_message *mhm)); 95 void amd_message_stream_close __P((struct _amd_message *mhm));
99 void amd_cleanup (void *arg); 96 void amd_cleanup (void *arg);
100 int amd_url_init (url_t url, const char *scheme); 97 int amd_url_init (url_t url, const char *scheme);
98 struct _amd_message *_amd_get_message __P((struct _amd_data *amd,
99 size_t msgno));
100 int amd_msg_lookup __P((struct _amd_data *amd, struct _amd_message *msg,
101 size_t *pret));
......
...@@ -324,7 +324,8 @@ maildir_message_uid (message_t msg, size_t *puid) ...@@ -324,7 +324,8 @@ maildir_message_uid (message_t msg, size_t *puid)
324 static size_t 324 static size_t
325 maildir_next_uid (struct _amd_data *amd) 325 maildir_next_uid (struct _amd_data *amd)
326 { 326 {
327 struct _maildir_message *msg = (struct _maildir_message *) amd->msg_tail; 327 struct _maildir_message *msg = (struct _maildir_message *)
328 _amd_get_message (amd, amd->msg_count);
328 return (msg ? msg->uid : 0) + 1; 329 return (msg ? msg->uid : 0) + 1;
329 } 330 }
330 331
...@@ -489,13 +490,17 @@ maildir_message_lookup (struct _amd_data *amd, char *file_name) ...@@ -489,13 +490,17 @@ maildir_message_lookup (struct _amd_data *amd, char *file_name)
489 char *p = strchr (file_name, ':'); 490 char *p = strchr (file_name, ':');
490 size_t length = p ? p - file_name : strlen (file_name); 491 size_t length = p ? p - file_name : strlen (file_name);
491 int rc; 492 int rc;
493 size_t i;
492 494
493 for (msg = (struct _maildir_message *) amd->msg_head; 495 /*FIXME!*/
494 msg 496 for (i = 0; i < amd->msg_count; i++)
495 && strlen (msg->file_name) >= length 497 {
496 && (rc = memcmp (msg->file_name, file_name, length)) < 0; 498 msg = (struct _maildir_message *) amd->msg_array[i];
497 msg = (struct _maildir_message *) msg->amd_message.next) 499
498 ; 500 if (strlen (msg->file_name) <= length
501 && (rc = memcmp (msg->file_name, file_name, length)) == 0)
502 break;
503 }
499 return rc == 0 ? msg : NULL; 504 return rc == 0 ? msg : NULL;
500 } 505 }
501 506
...@@ -588,8 +593,8 @@ maildir_scan0 (mailbox_t mailbox, size_t msgno ARG_UNUSED, size_t *pcount, ...@@ -588,8 +593,8 @@ maildir_scan0 (mailbox_t mailbox, size_t msgno ARG_UNUSED, size_t *pcount,
588 593
589 if (do_notify) 594 if (do_notify)
590 { 595 {
591 struct _amd_message *mp; 596 size_t i;
592 for (mp = amd->msg_head; mp; mp = mp->next) 597 for (i = 0; i < amd->msg_count++; i++)
593 { 598 {
594 DISPATCH_ADD_MSG(mailbox, amd); 599 DISPATCH_ADD_MSG(mailbox, amd);
595 } 600 }
...@@ -609,11 +614,11 @@ maildir_scan0 (mailbox_t mailbox, size_t msgno ARG_UNUSED, size_t *pcount, ...@@ -609,11 +614,11 @@ maildir_scan0 (mailbox_t mailbox, size_t msgno ARG_UNUSED, size_t *pcount,
609 amd->uidvalidity = (unsigned long) time (NULL); 614 amd->uidvalidity = (unsigned long) time (NULL);
610 /* FIXME amd->uidnext = amd->msg_count + 1;*/ 615 /* FIXME amd->uidnext = amd->msg_count + 1;*/
611 /* Tell that we have been modified for expunging. */ 616 /* Tell that we have been modified for expunging. */
612 if (amd->msg_head) 617 if (amd->msg_count)
613 { 618 {
614 amd_message_stream_open (amd->msg_head); 619 amd_message_stream_open (amd->msg_array[0]);
615 amd_message_stream_close (amd->msg_head); 620 amd_message_stream_close (amd->msg_array[0]);
616 amd->msg_head->attr_flags |= MU_ATTRIBUTE_MODIFIED; 621 amd->msg_array[0]->attr_flags |= MU_ATTRIBUTE_MODIFIED;
617 } 622 }
618 } 623 }
619 } 624 }
......
...@@ -85,7 +85,8 @@ mh_message_cmp (struct _amd_message *a, struct _amd_message *b) ...@@ -85,7 +85,8 @@ mh_message_cmp (struct _amd_message *a, struct _amd_message *b)
85 static size_t 85 static size_t
86 _mh_next_seq (struct _amd_data *amd) 86 _mh_next_seq (struct _amd_data *amd)
87 { 87 {
88 struct _mh_message *msg = (struct _mh_message *) amd->msg_tail; 88 struct _mh_message *msg = (struct _mh_message *)
89 _amd_get_message (amd, amd->msg_count);
89 return (msg ? msg->seq_number : 0) + 1; 90 return (msg ? msg->seq_number : 0) + 1;
90 } 91 }
91 92
...@@ -111,16 +112,14 @@ _mh_message_name (struct _amd_message *amsg, int deleted) ...@@ -111,16 +112,14 @@ _mh_message_name (struct _amd_message *amsg, int deleted)
111 static struct _mh_message * 112 static struct _mh_message *
112 _mh_get_message_seq (struct _amd_data *amd, size_t seq) 113 _mh_get_message_seq (struct _amd_data *amd, size_t seq)
113 { 114 {
114 struct _mh_message *msg; 115 struct _mh_message msg;
115 116 size_t index;
116 for (msg = (struct _mh_message *) amd->msg_head;
117 msg && msg->seq_number < seq;
118 msg = (struct _mh_message *) msg->amd_message.next)
119 ;
120 117
121 if (msg) 118 msg.seq_number = seq;
122 return msg->seq_number == seq ? msg : NULL; 119 if (amd_msg_lookup (amd, (struct _amd_message*) &msg, &index))
123 return NULL; 120 return NULL;
121
122 return (struct _mh_message *) _amd_get_message (amd, index);
124 } 123 }
125 124
126 /* Scan the mailbox */ 125 /* Scan the mailbox */
...@@ -205,8 +204,9 @@ mh_scan0 (mailbox_t mailbox, size_t msgno ARG_UNUSED, size_t *pcount, ...@@ -205,8 +204,9 @@ mh_scan0 (mailbox_t mailbox, size_t msgno ARG_UNUSED, size_t *pcount,
205 204
206 if (do_notify) 205 if (do_notify)
207 { 206 {
208 struct _amd_message *mp; 207 size_t i;
209 for (mp = amd->msg_head; mp; mp = mp->next) 208
209 for (i = 0; i < amd->msg_count; i++)
210 { 210 {
211 DISPATCH_ADD_MSG(mailbox, amd); 211 DISPATCH_ADD_MSG(mailbox, amd);
212 } 212 }
...@@ -225,11 +225,11 @@ mh_scan0 (mailbox_t mailbox, size_t msgno ARG_UNUSED, size_t *pcount, ...@@ -225,11 +225,11 @@ mh_scan0 (mailbox_t mailbox, size_t msgno ARG_UNUSED, size_t *pcount,
225 { 225 {
226 amd->uidvalidity = (unsigned long)time (NULL); 226 amd->uidvalidity = (unsigned long)time (NULL);
227 /* Tell that we have been modified for expunging. */ 227 /* Tell that we have been modified for expunging. */
228 if (amd->msg_head) 228 if (amd->msg_count)
229 { 229 {
230 amd_message_stream_open (amd->msg_head); 230 amd_message_stream_open (amd->msg_array[0]);
231 amd_message_stream_close (amd->msg_head); 231 amd_message_stream_close (amd->msg_array[0]);
232 amd->msg_head->attr_flags |= MU_ATTRIBUTE_MODIFIED; 232 amd->msg_array[0]->attr_flags |= MU_ATTRIBUTE_MODIFIED;
233 } 233 }
234 } 234 }
235 } 235 }
......