mail-cache.c revision 8b9342aa96b2f297e23afb261f9f7dd859800952
183bea41fa640dc8117f3eb45ff935cd81377a84Timo 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{
e8fd7988ec183fb6c104aed19a61f1a096c51d34Timo Sirainen i_assert(function != NULL);
e8fd7988ec183fb6c104aed19a61f1a096c51d34Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ENOSPACE(errno)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cache->index->nodiskspace = TRUE;
6bc0f424bcdb9119d8159874cf98adfa53eefd9aTimo Sirainen return;
6bc0f424bcdb9119d8159874cf98adfa53eefd9aTimo Sirainen }
6bc0f424bcdb9119d8159874cf98adfa53eefd9aTimo Sirainen
6bc0f424bcdb9119d8159874cf98adfa53eefd9aTimo Sirainen mail_index_set_error(cache->index,
6bc0f424bcdb9119d8159874cf98adfa53eefd9aTimo Sirainen "%s failed with index cache file %s: %m",
6bc0f424bcdb9119d8159874cf98adfa53eefd9aTimo Sirainen function, cache->filepath);
d35fee8d1e5e31614dba5e64d45ed23c7d6bfa53Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
6bc0f424bcdb9119d8159874cf98adfa53eefd9aTimo Sirainenvoid mail_cache_set_corrupted(struct mail_cache *cache, const char *fmt, ...)
ad850190d946d34966a56838cfdb216e021b5b5fTimo Sirainen{
ad850190d946d34966a56838cfdb216e021b5b5fTimo Sirainen va_list va;
d35fee8d1e5e31614dba5e64d45ed23c7d6bfa53Timo Sirainen
d35fee8d1e5e31614dba5e64d45ed23c7d6bfa53Timo Sirainen (void)unlink(cache->filepath);
d35fee8d1e5e31614dba5e64d45ed23c7d6bfa53Timo Sirainen
d35fee8d1e5e31614dba5e64d45ed23c7d6bfa53Timo Sirainen /* mark the cache as unusable */
d35fee8d1e5e31614dba5e64d45ed23c7d6bfa53Timo Sirainen cache->hdr = NULL;
d35fee8d1e5e31614dba5e64d45ed23c7d6bfa53Timo Sirainen
d35fee8d1e5e31614dba5e64d45ed23c7d6bfa53Timo Sirainen va_start(va, fmt);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen t_push();
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_set_error(cache->index, "Corrupted index cache file %s: %s",
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen cache->filepath, t_strdup_vprintf(fmt, va));
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen t_pop();
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen va_end(va);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen}
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
19e8adccba16ff419f5675b1575358c2956dce83Timo 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)
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen mail_cache_set_syscall_error(cache, "munmap()");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (cache->file_cache != NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen file_cache_set_fd(cache->file_cache, -1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cache->mmap_base = NULL;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen cache->data = NULL;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen cache->hdr = NULL;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen cache->mmap_length = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen if (cache->file_lock != NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen file_lock_free(&cache->file_lock);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cache->locked = FALSE;
6e235046e1d8e9d89fc948f5c623676c20421a28Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (cache->fd != -1) {
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen if (close(cache->fd) < 0)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen mail_cache_set_syscall_error(cache, "close()");
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen cache->fd = -1;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mail_cache_reopen(struct mail_cache *cache)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_index_view *view;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_index_ext *ext;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen i_assert(!cache->locked);
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen if (MAIL_CACHE_IS_UNUSABLE(cache) &&
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen (cache->need_compress_file_seq != 0 ||
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen MAIL_INDEX_IS_IN_MEMORY(cache->index))) {
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen /* reopening does no good */
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen return 0;
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen }
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen mail_cache_file_close(cache);
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen
85da8c055280cd45553b6b335e9fb226d6e2801eTimo Sirainen cache->fd = nfs_safe_open(cache->filepath, O_RDWR);
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen if (cache->fd == -1) {
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen if (errno == ENOENT)
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen cache->need_compress_file_seq = (uint32_t)-1;
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen else
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen mail_cache_set_syscall_error(cache, "open()");
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen return -1;
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen }
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen if (cache->file_cache != NULL)
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen file_cache_set_fd(cache->file_cache, cache->fd);
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen if (mail_cache_map(cache, 0, 0) < 0)
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen return -1;
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen if (mail_cache_header_fields_read(cache) < 0)
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen return -1;
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen view = mail_index_view_open(cache->index);
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen ext = mail_index_view_get_ext(view, cache->ext_id);
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen if (ext == NULL || cache->hdr->file_seq != ext->reset_id) {
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen /* still different - maybe a race condition or maybe the
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen file_seq really is corrupted. either way, this shouldn't
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen happen often so we'll just mark cache to be compressed
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen later which fixes this. */
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen cache->need_compress_file_seq = cache->hdr->file_seq;
66ecc94150cbce23aad3240135e0782e0a74d479Timo Sirainen mail_index_view_close(&view);
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen return 0;
04b8a90af181cc4c7959266855e8ed50a22ed413Timo Sirainen }
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen mail_index_view_close(&view);
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen return 1;
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen}
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainenstatic bool mail_cache_verify_header(struct mail_cache *cache)
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen{
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen const struct mail_cache_header *hdr = cache->data;
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen /* check that the header is still ok */
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen if (cache->mmap_length < sizeof(struct mail_cache_header)) {
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen mail_cache_set_corrupted(cache, "File too small");
66ecc94150cbce23aad3240135e0782e0a74d479Timo Sirainen return FALSE;
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen }
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen if (cache->hdr->version != MAIL_CACHE_VERSION) {
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen /* version changed - upgrade silently */
85da8c055280cd45553b6b335e9fb226d6e2801eTimo Sirainen return FALSE;
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen }
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen if (hdr->compat_sizeof_uoff_t != sizeof(uoff_t)) {
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen /* architecture change - handle silently(?) */
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen return FALSE;
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen }
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen if (cache->hdr->indexid != cache->index->indexid) {
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen /* index id changed */
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen mail_cache_set_corrupted(cache, "indexid changed");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return FALSE;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (cache->hdr->file_seq == 0) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen mail_cache_set_corrupted(cache, "file_seq is 0");
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen return FALSE;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen }
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen /* only check the header if we're locked */
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (!cache->locked)
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen return TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (hdr->used_file_size < sizeof(struct mail_cache_header)) {
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen mail_cache_set_corrupted(cache, "used_file_size too small");
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen return FALSE;
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen }
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if ((hdr->used_file_size % sizeof(uint32_t)) != 0) {
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen mail_cache_set_corrupted(cache, "used_file_size not aligned");
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen return FALSE;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen }
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (cache->mmap_base != NULL &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen hdr->used_file_size > cache->mmap_length) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_cache_set_corrupted(cache, "used_file_size too large");
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen return FALSE;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen }
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen return TRUE;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenint mail_cache_map(struct mail_cache *cache, size_t offset, size_t size)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen ssize_t ret;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (size == 0)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen size = sizeof(struct mail_cache_header);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (cache->file_cache != NULL) {
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen cache->data = NULL;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen cache->hdr = NULL;
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen ret = file_cache_read(cache->file_cache, offset, size);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (ret < 0) {
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen /* In case of ESTALE we'll simply fail without error
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen messages. The caller will then just have to
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen fallback to generating the value itself.
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen We can't simply reopen the cache flie, because
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen using it requires also having updated file
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen offsets. */
25c22e54d1071d120641e9eecd0023e7373e65ffTimo Sirainen if (errno != ESTALE)
25c22e54d1071d120641e9eecd0023e7373e65ffTimo Sirainen mail_cache_set_syscall_error(cache, "read()");
25c22e54d1071d120641e9eecd0023e7373e65ffTimo Sirainen return -1;
25c22e54d1071d120641e9eecd0023e7373e65ffTimo Sirainen }
25c22e54d1071d120641e9eecd0023e7373e65ffTimo Sirainen
25c22e54d1071d120641e9eecd0023e7373e65ffTimo Sirainen cache->data = file_cache_get_map(cache->file_cache,
25c22e54d1071d120641e9eecd0023e7373e65ffTimo Sirainen &cache->mmap_length);
25c22e54d1071d120641e9eecd0023e7373e65ffTimo Sirainen cache->hdr = cache->data;
25c22e54d1071d120641e9eecd0023e7373e65ffTimo Sirainen
25c22e54d1071d120641e9eecd0023e7373e65ffTimo Sirainen if (offset == 0 && !mail_cache_verify_header(cache)) {
25c22e54d1071d120641e9eecd0023e7373e65ffTimo Sirainen cache->need_compress_file_seq =
25c22e54d1071d120641e9eecd0023e7373e65ffTimo Sirainen cache->hdr->file_seq != 0 ?
25c22e54d1071d120641e9eecd0023e7373e65ffTimo Sirainen cache->hdr->file_seq : (uint32_t)-1;
25c22e54d1071d120641e9eecd0023e7373e65ffTimo Sirainen return -1;
25c22e54d1071d120641e9eecd0023e7373e65ffTimo Sirainen }
25c22e54d1071d120641e9eecd0023e7373e65ffTimo Sirainen return 0;
25c22e54d1071d120641e9eecd0023e7373e65ffTimo Sirainen }
25c22e54d1071d120641e9eecd0023e7373e65ffTimo Sirainen
25c22e54d1071d120641e9eecd0023e7373e65ffTimo Sirainen if (offset < cache->mmap_length &&
25c22e54d1071d120641e9eecd0023e7373e65ffTimo Sirainen size <= cache->mmap_length - offset) {
25c22e54d1071d120641e9eecd0023e7373e65ffTimo Sirainen /* already mapped */
25c22e54d1071d120641e9eecd0023e7373e65ffTimo Sirainen return 0;
25c22e54d1071d120641e9eecd0023e7373e65ffTimo Sirainen }
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (cache->mmap_base != NULL) {
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen if (munmap(cache->mmap_base, cache->mmap_length) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_cache_set_syscall_error(cache, "munmap()");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } else {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (cache->fd == -1) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* unusable, waiting for compression or
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen index is in memory */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(cache->need_compress_file_seq != 0 ||
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen MAIL_INDEX_IS_IN_MEMORY(cache->index));
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen return -1;
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen }
6bc0f424bcdb9119d8159874cf98adfa53eefd9aTimo Sirainen }
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen /* map the whole file */
e192a3b1ca8ae857e7d87298ea507d32977ba570Timo Sirainen cache->hdr = NULL;
e192a3b1ca8ae857e7d87298ea507d32977ba570Timo Sirainen cache->mmap_length = 0;
6bc0f424bcdb9119d8159874cf98adfa53eefd9aTimo Sirainen
e192a3b1ca8ae857e7d87298ea507d32977ba570Timo Sirainen cache->mmap_base = mmap_ro_file(cache->fd, &cache->mmap_length);
811f2e26d9782d9cb99fdf82e18ffa0a77564fe2Timo Sirainen if (cache->mmap_base == MAP_FAILED) {
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen cache->mmap_base = NULL;
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen cache->data = NULL;
c4877db8b6559846f4b58be8e42422dc734c193fTimo Sirainen mail_cache_set_syscall_error(cache, "mmap()");
6bc0f424bcdb9119d8159874cf98adfa53eefd9aTimo Sirainen return -1;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cache->data = cache->mmap_base;
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen cache->hdr = cache->mmap_base;
8b9342aa96b2f297e23afb261f9f7dd859800952Timo Sirainen
8b9342aa96b2f297e23afb261f9f7dd859800952Timo Sirainen if (!mail_cache_verify_header(cache)) {
8b9342aa96b2f297e23afb261f9f7dd859800952Timo Sirainen cache->need_compress_file_seq =
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen !MAIL_CACHE_IS_UNUSABLE(cache) &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cache->hdr->file_seq != 0 ?
37e6cf44d61a81c6839e3ab76234b54309d8d292Timo Sirainen cache->hdr->file_seq : (uint32_t)-1;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainenstatic int mail_cache_try_open(struct mail_cache *cache)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen cache->opened = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (MAIL_INDEX_IS_IN_MEMORY(cache->index))
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen return 0;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen cache->fd = nfs_safe_open(cache->filepath, O_RDWR);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (cache->fd == -1) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (errno == ENOENT) {
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen cache->need_compress_file_seq = (uint32_t)-1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_cache_set_syscall_error(cache, "open()");
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen return -1;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen }
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (cache->file_cache != NULL)
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen file_cache_set_fd(cache->file_cache, cache->fd);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mail_cache_map(cache, 0, sizeof(struct mail_cache_header)) < 0)
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen return -1;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen return 1;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen}
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainenint mail_cache_open_and_verify(struct mail_cache *cache)
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen{
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen int ret;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen ret = mail_cache_try_open(cache);
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen if (ret > 0)
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen ret = mail_cache_header_fields_read(cache);
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen if (ret < 0) {
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen /* failed for some reason - doesn't really matter,
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen it's disabled for now. */
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen mail_cache_file_close(cache);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen }
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen return ret;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen}
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainenstatic struct mail_cache *mail_cache_alloc(struct mail_index *index)
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen{
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen struct mail_cache *cache;
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen cache = i_new(struct mail_cache, 1);
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen cache->index = index;
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen cache->fd = -1;
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen cache->filepath =
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen i_strconcat(index->filepath, MAIL_CACHE_FILE_SUFFIX, NULL);
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen cache->field_pool = pool_alloconly_create("Cache fields", 1024);
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen cache->field_name_hash =
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen hash_create(default_pool, cache->field_pool, 0,
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen strcase_hash, (hash_cmp_callback_t *)strcasecmp);
25c22e54d1071d120641e9eecd0023e7373e65ffTimo Sirainen
25c22e54d1071d120641e9eecd0023e7373e65ffTimo Sirainen cache->dotlock_settings.use_excl_lock = index->use_excl_dotlocks;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen cache->dotlock_settings.timeout = MAIL_CACHE_LOCK_TIMEOUT;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen cache->dotlock_settings.stale_timeout = MAIL_CACHE_LOCK_CHANGE_TIMEOUT;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!MAIL_INDEX_IS_IN_MEMORY(index)) {
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (index->mmap_disable || index->mmap_no_write)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cache->file_cache = file_cache_new(-1);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cache->ext_id =
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_ext_register(index, "cache", 0,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen sizeof(uint32_t), sizeof(uint32_t));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_register_expunge_handler(index, cache->ext_id, FALSE,
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen mail_cache_expunge_handler, cache);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen mail_index_register_sync_handler(index, cache->ext_id,
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen mail_cache_sync_handler,
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen MAIL_INDEX_SYNC_HANDLER_FILE |
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen MAIL_INDEX_SYNC_HANDLER_HEAD |
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen (cache->file_cache == NULL ? 0 :
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen MAIL_INDEX_SYNC_HANDLER_VIEW));
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (cache->file_cache != NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_register_sync_lost_handler(index,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_cache_sync_lost_handler);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return cache;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct mail_cache *mail_cache_open_or_create(struct mail_index *index)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen struct mail_cache *cache;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cache = mail_cache_alloc(index);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return cache;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainenstruct mail_cache *mail_cache_create(struct mail_index *index)
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen{
f519e4c2ad4ef826f1b08f3e0138b9b287a52c80Timo Sirainen struct mail_cache *cache;
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen cache = mail_cache_alloc(index);
d565eaa943f29a49b97230ced57eec40ee65b4f9Timo Sirainen cache->opened = TRUE;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen cache->need_compress_file_seq = (uint32_t)-1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return cache;
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen}
25c22e54d1071d120641e9eecd0023e7373e65ffTimo Sirainen
25c22e54d1071d120641e9eecd0023e7373e65ffTimo Sirainenvoid mail_cache_free(struct mail_cache **_cache)
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_cache *cache = *_cache;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen *_cache = NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (cache->file_cache != NULL) {
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen mail_index_unregister_sync_lost_handler(cache->index,
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen mail_cache_sync_lost_handler);
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen file_cache_free(&cache->file_cache);
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen }
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen mail_index_unregister_expunge_handler(cache->index, cache->ext_id);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_unregister_sync_handler(cache->index, cache->ext_id);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen mail_cache_file_close(cache);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen hash_destroy(cache->field_name_hash);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen pool_unref(cache->field_pool);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_free(cache->field_file_map);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_free(cache->file_field_map);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_free(cache->fields);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_free(cache->filepath);
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen i_free(cache);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic int mail_cache_lock_file(struct mail_cache *cache, int lock_type)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen if (cache->index->lock_method != FILE_LOCK_METHOD_DOTLOCK) {
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen i_assert(cache->file_lock == NULL);
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen return mail_index_lock_fd(cache->index, cache->filepath,
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen cache->fd, lock_type,
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen MAIL_INDEX_LOCK_SECS,
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen &cache->file_lock);
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen } else {
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen i_assert(cache->dotlock == NULL);
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen return file_dotlock_create(&cache->dotlock_settings,
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen cache->filepath, 0, &cache->dotlock);
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen }
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen}
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainenstatic void mail_cache_unlock_file(struct mail_cache *cache)
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen{
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen if (cache->index->lock_method != FILE_LOCK_METHOD_DOTLOCK)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen file_unlock(&cache->file_lock);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen (void)file_dotlock_delete(&cache->dotlock);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mail_cache_lock(struct mail_cache *cache)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_index_view *view;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_index_ext *ext;
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen int i, ret;
a835194f9a9dae88528367a791cbc282589f6c01Timo Sirainen
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen i_assert(!cache->locked);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen if (!cache->opened)
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen (void)mail_cache_open_and_verify(cache);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
66ecc94150cbce23aad3240135e0782e0a74d479Timo Sirainen if (MAIL_CACHE_IS_UNUSABLE(cache) ||
66ecc94150cbce23aad3240135e0782e0a74d479Timo Sirainen MAIL_INDEX_IS_IN_MEMORY(cache->index))
66ecc94150cbce23aad3240135e0782e0a74d479Timo Sirainen return 0;
66ecc94150cbce23aad3240135e0782e0a74d479Timo Sirainen
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen view = mail_index_view_open(cache->index);
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen ext = mail_index_view_get_ext(view, cache->ext_id);
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen if (ext == NULL) {
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen /* cache not used */
66ecc94150cbce23aad3240135e0782e0a74d479Timo Sirainen mail_index_view_close(&view);
66ecc94150cbce23aad3240135e0782e0a74d479Timo Sirainen return 0;
66ecc94150cbce23aad3240135e0782e0a74d479Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (cache->hdr->file_seq != ext->reset_id) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen /* we want the latest cache file */
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if ((ret = mail_cache_reopen(cache)) <= 0) {
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen mail_index_view_close(&view);
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen return ret;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen }
9315dd69233d554452df0c12bc57002d2042a8f4Timo Sirainen
9315dd69233d554452df0c12bc57002d2042a8f4Timo Sirainen for (i = 0; i < 3; i++) {
69bd816e46fdee6182d0cb2e4c6be32399a555c8Timo Sirainen ret = mail_cache_lock_file(cache, F_WRLCK);
69bd816e46fdee6182d0cb2e4c6be32399a555c8Timo Sirainen if (ret <= 0)
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen break;
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen cache->locked = TRUE;
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen if (cache->hdr->file_seq == ext->reset_id) {
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen /* got it */
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen /* okay, so it was just compressed. try again. */
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen (void)mail_cache_unlock(cache);
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen if ((ret = mail_cache_reopen(cache)) <= 0)
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen break;
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen ret = 0;
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen }
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen if (ret > 0) {
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen /* make sure our header is up to date */
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen if (cache->file_cache != NULL) {
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen file_cache_invalidate(cache->file_cache, 0,
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen sizeof(struct mail_cache_header));
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen }
5196f9ea42d02000f9c3d22f20aa816140af4422Timo Sirainen if (mail_cache_map(cache, 0, 0) == 0)
5196f9ea42d02000f9c3d22f20aa816140af4422Timo Sirainen cache->hdr_copy = *cache->hdr;
5196f9ea42d02000f9c3d22f20aa816140af4422Timo Sirainen else {
5196f9ea42d02000f9c3d22f20aa816140af4422Timo Sirainen (void)mail_cache_unlock(cache);
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen ret = -1;
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen }
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen }
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_view_close(&view);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen i_assert((ret <= 0 && !cache->locked) || (ret > 0 && cache->locked));
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen return ret;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen}
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainenstatic void mail_cache_update_need_compress(struct mail_cache *cache)
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen{
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen const struct mail_cache_header *hdr = cache->hdr;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen unsigned int cont_percentage;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen uoff_t max_del_space;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen cont_percentage = hdr->continued_record_count * 100 /
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen (cache->index->map->records_count == 0 ? 1 :
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen cache->index->map->records_count);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (cont_percentage >= MAIL_CACHE_COMPRESS_CONTINUED_PERCENTAGE &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen hdr->used_file_size >= MAIL_CACHE_COMPRESS_MIN_SIZE) {
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen /* too many continued rows, compress */
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen cache->need_compress_file_seq = hdr->file_seq;
0cea9b1f4fa0495a48f5f097e40492517d67e1baTimo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
0cea9b1f4fa0495a48f5f097e40492517d67e1baTimo Sirainen /* see if we've reached the max. deleted space in file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen max_del_space = hdr->used_file_size / 100 *
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen MAIL_CACHE_COMPRESS_PERCENTAGE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (hdr->deleted_space >= max_del_space &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen hdr->used_file_size >= MAIL_CACHE_COMPRESS_MIN_SIZE)
d0bbbc7057aa33b52ee378196dee7d773437468fTimo Sirainen cache->need_compress_file_seq = hdr->file_seq;
2af769daebd83719ac696a440e06f6020471cec0Timo Sirainen}
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen
51b979b6414b940f04677a7e2d064be119345954Timo Sirainenint mail_cache_unlock(struct mail_cache *cache)
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen{
763f83d3cc47bce05cbc396419c4db2b71dd8e68Timo Sirainen int ret = 0;
763f83d3cc47bce05cbc396419c4db2b71dd8e68Timo Sirainen
763f83d3cc47bce05cbc396419c4db2b71dd8e68Timo Sirainen i_assert(cache->locked);
763f83d3cc47bce05cbc396419c4db2b71dd8e68Timo Sirainen
763f83d3cc47bce05cbc396419c4db2b71dd8e68Timo Sirainen if (cache->field_header_write_pending)
763f83d3cc47bce05cbc396419c4db2b71dd8e68Timo Sirainen ret = mail_cache_header_fields_update(cache);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen cache->locked = FALSE;
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen if (MAIL_CACHE_IS_UNUSABLE(cache)) {
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen /* we found it to be broken during the lock. just clean up. */
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen cache->hdr_modified = FALSE;
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen return -1;
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen }
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen if (cache->hdr_modified) {
d0bbbc7057aa33b52ee378196dee7d773437468fTimo Sirainen cache->hdr_modified = FALSE;
d0bbbc7057aa33b52ee378196dee7d773437468fTimo Sirainen if (mail_cache_write(cache, &cache->hdr_copy,
d0bbbc7057aa33b52ee378196dee7d773437468fTimo Sirainen sizeof(cache->hdr_copy), 0) < 0)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen ret = -1;
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen mail_cache_update_need_compress(cache);
d0bbbc7057aa33b52ee378196dee7d773437468fTimo Sirainen }
d0bbbc7057aa33b52ee378196dee7d773437468fTimo Sirainen
4aae8acbcfa9cac96b4af39bfabcbe569e804827Timo Sirainen mail_cache_unlock_file(cache);
5bdad39213d28ab35e615a7f4ea1712ab25b6a80Timo Sirainen return ret;
5bdad39213d28ab35e615a7f4ea1712ab25b6a80Timo Sirainen}
5bdad39213d28ab35e615a7f4ea1712ab25b6a80Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenint mail_cache_write(struct mail_cache *cache, const void *data, size_t size,
763f83d3cc47bce05cbc396419c4db2b71dd8e68Timo Sirainen uoff_t offset)
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen{
4aae8acbcfa9cac96b4af39bfabcbe569e804827Timo Sirainen if (pwrite_full(cache->fd, data, size, offset) < 0) {
4aae8acbcfa9cac96b4af39bfabcbe569e804827Timo Sirainen mail_cache_set_syscall_error(cache, "pwrite_full()");
4aae8acbcfa9cac96b4af39bfabcbe569e804827Timo Sirainen return -1;
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen }
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen if (cache->file_cache != NULL) {
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen file_cache_write(cache->file_cache, data, size, offset);
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen /* data/hdr pointers may change if file cache was grown */
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen cache->data = file_cache_get_map(cache->file_cache,
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen &cache->mmap_length);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen cache->hdr = cache->data;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen }
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen return 0;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen}
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenstruct mail_cache_view *
2af769daebd83719ac696a440e06f6020471cec0Timo Sirainenmail_cache_view_open(struct mail_cache *cache, struct mail_index_view *iview)
2af769daebd83719ac696a440e06f6020471cec0Timo Sirainen{
d0bbbc7057aa33b52ee378196dee7d773437468fTimo Sirainen struct mail_cache_view *view;
d0bbbc7057aa33b52ee378196dee7d773437468fTimo Sirainen
d0bbbc7057aa33b52ee378196dee7d773437468fTimo Sirainen view = i_new(struct mail_cache_view, 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen view->cache = cache;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen view->view = iview;
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen i_array_init(&view->tmp_offsets, 32);
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen view->cached_exists_buf =
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen buffer_create_dynamic(default_pool,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cache->file_fields_count + 10);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return view;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainenvoid mail_cache_view_close(struct mail_cache_view *view)
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen{
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen if (view->cache->field_header_write_pending)
1c0590b2729567ad60dafde4d2c5f19635755a3dTimo Sirainen (void)mail_cache_header_fields_update(view->cache);
1c0590b2729567ad60dafde4d2c5f19635755a3dTimo Sirainen
ba482d3624ca4f1b3d638e6e8470ba5134f21493Timo Sirainen if (view->trans_view != NULL)
ba482d3624ca4f1b3d638e6e8470ba5134f21493Timo Sirainen mail_index_view_close(&view->trans_view);
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen array_free(&view->tmp_offsets);
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen buffer_free(view->cached_exists_buf);
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen i_free(view);
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen}
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen