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