From: Timo Sirainen Date: Wed, 28 Apr 2004 02:39:03 +0000 (+0300) Subject: Locking changes. bugfixes. X-Git-Tag: 1.1.alpha1~4184 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5c1a8aee989af87bddefd71e2aa83aa2bd695155;p=thirdparty%2Fdovecot%2Fcore.git Locking changes. bugfixes. --HG-- branch : HEAD --- diff --git a/src/lib-index/mail-index-fsck.c b/src/lib-index/mail-index-fsck.c index 583d5ca820..f02124ded5 100644 --- a/src/lib-index/mail-index-fsck.c +++ b/src/lib-index/mail-index-fsck.c @@ -112,7 +112,7 @@ int mail_index_fsck(struct mail_index *index) if (mail_transaction_log_sync_lock(index->log, &file_seq, &file_offset) < 0) return -1; - if (mail_index_lock_exclusive(index, 0, 0, &lock_id) < 0) { + if (mail_index_lock_exclusive(index, &lock_id) < 0) { mail_transaction_log_sync_unlock(index->log); return -1; } diff --git a/src/lib-index/mail-index-lock.c b/src/lib-index/mail-index-lock.c index b829110bdb..74670147fd 100644 --- a/src/lib-index/mail-index-lock.c +++ b/src/lib-index/mail-index-lock.c @@ -108,8 +108,13 @@ static int mail_index_lock(struct mail_index *index, int lock_type, locks then, though */ if (lock_type == F_WRLCK) return 0; + if (update_index && index->lock_type == F_UNLCK) { + if (mail_index_has_changed(index) < 0) + return -1; + } if (mail_index_lock_mprotect(index, lock_type) < 0) return -1; + index->lock_type = lock_type; return 1; } @@ -227,23 +232,6 @@ static int mail_index_copy(struct mail_index *index) return fd; } -static int mail_index_need_lock(struct mail_index *index, - uint32_t log_file_seq, uoff_t log_file_offset) -{ - if (mail_index_map(index, FALSE) <= 0) - return 1; - - if (log_file_seq != 0 && - (index->hdr->log_file_seq > log_file_seq || - (index->hdr->log_file_seq == log_file_seq && - index->hdr->log_file_offset >= log_file_offset))) { - /* already synced */ - return 0; - } - - return 1; -} - static int mail_index_lock_exclusive_copy(struct mail_index *index) { int fd; @@ -252,7 +240,7 @@ static int mail_index_lock_exclusive_copy(struct mail_index *index) if (index->copy_lock_path != NULL) { index->excl_lock_count++; - return 1; + return 0; } /* copy the index to index.tmp and use it. when */ @@ -280,14 +268,12 @@ static int mail_index_lock_exclusive_copy(struct mail_index *index) } i_assert(index->excl_lock_count == 1); - return 1; + return 0; } int mail_index_lock_exclusive(struct mail_index *index, - uint32_t log_file_seq, uoff_t log_file_offset, unsigned int *lock_id_r) { - unsigned int lock_id; int ret; /* exclusive transaction log lock protects exclusive locking @@ -296,33 +282,11 @@ int mail_index_lock_exclusive(struct mail_index *index, /* wait two seconds for exclusive lock */ ret = mail_index_lock(index, F_WRLCK, 2, TRUE, lock_id_r); - if (ret > 0) { - if (mail_index_need_lock(index, log_file_seq, log_file_offset)) - return 1; - - mail_index_unlock(index, *lock_id_r); + if (ret > 0) return 0; - } if (ret < 0) return -1; - /* Grab shared lock to make sure it's not already being - exclusively locked */ - if (mail_index_lock_shared(index, TRUE, &lock_id) < 0) - return -1; - - if (log_file_seq != 0) { - /* check first if we really need to recreate it */ - ret = mail_index_need_lock(index, log_file_seq, - log_file_offset); - if (ret == 0) { - mail_index_unlock(index, lock_id); - return 0; - } - } - - mail_index_unlock(index, lock_id); - *lock_id_r = index->lock_id + 1; return mail_index_lock_exclusive_copy(index); } diff --git a/src/lib-index/mail-index-private.h b/src/lib-index/mail-index-private.h index d99bef075e..977d3031a1 100644 --- a/src/lib-index/mail-index-private.h +++ b/src/lib-index/mail-index-private.h @@ -99,9 +99,8 @@ int mail_index_create_tmp_file(struct mail_index *index, const char **path_r); races, unless transaction log is exclusively locked). */ int mail_index_lock_shared(struct mail_index *index, int update_index, unsigned int *lock_id_r); -/* Returns 1 = ok, 0 = already synced up to given log_file_offset, -1 = error */ +/* Returns 0 = ok, -1 = error. */ int mail_index_lock_exclusive(struct mail_index *index, - uint32_t log_file_seq, uoff_t log_file_offset, unsigned int *lock_id_r); void mail_index_unlock(struct mail_index *index, unsigned int lock_id); /* Returns 1 if given lock_id is valid, 0 if not. */ diff --git a/src/lib-index/mail-index-sync-update.c b/src/lib-index/mail-index-sync-update.c index 84c787d168..9c0cfefe12 100644 --- a/src/lib-index/mail-index-sync-update.c +++ b/src/lib-index/mail-index-sync-update.c @@ -176,6 +176,7 @@ int mail_index_sync_update_index(struct mail_index_sync_ctx *sync_ctx) unsigned int append_count; uint32_t count, file_seq, src_idx, dest_idx; uoff_t file_offset; + unsigned int lock_id; int ret; /* rewind */ @@ -188,6 +189,9 @@ int mail_index_sync_update_index(struct mail_index_sync_ctx *sync_ctx) return 0; } + if (mail_index_lock_exclusive(index, &lock_id) < 0) + return -1; + if (MAIL_INDEX_MAP_IS_IN_MEMORY(map)) map->write_to_disk = TRUE; @@ -261,12 +265,15 @@ int mail_index_sync_update_index(struct mail_index_sync_ctx *sync_ctx) if (!MAIL_INDEX_MAP_IS_IN_MEMORY(map)) { memcpy(map->mmap_base, &ctx.hdr, sizeof(ctx.hdr)); - if (msync(map->mmap_base, map->file_used_size, MS_SYNC) < 0) - return mail_index_set_syscall_error(index, "msync()"); + if (msync(map->mmap_base, map->file_used_size, MS_SYNC) < 0) { + mail_index_set_syscall_error(index, "msync()"); + ret = -1; + } } else { map->hdr_copy = ctx.hdr; map->hdr = &map->hdr_copy; } + mail_index_unlock(index, lock_id); return ret; } diff --git a/src/lib-index/mail-index-sync.c b/src/lib-index/mail-index-sync.c index f81e242d13..893302c11b 100644 --- a/src/lib-index/mail-index-sync.c +++ b/src/lib-index/mail-index-sync.c @@ -115,6 +115,19 @@ static int mail_index_sync_read_and_sort(struct mail_index_sync_ctx *ctx, return ret; } +static int mail_index_need_lock(struct mail_index *index, + uint32_t log_file_seq, uoff_t log_file_offset) +{ + if (index->hdr->log_file_seq > log_file_seq || + (index->hdr->log_file_seq == log_file_seq && + index->hdr->log_file_offset >= log_file_offset)) { + /* already synced */ + return 0; + } + + return 1; +} + int mail_index_sync_begin(struct mail_index *index, struct mail_index_sync_ctx **ctx_r, struct mail_index_view **view_r, @@ -125,25 +138,27 @@ int mail_index_sync_begin(struct mail_index *index, uoff_t offset; size_t size; unsigned int lock_id; - int ret; if (mail_transaction_log_sync_lock(index->log, &seq, &offset) < 0) return -1; - /* FIXME: really needed yet? If there are readers, the index file - is copied even if there are no changes.. */ - ret = mail_index_lock_exclusive(index, log_file_seq, - log_file_offset, &lock_id); - if (ret <= 0) { + if (mail_index_lock_shared(index, TRUE, &lock_id) < 0) { mail_transaction_log_sync_unlock(index->log); - return ret; + return -1; } if (mail_index_map(index, FALSE) <= 0) { mail_transaction_log_sync_unlock(index->log); + mail_index_unlock(index, lock_id); return -1; } + if (!mail_index_need_lock(index, log_file_seq, log_file_offset)) { + mail_index_unlock(index, lock_id); + mail_transaction_log_sync_unlock(index->log); + return 0; + } + ctx = i_new(struct mail_index_sync_ctx, 1); ctx->index = index; ctx->lock_id = lock_id; diff --git a/src/lib-index/mail-index-view.c b/src/lib-index/mail-index-view.c index 48d340aac5..ad0d2709d7 100644 --- a/src/lib-index/mail-index-view.c +++ b/src/lib-index/mail-index-view.c @@ -50,6 +50,8 @@ int mail_index_view_lock_head(struct mail_index_view *view, int update_index) view->inconsistent = TRUE; return -1; } + } else if (update_index) { + // FIXME: check if we need to reopen it! } return 0; diff --git a/src/lib-index/mail-transaction-log-view.c b/src/lib-index/mail-transaction-log-view.c index 62c68c5cb1..e933c13968 100644 --- a/src/lib-index/mail-transaction-log-view.c +++ b/src/lib-index/mail-transaction-log-view.c @@ -371,9 +371,15 @@ int mail_transaction_log_view_next(struct mail_transaction_log_view *view, view->expunges_buf); ret = mail_transaction_map(hdr, data, &seqfix_funcs, view); mail_transaction_expunge_traverse_deinit(view->exp_ctx); - i_assert(buffer_get_used_size(view->data_buf) == hdr->size); - *data_r = buffer_get_data(view->data_buf, NULL); + if (ret > 0) { + /* modified */ + i_assert(buffer_get_used_size(view->data_buf) == + hdr->size); + *data_r = buffer_get_data(view->data_buf, NULL); + } else { + i_assert(buffer_get_used_size(view->data_buf) == 0); + } } if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) != 0) { diff --git a/src/lib-index/mail-transaction-log.c b/src/lib-index/mail-transaction-log.c index 7c2e2cf751..f8ec536a83 100644 --- a/src/lib-index/mail-transaction-log.c +++ b/src/lib-index/mail-transaction-log.c @@ -327,7 +327,7 @@ static int mail_transaction_log_file_create(struct mail_transaction_log *log, if (index->fd != -1) { index->log_locked = TRUE; /* kludging around assert.. */ - if (mail_index_lock_exclusive(index, 0, 0, &lock_id) < 0) { + if (mail_index_lock_exclusive(index, &lock_id) < 0) { (void)file_dotlock_delete(path, fd); index->log_locked = FALSE; return -1; diff --git a/src/lib-index/mail-transaction-util.c b/src/lib-index/mail-transaction-util.c index 45f290c926..10fb78f7ff 100644 --- a/src/lib-index/mail-transaction-util.c +++ b/src/lib-index/mail-transaction-util.c @@ -72,7 +72,8 @@ int mail_transaction_map(const struct mail_transaction_header *hdr, } break; } - case MAIL_TRANSACTION_EXPUNGE: { + case MAIL_TRANSACTION_EXPUNGE: + case MAIL_TRANSACTION_EXPUNGE|MAIL_TRANSACTION_EXPUNGE_PROT: { const struct mail_transaction_expunge *rec, *end; if (map->expunge == NULL)