Mercurial > dovecot > core-2.2
changeset 2200:97bb7b127617 HEAD
Beginnings of getting cache file working again. Easy to break currently, but
basics seem to work.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 20 Jun 2004 11:05:41 +0300 |
parents | 89001f106f8d |
children | 7bdef5ea4591 |
files | src/lib-index/mail-cache-compress.c src/lib-index/mail-cache-lookup.c src/lib-index/mail-cache-old.c src/lib-index/mail-cache-private.h src/lib-index/mail-cache-transaction.c src/lib-index/mail-cache.c src/lib-index/mail-cache.h src/lib-index/mail-index.c src/lib-storage/index/index-mail.c src/lib-storage/index/index-storage.c src/lib-storage/index/index-transaction.c |
diffstat | 11 files changed, 176 insertions(+), 1181 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-index/mail-cache-compress.c Sun Jun 20 09:33:08 2004 +0300 +++ b/src/lib-index/mail-cache-compress.c Sun Jun 20 11:05:41 2004 +0300 @@ -241,7 +241,7 @@ MAIL_INDEX_HDR_FLAG_COMPRESS_CACHE); } - if (!mail_cache_unlock(cache)) + if (mail_cache_unlock(cache) < 0) ret = FALSE; return ret;
--- a/src/lib-index/mail-cache-lookup.c Sun Jun 20 09:33:08 2004 +0300 +++ b/src/lib-index/mail-cache-lookup.c Sun Jun 20 11:05:41 2004 +0300 @@ -5,7 +5,6 @@ #include "byteorder.h" #include "mail-cache-private.h" -#if 0 const char * mail_cache_get_header_fields_str(struct mail_cache *cache, unsigned int idx) { @@ -17,7 +16,7 @@ if (offset == 0) return NULL; - if (!mmap_update(cache, offset, 1024)) + if (mail_cache_mmap_update(cache, offset, 1024) < 0) return NULL; if (offset + sizeof(data_size) > cache->mmap_length) { @@ -37,7 +36,7 @@ return NULL; } - if (!mmap_update(cache, offset, data_size)) + if (mail_cache_mmap_update(cache, offset, data_size) < 0) return NULL; if (offset + data_size > cache->mmap_length) { @@ -107,17 +106,20 @@ } struct mail_cache_record * -mail_cache_get_record(struct mail_cache *cache, uint32_t offset) +mail_cache_get_record(struct mail_cache *cache, uint32_t offset, + int index_offset) { #define CACHE_PREFETCH 1024 struct mail_cache_record *cache_rec; size_t size; - offset = mail_cache_offset_to_uint32(offset); + if (!index_offset) + offset = mail_cache_offset_to_uint32(offset); if (offset == 0) return NULL; - if (!mmap_update(cache, offset, sizeof(*cache_rec) + CACHE_PREFETCH)) + if (mail_cache_mmap_update(cache, offset, + sizeof(*cache_rec) + CACHE_PREFETCH) < 0) return NULL; if (offset + sizeof(*cache_rec) > cache->mmap_length) { @@ -132,7 +134,7 @@ return NULL; } if (size > CACHE_PREFETCH) { - if (!mmap_update(cache, offset, size)) + if (mail_cache_mmap_update(cache, offset, size) < 0) return NULL; } @@ -149,7 +151,7 @@ { struct mail_cache_record *next; - next = mail_cache_get_record(cache, rec->next_offset); + next = mail_cache_get_record(cache, rec->next_offset, FALSE); if (next != NULL && next <= rec) { mail_cache_set_corrupted(cache, "next_offset points backwards"); return NULL; @@ -165,11 +167,13 @@ if (mail_cache_transaction_autocommit(view, seq, fields) < 0) return NULL; - // FIXME: check cache_offset in transaction - if (mail_index_lookup_latest(view->view, seq, &rec) < 0) + /* FIXME: check cache_offset in transaction + FIXME: if rec doesn't point to header record, the file seq may + be different and the offset wrong */ + if (mail_index_lookup(view->view, seq, &rec) < 0) return NULL; - return mail_cache_get_record(view->cache, rec->cache_offset); + return mail_cache_get_record(view->cache, rec->cache_offset, TRUE); } enum mail_cache_field @@ -318,5 +322,10 @@ memcpy(buffer, data, buffer_size); return TRUE; } -#else -#endif + +enum mail_cache_record_flag +mail_cache_get_record_flags(struct mail_cache_view *view, uint32_t seq) +{ + // FIXME: + return 0; +}
--- a/src/lib-index/mail-cache-old.c Sun Jun 20 09:33:08 2004 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,935 +0,0 @@ -static const char * -mail_cache_get_header_fields_str(struct mail_cache *cache, unsigned int idx); -static int mail_cache_write(struct mail_cache_transaction_ctx *ctx); -static struct mail_cache_record * -mail_cache_lookup(struct mail_cache *cache, - const struct mail_index_record *rec, - enum mail_cache_field fields); - -static void mail_cache_file_close(struct mail_cache *cache) -{ - if (cache->mmap_base != NULL) { - if (munmap(cache->mmap_base, cache->mmap_length) < 0) - mail_cache_set_syscall_error(cache, "munmap()"); - } - - cache->mmap_base = NULL; - cache->hdr = NULL; - cache->mmap_length = 0; - - if (cache->fd != -1) { - if (close(cache->fd) < 0) - mail_cache_set_syscall_error(cache, "close()"); - cache->fd = -1; - } -} - -static int mail_cache_file_reopen(struct mail_cache *cache) -{ - int fd; - - fd = open(cache->filepath, O_RDWR); - if (fd == -1) { - mail_cache_set_syscall_error(cache, "open()"); - return -1; - } - - mail_cache_file_close(cache); - - cache->fd = fd; - return 0; -} - -static int mmap_verify_header(struct mail_cache *cache) -{ - struct mail_cache_header *hdr; - - /* check that the header is still ok */ - if (cache->mmap_length < sizeof(struct mail_cache_header)) { - mail_cache_set_corrupted(cache, "File too small"); - return 0; - } - cache->hdr = hdr = cache->mmap_base; - - if (cache->hdr->indexid != cache->index->indexid) { - /* index id changed */ - if (cache->hdr->indexid != 0) - mail_cache_set_corrupted(cache, "indexid changed"); - return 0; - } - - if (cache->trans_ctx != NULL) { - /* we've updated used_file_size, do nothing */ - return 1; - } - - cache->used_file_size = nbo_to_uint32(hdr->used_file_size); - - /* only check the header if we're locked */ - if (cache->locks == 0) - return 1; - - if (cache->used_file_size < sizeof(struct mail_cache_header)) { - mail_cache_set_corrupted(cache, "used_file_size too small"); - return 0; - } - if ((cache->used_file_size % sizeof(uint32_t)) != 0) { - mail_cache_set_corrupted(cache, "used_file_size not aligned"); - return 0; - } - - if (cache->used_file_size > cache->mmap_length) { - /* maybe a crash truncated the file - just fix it */ - hdr->used_file_size = uint32_to_nbo(cache->mmap_length & ~3); - if (msync(cache->mmap_base, sizeof(*hdr), MS_SYNC) < 0) { - mail_cache_set_syscall_error(cache, "msync()"); - return -1; - } - } - return 1; -} - -static int mmap_update_nocheck(struct mail_cache *cache, - size_t offset, size_t size) -{ - struct stat st; - - /* if sequence has changed, the file has to be reopened. - note that if main index isn't locked, it may change again */ - if (cache->hdr->file_seq != cache->index->hdr->cache_file_seq && - cache->mmap_base != NULL) { - if (!mail_cache_file_reopen(cache)) - return -1; - } - - if (offset < cache->mmap_length && - size <= cache->mmap_length - offset && - !cache->mmap_refresh) { - /* already mapped */ - if (size != 0 || cache->anon_mmap) - return 1; - - /* requesting the whole file - see if we need to - re-mmap */ - if (fstat(cache->fd, &st) < 0) { - mail_cache_set_syscall_error(cache, "fstat()"); - return -1; - } - if ((uoff_t)st.st_size == cache->mmap_length) - return 1; - } - cache->mmap_refresh = FALSE; - - if (cache->anon_mmap) - return 1; - - if (cache->mmap_base != NULL) { - if (cache->locks != 0) { - /* in the middle of transaction - write the changes */ - if (msync(cache->mmap_base, cache->mmap_length, - MS_SYNC) < 0) { - mail_cache_set_syscall_error(cache, "msync()"); - return -1; - } - } - - if (munmap(cache->mmap_base, cache->mmap_length) < 0) - mail_cache_set_syscall_error(cache, "munmap()"); - } - - i_assert(cache->fd != -1); - - /* map the whole file */ - cache->hdr = NULL; - cache->mmap_length = 0; - - cache->mmap_base = mmap_rw_file(cache->fd, &cache->mmap_length); - if (cache->mmap_base == MAP_FAILED) { - cache->mmap_base = NULL; - mail_cache_set_syscall_error(cache, "mmap()"); - return -1; - } - - /* re-mmaped, check header */ - return 0; -} - -static int mmap_update(struct mail_cache *cache, size_t offset, size_t size) -{ - int synced, ret; - - for (synced = FALSE;; synced = TRUE) { - ret = mmap_update_nocheck(cache, offset, size); - if (ret > 0) - return TRUE; - if (ret < 0) - return FALSE; - - if (!mmap_verify_header(cache)) - return FALSE; - - /* see if cache file was rebuilt - do it only once to avoid - infinite looping */ - if (cache->hdr->sync_id == cache->index->cache_sync_id || - synced) - break; - - if (!mail_cache_file_reopen(cache)) - return FALSE; - } - return TRUE; -} - -static int mail_cache_open_and_verify(struct mail_cache *cache, int silent) -{ - struct stat st; - - mail_cache_file_close(cache); - - cache->fd = open(cache->filepath, O_RDWR); - if (cache->fd == -1) { - if (errno == ENOENT) - return 0; - - mail_cache_set_syscall_error(cache, "open()"); - return -1; - } - - if (fstat(cache->fd, &st) < 0) { - mail_cache_set_syscall_error(cache, "fstat()"); - return -1; - } - - if (st.st_size < sizeof(struct mail_cache_header)) - return 0; - - cache->mmap_refresh = TRUE; - if (mmap_update_nocheck(cache, 0, sizeof(struct mail_cache_header)) < 0) - return -1; - - /* verify that this really is the cache for wanted index */ - cache->silent = silent; - if (!mmap_verify_header(cache)) { - cache->silent = FALSE; - return 0; - } - - cache->silent = FALSE; - return 1; -} - -static int mail_cache_open_or_create_file(struct mail_cache *cache, - struct mail_cache_header *hdr) -{ - int ret, fd; - - cache->filepath = i_strconcat(cache->index->filepath, - MAIL_CACHE_FILE_PREFIX, NULL); - - ret = mail_cache_open_and_verify(cache, FALSE); - if (ret != 0) - return ret > 0; - - /* we'll have to clear cache_offsets which requires exclusive lock */ - if (!mail_index_set_lock(cache->index, MAIL_LOCK_EXCLUSIVE)) - return FALSE; - - /* maybe a rebuild.. */ - fd = file_dotlock_open(cache->filepath, NULL, MAIL_CACHE_LOCK_TIMEOUT, - MAIL_CACHE_LOCK_CHANGE_TIMEOUT, - MAIL_CACHE_LOCK_IMMEDIATE_TIMEOUT, NULL, NULL); - if (fd == -1) { - mail_cache_set_syscall_error(cache, "file_dotlock_open()"); - return FALSE; - } - - /* see if someone else just created the cache file */ - ret = mail_cache_open_and_verify(cache, TRUE); - if (ret != 0) { - (void)file_dotlock_delete(cache->filepath, fd); - return ret > 0; - } - - /* rebuild then */ - if (write_full(fd, hdr, sizeof(*hdr)) < 0) { - mail_cache_set_syscall_error(cache, "write_full()"); - (void)file_dotlock_delete(cache->filepath, fd); - return FALSE; - } - if (file_set_size(fd, MAIL_CACHE_INITIAL_SIZE) < 0) { - mail_cache_set_syscall_error(cache, "file_set_size()"); - (void)file_dotlock_delete(cache->filepath, fd); - return FALSE; - } - - if (cache->index->hdr.cache_file_seq != 0) { - // FIXME: recreate index file with cache_offsets cleared - } - - mail_cache_file_close(cache); - cache->fd = dup(fd); - - if (file_dotlock_replace(cache->filepath, fd, FALSE) < 0) { - mail_cache_set_syscall_error(cache, "file_dotlock_replace()"); - return FALSE; - } - - if (!mmap_update(cache, 0, sizeof(struct mail_cache_header))) - return FALSE; - - return TRUE; -} - -int mail_cache_open_or_create(struct mail_index *index) -{ - struct mail_cache_header hdr; - struct mail_cache *cache; - - memset(&hdr, 0, sizeof(hdr)); - hdr.indexid = index->indexid; - hdr.sync_id = index->hdr->cache_file_seq; // FIXME - hdr.used_file_size = uint32_to_nbo(sizeof(hdr)); - - cache = i_new(struct mail_cache, 1); - cache->index = index; - cache->fd = -1; - cache->split_header_pool = pool_alloconly_create("Headers", 512); - - index->cache = cache; - - /* we'll do anon-mmaping only if initially requested. if we fail - because of out of disk space, we'll just let the main index code - know it and fail. */ - if (!mail_cache_open_or_create_file(cache, &hdr)) { - mail_cache_free(cache); - return FALSE; - } - - return TRUE; -} - -void mail_cache_free(struct mail_cache *cache) -{ - i_assert(cache->trans_ctx == NULL); - - cache->index->cache = NULL; - - mail_cache_file_close(cache); - - pool_unref(cache->split_header_pool); - i_free(cache->filepath); - i_free(cache); -} - -void mail_cache_set_defaults(struct mail_cache *cache, - enum mail_cache_field default_cache_fields, - enum mail_cache_field never_cache_fields) -{ - cache->default_cache_fields = default_cache_fields; - cache->never_cache_fields = never_cache_fields; -} - -int mail_cache_reset(struct mail_cache *cache) -{ - struct mail_cache_header hdr; - int ret, fd; - - i_assert(cache->index->lock_type == MAIL_LOCK_EXCLUSIVE); - - memset(&hdr, 0, sizeof(hdr)); - hdr.indexid = cache->index->indexid; - hdr.sync_id = cache->sync_id = cache->index->cache_sync_id = - ++cache->index->hdr->cache_sync_id; - hdr.used_file_size = uint32_to_nbo(sizeof(hdr)); - cache->used_file_size = sizeof(hdr); - - fd = file_dotlock_open(cache->filepath, NULL, MAIL_CACHE_LOCK_TIMEOUT, - MAIL_CACHE_LOCK_CHANGE_TIMEOUT, - MAIL_CACHE_LOCK_IMMEDIATE_TIMEOUT, NULL, NULL); - if (fd == -1) { - mail_cache_set_syscall_error(cache, "file_dotlock_open()"); - return -1; - } - - if (write_full(fd, &hdr, sizeof(hdr)) < 0) { - mail_cache_set_syscall_error(cache, "write_full()"); - (void)file_dotlock_delete(cache->filepath, fd); - return -1; - } - if (file_set_size(fd, MAIL_CACHE_INITIAL_SIZE) < 0) { - mail_cache_set_syscall_error(cache, "file_set_size()"); - (void)file_dotlock_delete(cache->filepath, fd); - return -1; - } - - mail_cache_file_close(cache); - cache->fd = dup(fd); - - if (file_dotlock_replace(cache->filepath, fd, FALSE) < 0) { - mail_cache_set_syscall_error(cache, "file_dotlock_replace()"); - return -1; - } - - cache->mmap_refresh = TRUE; - if (!mmap_update(cache, 0, sizeof(struct mail_cache_header))) - return -1; - - return 0; -} - -int mail_cache_lock(struct mail_cache *cache, int nonblock) -{ - int ret; - - if (cache->locks++ != 0) - return TRUE; - - if (cache->anon_mmap) - return TRUE; - - if (nonblock) { - ret = file_try_lock(cache->fd, F_WRLCK); - if (ret < 0) - mail_cache_set_syscall_error(cache, "file_try_lock()"); - } else { - ret = file_wait_lock(cache->fd, F_WRLCK); - if (ret <= 0) - mail_cache_set_syscall_error(cache, "file_wait_lock()"); - } - - if (ret > 0) { - if (!mmap_update(cache, 0, 0)) { - (void)mail_cache_unlock(cache); - return -1; - } - if (cache->sync_id != cache->index->cache_sync_id) { - /* we have the cache file locked and sync_id still - doesn't match. it means we crashed between updating - cache file and updating sync_id in index header. - just update the sync_ids so they match. */ - i_warning("Updating broken sync_id in cache file %s", - cache->filepath); - cache->sync_id = cache->hdr->sync_id = - cache->index->cache_sync_id; - } - } - return ret; -} - -int mail_cache_unlock(struct mail_cache *cache) -{ - if (--cache->locks > 0) - return TRUE; - - if (cache->anon_mmap) - return TRUE; - - if (file_wait_lock(cache->fd, F_UNLCK) <= 0) { - mail_cache_set_syscall_error(cache, "file_wait_lock(F_UNLCK)"); - return FALSE; - } - - return TRUE; -} - -int mail_cache_is_locked(struct mail_cache *cache) -{ - return cache->locks > 0; -} - -struct mail_cache_view * -mail_cache_view_open(struct mail_cache *cache, struct mail_index_view *view) -{ - struct mail_cache_view *view; - - view = i_new(struct mail_cache_view, 1); - view->cache = cache; - view->view = view; - return view; -} - -void mail_cache_view_close(struct mail_cache_view *view) -{ - i_free(view); -} - -static const char * -mail_cache_get_header_fields_str(struct mail_cache *cache, unsigned int idx) -{ - uint32_t offset, data_size; - unsigned char *buf; - - offset = offset_to_uint32(cache->hdr->header_offsets[idx]); - - if (offset == 0) - return NULL; - - if (!mmap_update(cache, offset, 1024)) - return NULL; - - if (offset + sizeof(data_size) > cache->mmap_length) { - mail_cache_set_corrupted(cache, "Header %u points outside file", - idx); - return NULL; - } - - buf = cache->mmap_base; - memcpy(&data_size, buf + offset, sizeof(data_size)); - data_size = nbo_to_uint32(data_size); - offset += sizeof(data_size); - - if (data_size == 0) { - mail_cache_set_corrupted(cache, - "Header %u points to empty string", idx); - return NULL; - } - - if (!mmap_update(cache, offset, data_size)) - return NULL; - - if (offset + data_size > cache->mmap_length) { - mail_cache_set_corrupted(cache, "Header %u points outside file", - idx); - return NULL; - } - - buf = cache->mmap_base; - if (buf[offset + data_size - 1] != '\0') { - mail_cache_set_corrupted(cache, - "Header %u points to invalid string", idx); - return NULL; - } - - return buf + offset; -} - -static const char *const * -split_header(struct mail_cache *cache, const char *header) -{ - const char *const *arr, *const *tmp; - const char *null = NULL; - char *str; - buffer_t *buf; - - if (header == NULL) - return NULL; - - arr = t_strsplit(header, "\n"); - buf = buffer_create_dynamic(cache->split_header_pool, 32, (size_t)-1); - for (tmp = arr; *tmp != NULL; tmp++) { - str = p_strdup(cache->split_header_pool, *tmp); - buffer_append(buf, &str, sizeof(str)); - } - buffer_append(buf, &null, sizeof(null)); - - return buffer_get_data(buf, NULL); -} - -const char *const *mail_cache_get_header_fields(struct mail_cache *cache, - unsigned int idx) -{ - const char *str; - int i; - - i_assert(idx < MAIL_CACHE_HEADERS_COUNT); - - /* t_strsplit() is a bit slow, so we cache it */ - if (cache->hdr->header_offsets[idx] != cache->split_offsets[idx]) { - p_clear(cache->split_header_pool); - - t_push(); - for (i = 0; i < MAIL_CACHE_HEADERS_COUNT; i++) { - cache->split_offsets[i] = - cache->hdr->header_offsets[i]; - - str = mail_cache_get_header_fields_str(cache, i); - cache->split_headers[i] = split_header(cache, str); - } - t_pop(); - } - - return cache->split_headers[idx]; -} - -static const char *write_header_string(const char *const headers[], - uint32_t *size_r) -{ - buffer_t *buffer; - size_t size; - - buffer = buffer_create_dynamic(pool_datastack_create(), - 512, (size_t)-1); - - while (*headers != NULL) { - if (buffer_get_used_size(buffer) != 0) - buffer_append(buffer, "\n", 1); - buffer_append(buffer, *headers, strlen(*headers)); - headers++; - } - buffer_append(buffer, null4, 1); - - size = buffer_get_used_size(buffer); - if ((size & 3) != 0) { - buffer_append(buffer, null4, 4 - (size & 3)); - size += 4 - (size & 3); - } - *size_r = size; - return buffer_get_data(buffer, NULL); -} - -int mail_cache_set_header_fields(struct mail_cache_transaction_ctx *ctx, - unsigned int idx, const char *const headers[]) -{ - struct mail_cache *cache = ctx->cache; - uint32_t offset, update_offset, size; - const char *header_str, *prev_str; - - i_assert(*headers != NULL); - i_assert(idx < MAIL_CACHE_HEADERS_COUNT); - i_assert(idx >= ctx->next_unused_header_lowwater); - i_assert(offset_to_uint32(cache->hdr->header_offsets[idx]) == 0); - - t_push(); - - header_str = write_header_string(headers, &size); - if (idx != 0) { - prev_str = mail_cache_get_header_fields_str(cache, idx-1); - if (prev_str == NULL) { - t_pop(); - return FALSE; - } - - i_assert(strcmp(header_str, prev_str) != 0); - } - - offset = mail_cache_append_space(ctx, size + sizeof(uint32_t)); - if (offset != 0) { - memcpy((char *) cache->mmap_base + offset + sizeof(uint32_t), - header_str, size); - - size = uint32_to_nbo(size); - memcpy((char *) cache->mmap_base + offset, - &size, sizeof(uint32_t)); - - /* update cached headers */ - cache->split_offsets[idx] = cache->hdr->header_offsets[idx]; - cache->split_headers[idx] = split_header(cache, header_str); - - /* mark used-bit to be updated later. not really needed for - read-safety, but if transaction get rolled back we can't let - this point to invalid location. */ - update_offset = (char *) &cache->hdr->header_offsets[idx] - - (char *) cache->mmap_base; - mark_update(&ctx->cache_marks, update_offset, - uint32_to_offset(offset)); - - /* make sure get_header_fields() still works for this header - while the transaction isn't yet committed. */ - ctx->next_unused_header_lowwater = idx + 1; - } - - t_pop(); - return offset > 0; -} - -static struct mail_cache_record * -cache_get_record(struct mail_cache *cache, uint32_t offset) -{ -#define CACHE_PREFETCH 1024 - struct mail_cache_record *cache_rec; - size_t size; - - offset = offset_to_uint32(offset); - if (offset == 0) - return NULL; - - if (!mmap_update(cache, offset, sizeof(*cache_rec) + CACHE_PREFETCH)) - return NULL; - - if (offset + sizeof(*cache_rec) > cache->mmap_length) { - mail_cache_set_corrupted(cache, "record points outside file"); - return NULL; - } - cache_rec = CACHE_RECORD(cache, offset); - - size = nbo_to_uint32(cache_rec->size); - if (size < sizeof(*cache_rec)) { - mail_cache_set_corrupted(cache, "invalid record size"); - return NULL; - } - if (size > CACHE_PREFETCH) { - if (!mmap_update(cache, offset, size)) - return NULL; - } - - if (offset + size > cache->mmap_length) { - mail_cache_set_corrupted(cache, "record points outside file"); - return NULL; - } - return cache_rec; -} - -static struct mail_cache_record * -cache_get_next_record(struct mail_cache *cache, struct mail_cache_record *rec) -{ - struct mail_cache_record *next; - - next = cache_get_record(cache, rec->next_offset); - if (next != NULL && next <= rec) { - mail_cache_set_corrupted(cache, "next_offset points backwards"); - return NULL; - } - return next; -} - -static struct mail_cache_record * -mail_cache_lookup(struct mail_cache *cache, const struct mail_index_record *rec, - enum mail_cache_field fields) -{ - struct mail_cache_record *cache_rec; - unsigned int idx; - - if (cache->trans_ctx != NULL && - cache->trans_ctx->first_uid <= rec->uid && - cache->trans_ctx->last_uid >= rec->uid && - (cache->trans_ctx->prev_uid != rec->uid || fields == 0 || - (cache->trans_ctx->prev_fields & fields) != 0)) { - /* we have to auto-commit since we're not capable of looking - into uncommitted records. it would be possible by checking - index_marks and cache_marks, but it's just more trouble - than worth. */ - idx = INDEX_RECORD_INDEX(cache->index, rec); - if (cache->trans_ctx->last_idx == idx) { - if (!mail_cache_write(cache->trans_ctx)) - return NULL; - } - - if (!mail_cache_transaction_commit(cache->trans_ctx)) - return NULL; - } - - cache_rec = cache_get_record(cache, rec->cache_offset); - if (cache_rec == NULL) - return NULL; - - return cache_rec; -} - -enum mail_cache_field -mail_cache_get_fields(struct mail_cache *cache, - const struct mail_index_record *rec) -{ - struct mail_cache_record *cache_rec; - enum mail_cache_field fields = 0; - - cache_rec = mail_cache_lookup(cache, rec, 0); - while (cache_rec != NULL) { - fields |= cache_rec->fields; - cache_rec = cache_get_next_record(cache, cache_rec); - } - - return fields; -} - -static int cache_get_field(struct mail_cache *cache, - struct mail_cache_record *cache_rec, - enum mail_cache_field field, - void **data_r, size_t *size_r) -{ - unsigned char *buf; - unsigned int mask; - uint32_t rec_size, data_size; - size_t offset, next_offset; - int i; - - rec_size = nbo_to_uint32(cache_rec->size); - buf = (unsigned char *) cache_rec; - offset = sizeof(*cache_rec); - - for (i = 0, mask = 1; i < 31; i++, mask <<= 1) { - if ((cache_rec->fields & mask) == 0) - continue; - - /* all records are at least 32bit. we have to check this - before getting data_size. */ - if (offset + sizeof(uint32_t) > rec_size) { - mail_cache_set_corrupted(cache, - "Record continues outside it's allocated size"); - return FALSE; - } - - if ((mask & MAIL_CACHE_FIXED_MASK) != 0) - data_size = mail_cache_field_sizes[i]; - else { - memcpy(&data_size, buf + offset, sizeof(data_size)); - data_size = nbo_to_uint32(data_size); - offset += sizeof(data_size); - } - - next_offset = offset + ((data_size + 3) & ~3); - if (next_offset > rec_size) { - mail_cache_set_corrupted(cache, - "Record continues outside it's allocated size"); - return FALSE; - } - - if (field == mask) { - if (data_size == 0) { - mail_cache_set_corrupted(cache, - "Field size is 0"); - return FALSE; - } - *data_r = buf + offset; - *size_r = data_size; - return TRUE; - } - offset = next_offset; - } - - i_unreached(); - return FALSE; -} - -static int cache_lookup_field(struct mail_cache *cache, - const struct mail_index_record *rec, - enum mail_cache_field field, - void **data_r, size_t *size_r) -{ - struct mail_cache_record *cache_rec; - - cache_rec = mail_cache_lookup(cache, rec, field); - while (cache_rec != NULL) { - if ((cache_rec->fields & field) != 0) { - return cache_get_field(cache, cache_rec, field, - data_r, size_r); - } - cache_rec = cache_get_next_record(cache, cache_rec); - } - - return FALSE; -} - -int mail_cache_lookup_field(struct mail_cache *cache, - const struct mail_index_record *rec, - enum mail_cache_field field, - const void **data_r, size_t *size_r) -{ - void *data; - - if (!cache_lookup_field(cache, rec, field, &data, size_r)) - return FALSE; - - *data_r = data; - return TRUE; -} - -const char *mail_cache_lookup_string_field(struct mail_cache *cache, - const struct mail_index_record *rec, - enum mail_cache_field field) -{ - const void *data; - size_t size; - - i_assert((field & MAIL_CACHE_STRING_MASK) != 0); - - if (!mail_cache_lookup_field(cache, rec, field, &data, &size)) - return NULL; - - if (((const char *) data)[size-1] != '\0') { - mail_cache_set_corrupted(cache, - "String field %x doesn't end with NUL", field); - return NULL; - } - return data; -} - -int mail_cache_copy_fixed_field(struct mail_cache *cache, - const struct mail_index_record *rec, - enum mail_cache_field field, - void *buffer, size_t buffer_size) -{ - const void *data; - size_t size; - - i_assert((field & MAIL_CACHE_FIXED_MASK) != 0); - - if (!mail_cache_lookup_field(cache, rec, field, &data, &size)) - return FALSE; - - if (buffer_size != size) { - i_panic("cache: fixed field %x wrong size " - "(%"PRIuSIZE_T" vs %"PRIuSIZE_T")", - field, size, buffer_size); - } - - memcpy(buffer, data, buffer_size); - return TRUE; -} - -void mail_cache_mark_missing(struct mail_cache *cache, - enum mail_cache_field fields) -{ - // FIXME: count these -} - -enum mail_index_record_flag -mail_cache_get_index_flags(struct mail_cache *cache, - const struct mail_index_record *rec) -{ - enum mail_index_record_flag flags; - - if (!mail_cache_copy_fixed_field(cache, rec, MAIL_CACHE_INDEX_FLAGS, - &flags, sizeof(flags))) - return 0; - - return flags; -} - -int mail_cache_update_index_flags(struct mail_cache *cache, - const struct mail_index_record *rec, - enum mail_index_record_flag flags) -{ - void *data; - size_t size; - - i_assert(cache->locks > 0); - - if (!cache_lookup_field(cache, rec, MAIL_CACHE_INDEX_FLAGS, - &data, &size)) { - mail_cache_set_corrupted(cache, - "Missing index flags for record %u", rec->uid); - return FALSE; - } - - memcpy(data, &flags, sizeof(flags)); - return TRUE; -} - -int mail_cache_update_location_offset(struct mail_cache *cache, - const struct mail_index_record *rec, - uoff_t offset) -{ - void *data; - size_t size; - - i_assert(cache->locks > 0); - - if (!cache_lookup_field(cache, rec, MAIL_CACHE_LOCATION_OFFSET, - &data, &size)) { - mail_cache_set_corrupted(cache, - "Missing location offset for record %u", rec->uid); - return FALSE; - } - - memcpy(data, &offset, sizeof(offset)); - return TRUE; -} - -void *mail_cache_get_mmaped(struct mail_cache *cache, size_t *size) -{ - if (!mmap_update(cache, 0, 0)) - return NULL; - - *size = cache->mmap_length; - return cache->mmap_base; -}
--- a/src/lib-index/mail-cache-private.h Sun Jun 20 09:33:08 2004 +0300 +++ b/src/lib-index/mail-cache-private.h Sun Jun 20 11:05:41 2004 +0300 @@ -95,7 +95,8 @@ mail_cache_split_header(struct mail_cache *cache, const char *header); struct mail_cache_record * -mail_cache_get_record(struct mail_cache *cache, uint32_t offset); +mail_cache_get_record(struct mail_cache *cache, uint32_t offset, + int index_offset); struct mail_cache_record * mail_cache_get_next_record(struct mail_cache *cache, struct mail_cache_record *rec); @@ -108,6 +109,9 @@ mail_cache_transaction_autocommit(struct mail_cache_view *view, uint32_t seq, enum mail_cache_field fields); +int mail_cache_mmap_update(struct mail_cache *cache, + size_t offset, size_t size); + void mail_cache_set_syscall_error(struct mail_cache *cache, const char *function);
--- a/src/lib-index/mail-cache-transaction.c Sun Jun 20 09:33:08 2004 +0300 +++ b/src/lib-index/mail-cache-transaction.c Sun Jun 20 11:05:41 2004 +0300 @@ -9,7 +9,6 @@ #include <sys/stat.h> -#if 0 struct mail_cache_transaction_ctx { struct mail_cache *cache; struct mail_cache_view *view; @@ -171,7 +170,7 @@ if (cache->used_file_size + size <= (uoff_t)st.st_size) { /* no need to grow, just update mmap */ - if (mmap_update(cache, 0, 0) < 0) + if (mail_cache_mmap_update(cache, 0, 0) < 0) return -1; i_assert(cache->mmap_length >= (uoff_t)st.st_size); @@ -183,7 +182,7 @@ return -1; } - return mmap_update(cache, 0, 0); + return mail_cache_mmap_update(cache, 0, 0); } static uint32_t mail_cache_append_space(struct mail_cache_transaction_ctx *ctx, @@ -219,46 +218,54 @@ uint32_t write_offset, update_offset; const void *buf; size_t size, buf_size; + int ret; buf = buffer_get_data(ctx->cache_data, &buf_size); size = sizeof(*cache_rec) + buf_size; ctx->cache_rec.size = uint32_to_nbo(size); - write_offset = mail_cache_append_space(ctx, size); - if (write_offset == 0) - return -1; - // FIXME: check cache_offset in transaction - if (mail_index_lookup_latest(ctx->view->view, ctx->prev_seq, &rec) < 0) + ret = mail_index_lookup(ctx->view->view, ctx->prev_seq, &rec); + if (ret < 0) return -1; - cache_rec = mail_cache_get_record(cache, rec->cache_offset); - if (cache_rec == NULL) { - /* first cache record - update offset in index file */ - mail_index_update_cache(ctx->trans, ctx->prev_seq, - write_offset); + if (ret == 0) { + /* it's been expunged already, do nothing */ } else { - /* find the last cache record */ - while ((next = mail_cache_get_next_record(cache, - cache_rec)) != NULL) - cache_rec = next; + write_offset = mail_cache_append_space(ctx, size); + if (write_offset == 0) + return -1; - /* mark next_offset to be updated later */ - update_offset = (char *) &cache_rec->next_offset - - (char *) cache->mmap_base; - mark_update(&ctx->cache_marks, update_offset, - mail_cache_uint32_to_offset(write_offset)); + cache_rec = mail_cache_get_record(cache, rec->cache_offset, + TRUE); + if (cache_rec == NULL) { + /* first cache record - update offset in index file */ + mail_index_update_cache(ctx->trans, ctx->prev_seq, + write_offset); + } else { + /* find the last cache record */ + while ((next = mail_cache_get_next_record(cache, + cache_rec)) != NULL) + cache_rec = next; + + /* mark next_offset to be updated later */ + update_offset = (char *) &cache_rec->next_offset - + (char *) cache->mmap_base; + mark_update(&ctx->cache_marks, update_offset, + mail_cache_uint32_to_offset(write_offset)); + } + + memcpy((char *) cache->mmap_base + write_offset, + &ctx->cache_rec, sizeof(ctx->cache_rec)); + memcpy((char *) cache->mmap_base + write_offset + + sizeof(ctx->cache_rec), buf, buf_size); } + + /* reset the write context */ ctx->prev_seq = 0; ctx->prev_fields = 0; - memcpy((char *) cache->mmap_base + write_offset, - &ctx->cache_rec, sizeof(ctx->cache_rec)); - memcpy((char *) cache->mmap_base + write_offset + - sizeof(ctx->cache_rec), buf, buf_size); - - /* reset the write context */ memset(&ctx->cache_rec, 0, sizeof(ctx->cache_rec)); buffer_set_used_size(ctx->cache_data, 0); return 0; @@ -558,5 +565,9 @@ return 0; } -#else -#endif + +int mail_cache_update_record_flags(struct mail_cache_view *view, uint32_t seq, + enum mail_cache_record_flag flags) +{ + return -1; +}
--- a/src/lib-index/mail-cache.c Sun Jun 20 09:33:08 2004 +0300 +++ b/src/lib-index/mail-cache.c Sun Jun 20 11:05:41 2004 +0300 @@ -4,6 +4,7 @@ #include "buffer.h" #include "byteorder.h" #include "file-lock.h" +#include "file-set-size.h" #include "mmap-util.h" #include "write-full.h" #include "mail-cache-private.h" @@ -38,7 +39,6 @@ MAIL_CACHE_HEADERS4 }; -#if 0 uint32_t mail_cache_uint32_to_offset(uint32_t offset) { unsigned char buf[4]; @@ -187,13 +187,15 @@ { struct stat st; +#if 0 // FIXME /* if sequence has changed, the file has to be reopened. note that if main index isn't locked, it may change again */ if (cache->hdr->file_seq != cache->index->hdr->cache_file_seq && cache->mmap_base != NULL) { - if (!mail_cache_file_reopen(cache)) + if (mail_cache_file_reopen(cache) < 0) return -1; } +#endif if (offset < cache->mmap_length && size <= cache->mmap_length - offset && @@ -244,35 +246,38 @@ return 0; } -static int mmap_update(struct mail_cache *cache, size_t offset, size_t size) +int mail_cache_mmap_update(struct mail_cache *cache, size_t offset, size_t size) { int synced, ret; for (synced = FALSE;; synced = TRUE) { ret = mmap_update_nocheck(cache, offset, size); if (ret > 0) - return TRUE; + return 0; if (ret < 0) - return FALSE; + return -1; - if (!mmap_verify_header(cache)) - return FALSE; + if (mmap_verify_header(cache) <= 0) + return -1; +#if 0 // FIXME /* see if cache file was rebuilt - do it only once to avoid infinite looping */ - if (cache->hdr->sync_id == cache->index->cache_sync_id || + if (cache->hdr->file_seq == cache->index->hdr->cache_file_seq || synced) break; - if (!mail_cache_file_reopen(cache)) - return FALSE; + if (mail_cache_file_reopen(cache) < 0) + return -1; +#endif } - return TRUE; + return 0; } static int mail_cache_open_and_verify(struct mail_cache *cache, int silent) { struct stat st; + int ret; mail_cache_file_close(cache); @@ -299,9 +304,9 @@ /* verify that this really is the cache for wanted index */ cache->silent = silent; - if (!mmap_verify_header(cache)) { + if ((ret = mmap_verify_header(cache)) <= 0) { cache->silent = FALSE; - return 0; + return ret; } cache->silent = FALSE; @@ -318,66 +323,64 @@ ret = mail_cache_open_and_verify(cache, FALSE); if (ret != 0) - return ret > 0; - - /* we'll have to clear cache_offsets which requires exclusive lock */ - if (!mail_index_set_lock(cache->index, MAIL_LOCK_EXCLUSIVE)) - return FALSE; + return ret < 0 ? -1 : 0; /* maybe a rebuild.. */ - fd = file_dotlock_open(cache->filepath, NULL, MAIL_CACHE_LOCK_TIMEOUT, + fd = file_dotlock_open(cache->filepath, NULL, NULL, + MAIL_CACHE_LOCK_TIMEOUT, MAIL_CACHE_LOCK_CHANGE_TIMEOUT, MAIL_CACHE_LOCK_IMMEDIATE_TIMEOUT, NULL, NULL); if (fd == -1) { mail_cache_set_syscall_error(cache, "file_dotlock_open()"); - return FALSE; + return -1; } /* see if someone else just created the cache file */ ret = mail_cache_open_and_verify(cache, TRUE); if (ret != 0) { - (void)file_dotlock_delete(cache->filepath, fd); - return ret > 0; + (void)file_dotlock_delete(cache->filepath, NULL, fd); + return ret < 0 ? -1 : 0; } /* rebuild then */ if (write_full(fd, hdr, sizeof(*hdr)) < 0) { mail_cache_set_syscall_error(cache, "write_full()"); - (void)file_dotlock_delete(cache->filepath, fd); - return FALSE; + (void)file_dotlock_delete(cache->filepath, NULL, fd); + return -1; } if (file_set_size(fd, MAIL_CACHE_INITIAL_SIZE) < 0) { mail_cache_set_syscall_error(cache, "file_set_size()"); - (void)file_dotlock_delete(cache->filepath, fd); - return FALSE; + (void)file_dotlock_delete(cache->filepath, NULL, fd); + return -1; } - if (cache->index->hdr.cache_file_seq != 0) { - // FIXME: recreate index file with cache_offsets cleared + if (cache->index->hdr->cache_file_seq != 0) { + // FIXME: clear cache_offsets in index file } mail_cache_file_close(cache); cache->fd = dup(fd); - if (file_dotlock_replace(cache->filepath, fd, FALSE) < 0) { + if (file_dotlock_replace(cache->filepath, NULL, fd, FALSE) < 0) { mail_cache_set_syscall_error(cache, "file_dotlock_replace()"); - return FALSE; + return -1; } - if (!mmap_update(cache, 0, sizeof(struct mail_cache_header))) - return FALSE; + if (mail_cache_mmap_update(cache, 0, + sizeof(struct mail_cache_header)) < 0) + return -1; - return TRUE; + return 0; } -int mail_cache_open_or_create(struct mail_index *index) +struct mail_cache *mail_cache_open_or_create(struct mail_index *index) { struct mail_cache_header hdr; struct mail_cache *cache; memset(&hdr, 0, sizeof(hdr)); hdr.indexid = index->indexid; - hdr.sync_id = index->hdr->cache_file_seq; // FIXME + hdr.file_seq = index->hdr->cache_file_seq + 1; hdr.used_file_size = uint32_to_nbo(sizeof(hdr)); cache = i_new(struct mail_cache, 1); @@ -385,25 +388,21 @@ cache->fd = -1; cache->split_header_pool = pool_alloconly_create("Headers", 512); - index->cache = cache; - /* we'll do anon-mmaping only if initially requested. if we fail because of out of disk space, we'll just let the main index code know it and fail. */ - if (!mail_cache_open_or_create_file(cache, &hdr)) { + if (mail_cache_open_or_create_file(cache, &hdr) < 0) { mail_cache_free(cache); - return FALSE; + return NULL; } - return TRUE; + return cache; } void mail_cache_free(struct mail_cache *cache) { i_assert(cache->trans_ctx == NULL); - cache->index->cache = NULL; - mail_cache_file_close(cache); pool_unref(cache->split_header_pool); @@ -422,18 +421,20 @@ int mail_cache_reset(struct mail_cache *cache) { struct mail_cache_header hdr; - int ret, fd; + int fd; - i_assert(cache->index->lock_type == MAIL_LOCK_EXCLUSIVE); + i_assert(cache->index->lock_type == F_WRLCK); memset(&hdr, 0, sizeof(hdr)); hdr.indexid = cache->index->indexid; - hdr.sync_id = cache->sync_id = cache->index->cache_sync_id = - ++cache->index->hdr->cache_sync_id; + hdr.file_seq = cache->index->hdr->cache_file_seq + 1; hdr.used_file_size = uint32_to_nbo(sizeof(hdr)); cache->used_file_size = sizeof(hdr); - fd = file_dotlock_open(cache->filepath, NULL, MAIL_CACHE_LOCK_TIMEOUT, + // FIXME: update cache_offsets in index + + fd = file_dotlock_open(cache->filepath, NULL, NULL, + MAIL_CACHE_LOCK_TIMEOUT, MAIL_CACHE_LOCK_CHANGE_TIMEOUT, MAIL_CACHE_LOCK_IMMEDIATE_TIMEOUT, NULL, NULL); if (fd == -1) { @@ -443,25 +444,26 @@ if (write_full(fd, &hdr, sizeof(hdr)) < 0) { mail_cache_set_syscall_error(cache, "write_full()"); - (void)file_dotlock_delete(cache->filepath, fd); + (void)file_dotlock_delete(cache->filepath, NULL, fd); return -1; } if (file_set_size(fd, MAIL_CACHE_INITIAL_SIZE) < 0) { mail_cache_set_syscall_error(cache, "file_set_size()"); - (void)file_dotlock_delete(cache->filepath, fd); + (void)file_dotlock_delete(cache->filepath, NULL, fd); return -1; } mail_cache_file_close(cache); cache->fd = dup(fd); - if (file_dotlock_replace(cache->filepath, fd, FALSE) < 0) { + if (file_dotlock_replace(cache->filepath, NULL, fd, FALSE) < 0) { mail_cache_set_syscall_error(cache, "file_dotlock_replace()"); return -1; } cache->mmap_refresh = TRUE; - if (!mmap_update(cache, 0, sizeof(struct mail_cache_header))) + if (mail_cache_mmap_update(cache, 0, + sizeof(struct mail_cache_header)) < 0) return -1; return 0; @@ -472,7 +474,7 @@ int ret; if (cache->locks++ != 0) - return TRUE; + return 1; if (nonblock) { ret = file_try_lock(cache->fd, F_WRLCK); @@ -485,20 +487,22 @@ } if (ret > 0) { - if (!mmap_update(cache, 0, 0)) { + if (mail_cache_mmap_update(cache, 0, 0) < 0) { (void)mail_cache_unlock(cache); return -1; } - if (cache->sync_id != cache->index->cache_sync_id) { +#if 0 // FIXME + if (cache->hdr->file_seq != cache->index->hdr->cache_file_seq) { /* we have the cache file locked and sync_id still doesn't match. it means we crashed between updating cache file and updating sync_id in index header. just update the sync_ids so they match. */ i_warning("Updating broken sync_id in cache file %s", cache->filepath); - cache->sync_id = cache->hdr->sync_id = - cache->index->cache_sync_id; + cache->hdr->file_seq = + cache->index->hdr->cache_file_seq; } +#endif } return ret; } @@ -506,14 +510,14 @@ int mail_cache_unlock(struct mail_cache *cache) { if (--cache->locks > 0) - return TRUE; + return 0; if (file_wait_lock(cache->fd, F_UNLCK) <= 0) { mail_cache_set_syscall_error(cache, "file_wait_lock(F_UNLCK)"); - return FALSE; + return -1; } - return TRUE; + return 0; } int mail_cache_is_locked(struct mail_cache *cache) @@ -536,128 +540,9 @@ { i_free(view); } -#else -int mail_cache_open_or_create(struct mail_index *index) -{ - return 0; -} - -void mail_cache_free(struct mail_cache *cache) +void mail_cache_mark_missing(struct mail_cache_view *view, + enum mail_cache_field fields) { -} - -void mail_cache_set_defaults(struct mail_cache *cache, - enum mail_cache_field default_cache_fields, - enum mail_cache_field never_cache_fields) {} - -/* Compress cache file. */ -int mail_cache_compress(struct mail_cache *cache) {return 0;} - -/* Reset the cache file, clearing all data. */ -int mail_cache_reset(struct mail_cache *cache) {return 0;} - -/* Explicitly lock the cache file. Returns 1 if ok, 0 if nonblock is TRUE and - we couldn't immediately get a lock, or -1 if error. */ -int mail_cache_lock(struct mail_cache *cache, int nonblock) {return 0;} -int mail_cache_unlock(struct mail_cache *cache) {return 0;} - -/* Returns TRUE if cache file is locked. */ -int mail_cache_is_locked(struct mail_cache *cache) {return TRUE;} - -struct mail_cache_view * -mail_cache_view_open(struct mail_cache *cache, struct mail_index_view *iview) -{return i_new(struct mail_cache_view, 1);} -void mail_cache_view_close(struct mail_cache_view *view) {i_free(view);} - -/* Begin transaction. Cache transaction may be committed or rollbacked multiple - times. It will finish when index transaction is committed or rollbacked. - The transaction might also be partially committed automatically, so this - is kind of fake transaction, it's only purpose being optimizing writes. - Returns same as mail_cache_lock(). */ -int mail_cache_transaction_begin(struct mail_cache_view *view, int nonblock, - struct mail_index_transaction *t, - struct mail_cache_transaction_ctx **ctx_r) -{ - *ctx_r = NULL; - return 1; + // FIXME } -int mail_cache_transaction_commit(struct mail_cache_transaction_ctx *ctx) -{return 0;} -void mail_cache_transaction_rollback(struct mail_cache_transaction_ctx *ctx) {} - -/* Should be called only by mail_transaction_commit/rollback: */ -int mail_cache_transaction_end(struct mail_cache_transaction_ctx *ctx) -{return 0;} - -/* Return NULL-terminated list of headers for given index, or NULL if - header index isn't used. */ -const char *const *mail_cache_get_header_fields(struct mail_cache_view *view, - unsigned int idx) -{return NULL;} -/* Set list of headers for given index. */ -int mail_cache_set_header_fields(struct mail_cache_transaction_ctx *ctx, - unsigned int idx, const char *const headers[]) -{return 0;} - -/* Add new field to given record. Updates are not allowed. Fixed size fields - must be exactly the expected size and they're converted to network byte - order in disk. */ -int mail_cache_add(struct mail_cache_transaction_ctx *ctx, uint32_t seq, - enum mail_cache_field field, - const void *data, size_t data_size) -{return 0;} - -/* Mark the given record deleted. */ -int mail_cache_delete(struct mail_cache_transaction_ctx *ctx, uint32_t seq) -{return 0;} - -/* Return all fields that are currently cached for record. */ -enum mail_cache_field -mail_cache_get_fields(struct mail_cache_view *view, uint32_t seq) {return 0;} - -/* Set data_r and size_r to point to wanted field in cache file. - Returns TRUE if field was found. If field contains multiple fields, - first one found is returned. This is mostly useful for finding headers. */ -int mail_cache_lookup_field(struct mail_cache_view *view, uint32_t seq, - enum mail_cache_field field, - const void **data_r, size_t *size_r) {return 0;} - -/* Return string field. */ -const char * -mail_cache_lookup_string_field(struct mail_cache_view *view, uint32_t seq, - enum mail_cache_field field) {return 0;} - -/* Copy fixed size field to given buffer. buffer_size must be exactly the - expected size. The result will be converted to host byte order. - Returns TRUE if field was found. */ -int mail_cache_copy_fixed_field(struct mail_cache_view *view, uint32_t seq, - enum mail_cache_field field, - void *buffer, size_t buffer_size) {return 0;} - -/* Mark given fields as missing, ie. they should be cached when possible. */ -void mail_cache_mark_missing(struct mail_cache_view *view, - enum mail_cache_field fields) {} - -/* Return index flags. */ -enum mail_cache_record_flag -mail_cache_get_record_flags(struct mail_cache_view *view, uint32_t seq) -{return 0;} - -/* Update index flags. The cache file must be locked and the flags must be - already inserted to the record. */ -int mail_cache_update_record_flags(struct mail_cache_view *view, uint32_t seq, - enum mail_cache_record_flag flags) -{return 0;} - -/* Update location offset. External locking is assumed to take care of locking - readers out to prevent race conditions. */ -int mail_cache_update_location_offset(struct mail_cache_view *view, - uint32_t seq, uoff_t offset) -{return 0;} - -/* "Error in index cache file %s: ...". */ -void mail_cache_set_corrupted(struct mail_cache *cache, const char *fmt, ...) -{} - -#endif
--- a/src/lib-index/mail-cache.h Sun Jun 20 09:33:08 2004 +0300 +++ b/src/lib-index/mail-cache.h Sun Jun 20 11:05:41 2004 +0300 @@ -28,12 +28,9 @@ enum mail_cache_field { /* fixed size fields */ MAIL_CACHE_INDEX_FLAGS = 0x00000001, - MAIL_CACHE_LOCATION_OFFSET = 0x00000002, - MAIL_CACHE_MD5 = 0x00000004, MAIL_CACHE_SENT_DATE = 0x00000008, MAIL_CACHE_RECEIVED_DATE = 0x00000010, MAIL_CACHE_VIRTUAL_FULL_SIZE = 0x00000020, - MAIL_CACHE_PHYSICAL_BODY_SIZE = 0x00000040, /* variable sized field */ MAIL_CACHE_HEADERS1 = 0x40000000, @@ -47,12 +44,9 @@ MAIL_CACHE_MESSAGEPART = 0x00400000, MAIL_CACHE_FIXED_MASK = MAIL_CACHE_INDEX_FLAGS | - MAIL_CACHE_LOCATION_OFFSET | - MAIL_CACHE_MD5 | MAIL_CACHE_SENT_DATE | MAIL_CACHE_RECEIVED_DATE | - MAIL_CACHE_VIRTUAL_FULL_SIZE | - MAIL_CACHE_PHYSICAL_BODY_SIZE, + MAIL_CACHE_VIRTUAL_FULL_SIZE, MAIL_CACHE_HEADERS_MASK = MAIL_CACHE_HEADERS1 | MAIL_CACHE_HEADERS2 | MAIL_CACHE_HEADERS3 | @@ -74,7 +68,7 @@ extern enum mail_cache_field mail_cache_header_fields[MAIL_CACHE_HEADERS_COUNT]; -int mail_cache_open_or_create(struct mail_index *index); +struct mail_cache *mail_cache_open_or_create(struct mail_index *index); void mail_cache_free(struct mail_cache *cache); void mail_cache_set_defaults(struct mail_cache *cache, @@ -167,11 +161,6 @@ int mail_cache_update_record_flags(struct mail_cache_view *view, uint32_t seq, enum mail_cache_record_flag flags); -/* Update location offset. External locking is assumed to take care of locking - readers out to prevent race conditions. */ -int mail_cache_update_location_offset(struct mail_cache_view *view, - uint32_t seq, uoff_t offset); - /* "Error in index cache file %s: ...". */ void mail_cache_set_corrupted(struct mail_cache *cache, const char *fmt, ...) __attr_format__(2, 3);
--- a/src/lib-index/mail-index.c Sun Jun 20 09:33:08 2004 +0300 +++ b/src/lib-index/mail-index.c Sun Jun 20 11:05:41 2004 +0300 @@ -8,6 +8,7 @@ #include "write-full.h" #include "mail-index-private.h" #include "mail-transaction-log.h" +#include "mail-cache.h" #include <stdio.h> #include <stddef.h> @@ -553,7 +554,7 @@ ret = mail_index_try_open(index, NULL); if (ret != 0) { mail_transaction_log_sync_unlock(index->log); - return ret; + return ret < 0 ? -1 : 0; } /* create it fully in index.tmp first */ @@ -618,6 +619,7 @@ hdr->next_uid = 1; } +/* returns -1 = error, 0 = won't create, 1 = ok */ static int mail_index_open_files(struct mail_index *index, enum mail_index_open_flags flags) { @@ -643,9 +645,27 @@ if (index->log == NULL) return -1; - if (lock_id != 0) - mail_index_unlock(index, lock_id); - return index->fd != -1 ? 1 : mail_index_create(index, &hdr); + if (index->fd == -1) { + if (lock_id != 0) { + mail_index_unlock(index, lock_id); + lock_id = 0; + } + if (mail_index_create(index, &hdr) < 0) + return -1; + } + + if (lock_id == 0) { + if (mail_index_lock_shared(index, FALSE, &lock_id) < 0) + return -1; + + } + + index->cache = mail_cache_open_or_create(index); + if (index->cache == NULL) + return -1; + + mail_index_unlock(index, lock_id); + return 1; } int mail_index_open(struct mail_index *index, enum mail_index_open_flags flags) @@ -711,6 +731,11 @@ index->map = NULL; } + if (index->cache != NULL) { + mail_cache_free(index->cache); + index->cache = NULL; + } + if (index->fd != -1) { if (close(index->fd) < 0) mail_index_set_syscall_error(index, "close()");
--- a/src/lib-storage/index/index-mail.c Sun Jun 20 09:33:08 2004 +0300 +++ b/src/lib-storage/index/index-mail.c Sun Jun 20 11:05:41 2004 +0300 @@ -157,8 +157,8 @@ if (!index_mail_cache_can_add(mail, field)) return; - if (!mail_cache_add(mail->trans->cache_trans, mail->data.seq, - field, data, size)) + if (mail_cache_add(mail->trans->cache_trans, mail->data.seq, + field, data, size) < 0) mail_cache_transaction_rollback(mail->trans->cache_trans); mail->data.cached_fields |= field;
--- a/src/lib-storage/index/index-storage.c Sun Jun 20 09:33:08 2004 +0300 +++ b/src/lib-storage/index/index-storage.c Sun Jun 20 11:05:41 2004 +0300 @@ -350,6 +350,8 @@ } ibox->view = mail_index_view_open(index); + ibox->cache_view = + mail_cache_view_open(ibox->cache, ibox->view); return ibox; } while (0); @@ -362,6 +364,8 @@ { struct index_mailbox *ibox = (struct index_mailbox *) box; + if (ibox->cache_view != NULL) + mail_cache_view_close(ibox->cache_view); if (ibox->view != NULL) mail_index_view_close(ibox->view);
--- a/src/lib-storage/index/index-transaction.c Sun Jun 20 09:33:08 2004 +0300 +++ b/src/lib-storage/index/index-transaction.c Sun Jun 20 11:05:41 2004 +0300 @@ -20,8 +20,11 @@ uoff_t offset; int ret; - if (t->cache_trans != NULL) + if (t->cache_trans != NULL) { (void)mail_cache_transaction_commit(t->cache_trans); + (void)mail_cache_transaction_end(t->cache_trans); + t->cache_trans = NULL; + } ret = mail_index_transaction_commit(t->trans, &seq, &offset); if (ret < 0)