Mercurial > dovecot > original-hg > dovecot-1.2
changeset 1941:ced8e41c137a HEAD
automatically fix broken/missing transaction log files on the fly
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sat, 01 May 2004 18:32:24 +0300 |
parents | 876bd2849a00 |
children | 2b114aa7eeec |
files | src/lib-index/mail-index-sync.c src/lib-index/mail-index-view-sync.c src/lib-index/mail-transaction-log-view.c src/lib-index/mail-transaction-log.c src/lib-index/mail-transaction-log.h |
diffstat | 5 files changed, 76 insertions(+), 30 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-index/mail-index-sync.c Sat May 01 17:30:25 2004 +0300 +++ b/src/lib-index/mail-index-sync.c Sat May 01 18:32:24 2004 +0300 @@ -399,6 +399,7 @@ int mail_index_sync_end(struct mail_index_sync_ctx *ctx) { + const struct mail_index_header *hdr; uint32_t seq; uoff_t offset; int ret = 0; @@ -408,12 +409,14 @@ mail_transaction_log_get_head(ctx->index->log, &seq, &offset); - if (mail_transaction_log_view_set(ctx->view->log_view, - ctx->index->hdr->log_file_seq, - ctx->index->hdr->log_file_offset, - seq, offset, - MAIL_TRANSACTION_TYPE_MASK) < 0) - ret = -1; + if (ret == 0) { + hdr = ctx->index->hdr; + mail_transaction_log_view_unset(ctx->view->log_view); + if (mail_transaction_log_view_set(ctx->view->log_view, + hdr->log_file_seq, hdr->log_file_offset, + seq, offset, MAIL_TRANSACTION_TYPE_MASK) < 0) + ret = -1; + } if (ret == 0) { mail_index_sync_read_and_sort(ctx, TRUE); @@ -423,9 +426,8 @@ mail_index_unlock(ctx->index, ctx->lock_id); mail_transaction_log_sync_unlock(ctx->index->log); + mail_index_view_close(ctx->view); - if (ctx->view != NULL) - mail_index_view_close(ctx->view); if (ctx->expunges_buf != NULL) buffer_free(ctx->expunges_buf); if (ctx->updates_buf != NULL)
--- a/src/lib-index/mail-index-view-sync.c Sat May 01 17:30:25 2004 +0300 +++ b/src/lib-index/mail-index-view-sync.c Sat May 01 18:32:24 2004 +0300 @@ -50,6 +50,7 @@ buffer_append(*expunges_r, &exp->seq1, sizeof(exp->seq1)); buffer_append(*expunges_r, &exp->seq2, sizeof(exp->seq2)); } + mail_transaction_log_view_unset(view->log_view); return 0; } @@ -315,6 +316,8 @@ mail_index_unmap(view->index, view->map); view->map = ctx->sync_map; + mail_transaction_log_view_unset(view->log_view); + if (ctx->expunges != NULL) buffer_free(ctx->expunges);
--- a/src/lib-index/mail-transaction-log-view.c Sat May 01 17:30:25 2004 +0300 +++ b/src/lib-index/mail-transaction-log-view.c Sat May 01 18:32:24 2004 +0300 @@ -34,6 +34,7 @@ view = i_new(struct mail_transaction_log_view, 1); view->log = log; + view->broken = TRUE; view->expunges_buf = buffer_create_dynamic(default_pool, 512, (size_t)-1); @@ -42,24 +43,9 @@ return view; } -static void -mail_transaction_log_view_close_files(struct mail_transaction_log_view *view) -{ - struct mail_transaction_log_file *file; - - for (file = view->log->tail; file != NULL; file = file->next) { - if (file->hdr.file_seq > view->max_file_seq) - break; - if (file->hdr.file_seq >= view->min_file_seq) - file->refcount--; - } - - mail_transaction_logs_clean(view->log); -} - void mail_transaction_log_view_close(struct mail_transaction_log_view *view) { - mail_transaction_log_view_close_files(view); + mail_transaction_log_view_unset(view); if (view->data_buf != NULL) buffer_free(view->data_buf); buffer_free(view->expunges_buf); @@ -79,14 +65,11 @@ uoff_t end_offset; int ret; + i_assert(view->broken); i_assert(min_file_seq <= max_file_seq); i_assert(min_file_offset >= sizeof(struct mail_transaction_log_header)); i_assert(max_file_offset >= sizeof(struct mail_transaction_log_header)); - view->broken = TRUE; - - mail_transaction_log_view_close_files(view); - ret = mail_transaction_log_file_find(view->log, min_file_seq, &file); if (ret <= 0) { if (ret == 0 && @@ -161,6 +144,24 @@ return 0; } +void mail_transaction_log_view_unset(struct mail_transaction_log_view *view) +{ + struct mail_transaction_log_file *file; + + if (view->broken) + return; + + view->broken = TRUE; + for (file = view->log->tail; file != NULL; file = file->next) { + if (file->hdr.file_seq > view->max_file_seq) + break; + if (file->hdr.file_seq >= view->min_file_seq) + file->refcount--; + } + + mail_transaction_logs_clean(view->log); +} + void mail_transaction_log_view_get_prev_pos(struct mail_transaction_log_view *view, uint32_t *file_seq_r, @@ -176,6 +177,9 @@ { va_list va; + if (!view->broken) + mail_transaction_log_view_unset(view); + view->broken = TRUE; va_start(va, fmt);
--- a/src/lib-index/mail-transaction-log.c Sat May 01 17:30:25 2004 +0300 +++ b/src/lib-index/mail-transaction-log.c Sat May 01 18:32:24 2004 +0300 @@ -419,8 +419,14 @@ return NULL; } - for (p = &log->tail; *p != NULL; p = &(*p)->next) - ; + for (p = &log->tail; *p != NULL; p = &(*p)->next) { + if ((*p)->hdr.file_seq >= file->hdr.file_seq) { + /* log replaced with file having same sequence as + previous one. shouldn't happen unless previous + log file was corrupted.. */ + break; + } + } *p = file; return file; @@ -461,6 +467,9 @@ *p = next; } } + + if (log->tail == NULL) + log->head = NULL; } static int mail_transaction_log_rotate(struct mail_transaction_log *log) @@ -500,6 +509,24 @@ return 0; } +static int mail_transaction_log_recreate(struct mail_transaction_log *log) +{ + unsigned int lock_id; + int ret; + + if (mail_index_lock_shared(log->index, TRUE, &lock_id) < 0) + return -1; + + ret = mail_transaction_log_rotate(log); + mail_index_unlock(log->index, lock_id); + + if (ret == 0) { + if (mail_transaction_log_file_lock(log->head, F_UNLCK) < 0) + return -1; + } + return ret; +} + static int mail_transaction_log_refresh(struct mail_transaction_log *log) { struct mail_transaction_log_file *file; @@ -511,6 +538,10 @@ MAIL_TRANSACTION_LOG_PREFIX, NULL); if (stat(path, &st) < 0) { mail_index_file_set_syscall_error(log->index, path, "stat()"); + if (errno == ENOENT && log->head->lock_type == F_WRLCK) { + /* lost? */ + return mail_transaction_log_recreate(log); + } return -1; } @@ -519,6 +550,10 @@ log->head->st_dev == st.st_dev) { /* same file */ ret = mail_transaction_log_file_read_hdr(log->head, &st); + if (ret == 0 && log->head->lock_type == F_WRLCK) { + /* corrupted, recreate */ + return mail_transaction_log_recreate(log); + } return ret <= 0 ? -1 : 0; }
--- a/src/lib-index/mail-transaction-log.h Sat May 01 17:30:25 2004 +0300 +++ b/src/lib-index/mail-transaction-log.h Sat May 01 18:32:24 2004 +0300 @@ -67,6 +67,8 @@ uint32_t min_file_seq, uoff_t min_file_offset, uint32_t max_file_seq, uoff_t max_file_offset, enum mail_transaction_type type_mask); +/* Unset view, freeing all it's used resources. */ +void mail_transaction_log_view_unset(struct mail_transaction_log_view *view); /* Read next transaction record from current position. The position is updated. Returns -1 if error, 0 if we're at end of the view, 1 if ok. */