mail-cache.c revision a817fdcc43aedf423e2134091d5f83f91d64bcc9
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "array.h"
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen#include "buffer.h"
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen#include "hash.h"
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen#include "file-cache.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mmap-util.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "write-full.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-cache-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <unistd.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_cache_set_syscall_error(struct mail_cache *cache,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *function)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(function != NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ENOSPACE(errno)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cache->index->nodiskspace = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_set_error(cache->index,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "%s failed with index cache file %s: %m",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen function, cache->filepath);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_cache_set_corrupted(struct mail_cache *cache, const char *fmt, ...)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen va_list va;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen (void)unlink(cache->filepath);
ad850190d946d34966a56838cfdb216e021b5b5fTimo Sirainen
ad850190d946d34966a56838cfdb216e021b5b5fTimo Sirainen /* mark the cache as unusable */
ad850190d946d34966a56838cfdb216e021b5b5fTimo Sirainen cache->hdr = NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen va_start(va, fmt);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen t_push();
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_set_error(cache->index, "Corrupted index cache file %s: %s",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cache->filepath, t_strdup_vprintf(fmt, va));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen t_pop();
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen va_end(va);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainenvoid mail_cache_file_close(struct mail_cache *cache)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (cache->mmap_base != NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (munmap(cache->mmap_base, cache->mmap_length) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_cache_set_syscall_error(cache, "munmap()");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen if (cache->file_cache != NULL)
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen file_cache_set_fd(cache->file_cache, -1);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cache->mmap_base = NULL;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen cache->data = NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cache->hdr = NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cache->mmap_length = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (cache->fd != -1) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (close(cache->fd) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_cache_set_syscall_error(cache, "close()");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cache->fd = -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainenint mail_cache_reopen(struct mail_cache *cache)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen struct mail_index_view *view;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen const struct mail_index_ext *ext;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen if (MAIL_CACHE_IS_UNUSABLE(cache) &&
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen (cache->need_compress || MAIL_INDEX_IS_IN_MEMORY(cache->index))) {
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen /* reopening does no good */
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen return 0;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen mail_cache_file_close(cache);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen cache->fd = open(cache->filepath, O_RDWR);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (cache->fd == -1) {
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (errno == ENOENT)
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen cache->need_compress = TRUE;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen else
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen mail_cache_set_syscall_error(cache, "open()");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen if (cache->file_cache != NULL)
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen file_cache_set_fd(cache->file_cache, cache->fd);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (mail_cache_map(cache, 0, 0) < 0)
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (mail_cache_header_fields_read(cache) < 0)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return -1;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen view = mail_index_view_open(cache->index);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ext = mail_index_view_get_ext(view, cache->ext_id);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (ext == NULL || cache->hdr->file_seq != ext->reset_id) {
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen /* still different - maybe a race condition or maybe the
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen file_seq really is corrupted. either way, this shouldn't
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen happen often so we'll just mark cache to be compressed
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen later which fixes this. */
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen cache->need_compress = TRUE;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen mail_index_view_close(view);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen return 0;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen }
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen mail_index_view_close(view);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen return 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainenstatic int mail_cache_verify_header(struct mail_cache *cache)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen const struct mail_cache_header *hdr = cache->data;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* check that the header is still ok */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (cache->mmap_length < sizeof(struct mail_cache_header)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_cache_set_corrupted(cache, "File too small");
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen if (cache->hdr->version != MAIL_CACHE_VERSION) {
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen /* version changed - upgrade silently */
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen return FALSE;
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen }
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (cache->hdr->indexid != cache->index->indexid) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* index id changed */
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen mail_cache_set_corrupted(cache, "indexid changed");
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* only check the header if we're locked */
37e6cf44d61a81c6839e3ab76234b54309d8d292Timo Sirainen if (!cache->locked)
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen return TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen if (hdr->used_file_size < sizeof(struct mail_cache_header)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_cache_set_corrupted(cache, "used_file_size too small");
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen if ((hdr->used_file_size % sizeof(uint32_t)) != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_cache_set_corrupted(cache, "used_file_size not aligned");
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen if (cache->mmap_base != NULL &&
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen hdr->used_file_size > cache->mmap_length) {
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen mail_cache_set_corrupted(cache, "used_file_size too large");
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen return TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainenint mail_cache_map(struct mail_cache *cache, size_t offset, size_t size)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen ssize_t ret;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (size == 0)
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen size = sizeof(struct mail_cache_header);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen if (cache->file_cache != NULL) {
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen cache->data = NULL;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen cache->hdr = NULL;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen ret = file_cache_read(cache->file_cache, offset, size);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen if (ret < 0) {
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen // FIXME: ESTALE
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen mail_cache_set_syscall_error(cache, "read()");
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen return -1;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen }
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen cache->data = file_cache_get_map(cache->file_cache,
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen &cache->mmap_length);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen cache->hdr = cache->data;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen if (offset == 0 && !mail_cache_verify_header(cache)) {
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen cache->need_compress = TRUE;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen return -1;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen }
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen return 0;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen }
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (offset < cache->mmap_length &&
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen size <= cache->mmap_length - offset) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* already mapped */
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (cache->mmap_base != NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (munmap(cache->mmap_base, cache->mmap_length) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_cache_set_syscall_error(cache, "munmap()");
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen } else {
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (cache->fd == -1) {
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen /* unusable, waiting for compression or
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen index is in memory */
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen i_assert(cache->need_compress ||
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen MAIL_INDEX_IS_IN_MEMORY(cache->index));
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen return -1;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* map the whole file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cache->hdr = NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cache->mmap_length = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen cache->mmap_base = mmap_ro_file(cache->fd, &cache->mmap_length);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (cache->mmap_base == MAP_FAILED) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cache->mmap_base = NULL;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen cache->data = NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_cache_set_syscall_error(cache, "mmap()");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen cache->data = cache->mmap_base;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen cache->hdr = cache->mmap_base;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen if (!mail_cache_verify_header(cache)) {
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen cache->need_compress = TRUE;
d565eaa943f29a49b97230ced57eec40ee65b4f9Timo Sirainen return -1;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainenstatic int mail_cache_open_and_verify(struct mail_cache *cache)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen if (MAIL_INDEX_IS_IN_MEMORY(cache->index))
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen return 0;
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cache->fd = open(cache->filepath, O_RDWR);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (cache->fd == -1) {
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (errno == ENOENT) {
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen cache->need_compress = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_cache_set_syscall_error(cache, "open()");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen if (cache->file_cache != NULL)
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen file_cache_set_fd(cache->file_cache, cache->fd);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (mail_cache_map(cache, 0, sizeof(struct mail_cache_header)) < 0)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return -1;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return mail_cache_header_fields_read(cache);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainenstatic struct mail_cache *mail_cache_alloc(struct mail_index *index)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_cache *cache;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cache = i_new(struct mail_cache, 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cache->index = index;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cache->fd = -1;
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen cache->filepath =
a835194f9a9dae88528367a791cbc282589f6c01Timo Sirainen i_strconcat(index->filepath, MAIL_CACHE_FILE_SUFFIX, NULL);
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen cache->field_pool = pool_alloconly_create("Cache fields", 1024);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen cache->field_name_hash =
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen hash_create(default_pool, cache->field_pool, 0,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen strcase_hash, (hash_cmp_callback_t *)strcasecmp);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen cache->dotlock_settings.timeout = MAIL_CACHE_LOCK_TIMEOUT;
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen cache->dotlock_settings.stale_timeout = MAIL_CACHE_LOCK_CHANGE_TIMEOUT;
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen cache->dotlock_settings.immediate_stale_timeout =
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen MAIL_CACHE_LOCK_IMMEDIATE_TIMEOUT;
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen if (!MAIL_INDEX_IS_IN_MEMORY(index)) {
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen if (index->mmap_disable || index->mmap_no_write)
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen cache->file_cache = file_cache_new(-1);
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen cache->ext_id =
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen mail_index_ext_register(index, "cache", 0,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen sizeof(uint32_t), sizeof(uint32_t));
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen mail_index_register_expunge_handler(index, cache->ext_id,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen mail_cache_expunge_handler);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen mail_index_register_sync_handler(index, cache->ext_id,
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen mail_cache_sync_handler,
69bd816e46fdee6182d0cb2e4c6be32399a555c8Timo Sirainen MAIL_INDEX_SYNC_HANDLER_INDEX |
69bd816e46fdee6182d0cb2e4c6be32399a555c8Timo Sirainen (cache->file_cache == NULL ? 0 :
69bd816e46fdee6182d0cb2e4c6be32399a555c8Timo Sirainen MAIL_INDEX_SYNC_HANDLER_VIEW));
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen if (cache->file_cache != NULL) {
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen mail_index_register_sync_lost_handler(index,
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen mail_cache_sync_lost_handler);
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen }
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen return cache;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainenstruct mail_cache *mail_cache_open_or_create(struct mail_index *index)
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen{
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen struct mail_cache *cache;
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen cache = mail_cache_alloc(index);
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen if (mail_cache_open_and_verify(cache) < 0) {
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen /* failed for some reason - doesn't really matter,
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen it's disabled for now. */
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen mail_cache_file_close(cache);
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen }
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen return cache;
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen}
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainenstruct mail_cache *mail_cache_create(struct mail_index *index)
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen{
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen struct mail_cache *cache;
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen cache = mail_cache_alloc(index);
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen cache->need_compress = TRUE;
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen return cache;
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen}
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_cache_free(struct mail_cache *cache)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen if (cache->file_cache != NULL) {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen mail_index_unregister_sync_lost_handler(cache->index,
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen mail_cache_sync_lost_handler);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen file_cache_free(cache->file_cache);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen cache->file_cache = NULL;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen }
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen mail_index_unregister_expunge_handler(cache->index, cache->ext_id);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen mail_index_unregister_sync_handler(cache->index, cache->ext_id);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_cache_file_close(cache);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen hash_destroy(cache->field_name_hash);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen pool_unref(cache->field_pool);
0cea9b1f4fa0495a48f5f097e40492517d67e1baTimo Sirainen i_free(cache->field_file_map);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen i_free(cache->file_field_map);
0cea9b1f4fa0495a48f5f097e40492517d67e1baTimo Sirainen i_free(cache->fields);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_free(cache->filepath);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_free(cache);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
2af769daebd83719ac696a440e06f6020471cec0Timo Sirainenstatic int mail_cache_lock_file(struct mail_cache *cache, int lock_type)
2af769daebd83719ac696a440e06f6020471cec0Timo Sirainen{
2af769daebd83719ac696a440e06f6020471cec0Timo Sirainen if (cache->index->lock_method != MAIL_INDEX_LOCK_DOTLOCK) {
2af769daebd83719ac696a440e06f6020471cec0Timo Sirainen return mail_index_lock_fd(cache->index, cache->filepath,
2af769daebd83719ac696a440e06f6020471cec0Timo Sirainen cache->fd, lock_type,
2af769daebd83719ac696a440e06f6020471cec0Timo Sirainen MAIL_INDEX_LOCK_SECS);
2af769daebd83719ac696a440e06f6020471cec0Timo Sirainen }
2af769daebd83719ac696a440e06f6020471cec0Timo Sirainen
2af769daebd83719ac696a440e06f6020471cec0Timo Sirainen if (lock_type != F_UNLCK) {
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen return file_dotlock_create(&cache->dotlock_settings,
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen cache->filepath, 0, &cache->dotlock);
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen } else
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen return file_dotlock_delete(&cache->dotlock);
2af769daebd83719ac696a440e06f6020471cec0Timo Sirainen}
2af769daebd83719ac696a440e06f6020471cec0Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenint mail_cache_lock(struct mail_cache *cache)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen struct mail_index_view *view;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen const struct mail_index_ext *ext;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen int i, ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen i_assert(!cache->locked);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (MAIL_CACHE_IS_UNUSABLE(cache))
ba482d3624ca4f1b3d638e6e8470ba5134f21493Timo Sirainen return 0;
ba482d3624ca4f1b3d638e6e8470ba5134f21493Timo Sirainen
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen view = mail_index_view_open(cache->index);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ext = mail_index_view_get_ext(view, cache->ext_id);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (ext == NULL) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen /* cache not used */
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen mail_index_view_close(view);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return 0;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (cache->hdr->file_seq != ext->reset_id) {
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen /* we want the latest cache file */
21455709020274a628faa9b9bd7839cb8efe3c73Timo Sirainen if ((ret = mail_cache_reopen(cache)) <= 0) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen mail_index_view_close(view);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen return ret;
21455709020274a628faa9b9bd7839cb8efe3c73Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen for (i = 0; i < 3; i++) {
2af769daebd83719ac696a440e06f6020471cec0Timo Sirainen ret = mail_cache_lock_file(cache, F_WRLCK);
2af769daebd83719ac696a440e06f6020471cec0Timo Sirainen if (ret <= 0)
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen break;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen cache->locked = TRUE;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (cache->hdr->file_seq == ext->reset_id) {
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen /* got it */
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen /* okay, so it was just compressed. try again. */
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen (void)mail_cache_unlock(cache);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if ((ret = mail_cache_reopen(cache)) <= 0)
21455709020274a628faa9b9bd7839cb8efe3c73Timo Sirainen break;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen ret = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen if (ret > 0) {
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen /* make sure our header is up to date */
114a0f74e0f825c6bd8aeadfafb248a030762a1fTimo Sirainen if (cache->file_cache != NULL) {
114a0f74e0f825c6bd8aeadfafb248a030762a1fTimo Sirainen file_cache_invalidate(cache->file_cache, 0,
114a0f74e0f825c6bd8aeadfafb248a030762a1fTimo Sirainen sizeof(struct mail_cache_header));
114a0f74e0f825c6bd8aeadfafb248a030762a1fTimo Sirainen }
7981779f9aebd25728d3c26555d598ff842cf2e2Timo Sirainen if (mail_cache_map(cache, 0, 0) == 0)
7981779f9aebd25728d3c26555d598ff842cf2e2Timo Sirainen cache->hdr_copy = *cache->hdr;
7981779f9aebd25728d3c26555d598ff842cf2e2Timo Sirainen else {
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen (void)mail_cache_unlock(cache);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen ret = -1;
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen }
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen mail_index_view_close(view);
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen i_assert((ret <= 0 && !cache->locked) || (ret > 0 && cache->locked));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenstatic void mail_cache_update_need_compress(struct mail_cache *cache)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen const struct mail_cache_header *hdr = cache->hdr;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen unsigned int cont_percentage;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen uoff_t max_del_space;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen cont_percentage = hdr->continued_record_count * 100 /
089756ceca55966f1a70e8591f6086026e51015cTimo Sirainen (cache->index->map->records_count == 0 ? 1 :
089756ceca55966f1a70e8591f6086026e51015cTimo Sirainen cache->index->map->records_count);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (cont_percentage >= COMPRESS_CONTINUED_PERCENTAGE &&
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen hdr->used_file_size >= COMPRESS_MIN_SIZE) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen /* too many continued rows, compress */
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen cache->need_compress = TRUE;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen /* see if we've reached the max. deleted space in file */
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen max_del_space = hdr->used_file_size / 100 * COMPRESS_PERCENTAGE;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (hdr->deleted_space >= max_del_space &&
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen hdr->used_file_size >= COMPRESS_MIN_SIZE)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen cache->need_compress = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainenint mail_cache_unlock(struct mail_cache *cache)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen int ret = 0;
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen i_assert(cache->locked);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen if (cache->field_header_write_pending)
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen ret = mail_cache_header_fields_update(cache);
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen cache->locked = FALSE;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
62cfc346eb7b0a4fd9e1ab6edd63b98711161229Timo Sirainen if (MAIL_CACHE_IS_UNUSABLE(cache)) {
62cfc346eb7b0a4fd9e1ab6edd63b98711161229Timo Sirainen /* we found it to be broken during the lock. just clean up. */
62cfc346eb7b0a4fd9e1ab6edd63b98711161229Timo Sirainen cache->hdr_modified = FALSE;
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen return -1;
62cfc346eb7b0a4fd9e1ab6edd63b98711161229Timo Sirainen }
62cfc346eb7b0a4fd9e1ab6edd63b98711161229Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (cache->hdr_modified) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen cache->hdr_modified = FALSE;
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen if (mail_cache_write(cache, &cache->hdr_copy,
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen sizeof(cache->hdr_copy), 0) < 0)
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen ret = -1;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen mail_cache_update_need_compress(cache);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
2af769daebd83719ac696a440e06f6020471cec0Timo Sirainen (void)mail_cache_lock_file(cache, F_UNLCK);
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen return ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainenint mail_cache_write(struct mail_cache *cache, const void *data, size_t size,
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen uoff_t offset)
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen{
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen if (pwrite_full(cache->fd, data, size, offset) < 0) {
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen mail_cache_set_syscall_error(cache, "pwrite_full()");
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen return -1;
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen }
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen
9566c1b4506d49778659e3dc65997f3c0399cb7eTimo Sirainen if (cache->file_cache != NULL) {
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen file_cache_write(cache->file_cache, data, size, offset);
9566c1b4506d49778659e3dc65997f3c0399cb7eTimo Sirainen
9566c1b4506d49778659e3dc65997f3c0399cb7eTimo Sirainen /* data/hdr pointers may change if file cache was grown */
9566c1b4506d49778659e3dc65997f3c0399cb7eTimo Sirainen cache->data = file_cache_get_map(cache->file_cache,
9566c1b4506d49778659e3dc65997f3c0399cb7eTimo Sirainen &cache->mmap_length);
9566c1b4506d49778659e3dc65997f3c0399cb7eTimo Sirainen cache->hdr = cache->data;
9566c1b4506d49778659e3dc65997f3c0399cb7eTimo Sirainen }
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen return 0;
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen}
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct mail_cache_view *
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmail_cache_view_open(struct mail_cache *cache, struct mail_index_view *iview)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_cache_view *view;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen view = i_new(struct mail_cache_view, 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen view->cache = cache;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen view->view = iview;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen ARRAY_CREATE(&view->tmp_offsets, default_pool, uint32_t, 32);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen view->cached_exists_buf =
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen buffer_create_dynamic(default_pool,
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen cache->file_fields_count + 10);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return view;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_cache_view_close(struct mail_cache_view *view)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen if (view->cache->field_header_write_pending)
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen (void)mail_cache_header_fields_update(view->cache);
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (view->trans_view != NULL)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen mail_index_view_close(view->trans_view);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_free(&view->tmp_offsets);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen buffer_free(view->cached_exists_buf);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_free(view);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}