bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2003-2018 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen#include "ioloop.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "array.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "buffer.h"
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen#include "module-context.h"
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen#include "file-cache.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "file-set-size.h"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#include "read-full.h"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#include "write-full.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-cache-private.h"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#include "mail-index-transaction-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen#include <stddef.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <sys/stat.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen#define MAIL_CACHE_INIT_WRITE_BUFFER (1024*16)
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen#define MAIL_CACHE_MAX_WRITE_BUFFER (1024*256)
dd0ba1bab2c1b89c7e063fa45d156fa72b8260d5Timo Sirainen
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen#define CACHE_TRANS_CONTEXT(obj) \
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen MODULE_CONTEXT(obj, cache_mail_index_transaction_module)
c04adbeb0f214dc323ced079c7380fe9a226cdc5Aki Tuomi#define CACHE_TRANS_CONTEXT_REQUIRE(obj) \
c04adbeb0f214dc323ced079c7380fe9a226cdc5Aki Tuomi MODULE_CONTEXT_REQUIRE(obj, cache_mail_index_transaction_module)
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainenstruct mail_cache_transaction_rec {
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen uint32_t seq;
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen uint32_t cache_data_pos;
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen};
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct mail_cache_transaction_ctx {
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen union mail_index_transaction_module_context module_ctx;
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen struct mail_index_transaction_vfuncs super;
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_cache *cache;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_cache_view *view;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_index_transaction *trans;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen uint32_t cache_file_seq;
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen uint32_t first_new_seq;
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen
e9f2d9104d395bcf54be3f8ba8d9f63aecf0bcbeTimo Sirainen buffer_t *cache_data;
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen ARRAY(struct mail_cache_transaction_rec) cache_data_seq;
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen ARRAY_TYPE(seq_range) cache_data_wanted_seqs;
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen uint32_t prev_seq, min_seq;
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen size_t last_rec_pos;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
f0ff961282e618945dfe997dc45ff95d656e5790Timo Sirainen unsigned int records_written;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool tried_compression:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool changes:1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen};
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(cache_mail_index_transaction_module,
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen &mail_index_module_register);
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainenstatic int mail_cache_transaction_lock(struct mail_cache_transaction_ctx *ctx);
127f99adeb10d9f9e06896f97dc187eac4ca8852Timo Sirainenstatic size_t mail_cache_transaction_update_last_rec_size(struct mail_cache_transaction_ctx *ctx);
e1f05b193ac1edd3267294e9501e8063aa0f791aTimo Sirainen
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainenstatic void mail_index_transaction_cache_reset(struct mail_index_transaction *t)
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen{
c04adbeb0f214dc323ced079c7380fe9a226cdc5Aki Tuomi struct mail_cache_transaction_ctx *ctx = CACHE_TRANS_CONTEXT_REQUIRE(t);
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen struct mail_index_transaction_vfuncs super = ctx->super;
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen
61b6d1256936065321153bcd9228b9e45d95c9abTimo Sirainen mail_cache_transaction_reset(ctx);
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen super.reset(t);
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen}
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainenstatic int
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainenmail_index_transaction_cache_commit(struct mail_index_transaction *t,
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen struct mail_index_transaction_commit_result *result_r)
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen{
c04adbeb0f214dc323ced079c7380fe9a226cdc5Aki Tuomi struct mail_cache_transaction_ctx *ctx = CACHE_TRANS_CONTEXT_REQUIRE(t);
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen struct mail_index_transaction_vfuncs super = ctx->super;
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen /* a failed cache commit isn't important enough to fail the entire
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen index transaction, so we'll just ignore it */
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen (void)mail_cache_transaction_commit(&ctx);
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen return super.commit(t, result_r);
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen}
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainenstatic void
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainenmail_index_transaction_cache_rollback(struct mail_index_transaction *t)
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen{
c04adbeb0f214dc323ced079c7380fe9a226cdc5Aki Tuomi struct mail_cache_transaction_ctx *ctx = CACHE_TRANS_CONTEXT_REQUIRE(t);
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen struct mail_index_transaction_vfuncs super = ctx->super;
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen mail_cache_transaction_rollback(&ctx);
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen super.rollback(t);
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen}
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenstruct mail_cache_transaction_ctx *
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenmail_cache_get_transaction(struct mail_cache_view *view,
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen struct mail_index_transaction *t)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
61b6d1256936065321153bcd9228b9e45d95c9abTimo Sirainen struct mail_cache_transaction_ctx *ctx;
61b6d1256936065321153bcd9228b9e45d95c9abTimo Sirainen
61b6d1256936065321153bcd9228b9e45d95c9abTimo Sirainen ctx = !cache_mail_index_transaction_module.id.module_id_set ? NULL :
61b6d1256936065321153bcd9228b9e45d95c9abTimo Sirainen CACHE_TRANS_CONTEXT(t);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen if (ctx != NULL)
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen return ctx;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx = i_new(struct mail_cache_transaction_ctx, 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->cache = view->cache;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->view = view;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->trans = t;
ee26329cb5cc679b5645e4933d529f86accb976aTimo Sirainen
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen i_assert(view->transaction == NULL);
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen view->transaction = ctx;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen view->trans_view = mail_index_transaction_open_updated_view(t);
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen ctx->super = t->v;
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen t->v.reset = mail_index_transaction_cache_reset;
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen t->v.commit = mail_index_transaction_cache_commit;
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen t->v.rollback = mail_index_transaction_cache_rollback;
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen MODULE_CONTEXT_SET(t, cache_mail_index_transaction_module, ctx);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return ctx;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
61b6d1256936065321153bcd9228b9e45d95c9abTimo Sirainenvoid mail_cache_transaction_reset(struct mail_cache_transaction_ctx *ctx)
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen{
1a5fcc972dbadfe7959011b8ad422707e2dfc19fTimo Sirainen ctx->cache_file_seq = MAIL_CACHE_IS_UNUSABLE(ctx->cache) ? 0 :
1a5fcc972dbadfe7959011b8ad422707e2dfc19fTimo Sirainen ctx->cache->hdr->file_seq;
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen mail_index_ext_set_reset_id(ctx->trans, ctx->cache->ext_id,
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen ctx->cache_file_seq);
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen
cfbf891f065b18602703ed6fa2af1a541d4d0b04Timo Sirainen if (ctx->cache_data != NULL)
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen buffer_set_used_size(ctx->cache_data, 0);
e9f2d9104d395bcf54be3f8ba8d9f63aecf0bcbeTimo Sirainen if (array_is_created(&ctx->cache_data_seq))
e9f2d9104d395bcf54be3f8ba8d9f63aecf0bcbeTimo Sirainen array_clear(&ctx->cache_data_seq);
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen ctx->prev_seq = 0;
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen ctx->last_rec_pos = 0;
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen ctx->changes = FALSE;
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen}
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainenvoid mail_cache_transaction_rollback(struct mail_cache_transaction_ctx **_ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
6f73af3a3a6ee900c7e736874587968d76a20bc0Timo Sirainen struct mail_cache_transaction_ctx *ctx = *_ctx;
6f73af3a3a6ee900c7e736874587968d76a20bc0Timo Sirainen
6f73af3a3a6ee900c7e736874587968d76a20bc0Timo Sirainen *_ctx = NULL;
6f73af3a3a6ee900c7e736874587968d76a20bc0Timo Sirainen
f0ff961282e618945dfe997dc45ff95d656e5790Timo Sirainen if (ctx->records_written > 0) {
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen /* we already wrote to the cache file. we can't (or don't want
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen to) delete that data, so just mark it as deleted space */
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen if (mail_cache_transaction_lock(ctx) > 0) {
f0ff961282e618945dfe997dc45ff95d656e5790Timo Sirainen ctx->cache->hdr_copy.deleted_record_count +=
f0ff961282e618945dfe997dc45ff95d656e5790Timo Sirainen ctx->records_written;
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen (void)mail_cache_unlock(ctx->cache);
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen }
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen }
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen MODULE_CONTEXT_UNSET(ctx->trans, cache_mail_index_transaction_module);
5e40ed3f0a2c2acddc9b8eab59670c7a850114c5Timo Sirainen
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen ctx->view->transaction = NULL;
ca316aeb7648d3f1bcf45231f73ddeb1b67a6961Timo Sirainen ctx->view->trans_seq1 = ctx->view->trans_seq2 = 0;
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen
6f73af3a3a6ee900c7e736874587968d76a20bc0Timo Sirainen mail_index_view_close(&ctx->view->trans_view);
6307d76096764e66bddc63d4a3e5a1aa19cc528fJosef 'Jeff' Sipek buffer_free(&ctx->cache_data);
e9f2d9104d395bcf54be3f8ba8d9f63aecf0bcbeTimo Sirainen if (array_is_created(&ctx->cache_data_seq))
e9f2d9104d395bcf54be3f8ba8d9f63aecf0bcbeTimo Sirainen array_free(&ctx->cache_data_seq);
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen if (array_is_created(&ctx->cache_data_wanted_seqs))
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen array_free(&ctx->cache_data_wanted_seqs);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_free(ctx);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainenstatic int
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainenmail_cache_transaction_compress(struct mail_cache_transaction_ctx *ctx)
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen{
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen struct mail_cache *cache = ctx->cache;
d24daa83c25063ef12b524c9ffcc9ecca34dadb9Timo Sirainen struct mail_index_view *view;
d24daa83c25063ef12b524c9ffcc9ecca34dadb9Timo Sirainen struct mail_index_transaction *trans;
0f833d18af36bf307cd69f235eb3fb779245b478Timo Sirainen struct mail_cache_compress_lock *lock;
d24daa83c25063ef12b524c9ffcc9ecca34dadb9Timo Sirainen int ret;
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen ctx->tried_compression = TRUE;
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen cache->need_compress_file_seq =
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen MAIL_CACHE_IS_UNUSABLE(cache) ? 0 : cache->hdr->file_seq;
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen
d24daa83c25063ef12b524c9ffcc9ecca34dadb9Timo Sirainen view = mail_index_view_open(cache->index);
d24daa83c25063ef12b524c9ffcc9ecca34dadb9Timo Sirainen trans = mail_index_transaction_begin(view,
d24daa83c25063ef12b524c9ffcc9ecca34dadb9Timo Sirainen MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL);
0f833d18af36bf307cd69f235eb3fb779245b478Timo Sirainen if (mail_cache_compress(cache, trans, &lock) < 0) {
d24daa83c25063ef12b524c9ffcc9ecca34dadb9Timo Sirainen mail_index_transaction_rollback(&trans);
d24daa83c25063ef12b524c9ffcc9ecca34dadb9Timo Sirainen ret = -1;
d24daa83c25063ef12b524c9ffcc9ecca34dadb9Timo Sirainen } else {
9404a7b90dcb80d31bd37ee2493f03751acdb1bdTimo Sirainen ret = mail_index_transaction_commit(&trans);
0f833d18af36bf307cd69f235eb3fb779245b478Timo Sirainen if (lock != NULL)
0f833d18af36bf307cd69f235eb3fb779245b478Timo Sirainen mail_cache_compress_unlock(&lock);
d24daa83c25063ef12b524c9ffcc9ecca34dadb9Timo Sirainen }
d24daa83c25063ef12b524c9ffcc9ecca34dadb9Timo Sirainen mail_index_view_close(&view);
d24daa83c25063ef12b524c9ffcc9ecca34dadb9Timo Sirainen mail_cache_transaction_reset(ctx);
d24daa83c25063ef12b524c9ffcc9ecca34dadb9Timo Sirainen return ret;
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen}
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainenstatic void
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainenmail_cache_transaction_open_if_needed(struct mail_cache_transaction_ctx *ctx)
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen{
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen struct mail_cache *cache = ctx->cache;
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen const struct mail_index_ext *ext;
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen uint32_t idx;
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen int i;
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen if (!cache->opened) {
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen (void)mail_cache_open_and_verify(cache);
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen return;
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen }
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen /* see if we should try to reopen the cache file */
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen for (i = 0;; i++) {
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen if (MAIL_CACHE_IS_UNUSABLE(cache))
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen return;
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen if (!mail_index_map_get_ext_idx(cache->index->map,
8fcaba5977f7d596632df1ed2af8541e5f154258Timo Sirainen cache->ext_id, &idx)) {
8fcaba5977f7d596632df1ed2af8541e5f154258Timo Sirainen /* index doesn't have a cache extension, but the cache
8fcaba5977f7d596632df1ed2af8541e5f154258Timo Sirainen file exists (corrupted indexes fixed?). fix it. */
8fcaba5977f7d596632df1ed2af8541e5f154258Timo Sirainen if (i == 2)
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen break;
8fcaba5977f7d596632df1ed2af8541e5f154258Timo Sirainen } else {
8fcaba5977f7d596632df1ed2af8541e5f154258Timo Sirainen ext = array_idx(&cache->index->map->extensions, idx);
8fcaba5977f7d596632df1ed2af8541e5f154258Timo Sirainen if (ext->reset_id == cache->hdr->file_seq || i == 2)
8fcaba5977f7d596632df1ed2af8541e5f154258Timo Sirainen break;
8fcaba5977f7d596632df1ed2af8541e5f154258Timo Sirainen
8fcaba5977f7d596632df1ed2af8541e5f154258Timo Sirainen /* index offsets don't match the cache file */
8fcaba5977f7d596632df1ed2af8541e5f154258Timo Sirainen if (ext->reset_id > cache->hdr->file_seq) {
8fcaba5977f7d596632df1ed2af8541e5f154258Timo Sirainen /* the cache file appears to be too old.
8fcaba5977f7d596632df1ed2af8541e5f154258Timo Sirainen reopening should help. */
8fcaba5977f7d596632df1ed2af8541e5f154258Timo Sirainen if (mail_cache_reopen(cache) != 0)
8fcaba5977f7d596632df1ed2af8541e5f154258Timo Sirainen break;
8fcaba5977f7d596632df1ed2af8541e5f154258Timo Sirainen }
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen }
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen /* cache file sequence might be broken. it's also possible
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen that it was just compressed and we just haven't yet seen
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen the changes in index. try if refreshing index helps.
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen if not, compress the cache file. */
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen if (i == 0) {
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen if (ctx->tried_compression)
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen break;
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen /* get the latest reset ID */
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen if (mail_index_refresh(ctx->cache->index) < 0)
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen return;
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen } else {
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen i_assert(i == 1);
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen (void)mail_cache_transaction_compress(ctx);
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen }
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen }
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen}
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainenstatic int mail_cache_transaction_lock(struct mail_cache_transaction_ctx *ctx)
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen{
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen struct mail_cache *cache = ctx->cache;
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen int ret;
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen mail_cache_transaction_open_if_needed(ctx);
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen
ab70f55bb8d824ca1ed7c74196f2f502edd29cc7Timo Sirainen if ((ret = mail_cache_lock(cache)) <= 0) {
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen if (ret < 0)
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen return -1;
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen if (!ctx->tried_compression && MAIL_CACHE_IS_UNUSABLE(cache)) {
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen if (mail_cache_transaction_compress(ctx) < 0)
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen return -1;
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen return mail_cache_transaction_lock(ctx);
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen } else {
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen return 0;
cfbf891f065b18602703ed6fa2af1a541d4d0b04Timo Sirainen }
a2ec607689dc88112bf08785960e441153f35d57Timo Sirainen }
20ecea31024db11ea4ca51c87f34fa15470e9c28Timo Sirainen i_assert(!MAIL_CACHE_IS_UNUSABLE(cache));
a2ec607689dc88112bf08785960e441153f35d57Timo Sirainen
20ecea31024db11ea4ca51c87f34fa15470e9c28Timo Sirainen if (ctx->cache_file_seq == 0) {
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen i_assert(ctx->cache_data == NULL ||
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen ctx->cache_data->used == 0);
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen ctx->cache_file_seq = cache->hdr->file_seq;
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen } else if (ctx->cache_file_seq != cache->hdr->file_seq) {
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen if (mail_cache_unlock(cache) < 0)
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen return -1;
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen mail_cache_transaction_reset(ctx);
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen return 0;
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen }
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen return 1;
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen}
a2ce2eb4c266e2854fd34416ea5cfbe05dfd3971Timo Sirainen
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainenconst struct mail_cache_record *
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainenmail_cache_transaction_lookup_rec(struct mail_cache_transaction_ctx *ctx,
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen unsigned int seq,
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen unsigned int *trans_next_idx)
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen{
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen const struct mail_cache_transaction_rec *recs;
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen unsigned int i, count;
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen
3da9825732c865b8ea11ea070e5b6f881ffae424Timo Sirainen if (!MAIL_INDEX_IS_IN_MEMORY(ctx->cache->index) &&
3da9825732c865b8ea11ea070e5b6f881ffae424Timo Sirainen (MAIL_CACHE_IS_UNUSABLE(ctx->cache) ||
3da9825732c865b8ea11ea070e5b6f881ffae424Timo Sirainen ctx->cache_file_seq != ctx->cache->hdr->file_seq)) {
1c783b6d9cbdf0cdb84507472f0aa6a50a1861cdTimo Sirainen /* Cache was compressed during this transaction. We can't
1c783b6d9cbdf0cdb84507472f0aa6a50a1861cdTimo Sirainen safely use the data anymore, since its fields won't match
1c783b6d9cbdf0cdb84507472f0aa6a50a1861cdTimo Sirainen cache->file_fields_map. */
1c783b6d9cbdf0cdb84507472f0aa6a50a1861cdTimo Sirainen return NULL;
1c783b6d9cbdf0cdb84507472f0aa6a50a1861cdTimo Sirainen }
1c783b6d9cbdf0cdb84507472f0aa6a50a1861cdTimo Sirainen
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen recs = array_get(&ctx->cache_data_seq, &count);
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen for (i = *trans_next_idx; i < count; i++) {
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen if (recs[i].seq == seq) {
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen *trans_next_idx = i + 1;
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen return CONST_PTR_OFFSET(ctx->cache_data->data,
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen recs[i].cache_data_pos);
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen }
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen }
127f99adeb10d9f9e06896f97dc187eac4ca8852Timo Sirainen *trans_next_idx = i + 1;
127f99adeb10d9f9e06896f97dc187eac4ca8852Timo Sirainen if (seq == ctx->prev_seq && i == count) {
127f99adeb10d9f9e06896f97dc187eac4ca8852Timo Sirainen /* update the unfinished record's (temporary) size and
127f99adeb10d9f9e06896f97dc187eac4ca8852Timo Sirainen return it */
127f99adeb10d9f9e06896f97dc187eac4ca8852Timo Sirainen mail_cache_transaction_update_last_rec_size(ctx);
127f99adeb10d9f9e06896f97dc187eac4ca8852Timo Sirainen return CONST_PTR_OFFSET(ctx->cache_data->data,
127f99adeb10d9f9e06896f97dc187eac4ca8852Timo Sirainen ctx->last_rec_pos);
127f99adeb10d9f9e06896f97dc187eac4ca8852Timo Sirainen }
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen return NULL;
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen}
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen
e37fbcda56ab154557e84f990012502be53aa6c6Timo Sirainenstatic int
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainenmail_cache_transaction_update_index(struct mail_cache_transaction_ctx *ctx,
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen uint32_t write_offset)
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen{
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen struct mail_cache *cache = ctx->cache;
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen const struct mail_cache_record *rec = ctx->cache_data->data;
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen const struct mail_cache_transaction_rec *recs;
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen uint32_t i, seq_count;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
16c28dd75976f94acc4940d6ba68b6cd4853aac7Timo Sirainen mail_index_ext_using_reset_id(ctx->trans, ctx->cache->ext_id,
16c28dd75976f94acc4940d6ba68b6cd4853aac7Timo Sirainen ctx->cache_file_seq);
16c28dd75976f94acc4940d6ba68b6cd4853aac7Timo Sirainen
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen /* write the cache_offsets to index file. records' prev_offset
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen is updated to point to old cache record when index is being
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen synced. */
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen recs = array_get(&ctx->cache_data_seq, &seq_count);
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen for (i = 0; i < seq_count; i++) {
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen mail_index_update_ext(ctx->trans, recs[i].seq, cache->ext_id,
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen &write_offset, NULL);
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen write_offset += rec->size;
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen rec = CONST_PTR_OFFSET(rec, rec->size);
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen }
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen return 0;
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen}
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainenstatic int
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainenmail_cache_link_records(struct mail_cache_transaction_ctx *ctx,
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen uint32_t write_offset)
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen{
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen struct mail_index_map *map;
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen struct mail_cache_record *rec;
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen const struct mail_cache_transaction_rec *recs;
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen const uint32_t *prev_offsetp;
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen ARRAY_TYPE(uint32_t) seq_offsets;
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen uint32_t i, seq_count, reset_id, prev_offset, *offsetp;
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen const void *data;
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen i_assert(ctx->min_seq != 0);
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen i_array_init(&seq_offsets, 64);
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen recs = array_get(&ctx->cache_data_seq, &seq_count);
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen rec = buffer_get_modifiable_data(ctx->cache_data, NULL);
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen for (i = 0; i < seq_count; i++) {
139143f1b798472438b813343a48601f1c564060Sergey Kitov offsetp = array_idx_get_space(&seq_offsets,
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen recs[i].seq - ctx->min_seq);
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen if (*offsetp != 0)
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen prev_offset = *offsetp;
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen else {
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen mail_index_lookup_ext_full(ctx->view->trans_view, recs[i].seq,
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen ctx->cache->ext_id, &map,
03860f6dd70abfa2551a846e77a5c41cb40dc141Timo Sirainen &data, NULL);
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen prev_offsetp = data;
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen if (prev_offsetp == NULL || *prev_offsetp == 0)
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen prev_offset = 0;
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen else if (mail_index_ext_get_reset_id(ctx->view->trans_view, map,
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen ctx->cache->ext_id,
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen &reset_id) &&
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen reset_id == ctx->cache_file_seq)
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen prev_offset = *prev_offsetp;
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen else
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen prev_offset = 0;
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen if (prev_offset >= write_offset) {
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen mail_cache_set_corrupted(ctx->cache,
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen "Cache record offset points outside existing file");
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen array_free(&seq_offsets);
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen return -1;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen }
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen }
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen if (prev_offset != 0) {
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen /* link this record to previous one */
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen rec->prev_offset = prev_offset;
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen ctx->cache->hdr_copy.continued_record_count++;
f0ff961282e618945dfe997dc45ff95d656e5790Timo Sirainen } else {
f0ff961282e618945dfe997dc45ff95d656e5790Timo Sirainen ctx->cache->hdr_copy.record_count++;
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen }
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen *offsetp = write_offset;
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen write_offset += rec->size;
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen rec = PTR_OFFSET(rec, rec->size);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen }
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen array_free(&seq_offsets);
f0ff961282e618945dfe997dc45ff95d656e5790Timo Sirainen ctx->cache->hdr_modified = TRUE;
e37fbcda56ab154557e84f990012502be53aa6c6Timo Sirainen return 0;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen}
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenstatic int
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenmail_cache_transaction_flush(struct mail_cache_transaction_ctx *ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen struct stat st;
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen uint32_t write_offset = 0;
daf0035ef39182601facf6d01c5c39e113c024c5Timo Sirainen int ret = 0;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen i_assert(!ctx->cache->locked);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
330d54e9e3bf076efe91f101c562d1268160b128Timo Sirainen if (array_count(&ctx->cache_data_seq) == 0) {
330d54e9e3bf076efe91f101c562d1268160b128Timo Sirainen /* we had done some changes, but they were aborted. */
330d54e9e3bf076efe91f101c562d1268160b128Timo Sirainen i_assert(ctx->last_rec_pos == 0);
330d54e9e3bf076efe91f101c562d1268160b128Timo Sirainen ctx->min_seq = 0;
330d54e9e3bf076efe91f101c562d1268160b128Timo Sirainen return 0;
330d54e9e3bf076efe91f101c562d1268160b128Timo Sirainen }
330d54e9e3bf076efe91f101c562d1268160b128Timo Sirainen
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen if (mail_cache_transaction_lock(ctx) <= 0)
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen return -1;
e37fbcda56ab154557e84f990012502be53aa6c6Timo Sirainen
c1b9c4531186c6a7cd92d2c353273a834f8ee66fTimo Sirainen i_assert(ctx->cache_data != NULL);
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen i_assert(ctx->last_rec_pos <= ctx->cache_data->used);
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen /* we need to get the final write offset for linking records */
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen if (fstat(ctx->cache->fd, &st) < 0) {
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen if (!ESTALE_FSTAT(errno))
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen mail_cache_set_syscall_error(ctx->cache, "fstat()");
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen ret = -1;
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen } else if ((uint32_t)-1 < st.st_size + ctx->last_rec_pos) {
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen mail_cache_set_corrupted(ctx->cache, "Cache file too large");
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen ret = -1;
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen } else {
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen write_offset = st.st_size;
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen if (mail_cache_link_records(ctx, write_offset) < 0)
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen ret = -1;
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen }
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen /* write to cache file */
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen if (ret < 0 ||
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen mail_cache_append(ctx->cache, ctx->cache_data->data,
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen ctx->last_rec_pos, &write_offset) < 0)
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen ret = -1;
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen else {
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen /* update records' cache offsets to index */
f0ff961282e618945dfe997dc45ff95d656e5790Timo Sirainen ctx->records_written++;
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen ret = mail_cache_transaction_update_index(ctx, write_offset);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen if (mail_cache_unlock(ctx->cache) < 0)
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen ret = -1;
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen /* drop the written data from buffer */
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen buffer_copy(ctx->cache_data, 0,
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen ctx->cache_data, ctx->last_rec_pos, (size_t)-1);
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen buffer_set_used_size(ctx->cache_data,
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen ctx->cache_data->used - ctx->last_rec_pos);
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen ctx->last_rec_pos = 0;
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen ctx->min_seq = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e9f2d9104d395bcf54be3f8ba8d9f63aecf0bcbeTimo Sirainen array_clear(&ctx->cache_data_seq);
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen array_clear(&ctx->cache_data_wanted_seqs);
c58c35722c23363b83db38641a928274def96725Timo Sirainen return ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainenstatic void
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainenmail_cache_transaction_drop_unwanted(struct mail_cache_transaction_ctx *ctx,
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen size_t space_needed)
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen{
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen struct mail_cache_transaction_rec *recs;
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen unsigned int i, count;
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen recs = array_get_modifiable(&ctx->cache_data_seq, &count);
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen /* find out how many records to delete. delete all unwanted sequences,
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen and if that's not enough delete some more. */
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen for (i = 0; i < count; i++) {
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen if (seq_range_exists(&ctx->cache_data_wanted_seqs, recs[i].seq)) {
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen if (recs[i].cache_data_pos >= space_needed)
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen break;
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen /* we're going to forcibly delete it - remove it also
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen from the array since it's no longer useful there */
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen seq_range_array_remove(&ctx->cache_data_wanted_seqs,
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen recs[i].seq);
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen }
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen }
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen unsigned int deleted_count = i;
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen size_t deleted_space = i < count ?
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen recs[i].cache_data_pos : ctx->last_rec_pos;
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen for (; i < count; i++)
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen recs[i].cache_data_pos -= deleted_space;
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen ctx->last_rec_pos -= deleted_space;
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen array_delete(&ctx->cache_data_seq, 0, deleted_count);
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen buffer_delete(ctx->cache_data, 0, deleted_space);
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen}
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen
127f99adeb10d9f9e06896f97dc187eac4ca8852Timo Sirainenstatic size_t
127f99adeb10d9f9e06896f97dc187eac4ca8852Timo Sirainenmail_cache_transaction_update_last_rec_size(struct mail_cache_transaction_ctx *ctx)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen{
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen struct mail_cache_record *rec;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen void *data;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen size_t size;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen data = buffer_get_modifiable_data(ctx->cache_data, &size);
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen rec = PTR_OFFSET(data, ctx->last_rec_pos);
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen rec->size = size - ctx->last_rec_pos;
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen i_assert(rec->size > sizeof(*rec));
127f99adeb10d9f9e06896f97dc187eac4ca8852Timo Sirainen return rec->size;
127f99adeb10d9f9e06896f97dc187eac4ca8852Timo Sirainen}
127f99adeb10d9f9e06896f97dc187eac4ca8852Timo Sirainen
127f99adeb10d9f9e06896f97dc187eac4ca8852Timo Sirainenstatic void
127f99adeb10d9f9e06896f97dc187eac4ca8852Timo Sirainenmail_cache_transaction_update_last_rec(struct mail_cache_transaction_ctx *ctx)
127f99adeb10d9f9e06896f97dc187eac4ca8852Timo Sirainen{
127f99adeb10d9f9e06896f97dc187eac4ca8852Timo Sirainen struct mail_cache_transaction_rec *trans_rec;
127f99adeb10d9f9e06896f97dc187eac4ca8852Timo Sirainen size_t size;
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen
127f99adeb10d9f9e06896f97dc187eac4ca8852Timo Sirainen size = mail_cache_transaction_update_last_rec_size(ctx);
67bbcd664bebce9a507a49c67273be4814d07c97Timo Sirainen if (size > ctx->cache->index->optimization_set.cache.record_max_size) {
330d54e9e3bf076efe91f101c562d1268160b128Timo Sirainen buffer_set_used_size(ctx->cache_data, ctx->last_rec_pos);
330d54e9e3bf076efe91f101c562d1268160b128Timo Sirainen return;
330d54e9e3bf076efe91f101c562d1268160b128Timo Sirainen }
330d54e9e3bf076efe91f101c562d1268160b128Timo Sirainen
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen if (ctx->min_seq > ctx->prev_seq || ctx->min_seq == 0)
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen ctx->min_seq = ctx->prev_seq;
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen trans_rec = array_append_space(&ctx->cache_data_seq);
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen trans_rec->seq = ctx->prev_seq;
d33fc6c584718efd46159e1d8f46488b9dfc66f5Timo Sirainen trans_rec->cache_data_pos = ctx->last_rec_pos;
7f5ddd0423db2e2e3d578e017c4eae32a08a4ed7Timo Sirainen ctx->last_rec_pos = ctx->cache_data->used;
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen}
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainenstatic void
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainenmail_cache_transaction_switch_seq(struct mail_cache_transaction_ctx *ctx)
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen{
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen struct mail_cache_record new_rec;
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (ctx->prev_seq != 0) {
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen /* update previously added cache record's size */
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen mail_cache_transaction_update_last_rec(ctx);
50c4a9739b55370b1d3950d7b3ec2f7cd2ed5f49Timo Sirainen } else if (ctx->cache_data == NULL) {
dd0ba1bab2c1b89c7e063fa45d156fa72b8260d5Timo Sirainen ctx->cache_data =
dd0ba1bab2c1b89c7e063fa45d156fa72b8260d5Timo Sirainen buffer_create_dynamic(default_pool,
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen MAIL_CACHE_INIT_WRITE_BUFFER);
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen i_array_init(&ctx->cache_data_seq, 64);
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen i_array_init(&ctx->cache_data_wanted_seqs, 32);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&new_rec);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen buffer_append(ctx->cache_data, &new_rec, sizeof(new_rec));
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen ctx->prev_seq = 0;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen ctx->changes = TRUE;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen}
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
6f73af3a3a6ee900c7e736874587968d76a20bc0Timo Sirainenint mail_cache_transaction_commit(struct mail_cache_transaction_ctx **_ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
6f73af3a3a6ee900c7e736874587968d76a20bc0Timo Sirainen struct mail_cache_transaction_ctx *ctx = *_ctx;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen int ret = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen if (ctx->changes) {
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen if (ctx->prev_seq != 0)
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen mail_cache_transaction_update_last_rec(ctx);
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen if (mail_cache_transaction_flush(ctx) < 0)
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen ret = -1;
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen else {
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen /* successfully wrote everything */
f0ff961282e618945dfe997dc45ff95d656e5790Timo Sirainen ctx->records_written = 0;
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen }
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen /* Here would be a good place to do fdatasync() to make sure
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen everything is written before offsets are updated to index.
19557f192d37cd54a1a090a8a26d9d47265e4413Aki Tuomi However it slows down I/O needlessly and we're pretty good
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen at catching and fixing cache corruption, so we no longer do
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen it. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen mail_cache_transaction_rollback(_ctx);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainenstatic int
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainenmail_cache_header_fields_write(struct mail_cache_transaction_ctx *ctx,
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen const buffer_t *buffer)
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen{
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen struct mail_cache *cache = ctx->cache;
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen uint32_t offset, hdr_offset;
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen i_assert(cache->locked);
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen
131b073bdc3650083b00616dc778dd3017c2bbb5Timo Sirainen offset = 0;
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen if (mail_cache_append(cache, buffer->data, buffer->used, &offset) < 0)
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen return -1;
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen
b780aa272b742a43579cdb523cc79cc8d4521306Timo Sirainen if (cache->index->fsync_mode == FSYNC_MODE_ALWAYS) {
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen if (fdatasync(cache->fd) < 0) {
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen mail_cache_set_syscall_error(cache, "fdatasync()");
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen return -1;
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen }
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen }
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen /* find offset to the previous header's "next_offset" field */
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen if (mail_cache_header_fields_get_next_offset(cache, &hdr_offset) < 0)
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen return -1;
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen /* update the next_offset offset, so our new header will be found */
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen offset = mail_index_uint32_to_offset(offset);
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen if (mail_cache_write(cache, &offset, sizeof(offset), hdr_offset) < 0)
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen return -1;
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen if (hdr_offset == offsetof(struct mail_cache_header,
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen field_header_offset)) {
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen /* we're adding the first field. hdr_copy needs to be kept
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen in sync so unlocking won't overwrite it. */
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen cache->hdr_copy.field_header_offset = hdr_offset;
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen cache->hdr_ro_copy.field_header_offset = hdr_offset;
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen }
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen return 0;
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen}
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen
ddbad7a661c0663fafd2b79393efa85f840d6af6Timo Sirainenstatic void mail_cache_mark_adding(struct mail_cache *cache, bool set)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
fe6cf42464c36ab281c0e0740f0255be77453670Timo Sirainen unsigned int i;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fe6cf42464c36ab281c0e0740f0255be77453670Timo Sirainen /* we want to avoid adding all the fields one by one to the cache file,
fe6cf42464c36ab281c0e0740f0255be77453670Timo Sirainen so just add all of them at once in here. the unused ones get dropped
fe6cf42464c36ab281c0e0740f0255be77453670Timo Sirainen later when compressing. */
ddbad7a661c0663fafd2b79393efa85f840d6af6Timo Sirainen for (i = 0; i < cache->fields_count; i++) {
ddbad7a661c0663fafd2b79393efa85f840d6af6Timo Sirainen if (set)
ddbad7a661c0663fafd2b79393efa85f840d6af6Timo Sirainen cache->fields[i].used = TRUE;
ddbad7a661c0663fafd2b79393efa85f840d6af6Timo Sirainen cache->fields[i].adding = set;
ddbad7a661c0663fafd2b79393efa85f840d6af6Timo Sirainen }
ddbad7a661c0663fafd2b79393efa85f840d6af6Timo Sirainen}
ddbad7a661c0663fafd2b79393efa85f840d6af6Timo Sirainen
ddbad7a661c0663fafd2b79393efa85f840d6af6Timo Sirainenstatic int mail_cache_header_add_field(struct mail_cache_transaction_ctx *ctx,
ddbad7a661c0663fafd2b79393efa85f840d6af6Timo Sirainen unsigned int field_idx)
ddbad7a661c0663fafd2b79393efa85f840d6af6Timo Sirainen{
ddbad7a661c0663fafd2b79393efa85f840d6af6Timo Sirainen struct mail_cache *cache = ctx->cache;
ddbad7a661c0663fafd2b79393efa85f840d6af6Timo Sirainen int ret;
fe6cf42464c36ab281c0e0740f0255be77453670Timo Sirainen
91496fd60a7980f4ebdf93cbb099b9db198a0e74Timo Sirainen if (MAIL_INDEX_IS_IN_MEMORY(cache->index)) {
91496fd60a7980f4ebdf93cbb099b9db198a0e74Timo Sirainen if (cache->file_fields_count <= field_idx) {
91496fd60a7980f4ebdf93cbb099b9db198a0e74Timo Sirainen cache->file_field_map =
e6d4f540bf5c3b7ef5d6e154b217a2422210048cTimo Sirainen i_realloc_type(cache->file_field_map,
e6d4f540bf5c3b7ef5d6e154b217a2422210048cTimo Sirainen unsigned int,
e6d4f540bf5c3b7ef5d6e154b217a2422210048cTimo Sirainen cache->file_fields_count,
e6d4f540bf5c3b7ef5d6e154b217a2422210048cTimo Sirainen field_idx+1);
91496fd60a7980f4ebdf93cbb099b9db198a0e74Timo Sirainen cache->file_fields_count = field_idx+1;
91496fd60a7980f4ebdf93cbb099b9db198a0e74Timo Sirainen }
91496fd60a7980f4ebdf93cbb099b9db198a0e74Timo Sirainen cache->file_field_map[field_idx] = field_idx;
91496fd60a7980f4ebdf93cbb099b9db198a0e74Timo Sirainen cache->field_file_map[field_idx] = field_idx;
91496fd60a7980f4ebdf93cbb099b9db198a0e74Timo Sirainen return 0;
91496fd60a7980f4ebdf93cbb099b9db198a0e74Timo Sirainen }
91496fd60a7980f4ebdf93cbb099b9db198a0e74Timo Sirainen
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainen if (mail_cache_transaction_lock(ctx) <= 0) {
3157004d1281d5c203f739fa2e83f7a8488de92dTimo Sirainen if (MAIL_CACHE_IS_UNUSABLE(cache))
3157004d1281d5c203f739fa2e83f7a8488de92dTimo Sirainen return -1;
3157004d1281d5c203f739fa2e83f7a8488de92dTimo Sirainen
ac90bc1130bc014e41c47a1eb81dc1a3d1108115Timo Sirainen /* if we compressed the cache, the field should be there now.
ac90bc1130bc014e41c47a1eb81dc1a3d1108115Timo Sirainen it's however possible that someone else just compressed it
ac90bc1130bc014e41c47a1eb81dc1a3d1108115Timo Sirainen and we only reopened the cache file. */
ac90bc1130bc014e41c47a1eb81dc1a3d1108115Timo Sirainen if (cache->field_file_map[field_idx] != (uint32_t)-1)
ac90bc1130bc014e41c47a1eb81dc1a3d1108115Timo Sirainen return 0;
ac90bc1130bc014e41c47a1eb81dc1a3d1108115Timo Sirainen
ac90bc1130bc014e41c47a1eb81dc1a3d1108115Timo Sirainen /* need to add it */
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainen if (mail_cache_transaction_lock(ctx) <= 0)
ac90bc1130bc014e41c47a1eb81dc1a3d1108115Timo Sirainen return -1;
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
5ebddd2d812296900bc255b24bcd508878784c37Timo Sirainen /* re-read header to make sure we don't lose any fields. */
5ebddd2d812296900bc255b24bcd508878784c37Timo Sirainen if (mail_cache_header_fields_read(cache) < 0) {
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen (void)mail_cache_unlock(cache);
5ebddd2d812296900bc255b24bcd508878784c37Timo Sirainen return -1;
5ebddd2d812296900bc255b24bcd508878784c37Timo Sirainen }
5ebddd2d812296900bc255b24bcd508878784c37Timo Sirainen
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen if (cache->field_file_map[field_idx] != (uint32_t)-1) {
5ebddd2d812296900bc255b24bcd508878784c37Timo Sirainen /* it was already added */
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen if (mail_cache_unlock(cache) < 0)
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen return -1;
5ebddd2d812296900bc255b24bcd508878784c37Timo Sirainen return 0;
5ebddd2d812296900bc255b24bcd508878784c37Timo Sirainen }
5ebddd2d812296900bc255b24bcd508878784c37Timo Sirainen
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen T_BEGIN {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen buffer_t *buffer;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
c147bff818798a979d93537f72f5c1f68f5d5ba8Aki Tuomi buffer = t_buffer_create(256);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen mail_cache_header_fields_get(cache, buffer);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen ret = mail_cache_header_fields_write(ctx, buffer);
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen } T_END;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen if (ret == 0) {
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen /* we wrote all the headers, so there are no pending changes */
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen cache->field_header_write_pending = FALSE;
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen ret = mail_cache_header_fields_read(cache);
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen }
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen if (ret == 0 && cache->field_file_map[field_idx] == (uint32_t)-1) {
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen mail_index_set_error(cache->index,
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen "Cache file %s: Newly added field got "
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen "lost unexpectedly", cache->filepath);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen ret = -1;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen if (mail_cache_unlock(cache) < 0)
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen ret = -1;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenvoid mail_cache_add(struct mail_cache_transaction_ctx *ctx, uint32_t seq,
710deabc6b3c305c3a842e7a2e0d173c526d13a7Timo Sirainen unsigned int field_idx, const void *data, size_t data_size)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen uint32_t file_field, data_size32;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen unsigned int fixed_size;
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen size_t full_size;
ddbad7a661c0663fafd2b79393efa85f840d6af6Timo Sirainen int ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
710deabc6b3c305c3a842e7a2e0d173c526d13a7Timo Sirainen i_assert(field_idx < ctx->cache->fields_count);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(data_size < (uint32_t)-1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
710deabc6b3c305c3a842e7a2e0d173c526d13a7Timo Sirainen if (ctx->cache->fields[field_idx].field.decision ==
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen (MAIL_CACHE_DECISION_NO | MAIL_CACHE_DECISION_FORCED))
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
cfbf891f065b18602703ed6fa2af1a541d4d0b04Timo Sirainen if (ctx->cache_file_seq == 0) {
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen mail_cache_transaction_open_if_needed(ctx);
b387ee112301fef59d16ab3b120e3821cd0c70dfTimo Sirainen if (!MAIL_CACHE_IS_UNUSABLE(ctx->cache))
b387ee112301fef59d16ab3b120e3821cd0c70dfTimo Sirainen ctx->cache_file_seq = ctx->cache->hdr->file_seq;
da5dd6f1141e8b134199e1a2a23af4e05173464aTimo Sirainen } else if (!MAIL_CACHE_IS_UNUSABLE(ctx->cache) &&
da5dd6f1141e8b134199e1a2a23af4e05173464aTimo Sirainen ctx->cache_file_seq != ctx->cache->hdr->file_seq) {
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen /* cache was compressed within this transaction */
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen mail_cache_transaction_reset(ctx);
cfbf891f065b18602703ed6fa2af1a541d4d0b04Timo Sirainen }
cfbf891f065b18602703ed6fa2af1a541d4d0b04Timo Sirainen
710deabc6b3c305c3a842e7a2e0d173c526d13a7Timo Sirainen file_field = ctx->cache->field_file_map[field_idx];
17118d434fcd48b0f0211bdac2747276f0b05223Timo Sirainen if (MAIL_CACHE_IS_UNUSABLE(ctx->cache) || file_field == (uint32_t)-1) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* we'll have to add this field to headers */
ddbad7a661c0663fafd2b79393efa85f840d6af6Timo Sirainen mail_cache_mark_adding(ctx->cache, TRUE);
ddbad7a661c0663fafd2b79393efa85f840d6af6Timo Sirainen ret = mail_cache_header_add_field(ctx, field_idx);
ddbad7a661c0663fafd2b79393efa85f840d6af6Timo Sirainen mail_cache_mark_adding(ctx->cache, FALSE);
ddbad7a661c0663fafd2b79393efa85f840d6af6Timo Sirainen if (ret < 0)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
91496fd60a7980f4ebdf93cbb099b9db198a0e74Timo Sirainen if (ctx->cache_file_seq == 0) {
91496fd60a7980f4ebdf93cbb099b9db198a0e74Timo Sirainen if (MAIL_INDEX_IS_IN_MEMORY(ctx->cache->index))
91496fd60a7980f4ebdf93cbb099b9db198a0e74Timo Sirainen ctx->cache_file_seq = 1;
91496fd60a7980f4ebdf93cbb099b9db198a0e74Timo Sirainen else
91496fd60a7980f4ebdf93cbb099b9db198a0e74Timo Sirainen ctx->cache_file_seq = ctx->cache->hdr->file_seq;
91496fd60a7980f4ebdf93cbb099b9db198a0e74Timo Sirainen }
fe6cf42464c36ab281c0e0740f0255be77453670Timo Sirainen
710deabc6b3c305c3a842e7a2e0d173c526d13a7Timo Sirainen file_field = ctx->cache->field_file_map[field_idx];
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen i_assert(file_field != (uint32_t)-1);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
17118d434fcd48b0f0211bdac2747276f0b05223Timo Sirainen i_assert(ctx->cache_file_seq != 0);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
710deabc6b3c305c3a842e7a2e0d173c526d13a7Timo Sirainen mail_cache_decision_add(ctx->view, seq, field_idx);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
710deabc6b3c305c3a842e7a2e0d173c526d13a7Timo Sirainen fixed_size = ctx->cache->fields[field_idx].field.field_size;
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen i_assert(fixed_size == UINT_MAX || fixed_size == data_size);
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen data_size32 = (uint32_t)data_size;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (ctx->prev_seq != seq) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen mail_cache_transaction_switch_seq(ctx);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen ctx->prev_seq = seq;
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen seq_range_array_add(&ctx->cache_data_wanted_seqs, seq);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen /* remember roughly what we have modified, so cache lookups can
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen look into transactions to see changes. */
ca316aeb7648d3f1bcf45231f73ddeb1b67a6961Timo Sirainen if (seq < ctx->view->trans_seq1 || ctx->view->trans_seq1 == 0)
ca316aeb7648d3f1bcf45231f73ddeb1b67a6961Timo Sirainen ctx->view->trans_seq1 = seq;
ca316aeb7648d3f1bcf45231f73ddeb1b67a6961Timo Sirainen if (seq > ctx->view->trans_seq2)
ca316aeb7648d3f1bcf45231f73ddeb1b67a6961Timo Sirainen ctx->view->trans_seq2 = seq;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
988f9ad3b5e973c12453a780effc477031107648Timo Sirainen /* remember that this value exists, in case we try to look it up */
988f9ad3b5e973c12453a780effc477031107648Timo Sirainen buffer_write(ctx->view->cached_exists_buf, field_idx,
988f9ad3b5e973c12453a780effc477031107648Timo Sirainen &ctx->view->cached_exists_value, 1);
988f9ad3b5e973c12453a780effc477031107648Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen full_size = (data_size + 3) & ~3;
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen if (fixed_size == UINT_MAX)
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen full_size += sizeof(data_size32);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen if (ctx->cache_data->used + full_size > MAIL_CACHE_MAX_WRITE_BUFFER &&
289064eb21595d3e4460439eccdc48232d13f5e1Timo Sirainen ctx->last_rec_pos > 0) {
dd0ba1bab2c1b89c7e063fa45d156fa72b8260d5Timo Sirainen /* time to flush our buffer. if flushing fails because the
dd0ba1bab2c1b89c7e063fa45d156fa72b8260d5Timo Sirainen cache file had been compressed and was reopened, return
dd0ba1bab2c1b89c7e063fa45d156fa72b8260d5Timo Sirainen without adding the cached data since cache_data buffer
dd0ba1bab2c1b89c7e063fa45d156fa72b8260d5Timo Sirainen doesn't contain the cache_rec anymore. */
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen if (MAIL_INDEX_IS_IN_MEMORY(ctx->cache->index)) {
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen /* just drop the old data to free up memory */
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen size_t space_needed = ctx->cache_data->used +
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen full_size - MAIL_CACHE_MAX_WRITE_BUFFER;
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen mail_cache_transaction_drop_unwanted(ctx, space_needed);
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen } else if (mail_cache_transaction_flush(ctx) < 0) {
6a669919418a1c7469f9faf55d11b3c723f72cffTimo Sirainen /* make sure the transaction is reset, so we don't
6a669919418a1c7469f9faf55d11b3c723f72cffTimo Sirainen constantly try to flush for each call to this
6a669919418a1c7469f9faf55d11b3c723f72cffTimo Sirainen function */
6a669919418a1c7469f9faf55d11b3c723f72cffTimo Sirainen mail_cache_transaction_reset(ctx);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return;
6a669919418a1c7469f9faf55d11b3c723f72cffTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen buffer_append(ctx->cache_data, &file_field, sizeof(file_field));
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen if (fixed_size == UINT_MAX) {
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen buffer_append(ctx->cache_data, &data_size32,
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen sizeof(data_size32));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen buffer_append(ctx->cache_data, data, data_size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((data_size & 3) != 0)
dd0ba1bab2c1b89c7e063fa45d156fa72b8260d5Timo Sirainen buffer_append_zero(ctx->cache_data, 4 - (data_size & 3));
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen}
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
e0127c3244319fffb07bf65a3ed9e4a5d6e555b7Timo Sirainenbool mail_cache_field_want_add(struct mail_cache_transaction_ctx *ctx,
710deabc6b3c305c3a842e7a2e0d173c526d13a7Timo Sirainen uint32_t seq, unsigned int field_idx)
e0127c3244319fffb07bf65a3ed9e4a5d6e555b7Timo Sirainen{
e0127c3244319fffb07bf65a3ed9e4a5d6e555b7Timo Sirainen enum mail_cache_decision_type decision;
e0127c3244319fffb07bf65a3ed9e4a5d6e555b7Timo Sirainen
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen mail_cache_transaction_open_if_needed(ctx);
65b73edef55f8d1a4e343fdc47c2a3f9d4554db3Timo Sirainen
710deabc6b3c305c3a842e7a2e0d173c526d13a7Timo Sirainen decision = mail_cache_field_get_decision(ctx->view->cache, field_idx);
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen decision &= ~MAIL_CACHE_DECISION_FORCED;
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen switch (decision) {
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen case MAIL_CACHE_DECISION_NO:
e0127c3244319fffb07bf65a3ed9e4a5d6e555b7Timo Sirainen return FALSE;
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen case MAIL_CACHE_DECISION_TEMP:
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen /* add it only if it's newer than what we would drop when
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen compressing */
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen if (ctx->first_new_seq == 0) {
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen ctx->first_new_seq =
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen mail_cache_get_first_new_seq(ctx->view->view);
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen }
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen if (seq < ctx->first_new_seq)
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen return FALSE;
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen break;
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen default:
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen break;
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen }
e0127c3244319fffb07bf65a3ed9e4a5d6e555b7Timo Sirainen
710deabc6b3c305c3a842e7a2e0d173c526d13a7Timo Sirainen return mail_cache_field_exists(ctx->view, seq, field_idx) == 0;
e0127c3244319fffb07bf65a3ed9e4a5d6e555b7Timo Sirainen}
e0127c3244319fffb07bf65a3ed9e4a5d6e555b7Timo Sirainen
e0127c3244319fffb07bf65a3ed9e4a5d6e555b7Timo Sirainenbool mail_cache_field_can_add(struct mail_cache_transaction_ctx *ctx,
710deabc6b3c305c3a842e7a2e0d173c526d13a7Timo Sirainen uint32_t seq, unsigned int field_idx)
e0127c3244319fffb07bf65a3ed9e4a5d6e555b7Timo Sirainen{
e0127c3244319fffb07bf65a3ed9e4a5d6e555b7Timo Sirainen enum mail_cache_decision_type decision;
e0127c3244319fffb07bf65a3ed9e4a5d6e555b7Timo Sirainen
b159b7fb9740b6e37238016d8395a351de498d50Timo Sirainen mail_cache_transaction_open_if_needed(ctx);
65b73edef55f8d1a4e343fdc47c2a3f9d4554db3Timo Sirainen
710deabc6b3c305c3a842e7a2e0d173c526d13a7Timo Sirainen decision = mail_cache_field_get_decision(ctx->view->cache, field_idx);
e0127c3244319fffb07bf65a3ed9e4a5d6e555b7Timo Sirainen if (decision == (MAIL_CACHE_DECISION_FORCED | MAIL_CACHE_DECISION_NO))
e0127c3244319fffb07bf65a3ed9e4a5d6e555b7Timo Sirainen return FALSE;
e0127c3244319fffb07bf65a3ed9e4a5d6e555b7Timo Sirainen
710deabc6b3c305c3a842e7a2e0d173c526d13a7Timo Sirainen return mail_cache_field_exists(ctx->view, seq, field_idx) == 0;
e0127c3244319fffb07bf65a3ed9e4a5d6e555b7Timo Sirainen}
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainenvoid mail_cache_close_mail(struct mail_cache_transaction_ctx *ctx,
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen uint32_t seq)
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen{
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen if (array_is_created(&ctx->cache_data_wanted_seqs))
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen seq_range_array_remove(&ctx->cache_data_wanted_seqs, seq);
93cb78fb1947d34e98efffecc2b73f035e711f18Timo Sirainen}