Mercurial > dovecot > original-hg > dovecot-1.2
comparison src/lib-storage/index/maildir/maildir-sync.c @ 4848:967de900c73a HEAD
Mailbox list indexing and related changes. Currently works only with
maildir and mmap_disable=no. This allows doing STATUS to synced mailboxes
without opening their index files at all.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 26 Nov 2006 00:17:39 +0200 |
parents | 615b7738a62f |
children | 24afafbfe47b |
comparison
equal
deleted
inserted
replaced
4847:7f250cd01843 | 4848:967de900c73a |
---|---|
177 #include "hash.h" | 177 #include "hash.h" |
178 #include "str.h" | 178 #include "str.h" |
179 #include "maildir-storage.h" | 179 #include "maildir-storage.h" |
180 #include "maildir-uidlist.h" | 180 #include "maildir-uidlist.h" |
181 #include "maildir-keywords.h" | 181 #include "maildir-keywords.h" |
182 #include "maildir-sync.h" | |
182 | 183 |
183 #include <stdio.h> | 184 #include <stdio.h> |
184 #include <stddef.h> | 185 #include <stddef.h> |
185 #include <unistd.h> | 186 #include <unistd.h> |
186 #include <dirent.h> | 187 #include <dirent.h> |
187 #include <sys/stat.h> | 188 #include <sys/stat.h> |
188 | |
189 #define MAILDIR_SYNC_SECS 1 | |
190 | 189 |
191 #define MAILDIR_FILENAME_FLAG_FOUND 128 | 190 #define MAILDIR_FILENAME_FLAG_FOUND 128 |
192 | 191 |
193 /* When rename()ing many files from new/ to cur/, it's possible that next | 192 /* When rename()ing many files from new/ to cur/, it's possible that next |
194 readdir() skips some files. we don't of course wish to lose them, so we | 193 readdir() skips some files. we don't of course wish to lose them, so we |
772 t_pop(); | 771 t_pop(); |
773 return ret < 0 ? -1 : (moves <= MAILDIR_RENAME_RESCAN_COUNT ? 0 : 1); | 772 return ret < 0 ? -1 : (moves <= MAILDIR_RENAME_RESCAN_COUNT ? 0 : 1); |
774 } | 773 } |
775 | 774 |
776 static void | 775 static void |
777 maildir_sync_update_from_header(struct maildir_mailbox *mbox) | 776 maildir_sync_update_from_header(struct maildir_mailbox *mbox, |
778 { | 777 struct mail_index_header *hdr_r) |
779 uint64_t value; | 778 { |
779 struct mail_index_view *view; | |
780 const struct mail_index_header *hdr; | |
781 | |
782 /* open a new view so we get the latest header */ | |
783 view = mail_index_view_open(mbox->ibox.index); | |
784 hdr = mail_index_get_header(view); | |
780 | 785 |
781 /* FIXME: ugly, replace with extension header */ | 786 /* FIXME: ugly, replace with extension header */ |
782 value = mail_index_get_header(mbox->ibox.view)->sync_size; | 787 mbox->last_new_mtime = hdr->sync_size & 0xffffffff; |
783 mbox->last_new_mtime = value & 0xffffffff; | 788 mbox->last_dirty_flags = (hdr->sync_size >> 32) & |
784 mbox->last_new_sync_time = value >> 32; | 789 (MAILDIR_DIRTY_NEW | MAILDIR_DIRTY_CUR); |
785 | 790 |
786 mbox->last_cur_mtime = | 791 mbox->last_cur_mtime = hdr->sync_stamp; |
787 mail_index_get_header(mbox->ibox.view)->sync_stamp; | 792 |
793 if ((mbox->last_dirty_flags & MAILDIR_DIRTY_CUR) != 0 && | |
794 mbox->dirty_cur_time < mbox->last_cur_mtime) | |
795 mbox->dirty_cur_time = mbox->last_cur_mtime; | |
796 | |
797 *hdr_r = *hdr; | |
798 mail_index_view_close(&view); | |
788 } | 799 } |
789 | 800 |
790 static int | 801 static int |
791 maildir_sync_quick_check(struct maildir_mailbox *mbox, | 802 maildir_sync_quick_check(struct maildir_mailbox *mbox, |
792 const char *new_dir, const char *cur_dir, | 803 const char *new_dir, const char *cur_dir, |
793 bool *new_changed_r, bool *cur_changed_r) | 804 bool *new_changed_r, bool *cur_changed_r) |
794 { | 805 { |
795 struct index_mailbox *ibox = &mbox->ibox; | 806 struct index_mailbox *ibox = &mbox->ibox; |
807 struct mail_index_header hdr; | |
796 struct stat st; | 808 struct stat st; |
797 time_t new_mtime, cur_mtime; | 809 time_t new_mtime, cur_mtime; |
798 | 810 |
799 *new_changed_r = *cur_changed_r = FALSE; | 811 *new_changed_r = *cur_changed_r = FALSE; |
800 | 812 |
815 /* cur stamp is kept in index, we don't have to sync if | 827 /* cur stamp is kept in index, we don't have to sync if |
816 someone else has done it and updated the index. | 828 someone else has done it and updated the index. |
817 | 829 |
818 FIXME: For now we're using sync_size field as the new/ dir's stamp. | 830 FIXME: For now we're using sync_size field as the new/ dir's stamp. |
819 Pretty ugly.. */ | 831 Pretty ugly.. */ |
820 maildir_sync_update_from_header(mbox); | 832 maildir_sync_update_from_header(mbox, &hdr); |
821 if ((mbox->dirty_cur_time == 0 && cur_mtime != mbox->last_cur_mtime) || | 833 if ((mbox->dirty_cur_time == 0 && cur_mtime != mbox->last_cur_mtime) || |
822 (new_mtime != mbox->last_new_mtime)) { | 834 (new_mtime != mbox->last_new_mtime)) { |
823 /* check if the index has been updated.. */ | 835 /* check if the index has been updated.. */ |
824 if (mail_index_refresh(ibox->index) < 0) { | 836 if (mail_index_refresh(ibox->index) < 0) { |
825 mail_storage_set_index_error(ibox); | 837 mail_storage_set_index_error(ibox); |
826 return -1; | 838 return -1; |
827 } | 839 } |
828 | 840 |
829 maildir_sync_update_from_header(mbox); | 841 maildir_sync_update_from_header(mbox, &hdr); |
830 } | 842 } |
831 | 843 |
832 /* If we're removing recent flags, always sync new/ directory if | 844 /* If we're removing recent flags, always sync new/ directory if |
833 it has mails. */ | 845 it has mails. */ |
834 if (new_mtime != mbox->last_new_mtime || | 846 if (new_mtime != mbox->last_new_mtime || |
835 new_mtime >= mbox->last_new_sync_time - MAILDIR_SYNC_SECS || | 847 ((mbox->last_dirty_flags & MAILDIR_DIRTY_NEW) != 0 && |
836 (!ibox->keep_recent && | 848 new_mtime < ioloop_time - MAILDIR_SYNC_SECS) || |
837 mail_index_get_header(ibox->view)->recent_messages_count > 0)) { | 849 (!ibox->keep_recent && hdr.recent_messages_count > 0)) { |
838 *new_changed_r = TRUE; | 850 *new_changed_r = TRUE; |
839 mbox->last_new_mtime = new_mtime; | 851 mbox->last_new_mtime = new_mtime; |
840 mbox->last_new_sync_time = ioloop_time; | 852 |
853 if (new_mtime < ioloop_time - MAILDIR_SYNC_SECS) | |
854 mbox->last_dirty_flags &= ~MAILDIR_DIRTY_NEW; | |
855 else | |
856 mbox->last_dirty_flags |= MAILDIR_DIRTY_NEW; | |
841 } | 857 } |
842 | 858 |
843 if (cur_mtime != mbox->last_cur_mtime || | 859 if (cur_mtime != mbox->last_cur_mtime || |
844 (mbox->dirty_cur_time != 0 && | 860 (mbox->dirty_cur_time != 0 && |
845 ioloop_time - mbox->dirty_cur_time > MAILDIR_SYNC_SECS)) { | 861 ioloop_time - mbox->dirty_cur_time > MAILDIR_SYNC_SECS)) { |
846 /* cur/ changed, or delayed cur/ check */ | 862 /* cur/ changed, or delayed cur/ check */ |
847 *cur_changed_r = TRUE; | 863 *cur_changed_r = TRUE; |
848 mbox->last_cur_mtime = cur_mtime; | 864 mbox->last_cur_mtime = cur_mtime; |
849 | 865 |
850 mbox->dirty_cur_time = | 866 if (cur_mtime < ioloop_time - MAILDIR_SYNC_SECS) { |
851 cur_mtime >= ioloop_time - MAILDIR_SYNC_SECS ? | 867 mbox->last_dirty_flags &= ~MAILDIR_DIRTY_CUR; |
852 cur_mtime : 0; | 868 mbox->dirty_cur_time = 0; |
869 } else { | |
870 mbox->last_dirty_flags |= MAILDIR_DIRTY_CUR; | |
871 mbox->dirty_cur_time = cur_mtime; | |
872 } | |
853 } | 873 } |
854 | 874 |
855 return 0; | 875 return 0; |
856 } | 876 } |
857 | 877 |
945 enum mail_flags flags; | 965 enum mail_flags flags; |
946 ARRAY_TYPE(keyword_indexes) keywords; | 966 ARRAY_TYPE(keyword_indexes) keywords; |
947 ARRAY_TYPE(keyword_indexes) idx_keywords; | 967 ARRAY_TYPE(keyword_indexes) idx_keywords; |
948 uint32_t uid_validity, next_uid; | 968 uint32_t uid_validity, next_uid; |
949 uint64_t value; | 969 uint64_t value; |
950 time_t old_new_sync_time; | |
951 int ret = 0; | 970 int ret = 0; |
952 bool full_rescan = FALSE; | 971 bool full_rescan = FALSE; |
953 | 972 |
954 i_assert(maildir_uidlist_is_locked(sync_ctx->mbox->uidlist)); | 973 i_assert(maildir_uidlist_is_locked(sync_ctx->mbox->uidlist)); |
955 | 974 |
1177 if (maildir_sync_index_records(sync_ctx) < 0) | 1196 if (maildir_sync_index_records(sync_ctx) < 0) |
1178 ret = -1; | 1197 ret = -1; |
1179 mbox->syncing_commit = FALSE; | 1198 mbox->syncing_commit = FALSE; |
1180 } | 1199 } |
1181 | 1200 |
1182 if (mbox->dirty_cur_time == 0 && | 1201 if (mbox->dirty_cur_time != 0) |
1183 mbox->last_cur_mtime != (time_t)hdr->sync_stamp) { | 1202 mbox->last_dirty_flags |= MAILDIR_DIRTY_CUR; |
1203 | |
1204 if (mbox->last_cur_mtime != (time_t)hdr->sync_stamp) { | |
1184 uint32_t sync_stamp = mbox->last_cur_mtime; | 1205 uint32_t sync_stamp = mbox->last_cur_mtime; |
1185 | 1206 |
1186 mail_index_update_header(trans, | 1207 mail_index_update_header(trans, |
1187 offsetof(struct mail_index_header, sync_stamp), | 1208 offsetof(struct mail_index_header, sync_stamp), |
1188 &sync_stamp, sizeof(sync_stamp), TRUE); | 1209 &sync_stamp, sizeof(sync_stamp), TRUE); |
1189 } | 1210 } |
1190 | 1211 |
1191 /* FIXME: use a header extension instead of sync_size.. */ | 1212 /* FIXME: use a header extension instead of sync_size.. */ |
1192 value = mbox->last_new_mtime; | 1213 value = mbox->last_new_mtime | |
1193 old_new_sync_time = hdr->sync_size >> 32; | 1214 ((uint64_t)mbox->last_dirty_flags << 32); |
1194 if (mbox->last_new_mtime >= old_new_sync_time - MAILDIR_SYNC_SECS) { | |
1195 value |= (uint64_t)mbox->last_new_sync_time << 32; | |
1196 } else { | |
1197 value |= (uint64_t)old_new_sync_time << 32; | |
1198 } | |
1199 if (value != hdr->sync_size) { | 1215 if (value != hdr->sync_size) { |
1200 uint64_t sync_stamp = mbox->last_new_mtime | | |
1201 ((uint64_t)mbox->last_new_sync_time << 32); | |
1202 | |
1203 mail_index_update_header(trans, | 1216 mail_index_update_header(trans, |
1204 offsetof(struct mail_index_header, sync_size), | 1217 offsetof(struct mail_index_header, sync_size), |
1205 &sync_stamp, sizeof(sync_stamp), TRUE); | 1218 &value, sizeof(value), TRUE); |
1206 } | 1219 } |
1207 | 1220 |
1208 if (hdr->uid_validity == 0) { | 1221 if (hdr->uid_validity == 0) { |
1209 /* get the initial uidvalidity */ | 1222 /* get the initial uidvalidity */ |
1210 if (maildir_uidlist_update(mbox->uidlist) < 0) | 1223 if (maildir_uidlist_update(mbox->uidlist) < 0) |
1382 { | 1395 { |
1383 struct maildir_mailbox *mbox = (struct maildir_mailbox *)box; | 1396 struct maildir_mailbox *mbox = (struct maildir_mailbox *)box; |
1384 struct maildir_sync_context *ctx; | 1397 struct maildir_sync_context *ctx; |
1385 int ret = 0; | 1398 int ret = 0; |
1386 | 1399 |
1400 if (!box->opened) { | |
1401 if (index_storage_mailbox_open(&mbox->ibox) < 0) | |
1402 return index_mailbox_sync_init(box, 0, TRUE); | |
1403 } | |
1404 | |
1387 if ((flags & MAILBOX_SYNC_FLAG_FAST) == 0 || | 1405 if ((flags & MAILBOX_SYNC_FLAG_FAST) == 0 || |
1388 mbox->ibox.sync_last_check + MAILBOX_FULL_SYNC_INTERVAL <= | 1406 mbox->ibox.sync_last_check + MAILBOX_FULL_SYNC_INTERVAL <= |
1389 ioloop_time) { | 1407 ioloop_time) { |
1390 mbox->ibox.sync_last_check = ioloop_time; | 1408 mbox->ibox.sync_last_check = ioloop_time; |
1391 | 1409 |