mail-cache-sync-update.c revision 5d1833b98fa85d8061626aa986f38dcbcd70553e
89a126810703c666309310d0f3189e9834d70b5bTimo Sirainen/* Copyright (c) 2004-2007 Dovecot authors, see the included COPYING file */
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen#include "lib.h"
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen#include "file-cache.h"
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen#include "mail-cache-private.h"
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen#include "mail-index-view-private.h"
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen#include "mail-index-sync-private.h"
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenstruct mail_cache_sync_context {
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen uoff_t invalidate_highwater;
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen unsigned int locked:1;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen unsigned int lock_failed:1;
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen unsigned int nfs_attr_cache_flushed:1;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen};
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenstatic void mail_cache_handler_deinit(struct mail_index_sync_map_ctx *sync_ctx,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen struct mail_cache_sync_context *ctx)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen{
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (ctx == NULL)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (ctx->locked)
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen (void)mail_cache_unlock(sync_ctx->view->index->cache);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen i_free(ctx);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen}
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainenstatic struct mail_cache_sync_context *mail_cache_handler_init(void **context)
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen{
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen struct mail_cache_sync_context *ctx;
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen if (*context != NULL)
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen ctx = *context;
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen else {
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen *context = i_new(struct mail_cache_sync_context, 1);
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen ctx = *context;
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen ctx->invalidate_highwater = (uoff_t)-1;
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen }
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen return ctx;
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen}
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainenstatic int mail_cache_handler_lock(struct mail_cache_sync_context *ctx,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen struct mail_cache *cache)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen{
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen int ret;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6026802106043826932c09b7456f4ae80150d75bTimo Sirainen if (ctx->locked)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return 1;
6026802106043826932c09b7456f4ae80150d75bTimo Sirainen if (ctx->lock_failed)
6026802106043826932c09b7456f4ae80150d75bTimo Sirainen return 0;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (!ctx->locked) {
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen if ((ret = mail_cache_lock(cache, TRUE)) <= 0) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ctx->lock_failed = TRUE;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return ret;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ctx->locked = TRUE;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return 1;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen}
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenstatic int get_cache_file_seq(struct mail_index_view *view,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen uint32_t *cache_file_seq_r)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen{
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen const struct mail_index_ext *ext;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ext = mail_index_view_get_ext(view, view->index->cache->ext_id);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (ext == NULL)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return 0;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen *cache_file_seq_r = ext->reset_id;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return 1;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen}
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenint mail_cache_expunge_handler(struct mail_index_sync_map_ctx *sync_ctx,
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen uint32_t seq ATTR_UNUSED, const void *data,
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen void **sync_context, void *context)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen{
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen struct mail_cache *cache = context;
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen struct mail_cache_sync_context *ctx = *sync_context;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen const uint32_t *cache_offset = data;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen uint32_t cache_file_seq;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen int ret;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (data == NULL) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen mail_cache_handler_deinit(sync_ctx, ctx);
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen *sync_context = NULL;
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen return 0;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (*cache_offset == 0)
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen return 0;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
5d1833b98fa85d8061626aa986f38dcbcd70553eTimo Sirainen ctx = mail_cache_handler_init(sync_context);
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen ret = mail_cache_handler_lock(ctx, cache);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (ret <= 0)
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen return ret;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen if (!get_cache_file_seq(sync_ctx->view, &cache_file_seq))
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen return 0;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (!MAIL_CACHE_IS_UNUSABLE(cache) &&
b053c4961786b3d08d9dc0c31352997a15a2e760Timo Sirainen cache_file_seq == cache->hdr->file_seq)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen (void)mail_cache_delete(cache, *cache_offset);
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen return 0;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen}
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenint mail_cache_sync_handler(struct mail_index_sync_map_ctx *sync_ctx,
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen uint32_t seq ATTR_UNUSED,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen void *old_data, const void *new_data,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen void **context)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen{
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen struct mail_index_view *view = sync_ctx->view;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen struct mail_cache *cache = view->index->cache;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen struct mail_cache_sync_context *ctx = *context;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen const uint32_t *old_cache_offset = old_data;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen const uint32_t *new_cache_offset = new_data;
0f20dd043770d8c4460e5cfc2e8741e58c949ab6Timo Sirainen uint32_t cache_file_seq, cur_seq, tail_seq;
0f20dd043770d8c4460e5cfc2e8741e58c949ab6Timo Sirainen uoff_t cur_offset, tail_offset;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen int ret;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (new_cache_offset == NULL) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen mail_cache_handler_deinit(sync_ctx, ctx);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen *context = NULL;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return 1;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen ctx = mail_cache_handler_init(context);
5d1833b98fa85d8061626aa986f38dcbcd70553eTimo Sirainen if (cache->file_cache != NULL && !MAIL_CACHE_IS_UNUSABLE(cache)) {
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen /* flush attribute cache only once per sync */
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen if (!ctx->nfs_attr_cache_flushed && cache->index->nfs_flush) {
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen ctx->nfs_attr_cache_flushed = TRUE;
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen mail_cache_flush_read_cache(cache, FALSE);
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen }
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen /* don't invalidate anything that's already been invalidated
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen within this sync. */
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen if (*new_cache_offset < ctx->invalidate_highwater) {
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen file_cache_invalidate(cache->file_cache,
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen *new_cache_offset,
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen ctx->invalidate_highwater -
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen *new_cache_offset);
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen ctx->invalidate_highwater = *new_cache_offset;
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen }
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen }
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
1840618d2d042deed70f141143ef0a2cd8d01fc0Timo Sirainen if (*old_cache_offset == 0 || *old_cache_offset == *new_cache_offset ||
1840618d2d042deed70f141143ef0a2cd8d01fc0Timo Sirainen sync_ctx->type == MAIL_INDEX_SYNC_HANDLER_VIEW)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return 1;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
0f20dd043770d8c4460e5cfc2e8741e58c949ab6Timo Sirainen mail_transaction_log_view_get_prev_pos(view->log_view,
0f20dd043770d8c4460e5cfc2e8741e58c949ab6Timo Sirainen &cur_seq, &cur_offset);
0f20dd043770d8c4460e5cfc2e8741e58c949ab6Timo Sirainen mail_transaction_log_get_mailbox_sync_pos(view->index->log,
0f20dd043770d8c4460e5cfc2e8741e58c949ab6Timo Sirainen &tail_seq, &tail_offset);
0f20dd043770d8c4460e5cfc2e8741e58c949ab6Timo Sirainen if (LOG_IS_BEFORE(cur_seq, cur_offset, tail_seq, tail_offset)) {
0f20dd043770d8c4460e5cfc2e8741e58c949ab6Timo Sirainen /* already been linked */
0f20dd043770d8c4460e5cfc2e8741e58c949ab6Timo Sirainen return 1;
0f20dd043770d8c4460e5cfc2e8741e58c949ab6Timo Sirainen }
1840618d2d042deed70f141143ef0a2cd8d01fc0Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen /* we'll need to link the old and new cache records */
1b75126c39121b25f0bba048758b56d4b4b9bf1aTimo Sirainen ret = mail_cache_handler_lock(ctx, cache);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (ret <= 0)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return ret < 0 ? -1 : 1;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (!get_cache_file_seq(view, &cache_file_seq))
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return 1;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen if (cache_file_seq != cache->hdr->file_seq) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen /* cache has been compressed, don't modify it */
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return 1;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen if (mail_cache_link(cache, *old_cache_offset, *new_cache_offset) < 0)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return -1;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return 1;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen}
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainenvoid mail_cache_sync_lost_handler(struct mail_index *index)
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen{
f8523f81a8f5fafbb30bb09c0fbeb4d4625be5d5Timo Sirainen if (!MAIL_CACHE_IS_UNUSABLE(index->cache))
f8523f81a8f5fafbb30bb09c0fbeb4d4625be5d5Timo Sirainen mail_cache_flush_read_cache(index->cache, FALSE);
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen file_cache_invalidate(index->cache->file_cache, 0, (uoff_t)-1);
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen}