]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
handle losing index file
authorTimo Sirainen <tss@iki.fi>
Sat, 1 May 2004 16:08:15 +0000 (19:08 +0300)
committerTimo Sirainen <tss@iki.fi>
Sat, 1 May 2004 16:08:15 +0000 (19:08 +0300)
--HG--
branch : HEAD

src/lib-index/mail-index-lock.c
src/lib-index/mail-index-private.h
src/lib-index/mail-index-reset.c
src/lib-index/mail-index-view.c
src/lib-index/mail-index.c
src/lib-index/mail-transaction-log-view.c
src/lib-index/mail-transaction-log.c
src/lib-index/mail-transaction-log.h

index 15a38f301771dad5d200a87c6c920243fd9bd8af..5a1c1bcd234b818b795c9e8296e033ecaba8864c 100644 (file)
@@ -100,8 +100,15 @@ static int mail_index_has_changed(struct mail_index *index)
 
        if (fstat(index->fd, &st1) < 0)
                return mail_index_set_syscall_error(index, "fstat()");
-       if (stat(index->filepath, &st2) < 0)
-               return mail_index_set_syscall_error(index, "stat()");
+       if (stat(index->filepath, &st2) < 0) {
+               mail_index_set_syscall_error(index, "stat()");
+               if (errno != ENOENT)
+                       return -1;
+
+               /* lost it? recreate */
+               (void)mail_index_reset(index);
+               return -1;
+       }
 
        if (st1.st_ino != st2.st_ino ||
            !CMP_DEV_T(st1.st_dev, st2.st_dev)) {
index b6dbef10ba4e02afd7cfe16c38d5420d03cdb5e1..fcc9d8a6673e14446313f37482ce462d1cc9f119 100644 (file)
@@ -87,7 +87,6 @@ void mail_index_header_init(struct mail_index_header *hdr);
 int mail_index_write_header(struct mail_index *index,
                            const struct mail_index_header *hdr);
 
-int mail_index_create(struct mail_index *index, struct mail_index_header *hdr);
 int mail_index_try_open_only(struct mail_index *index);
 int mail_index_try_open(struct mail_index *index, unsigned int *lock_id_r);
 int mail_index_create_tmp_file(struct mail_index *index, const char **path_r);
@@ -129,7 +128,6 @@ int mail_index_sync_get_rec(struct mail_index_view *view,
                            const void *data, size_t *data_offset);
 
 void mail_index_set_inconsistent(struct mail_index *index);
-int mail_index_mark_corrupted(struct mail_index *index);
 
 int mail_index_set_error(struct mail_index *index, const char *fmt, ...)
        __attr_format__(2, 3);
index c5d04156026d4de304b055cb34a6b9cc2363641d..ec608fcd2db9c2d992bc6786a818af1bb24a619a 100644 (file)
@@ -6,28 +6,60 @@
 #include "mail-index-private.h"
 #include "mail-transaction-log.h"
 
-int mail_index_reset(struct mail_index *index)
+static int mail_index_mark_corrupted(struct mail_index *index)
 {
        struct mail_index_header hdr;
 
-       if (mail_index_mark_corrupted(index) < 0)
+       if (index->readonly)
+               return 0;
+
+       /* make sure we can write the header */
+       if (!MAIL_INDEX_MAP_IS_IN_MEMORY(index->map)) {
+               if (mprotect(index->map->mmap_base, sizeof(hdr),
+                            PROT_READ | PROT_WRITE) < 0) {
+                       mail_index_set_syscall_error(index, "mprotect()");
+                       return -1;
+               }
+       }
+
+       hdr = *index->hdr;
+       hdr.flags |= MAIL_INDEX_HDR_FLAG_CORRUPTED;
+       if (mail_index_write_header(index, &hdr) < 0)
                return -1;
 
+       if (fsync(index->fd) < 0)
+               return mail_index_set_syscall_error(index, "fsync()");
+
+       mail_index_set_inconsistent(index);
+       return 0;
+}
+
+int mail_index_reset(struct mail_index *index)
+{
+       struct mail_index_header hdr;
+       uint32_t file_seq;
+       uoff_t file_offset;
+       int log_locked;
+
        mail_index_header_init(&hdr);
        if (hdr.indexid == index->indexid)
                hdr.indexid++;
 
-       // FIXME: close it? ..
-       if (mail_index_create(index, &hdr) < 0)
+       if (mail_index_mark_corrupted(index) < 0)
                return -1;
 
-       /* reopen transaction log - FIXME: doesn't work, we have log views
-          open.. */
-        mail_transaction_log_close(index->log);
-       index->log = mail_transaction_log_open_or_create(index);
-       if (index->log == NULL) {
-               /* FIXME: creates potential crashes.. */
+       log_locked = index->log_locked;
+       if (log_locked)
+                mail_transaction_log_sync_unlock(index->log);
+        mail_index_close(index);
+
+       if (mail_index_open(index, MAIL_INDEX_OPEN_FLAG_CREATE) < 0)
                return -1;
+
+       if (log_locked) {
+               if (mail_transaction_log_sync_lock(index->log,
+                                                  &file_seq, &file_offset) < 0)
+                       return -1;
        }
 
        return 0;
index 979736b1ffd7e7af6f76eac292707ea06c64627c..6884855db97adf2fda339a452a4f523c86299b13 100644 (file)
@@ -83,7 +83,7 @@ int mail_index_view_lock_head(struct mail_index_view *view, int update_index)
 
 int mail_index_view_lock(struct mail_index_view *view)
 {
-       if (view->inconsistent)
+       if (mail_index_view_is_inconsistent(view))
                return -1;
 
        if (view->map != view->index->map) {
@@ -116,6 +116,8 @@ uint32_t mail_index_view_get_message_count(struct mail_index_view *view)
 
 int mail_index_view_is_inconsistent(struct mail_index_view *view)
 {
+       if (view->index->indexid != view->indexid)
+               view->inconsistent = TRUE;
        return view->inconsistent;
 }
 
index e865a7d04afe75c35ba844830042ddda456ae399..672c7f04b8a661d72194737e6e267c33e7434137 100644 (file)
@@ -399,7 +399,8 @@ int mail_index_create_tmp_file(struct mail_index *index, const char **path_r)
        return fd;
 }
 
-int mail_index_create(struct mail_index *index, struct mail_index_header *hdr)
+static int mail_index_create(struct mail_index *index,
+                            struct mail_index_header *hdr)
 {
        const char *path;
        uint32_t seq;
@@ -518,8 +519,8 @@ int mail_index_try_open(struct mail_index *index, unsigned int *lock_id_r)
        return ret;
 }
 
-static int
-mail_index_open2(struct mail_index *index, enum mail_index_open_flags flags)
+static int mail_index_open_files(struct mail_index *index,
+                                enum mail_index_open_flags flags)
 {
        struct mail_index_header hdr;
        unsigned int lock_id = 0;
@@ -573,7 +574,7 @@ int mail_index_open(struct mail_index *index, enum mail_index_open_flags flags)
 
                index->filepath = i_strconcat(index->dir, "/",
                                              index->prefix, NULL);
-               ret = mail_index_open2(index, flags);
+               ret = mail_index_open_files(index, flags);
                if (ret <= 0)
                        break;
 
@@ -654,35 +655,6 @@ void mail_index_set_inconsistent(struct mail_index *index)
        index->indexid = 0;
 }
 
-int mail_index_mark_corrupted(struct mail_index *index)
-{
-       struct mail_index_header hdr;
-
-       if (index->readonly || index->hdr == NULL ||
-           (index->hdr->flags & MAIL_INDEX_HDR_FLAG_CORRUPTED) != 0)
-               return 0;
-
-       /* make sure we can write the header */
-       if (!MAIL_INDEX_MAP_IS_IN_MEMORY(index->map)) {
-               if (mprotect(index->map->mmap_base, sizeof(hdr),
-                            PROT_READ | PROT_WRITE) < 0) {
-                       mail_index_set_syscall_error(index, "mprotect()");
-                       return -1;
-               }
-       }
-
-       hdr = *index->hdr;
-       hdr.flags |= MAIL_INDEX_HDR_FLAG_CORRUPTED;
-       if (mail_index_write_header(index, &hdr) < 0)
-               return -1;
-
-       if (fsync(index->fd) < 0)
-               return mail_index_set_syscall_error(index, "fsync()");
-
-       mail_index_set_inconsistent(index);
-       return 0;
-}
-
 int mail_index_set_syscall_error(struct mail_index *index,
                                 const char *function)
 {
index 630b8de7cd71ec3ec0611fa72e8b675ca707e322..b91c1b3dcff880909bc9770a0fae24a910a59d9b 100644 (file)
@@ -45,6 +45,15 @@ mail_transaction_log_view_open(struct mail_transaction_log *log)
 
 void mail_transaction_log_view_close(struct mail_transaction_log_view *view)
 {
+       struct mail_transaction_log_view **p;
+
+       for (p = &view->log->views; *p != NULL; p = &(*p)->next) {
+               if (*p == view) {
+                       *p = view->next;
+                       break;
+               }
+       }
+
        mail_transaction_log_view_unset(view);
        if (view->data_buf != NULL)
                buffer_free(view->data_buf);
@@ -52,6 +61,14 @@ void mail_transaction_log_view_close(struct mail_transaction_log_view *view)
        i_free(view);
 }
 
+void mail_transaction_log_views_close(struct mail_transaction_log *log)
+{
+       struct mail_transaction_log_view *view;
+
+       for (view = log->views; view != NULL; view = view->next)
+               view->log = NULL;
+}
+
 int
 mail_transaction_log_view_set(struct mail_transaction_log_view *view,
                              uint32_t min_file_seq, uoff_t min_file_offset,
@@ -70,6 +87,9 @@ mail_transaction_log_view_set(struct mail_transaction_log_view *view,
        i_assert(min_file_offset >= sizeof(struct mail_transaction_log_header));
        i_assert(max_file_offset >= sizeof(struct mail_transaction_log_header));
 
+       if (view->log == NULL)
+               return -1;
+
        ret = mail_transaction_log_file_find(view->log, min_file_seq, &file);
        if (ret <= 0) {
                if (ret == 0 &&
index 45d9c4ca61954cd5b88efd5e4f3a5e51daafc814..5f34130fa4ad4131533148643969c0a2d6af7315 100644 (file)
@@ -127,8 +127,9 @@ mail_transaction_log_open_or_create(struct mail_index *index)
 
 void mail_transaction_log_close(struct mail_transaction_log *log)
 {
-       i_assert(log->views == NULL);
+       mail_transaction_log_views_close(log);
 
+       log->index->log = NULL;
        i_free(log);
 }
 
@@ -683,7 +684,8 @@ int mail_transaction_log_file_map(struct mail_transaction_log_file *file,
        if (st.st_size == file->hdr.used_size &&
            file->buffer_offset <= start_offset && end_offset == (uoff_t)-1) {
                /* we've seen the whole file.. do we have all of it mapped? */
-               size = buffer_get_used_size(file->buffer);
+               size = file->buffer == NULL ? 0 :
+                       buffer_get_used_size(file->buffer);
                if (file->buffer_offset + size == file->hdr.used_size)
                        return 1;
        }
@@ -709,13 +711,13 @@ int mail_transaction_log_file_map(struct mail_transaction_log_file *file,
 
        if (start_offset < sizeof(file->hdr)) {
                mail_transaction_log_file_set_corrupted(file,
-                       "offset (%"PRIuUOFF_T"u) < header size (%"PRIuSIZE_T")",
+                       "offset (%"PRIuUOFF_T") < header size (%"PRIuSIZE_T")",
                        start_offset, sizeof(file->hdr));
                return -1;
        }
        if (end_offset > file->hdr.used_size) {
                mail_transaction_log_file_set_corrupted(file,
-                       "offset (%"PRIuUOFF_T"u) > used_size (%u)",
+                       "offset (%"PRIuUOFF_T") > used_size (%u)",
                        end_offset, file->hdr.used_size);
                return -1;
        }
index d99d3f1a791d41ff6d10b6dbe155e9603403c55b..d0a9cb295e3768450e27000d95aebe8bbb942900 100644 (file)
@@ -94,6 +94,8 @@ mail_transaction_log_view_set_corrupted(struct mail_transaction_log_view *view,
 int
 mail_transaction_log_view_is_corrupted(struct mail_transaction_log_view *view);
 
+void mail_transaction_log_views_close(struct mail_transaction_log *log);
+
 /* Write data to transaction log. This is atomic operation. Sequences in
    updates[] and expunges[] are relative to given view, they're modified
    to real ones. */