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
Showing
4 changed files
with
246 additions
and
126 deletions
... | @@ -107,15 +107,139 @@ static int amd_pool_open_count __P((struct _amd_data *amd)); | ... | @@ -107,15 +107,139 @@ static int amd_pool_open_count __P((struct _amd_data *amd)); |
107 | static struct _amd_message **amd_pool_lookup __P((struct _amd_message *mhm)); | 107 | static struct _amd_message **amd_pool_lookup __P((struct _amd_message *mhm)); |
108 | 108 | ||
109 | static int amd_envelope_date __P((envelope_t envelope, char *buf, size_t len, | 109 | static int amd_envelope_date __P((envelope_t envelope, char *buf, size_t len, |
110 | size_t *psize)); | 110 | size_t *psize)); |
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 | |||
114 | /* Operations on message array */ | ||
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 | } | ||
113 | 227 | ||
114 | /* Should be in other header file. */ | 228 | /* Shrink the message array by removing element at INDEX-1 and |
115 | extern int amd_message_number __P ((message_t msg, size_t *pnum)); | 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 | } | ||
116 | 239 | ||
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) |
119 | { | 243 | { |
120 | struct _amd_data *amd; | 244 | struct _amd_data *amd; |
121 | size_t name_len; | 245 | size_t name_len; |
... | @@ -171,21 +295,19 @@ static void | ... | @@ -171,21 +295,19 @@ 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 | } |
188 | 309 | free (amd->msg_array); | |
310 | |||
189 | if (amd->name) | 311 | if (amd->name) |
190 | free (amd->name); | 312 | free (amd->name); |
191 | 313 | ||
... | @@ -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,7 +762,8 @@ amd_expunge (mailbox_t mailbox) | ... | @@ -640,7 +762,8 @@ 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; |
643 | 765 | size_t i; | |
766 | |||
644 | if (amd == NULL) | 767 | if (amd == NULL) |
645 | return EINVAL; | 768 | return EINVAL; |
646 | 769 | ||
... | @@ -648,21 +771,19 @@ amd_expunge (mailbox_t mailbox) | ... | @@ -648,21 +771,19 @@ 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 | { |
668 | if (!mhm->deleted) | 789 | if (!mhm->deleted) |
... | @@ -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 |
681 | || (mhm->message && message_is_modified (mhm->message))) | ||
682 | { | 803 | { |
683 | _amd_attach_message (mailbox, mhm, NULL); | 804 | if ((mhm->attr_flags & MU_ATTRIBUTE_MODIFIED) |
684 | mhm->deleted = mhm->attr_flags & MU_ATTRIBUTE_DELETED; | 805 | || (mhm->message && message_is_modified (mhm->message))) |
685 | _amd_message_save (amd, mhm, 1); | 806 | { |
807 | _amd_attach_message (mailbox, mhm, NULL); | ||
808 | mhm->deleted = mhm->attr_flags & MU_ATTRIBUTE_DELETED; | ||
809 | _amd_message_save (amd, mhm, 1); | ||
810 | } | ||
811 | i++; /* Move to the next message */ | ||
686 | } | 812 | } |
687 | mhm = next; | ||
688 | } | 813 | } |
689 | 814 | ||
690 | return 0; | 815 | return 0; |
... | @@ -695,7 +820,8 @@ amd_save_attributes (mailbox_t mailbox) | ... | @@ -695,7 +820,8 @@ 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; |
698 | 823 | size_t i; | |
824 | |||
699 | if (amd == NULL) | 825 | if (amd == NULL) |
700 | return EINVAL; | 826 | return EINVAL; |
701 | 827 | ||
... | @@ -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; |
936 | |||
937 | if (amd_msg_lookup (amd, msg, &index)) | ||
938 | { | ||
939 | /* FIXME: Not found? */ | ||
940 | return; | ||
941 | } | ||
942 | |||
943 | msg = _amd_get_message (amd, index); | ||
821 | 944 | ||
945 | pp = amd_pool_lookup (msg); | ||
822 | if (pp) | 946 | if (pp) |
823 | *pp = NULL; | 947 | *pp = NULL; |
824 | 948 | ||
825 | if ((p = msg->next) != NULL) | ||
826 | p->prev = msg->prev; | ||
827 | else | ||
828 | amd->msg_tail = msg->prev; | ||
829 | |||
830 | if ((p = msg->prev) != NULL) | ||
831 | p->next = msg->next; | ||
832 | else | ||
833 | amd->msg_head = msg->next; | ||
834 | |||
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 | |
117 | msg && msg->seq_number < seq; | 118 | msg.seq_number = seq; |
118 | msg = (struct _mh_message *) msg->amd_message.next) | 119 | if (amd_msg_lookup (amd, (struct _amd_message*) &msg, &index)) |
119 | ; | 120 | return NULL; |
120 | 121 | ||
121 | if (msg) | 122 | return (struct _mh_message *) _amd_get_message (amd, index); |
122 | return msg->seq_number == seq ? msg : NULL; | ||
123 | return NULL; | ||
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 | } | ... | ... |
-
Please register or sign in to post a comment