mail-cache-sync-update.c revision bc564f1d3d953cf724828322b11ae89e0f59ffc9
89a126810703c666309310d0f3189e9834d70b5bTimo Sirainen/* Copyright (c) 2004-2007 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen#include "file-cache.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "mail-cache-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-index-view-private.h"
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen#include "mail-index-sync-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenstruct mail_cache_sync_context {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen uoff_t invalidate_highwater;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen unsigned int locked:1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int lock_failed:1;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen unsigned int nfs_read_cache_flushed:1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen};
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
dd0ba1bab2c1b89c7e063fa45d156fa72b8260d5Timo Sirainenstatic void mail_cache_handler_deinit(struct mail_index_sync_map_ctx *sync_ctx,
dd0ba1bab2c1b89c7e063fa45d156fa72b8260d5Timo Sirainen struct mail_cache_sync_context *ctx)
6cd02a9525acb9897a65b05bfeee9b8d283e0f74Timo Sirainen{
6cd02a9525acb9897a65b05bfeee9b8d283e0f74Timo Sirainen if (ctx == NULL)
6cd02a9525acb9897a65b05bfeee9b8d283e0f74Timo Sirainen return;
6cd02a9525acb9897a65b05bfeee9b8d283e0f74Timo Sirainen
6cd02a9525acb9897a65b05bfeee9b8d283e0f74Timo Sirainen if (ctx->locked)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (void)mail_cache_unlock(sync_ctx->view->index->cache);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_free(ctx);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic struct mail_cache_sync_context *mail_cache_handler_init(void **context)
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen{
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen struct mail_cache_sync_context *ctx;
e9f2d9104d395bcf54be3f8ba8d9f63aecf0bcbeTimo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen if (*context != NULL)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen ctx = *context;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen else {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *context = i_new(struct mail_cache_sync_context, 1);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen ctx = *context;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen ctx->invalidate_highwater = (uoff_t)-1;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return ctx;
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen}
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int mail_cache_handler_lock(struct mail_cache_sync_context *ctx,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_cache *cache)
e1f05b193ac1edd3267294e9501e8063aa0f791aTimo Sirainen{
e1f05b193ac1edd3267294e9501e8063aa0f791aTimo Sirainen int ret;
e1f05b193ac1edd3267294e9501e8063aa0f791aTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (ctx->locked)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return 1;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (ctx->lock_failed)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!ctx->locked) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if ((ret = mail_cache_lock(cache, TRUE)) <= 0) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen ctx->lock_failed = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->locked = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 1;
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen}
ee26329cb5cc679b5645e4933d529f86accb976aTimo Sirainen
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainenstatic int get_cache_file_seq(struct mail_index_view *view,
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen uint32_t *cache_file_seq_r)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen{
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen const struct mail_index_ext *ext;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen ext = mail_index_view_get_ext(view, view->index->cache->ext_id);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ext == NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen *cache_file_seq_r = ext->reset_id;
1a5fcc972dbadfe7959011b8ad422707e2dfc19fTimo Sirainen return 1;
1a5fcc972dbadfe7959011b8ad422707e2dfc19fTimo Sirainen}
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainenint mail_cache_expunge_handler(struct mail_index_sync_map_ctx *sync_ctx,
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen uint32_t seq ATTR_UNUSED, const void *data,
cfbf891f065b18602703ed6fa2af1a541d4d0b04Timo Sirainen void **sync_context, void *context)
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen{
e9f2d9104d395bcf54be3f8ba8d9f63aecf0bcbeTimo Sirainen struct mail_cache *cache = context;
e9f2d9104d395bcf54be3f8ba8d9f63aecf0bcbeTimo Sirainen struct mail_cache_sync_context *ctx = *sync_context;
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen const uint32_t *cache_offset = data;
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen uint32_t cache_file_seq;
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen int ret;
6cd02a9525acb9897a65b05bfeee9b8d283e0f74Timo Sirainen
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen if (data == NULL) {
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen mail_cache_handler_deinit(sync_ctx, ctx);
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen *sync_context = NULL;
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen return 0;
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen }
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen if (*cache_offset == 0)
6f73af3a3a6ee900c7e736874587968d76a20bc0Timo Sirainen return 0;
6f73af3a3a6ee900c7e736874587968d76a20bc0Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx = mail_cache_handler_init(sync_context);
6f73af3a3a6ee900c7e736874587968d76a20bc0Timo Sirainen ret = mail_cache_handler_lock(ctx, cache);
6f73af3a3a6ee900c7e736874587968d76a20bc0Timo Sirainen if (ret <= 0)
6f73af3a3a6ee900c7e736874587968d76a20bc0Timo Sirainen return ret;
6f73af3a3a6ee900c7e736874587968d76a20bc0Timo Sirainen
6f73af3a3a6ee900c7e736874587968d76a20bc0Timo Sirainen if (!get_cache_file_seq(sync_ctx->view, &cache_file_seq))
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen return 0;
ca316aeb7648d3f1bcf45231f73ddeb1b67a6961Timo Sirainen
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen if (!MAIL_CACHE_IS_UNUSABLE(cache) &&
6f73af3a3a6ee900c7e736874587968d76a20bc0Timo Sirainen cache_file_seq == cache->hdr->file_seq)
50c4a9739b55370b1d3950d7b3ec2f7cd2ed5f49Timo Sirainen (void)mail_cache_delete(cache, *cache_offset);
0f66f12eb4cdbf47670975044c88d8f388bf92dfTimo Sirainen return 0;
e9f2d9104d395bcf54be3f8ba8d9f63aecf0bcbeTimo Sirainen}
e9f2d9104d395bcf54be3f8ba8d9f63aecf0bcbeTimo Sirainen
6cd02a9525acb9897a65b05bfeee9b8d283e0f74Timo Sirainenint mail_cache_sync_handler(struct mail_index_sync_map_ctx *sync_ctx,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uint32_t seq ATTR_UNUSED,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen void *old_data, const void *new_data,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen void **context)
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen{
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen struct mail_index_view *view = sync_ctx->view;
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen struct mail_cache *cache = view->index->cache;
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen struct mail_cache_sync_context *ctx = *context;
a2ec607689dc88112bf08785960e441153f35d57Timo Sirainen const uint32_t *old_cache_offset = old_data;
a2ec607689dc88112bf08785960e441153f35d57Timo Sirainen const uint32_t *new_cache_offset = new_data;
a2ec607689dc88112bf08785960e441153f35d57Timo Sirainen uint32_t cache_file_seq, cur_seq, tail_seq;
cfbf891f065b18602703ed6fa2af1a541d4d0b04Timo Sirainen uoff_t cur_offset, tail_offset;
cfbf891f065b18602703ed6fa2af1a541d4d0b04Timo Sirainen int ret;
cfbf891f065b18602703ed6fa2af1a541d4d0b04Timo Sirainen
a2ec607689dc88112bf08785960e441153f35d57Timo Sirainen if (new_cache_offset == NULL) {
cfbf891f065b18602703ed6fa2af1a541d4d0b04Timo Sirainen mail_cache_handler_deinit(sync_ctx, ctx);
a2ec607689dc88112bf08785960e441153f35d57Timo Sirainen *context = NULL;
a2ec607689dc88112bf08785960e441153f35d57Timo Sirainen return 1;
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen }
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen ctx = mail_cache_handler_init(context);
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen if (cache->file_cache != NULL && !MAIL_CACHE_IS_UNUSABLE(cache)) {
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen /* flush read cache only once per sync */
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen if (!ctx->nfs_read_cache_flushed && cache->index->nfs_flush) {
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen ctx->nfs_read_cache_flushed = TRUE;
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen mail_index_flush_read_cache(cache->index,
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen cache->filepath, cache->fd,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cache->locked);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen /* don't invalidate anything that's already been invalidated
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen within this sync. */
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (*new_cache_offset < ctx->invalidate_highwater) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen file_cache_invalidate(cache->file_cache,
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen *new_cache_offset,
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen ctx->invalidate_highwater -
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen *new_cache_offset);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen ctx->invalidate_highwater = *new_cache_offset;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (*old_cache_offset == 0 || *old_cache_offset == *new_cache_offset ||
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen sync_ctx->type == MAIL_INDEX_SYNC_HANDLER_VIEW)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return 1;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen mail_transaction_log_view_get_prev_pos(view->log_view,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen &cur_seq, &cur_offset);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen mail_transaction_log_get_mailbox_sync_pos(view->index->log,
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen &tail_seq, &tail_offset);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (LOG_IS_BEFORE(cur_seq, cur_offset, tail_seq, tail_offset)) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen /* already been linked */
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return 1;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* we'll need to link the old and new cache records */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = mail_cache_handler_lock(ctx, cache);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen if (ret <= 0)
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen return ret < 0 ? -1 : 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (!get_cache_file_seq(view, &cache_file_seq))
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return 1;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (cache_file_seq != cache->hdr->file_seq) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen /* cache has been compressed, don't modify it */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 1;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (mail_cache_link(cache, *old_cache_offset, *new_cache_offset) < 0)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return -1;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return 1;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen}
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenvoid mail_cache_sync_lost_handler(struct mail_index *index)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen{
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen struct mail_cache *cache = index->cache;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (!MAIL_CACHE_IS_UNUSABLE(cache)) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen mail_index_flush_read_cache(cache->index, cache->filepath,
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen cache->fd, cache->locked);
faef57a36800fe952a5794328467f846d5480ae6Timo Sirainen }
faef57a36800fe952a5794328467f846d5480ae6Timo Sirainen file_cache_invalidate(cache->file_cache, 0, (uoff_t)-1);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen