From: Timo Sirainen Date: Tue, 25 May 2004 23:13:57 +0000 (+0300) Subject: mail_index_refresh() - allows forcing a refresh check X-Git-Tag: 1.1.alpha1~4043 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e4b09b008ab544eb8994beecbfffefa21d855e43;p=thirdparty%2Fdovecot%2Fcore.git mail_index_refresh() - allows forcing a refresh check --HG-- branch : HEAD --- diff --git a/src/lib-index/mail-index-lock.c b/src/lib-index/mail-index-lock.c index afd260eee0..11da7a3cde 100644 --- a/src/lib-index/mail-index-lock.c +++ b/src/lib-index/mail-index-lock.c @@ -27,99 +27,6 @@ #include #include -static int mail_index_reopen(struct mail_index *index, int fd) -{ - struct mail_index_map *old_map; - unsigned int old_shared_locks, old_lock_id, lock_id = 0; - int ret, old_fd, old_lock_type; - - old_map = index->map; - old_fd = index->fd; - - index->map = NULL; - index->hdr = NULL; - - /* new file, new locks. the old fd can keep it's locks, they don't - matter anymore as no-one's going to modify the file. */ - old_lock_type = index->lock_type; - old_lock_id = index->lock_id; - old_shared_locks = index->shared_lock_count; - - if (index->lock_type == F_RDLCK) - index->lock_type = F_UNLCK; - index->lock_id += 2; - index->shared_lock_count = 0; - - if (fd != -1) { - index->fd = fd; - ret = 0; - } else { - i_assert(index->excl_lock_count == 0); - ret = mail_index_try_open_only(index); - if (ret > 0) - ret = mail_index_lock_shared(index, FALSE, &lock_id); - else if (ret == 0) { - /* index file is lost */ - ret = -1; - } - } - - if (ret == 0) { - if (mail_index_map(index, FALSE) <= 0) - ret = -1; - } - - if (lock_id != 0) - mail_index_unlock(index, lock_id); - - if (ret == 0) { - mail_index_unmap(index, old_map); - if (close(old_fd) < 0) - mail_index_set_syscall_error(index, "close()"); - } else { - if (index->map != NULL) - mail_index_unmap(index, index->map); - if (index->fd != -1) { - if (close(index->fd) < 0) - mail_index_set_syscall_error(index, "close()"); - } - - index->map = old_map; - index->hdr = index->map->hdr; - index->fd = old_fd; - index->lock_type = old_lock_type; - index->lock_id = old_lock_id; - index->shared_lock_count = old_shared_locks; - } - return ret; -} - -static int mail_index_has_changed(struct mail_index *index) -{ - struct stat st1, st2; - - if (fstat(index->fd, &st1) < 0) - return mail_index_set_syscall_error(index, "fstat()"); - if (stat(index->filepath, &st2) < 0) { - mail_index_set_syscall_error(index, "stat()"); - if (errno != ENOENT) - return -1; - - /* lost it? recreate */ - (void)mail_index_mark_corrupted(index); - return -1; - } - - if (st1.st_ino != st2.st_ino || - !CMP_DEV_T(st1.st_dev, st2.st_dev)) { - if (mail_index_reopen(index, -1) < 0) - return -1; - return 1; - } else { - return 0; - } -} - int mail_index_map_lock_mprotect(struct mail_index *index, struct mail_index_map *map, int lock_type) { @@ -167,7 +74,7 @@ static int mail_index_lock(struct mail_index *index, int lock_type, } if (update_index && index->excl_lock_count == 0) { - if ((ret2 = mail_index_has_changed(index)) < 0) + if ((ret2 = mail_index_refresh(index)) < 0) return -1; if (ret > 0 && ret2 == 0) return 1; @@ -184,7 +91,7 @@ static int mail_index_lock(struct mail_index *index, int lock_type, if (lock_type == F_WRLCK) return 0; if (update_index && index->lock_type == F_UNLCK) { - if (mail_index_has_changed(index) < 0) + if (mail_index_refresh(index) < 0) return -1; } if (mail_index_lock_mprotect(index, lock_type) < 0) diff --git a/src/lib-index/mail-index-private.h b/src/lib-index/mail-index-private.h index 70518ee2a7..b9b55cfe20 100644 --- a/src/lib-index/mail-index-private.h +++ b/src/lib-index/mail-index-private.h @@ -77,8 +77,7 @@ 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_try_open_only(struct mail_index *index); -int mail_index_try_open(struct mail_index *index, unsigned int *lock_id_r); +int mail_index_reopen(struct mail_index *index, int fd); int mail_index_create_tmp_file(struct mail_index *index, const char **path_r); /* Returns 0 = ok, -1 = error. If update_index is TRUE, reopens the index diff --git a/src/lib-index/mail-index.c b/src/lib-index/mail-index.c index 8088d70c94..1928f603aa 100644 --- a/src/lib-index/mail-index.c +++ b/src/lib-index/mail-index.c @@ -14,6 +14,8 @@ #include #include +static int mail_index_try_open_only(struct mail_index *index); + struct mail_index *mail_index_alloc(const char *dir, const char *prefix) { struct mail_index *index; @@ -361,6 +363,68 @@ struct mail_index_map *mail_index_map_to_memory(struct mail_index_map *map) return mem_map; } +static int mail_index_try_open_only(struct mail_index *index) +{ + int i; + + for (i = 0; i < 3; i++) { + index->fd = open(index->filepath, O_RDWR); + if (index->fd == -1 && errno == EACCES) { + index->fd = open(index->filepath, O_RDONLY); + index->readonly = TRUE; + } + if (index->fd != -1 || errno != ESTALE) + break; + + /* May happen with some OSes with NFS. Try again, although + there's still a race condition with another computer + creating the index file again. However, we can't try forever + as ESTALE happens also if index directory has been deleted + from server.. */ + } + if (index->fd == -1) { + if (errno != ENOENT) + return mail_index_set_syscall_error(index, "open()"); + + /* have to create it */ + return 0; + } + return 1; +} + +static int +mail_index_try_open(struct mail_index *index, unsigned int *lock_id_r) +{ + unsigned int lock_id; + int ret; + + if (lock_id_r != NULL) + *lock_id_r = 0; + + ret = mail_index_try_open_only(index); + if (ret <= 0) + return ret; + + if (mail_index_lock_shared(index, FALSE, &lock_id) < 0) + return -1; + ret = mail_index_map(index, FALSE); + if (ret == 0) { + /* it's corrupted - recreate it */ + mail_index_unlock(index, lock_id); + if (lock_id_r != NULL) + *lock_id_r = 0; + + (void)close(index->fd); + index->fd = -1; + } else { + if (lock_id_r != NULL) + *lock_id_r = lock_id; + else + mail_index_unlock(index, lock_id); + } + return ret; +} + void mail_index_header_init(struct mail_index_header *hdr) { time_t now = time(NULL); @@ -481,67 +545,6 @@ static int mail_index_create(struct mail_index *index, return 1; } -int mail_index_try_open_only(struct mail_index *index) -{ - int i; - - for (i = 0; i < 3; i++) { - index->fd = open(index->filepath, O_RDWR); - if (index->fd == -1 && errno == EACCES) { - index->fd = open(index->filepath, O_RDONLY); - index->readonly = TRUE; - } - if (index->fd != -1 || errno != ESTALE) - break; - - /* May happen with some OSes with NFS. Try again, although - there's still a race condition with another computer - creating the index file again. However, we can't try forever - as ESTALE happens also if index directory has been deleted - from server.. */ - } - if (index->fd == -1) { - if (errno != ENOENT) - return mail_index_set_syscall_error(index, "open()"); - - /* have to create it */ - return 0; - } - return 1; -} - -int mail_index_try_open(struct mail_index *index, unsigned int *lock_id_r) -{ - unsigned int lock_id; - int ret; - - if (lock_id_r != NULL) - *lock_id_r = 0; - - ret = mail_index_try_open_only(index); - if (ret <= 0) - return ret; - - if (mail_index_lock_shared(index, FALSE, &lock_id) < 0) - return -1; - ret = mail_index_map(index, FALSE); - if (ret == 0) { - /* it's corrupted - recreate it */ - mail_index_unlock(index, lock_id); - if (lock_id_r != NULL) - *lock_id_r = 0; - - (void)close(index->fd); - index->fd = -1; - } else { - if (lock_id_r != NULL) - *lock_id_r = lock_id; - else - mail_index_unlock(index, lock_id); - } - return ret; -} - static int mail_index_open_files(struct mail_index *index, enum mail_index_open_flags flags) { @@ -650,6 +653,99 @@ void mail_index_close(struct mail_index *index) index->opened = FALSE; } +int mail_index_reopen(struct mail_index *index, int fd) +{ + struct mail_index_map *old_map; + unsigned int old_shared_locks, old_lock_id, lock_id = 0; + int ret, old_fd, old_lock_type; + + old_map = index->map; + old_fd = index->fd; + + index->map = NULL; + index->hdr = NULL; + + /* new file, new locks. the old fd can keep it's locks, they don't + matter anymore as no-one's going to modify the file. */ + old_lock_type = index->lock_type; + old_lock_id = index->lock_id; + old_shared_locks = index->shared_lock_count; + + if (index->lock_type == F_RDLCK) + index->lock_type = F_UNLCK; + index->lock_id += 2; + index->shared_lock_count = 0; + + if (fd != -1) { + index->fd = fd; + ret = 0; + } else { + i_assert(index->excl_lock_count == 0); + ret = mail_index_try_open_only(index); + if (ret > 0) + ret = mail_index_lock_shared(index, FALSE, &lock_id); + else if (ret == 0) { + /* index file is lost */ + ret = -1; + } + } + + if (ret == 0) { + if (mail_index_map(index, FALSE) <= 0) + ret = -1; + } + + if (lock_id != 0) + mail_index_unlock(index, lock_id); + + if (ret == 0) { + mail_index_unmap(index, old_map); + if (close(old_fd) < 0) + mail_index_set_syscall_error(index, "close()"); + } else { + if (index->map != NULL) + mail_index_unmap(index, index->map); + if (index->fd != -1) { + if (close(index->fd) < 0) + mail_index_set_syscall_error(index, "close()"); + } + + index->map = old_map; + index->hdr = index->map->hdr; + index->fd = old_fd; + index->lock_type = old_lock_type; + index->lock_id = old_lock_id; + index->shared_lock_count = old_shared_locks; + } + return ret; +} + +int mail_index_refresh(struct mail_index *index) +{ + struct stat st1, st2; + + if (fstat(index->fd, &st1) < 0) + return mail_index_set_syscall_error(index, "fstat()"); + if (stat(index->filepath, &st2) < 0) { + mail_index_set_syscall_error(index, "stat()"); + if (errno != ENOENT) + return -1; + + /* lost it? recreate */ + (void)mail_index_mark_corrupted(index); + return -1; + } + + if (st1.st_ino != st2.st_ino || + !CMP_DEV_T(st1.st_dev, st2.st_dev)) { + if (mail_index_reopen(index, -1) < 0) + return -1; + return 1; + } else { + return 0; + } +} + struct mail_cache *mail_index_get_cache(struct mail_index *index) { return index->cache; diff --git a/src/lib-index/mail-index.h b/src/lib-index/mail-index.h index 216b2a6326..a11e31a52e 100644 --- a/src/lib-index/mail-index.h +++ b/src/lib-index/mail-index.h @@ -136,6 +136,9 @@ void mail_index_free(struct mail_index *index); int mail_index_open(struct mail_index *index, enum mail_index_open_flags flags); void mail_index_close(struct mail_index *index); +/* Force checking if index can be refreshed. */ +int mail_index_refresh(struct mail_index *index); + struct mail_cache *mail_index_get_cache(struct mail_index *index); /* View can be used to look into index. Sequence numbers inside view change