]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Use mtime to check changes in dovecot-uidlist file rather than inode changes
authorTimo Sirainen <tss@iki.fi>
Mon, 21 Apr 2003 13:42:00 +0000 (16:42 +0300)
committerTimo Sirainen <tss@iki.fi>
Mon, 21 Apr 2003 13:42:00 +0000 (16:42 +0300)
which aren't reliable.

--HG--
branch : HEAD

src/lib-index/mail-index.h
src/lib-index/maildir/maildir-sync.c
src/lib-index/maildir/maildir-uidlist.c
src/lib-index/maildir/maildir-uidlist.h

index de7257eebaa8d5526cb00e9c2b31b04bbc0b1841..9ee3131b5630ba8c8df65ee3f1482fa0db935410 100644 (file)
@@ -394,9 +394,7 @@ struct mail_index {
        ino_t mbox_ino;
 
        /* last maildir sync: */
-       dev_t uidlist_dev;
-       ino_t uidlist_ino;
-
+       time_t uidlist_mtime;
        int maildir_lock_fd;
 
        int fd; /* opened index file */
@@ -445,7 +443,7 @@ struct mail_index {
        0, 0, 0, 0, 0, 0, { 0, 0, 0 }, 0, 0, \
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
-       0, 0, 0, 0, 0, 0, 0, 0, 0
+       0, 0, 0, 0, 0, 0, 0, 0
 #endif
 
 /* defaults - same as above but prefixed with mail_index_. */
index 2a1c1b997cf3c37213c22a79fc962f66a49a8961..f821f85823c11c3ba0263db0b9fb154f843ce286 100644 (file)
@@ -197,6 +197,16 @@ static int maildir_sync_uidlist(struct mail_index *index, const char *dir,
                        return FALSE;
                }
 
+               if (uid_rec.uid > uid &&
+                   (hash_rec->action == MAILDIR_FILE_ACTION_UPDATE_FLAGS ||
+                    hash_rec->action == MAILDIR_FILE_ACTION_NONE)) {
+                       /* it's UID has changed */
+                       hash_rec->action = MAILDIR_FILE_ACTION_UPDATE_CONTENT;
+
+                       /* make sure filename is not invalidated by expunge */
+                       hash_insert(files, p_strdup(pool, fname), hash_rec);
+               }
+
                switch (hash_rec->action) {
                case MAILDIR_FILE_ACTION_EXPUNGE:
                        if (!index->expunge(index, rec, seq, TRUE))
@@ -247,7 +257,14 @@ static int maildir_sync_uidlist(struct mail_index *index, const char *dir,
                        i_assert(hash_rec->action == MAILDIR_FILE_ACTION_NEW);
 
                        /* make sure we set the same UID for it. */
-                       i_assert(index->header->next_uid <= uid_rec.uid);
+                       if (index->header->next_uid > uid_rec.uid) {
+                               index_set_corrupted(index,
+                                                   "index.next_uid (%u) > "
+                                                   "uid_rec.uid (%u)",
+                                                   index->header->next_uid,
+                                                   uid_rec.uid);
+                               return FALSE;
+                       }
                        index->header->next_uid = uid_rec.uid;
 
                         hash_rec->action = MAILDIR_FILE_ACTION_NONE;
@@ -428,7 +445,7 @@ static int maildir_index_lock_and_sync(struct mail_index *index, int *changes,
        struct utimbuf ut;
        struct maildir_uidlist *uidlist;
        const char *uidlist_path, *cur_dir, *new_dir;
-       time_t index_mtime;
+       time_t index_mtime, uidlist_mtime;
        int cur_changed;
 
        *uidlist_r = uidlist = NULL;
@@ -456,12 +473,13 @@ static int maildir_index_lock_and_sync(struct mail_index *index, int *changes,
 
                memset(&st, 0, sizeof(st));
                cur_changed = TRUE;
+                uidlist_mtime = 0;
        } else {
-               /* FIXME: save device and inode into index header, so we don't
+               /* FIXME: save mtime into index header, so we don't
                   have to read it every time mailbox is opened */
+                uidlist_mtime = st.st_mtime;
                cur_changed = index_mtime != std.st_mtime ||
-                       st.st_ino != index->uidlist_ino ||
-                       !CMP_DEV_T(st.st_dev, index->uidlist_dev);
+                       index->uidlist_mtime != uidlist_mtime;
        }
 
        if (new_dirp != NULL || cur_changed) {
@@ -556,18 +574,12 @@ static int maildir_index_lock_and_sync(struct mail_index *index, int *changes,
                        return TRUE;
                }
 
-               if (fstat(index->maildir_lock_fd, &st) < 0) {
-                       return index_file_set_syscall_error(index, uidlist_path,
-                                                           "fstat()");
-               }
-
-               if (!maildir_uidlist_rewrite(index))
+               if (!maildir_uidlist_rewrite(index, &uidlist_mtime))
                        return FALSE;
        }
 
        /* uidlist file synced */
-       index->uidlist_ino = st.st_ino;
-       index->uidlist_dev = st.st_dev;
+       index->uidlist_mtime = uidlist_mtime;
 
        /* update sync stamp */
        index->file_sync_stamp = std.st_mtime;
index 484bbc7a766ab1e63be4b29979ba0c2b1ccf9a86..5b8f194dd763400b4f0c348529e1906b73a6f480 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <stdio.h>
 #include <sys/stat.h>
+#include <utime.h>
 
 /* how many seconds to wait before overriding uidlist.lock */
 #define UIDLIST_LOCK_STALE_TIMEOUT (60*5)
@@ -168,23 +169,14 @@ void maildir_uidlist_close(struct maildir_uidlist *uidlist)
        i_free(uidlist);
 }
 
-int maildir_uidlist_rewrite(struct mail_index *index)
+static int maildir_uidlist_rewrite_fd(struct mail_index *index,
+                                     const char *temp_path, time_t *mtime)
 {
        struct mail_index_record *rec;
-       const char *temp_path, *db_path, *p, *fname;
+       struct utimbuf ut;
+       const char *p, *fname;
        string_t *str;
        size_t len;
-       int failed = FALSE;
-
-       i_assert(INDEX_IS_UIDLIST_LOCKED(index));
-
-       if (index->lock_type == MAIL_LOCK_UNLOCK) {
-               if (!index->set_lock(index, MAIL_LOCK_SHARED))
-                       return FALSE;
-       }
-
-       temp_path = t_strconcat(index->mailbox_path,
-                               "/" MAILDIR_UIDLIST_NAME ".lock", NULL);
 
        str = t_str_new(4096);
        str_printfa(str, "1 %u %u\n",
@@ -194,7 +186,7 @@ int maildir_uidlist_rewrite(struct mail_index *index)
        while (rec != NULL) {
                fname = maildir_get_location(index, rec);
                if (fname == NULL)
-                       break;
+                       return FALSE;
 
                p = strchr(fname, ':');
                len = p == NULL ? strlen(fname) : (size_t)(p-fname);
@@ -205,7 +197,7 @@ int maildir_uidlist_rewrite(struct mail_index *index)
                                       str_data(str), str_len(str)) < 0) {
                                index_file_set_syscall_error(index, temp_path,
                                                             "write_full()");
-                               break;
+                               return FALSE;
                        }
                        str_truncate(str, 0);
                }
@@ -220,20 +212,47 @@ int maildir_uidlist_rewrite(struct mail_index *index)
        if (write_full(index->maildir_lock_fd,
                       str_data(str), str_len(str)) < 0) {
                index_file_set_syscall_error(index, temp_path, "write_full()");
-               failed = TRUE;
+               return FALSE;
        }
 
-       if (fdatasync(index->maildir_lock_fd) < 0) {
-               index_file_set_syscall_error(index, temp_path, "fdatasync()");
-               failed = TRUE;
+       /* uidlist's mtime must grow every time */
+       *mtime = ioloop_time > *mtime ? ioloop_time : *mtime + 1;
+       ut.actime = ioloop_time;
+       ut.modtime = *mtime;
+       if (utime(temp_path, &ut) < 0)
+               index_set_syscall_error(index, "utime()");
+
+       if (fsync(index->maildir_lock_fd) < 0) {
+               index_file_set_syscall_error(index, temp_path, "fsync()");
+               return FALSE;
        }
+
+       return TRUE;
+}
+
+int maildir_uidlist_rewrite(struct mail_index *index, time_t *mtime)
+{
+       const char *temp_path, *db_path;
+       int failed = FALSE;
+
+       i_assert(INDEX_IS_UIDLIST_LOCKED(index));
+
+       if (index->lock_type == MAIL_LOCK_UNLOCK) {
+               if (!index->set_lock(index, MAIL_LOCK_SHARED))
+                       return FALSE;
+       }
+
+       temp_path = t_strconcat(index->mailbox_path,
+                               "/" MAILDIR_UIDLIST_NAME ".lock", NULL);
+
+       failed = !maildir_uidlist_rewrite_fd(index, temp_path, mtime);
        if (close(index->maildir_lock_fd) < 0) {
                index_file_set_syscall_error(index, temp_path, "close()");
                failed = TRUE;
        }
         index->maildir_lock_fd = -1;
 
-       if (rec == NULL) {
+       if (!failed) {
                db_path = t_strconcat(index->mailbox_path,
                                      "/" MAILDIR_UIDLIST_NAME, NULL);
 
index c8ab9db0e17941248d462b1e5b3ee6a9c6226090..9e95255a08408b9c61434e47eed483beae47c025 100644 (file)
@@ -22,7 +22,7 @@ struct maildir_uidlist_rec {
 
 int maildir_uidlist_try_lock(struct mail_index *index);
 void maildir_uidlist_unlock(struct mail_index *index);
-int maildir_uidlist_rewrite(struct mail_index *index);
+int maildir_uidlist_rewrite(struct mail_index *index, time_t *mtime);
 
 struct maildir_uidlist *maildir_uidlist_open(struct mail_index *index);
 void maildir_uidlist_close(struct maildir_uidlist *uidlist);