mail-cache.c revision d9fdacd5fb3e07997e5c389739d2054f0c8441d8
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"
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen#include "nfs-workarounds.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
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen if (cache->file_lock != NULL)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen file_lock_free(&cache->file_lock);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen cache->locked = FALSE;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo 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
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen i_assert(!cache->locked);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen if (MAIL_CACHE_IS_UNUSABLE(cache) &&
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen (cache->need_compress_file_seq != 0 ||
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen 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
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen cache->fd = nfs_safe_open(cache->filepath, O_RDWR);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (cache->fd == -1) {
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (errno == ENOENT)
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen cache->need_compress_file_seq = (uint32_t)-1;
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. */
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen cache->need_compress_file_seq = cache->hdr->file_seq;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen mail_index_view_close(&view);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen return 0;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen }
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen mail_index_view_close(&view);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen return 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenstatic bool 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 }
e192a3b1ca8ae857e7d87298ea507d32977ba570Timo Sirainen if (hdr->compat_sizeof_uoff_t != sizeof(uoff_t)) {
e192a3b1ca8ae857e7d87298ea507d32977ba570Timo Sirainen /* architecture change - handle silently(?) */
e192a3b1ca8ae857e7d87298ea507d32977ba570Timo Sirainen return FALSE;
811f2e26d9782d9cb99fdf82e18ffa0a77564fe2Timo 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) {
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen /* In case of ESTALE we'll simply fail without error
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen messages. The caller will then just have to
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen fallback to generating the value itself.
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen We can't simply reopen the cache flie, because
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen using it requires also having updated file
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen offsets. */
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen if (errno != ESTALE)
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo 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)) {
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen cache->need_compress_file_seq =
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen cache->hdr->file_seq != 0 ?
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen cache->hdr->file_seq : (uint32_t)-1;
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 */
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen i_assert(cache->need_compress_file_seq != 0 ||
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)) {
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen cache->need_compress_file_seq =
f519e4c2ad4ef826f1b08f3e0138b9b287a52c80Timo Sirainen !MAIL_CACHE_IS_UNUSABLE(cache) &&
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen cache->hdr->file_seq != 0 ?
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen cache->hdr->file_seq : (uint32_t)-1;
d565eaa943f29a49b97230ced57eec40ee65b4f9Timo Sirainen return -1;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainenstatic int mail_cache_try_open(struct mail_cache *cache)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen cache->opened = TRUE;
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen if (MAIL_INDEX_IS_IN_MEMORY(cache->index))
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen return 0;
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen cache->fd = nfs_safe_open(cache->filepath, O_RDWR);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (cache->fd == -1) {
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (errno == ENOENT) {
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen cache->need_compress_file_seq = (uint32_t)-1;
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
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen return 1;
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen}
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainenint mail_cache_open_and_verify(struct mail_cache *cache)
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen{
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen int ret;
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen ret = mail_cache_try_open(cache);
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen if (ret > 0)
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen ret = mail_cache_header_fields_read(cache);
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen if (ret < 0) {
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen /* failed for some reason - doesn't really matter,
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen it's disabled for now. */
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen mail_cache_file_close(cache);
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen }
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen return ret;
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
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,
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen mail_cache_expunge_handler,
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen cache, FALSE);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen mail_index_register_sync_handler(index, cache->ext_id,
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen mail_cache_sync_handler,
9315dd69233d554452df0c12bc57002d2042a8f4Timo Sirainen MAIL_INDEX_SYNC_HANDLER_FILE |
9315dd69233d554452df0c12bc57002d2042a8f4Timo Sirainen MAIL_INDEX_SYNC_HANDLER_HEAD |
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 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);
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen cache->opened = TRUE;
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen cache->need_compress_file_seq = (uint32_t)-1;
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen return cache;
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen}
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenvoid mail_cache_free(struct mail_cache **_cache)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen struct mail_cache *cache = *_cache;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen *_cache = NULL;
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
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen file_cache_free(&cache->file_cache);
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{
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen if (cache->index->lock_method != FILE_LOCK_METHOD_DOTLOCK) {
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen i_assert(cache->file_lock == NULL);
2af769daebd83719ac696a440e06f6020471cec0Timo Sirainen return mail_index_lock_fd(cache->index, cache->filepath,
2af769daebd83719ac696a440e06f6020471cec0Timo Sirainen cache->fd, lock_type,
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen MAIL_INDEX_LOCK_SECS,
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen &cache->file_lock);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen } else {
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen i_assert(cache->dotlock == NULL);
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen return file_dotlock_create(&cache->dotlock_settings,
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen cache->filepath, 0, &cache->dotlock);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen }
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen}
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenstatic void mail_cache_unlock_file(struct mail_cache *cache)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen{
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen if (cache->index->lock_method != FILE_LOCK_METHOD_DOTLOCK)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen file_unlock(&cache->file_lock);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen else
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen (void)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
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen if (!cache->opened)
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen (void)mail_cache_open_and_verify(cache);
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen if (MAIL_CACHE_IS_UNUSABLE(cache) ||
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen MAIL_INDEX_IS_IN_MEMORY(cache->index))
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 */
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo 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) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo 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
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo 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 */
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen cache->need_compress_file_seq = hdr->file_seq;
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)
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen cache->need_compress_file_seq = hdr->file_seq;
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
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen mail_cache_unlock_file(cache);
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;
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen i_array_init(&view->tmp_offsets, 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)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo 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}