mail-index-sync.c revision 0bea219e4f944cd17a9ccd1131b7fe081d1bb0a7
89a126810703c666309310d0f3189e9834d70b5bTimo Sirainen/* Copyright (c) 2003-2009 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "array.h"
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen#include "mail-index-view-private.h"
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen#include "mail-index-sync-private.h"
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen#include "mail-index-transaction-private.h"
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen#include "mail-transaction-log-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-cache.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <stdio.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <stdlib.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct mail_index_sync_ctx {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_index *index;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_index_view *view;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_index_transaction *sync_trans, *ext_trans;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen enum mail_index_sync_flags flags;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_transaction_header *hdr;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const void *data;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ARRAY_DEFINE(sync_list, struct mail_index_sync_list);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uint32_t next_uid;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uint32_t last_tail_seq, last_tail_offset;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uint32_t append_uid_first, append_uid_last;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int sync_appends:1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen};
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void mail_index_sync_add_expunge(struct mail_index_sync_ctx *ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen const struct mail_transaction_expunge *e = ctx->data;
ad850190d946d34966a56838cfdb216e021b5b5fTimo Sirainen size_t i, size = ctx->hdr->size / sizeof(*e);
ad850190d946d34966a56838cfdb216e021b5b5fTimo Sirainen uint32_t uid;
ad850190d946d34966a56838cfdb216e021b5b5fTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (i = 0; i < size; i++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (uid = e[i].uid1; uid <= e[i].uid2; uid++)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_expunge(ctx->sync_trans, uid);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void mail_index_sync_add_flag_update(struct mail_index_sync_ctx *ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_transaction_flag_update *u = ctx->data;
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen size_t i, size = ctx->hdr->size / sizeof(*u);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (i = 0; i < size; i++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (u[i].add_flags != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_update_flags_range(ctx->sync_trans,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen u[i].uid1, u[i].uid2,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen MODIFY_ADD,
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen u[i].add_flags);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen }
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen if (u[i].remove_flags != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_update_flags_range(ctx->sync_trans,
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen u[i].uid1, u[i].uid2,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen MODIFY_REMOVE,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen u[i].remove_flags);
6e235046e1d8e9d89fc948f5c623676c20421a28Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen}
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenstatic void mail_index_sync_add_keyword_update(struct mail_index_sync_ctx *ctx)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_transaction_keyword_update *u = ctx->data;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *keyword_names[2];
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_keywords *keywords;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const uint32_t *uids;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uint32_t uid;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen size_t uidset_offset, i, size;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen uidset_offset = sizeof(*u) + u->name_size;
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen if ((uidset_offset % 4) != 0)
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen uidset_offset += 4 - (uidset_offset % 4);
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen uids = CONST_PTR_OFFSET(u, uidset_offset);
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen keyword_names[0] = t_strndup(u + 1, u->name_size);
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen keyword_names[1] = NULL;
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen keywords = mail_index_keywords_create(ctx->index, keyword_names);
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen size = (ctx->hdr->size - uidset_offset) / sizeof(uint32_t);
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen for (i = 0; i < size; i += 2) {
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen /* FIXME: mail_index_update_keywords_range() */
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen for (uid = uids[i]; uid <= uids[i+1]; uid++) {
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen mail_index_update_keywords(ctx->sync_trans, uid,
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen u->modify_type, keywords);
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen }
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen }
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen mail_index_keywords_free(&keywords);
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen}
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainenstatic void mail_index_sync_add_keyword_reset(struct mail_index_sync_ctx *ctx)
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen{
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen const struct mail_transaction_keyword_reset *u = ctx->data;
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen size_t i, size = ctx->hdr->size / sizeof(*u);
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen struct mail_keywords *keywords;
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen uint32_t uid;
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen keywords = mail_index_keywords_create(ctx->index, NULL);
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen for (i = 0; i < size; i++) {
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen for (uid = u[i].uid1; uid <= u[i].uid2; uid++) {
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen mail_index_update_keywords(ctx->sync_trans, uid,
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen MODIFY_REPLACE, keywords);
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen }
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen }
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen mail_index_keywords_free(&keywords);
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen}
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainenstatic void mail_index_sync_add_append(struct mail_index_sync_ctx *ctx)
04b8a90af181cc4c7959266855e8ed50a22ed413Timo Sirainen{
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen const struct mail_index_record *rec = ctx->data;
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen if (ctx->append_uid_first == 0 || rec->uid < ctx->append_uid_first)
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen ctx->append_uid_first = rec->uid;
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen rec = CONST_PTR_OFFSET(ctx->data, ctx->hdr->size - sizeof(*rec));
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen if (rec->uid > ctx->append_uid_last)
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen ctx->append_uid_last = rec->uid;
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen ctx->sync_appends = TRUE;
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen}
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainenstatic bool mail_index_sync_add_transaction(struct mail_index_sync_ctx *ctx)
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen{
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen switch (ctx->hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen case MAIL_TRANSACTION_EXPUNGE:
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen mail_index_sync_add_expunge(ctx);
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen break;
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen case MAIL_TRANSACTION_FLAG_UPDATE:
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen mail_index_sync_add_flag_update(ctx);
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen break;
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen case MAIL_TRANSACTION_KEYWORD_UPDATE:
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen mail_index_sync_add_keyword_update(ctx);
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen break;
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen case MAIL_TRANSACTION_KEYWORD_RESET:
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen mail_index_sync_add_keyword_reset(ctx);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen case MAIL_TRANSACTION_APPEND:
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen mail_index_sync_add_append(ctx);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen break;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen default:
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen return FALSE;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen }
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen return TRUE;
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen}
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainenstatic void mail_index_sync_add_dirty_updates(struct mail_index_sync_ctx *ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen struct mail_transaction_flag_update update;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen const struct mail_index_record *rec;
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen uint32_t seq, messages_count;
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen memset(&update, 0, sizeof(update));
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen messages_count = mail_index_view_get_messages_count(ctx->view);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen for (seq = 1; seq <= messages_count; seq++) {
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen rec = mail_index_lookup(ctx->view, seq);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((rec->flags & MAIL_INDEX_MAIL_FLAG_DIRTY) == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen continue;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen mail_index_update_flags(ctx->sync_trans, rec->uid,
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen MODIFY_REPLACE, rec->flags);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen }
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic void
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenmail_index_sync_update_mailbox_pos(struct mail_index_sync_ctx *ctx)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen uint32_t seq;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen uoff_t offset;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen mail_transaction_log_view_get_prev_pos(ctx->view->log_view,
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen &seq, &offset);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen ctx->last_tail_seq = seq;
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen ctx->last_tail_offset = offset + ctx->hdr->size + sizeof(*ctx->hdr);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen}
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainenstatic int
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainenmail_index_sync_read_and_sort(struct mail_index_sync_ctx *ctx)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen{
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen struct mail_index_transaction *sync_trans = ctx->sync_trans;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen struct mail_index_sync_list *synclist;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_index_transaction_keyword_update *keyword_updates;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int i, keyword_count;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen int ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen if ((ctx->view->map->hdr.flags & MAIL_INDEX_HDR_FLAG_HAVE_DIRTY) &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (ctx->flags & MAIL_INDEX_SYNC_FLAG_FLUSH_DIRTY) != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* show dirty flags as flag updates */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_sync_add_dirty_updates(ctx);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* read all transactions from log into a transaction in memory.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen skip the external ones, they're already synced to mailbox and
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen included in our view */
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen while ((ret = mail_transaction_log_view_next(ctx->view->log_view,
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen &ctx->hdr,
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen &ctx->data)) > 0) {
e192a3b1ca8ae857e7d87298ea507d32977ba570Timo Sirainen if ((ctx->hdr->type & MAIL_TRANSACTION_EXTERNAL) != 0)
e192a3b1ca8ae857e7d87298ea507d32977ba570Timo Sirainen continue;
e192a3b1ca8ae857e7d87298ea507d32977ba570Timo Sirainen
811f2e26d9782d9cb99fdf82e18ffa0a77564fe2Timo Sirainen T_BEGIN {
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen if (mail_index_sync_add_transaction(ctx))
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen mail_index_sync_update_mailbox_pos(ctx);
c4877db8b6559846f4b58be8e42422dc734c193fTimo Sirainen } T_END;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen /* create an array containing all expunge, flag and keyword update
8b9342aa96b2f297e23afb261f9f7dd859800952Timo Sirainen arrays so we can easily go through all of the changes. */
8b9342aa96b2f297e23afb261f9f7dd859800952Timo Sirainen keyword_count = !array_is_created(&sync_trans->keyword_updates) ? 0 :
8b9342aa96b2f297e23afb261f9f7dd859800952Timo Sirainen array_count(&sync_trans->keyword_updates);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_array_init(&ctx->sync_list, keyword_count + 2);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
37e6cf44d61a81c6839e3ab76234b54309d8d292Timo Sirainen if (array_is_created(&sync_trans->expunges)) {
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen synclist = array_append_space(&ctx->sync_list);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen synclist->array = (void *)&sync_trans->expunges;
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (array_is_created(&sync_trans->updates)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen synclist = array_append_space(&ctx->sync_list);
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen synclist->array = (void *)&sync_trans->updates;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* we must return resets before keyword additions or they get lost */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (array_is_created(&sync_trans->keyword_resets)) {
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen synclist = array_append_space(&ctx->sync_list);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen synclist->array = (void *)&sync_trans->keyword_resets;
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen }
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen keyword_updates = keyword_count == 0 ? NULL :
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen array_idx(&sync_trans->keyword_updates, 0);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (i = 0; i < keyword_count; i++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (array_is_created(&keyword_updates[i].add_seq)) {
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen synclist = array_append_space(&ctx->sync_list);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen synclist->array = (void *)&keyword_updates[i].add_seq;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen synclist->keyword_idx = i;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen }
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (array_is_created(&keyword_updates[i].remove_seq)) {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen synclist = array_append_space(&ctx->sync_list);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen synclist->array =
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen (void *)&keyword_updates[i].remove_seq;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen synclist->keyword_idx = i;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen synclist->keyword_remove = TRUE;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen }
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen }
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen return ret;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen}
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainenstatic bool
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainenmail_index_need_sync(struct mail_index *index, enum mail_index_sync_flags flags,
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen uint32_t log_file_seq, uoff_t log_file_offset)
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen{
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen const struct mail_index_header *hdr = &index->map->hdr;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen if ((flags & MAIL_INDEX_SYNC_FLAG_REQUIRE_CHANGES) == 0)
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen return TRUE;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen /* sync only if there's something to do */
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen if (hdr->first_recent_uid < hdr->next_uid &&
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen (flags & MAIL_INDEX_SYNC_FLAG_DROP_RECENT) != 0)
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen return TRUE;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen if ((hdr->flags & MAIL_INDEX_HDR_FLAG_HAVE_DIRTY) &&
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen (flags & MAIL_INDEX_SYNC_FLAG_FLUSH_DIRTY) != 0)
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen return TRUE;
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen if (log_file_seq == (uint32_t)-1) {
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen /* we want to sync up to transaction log's head */
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen mail_transaction_log_get_head(index->log,
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen &log_file_seq, &log_file_offset);
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen }
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen if ((hdr->log_file_tail_offset < log_file_offset &&
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen hdr->log_file_seq == log_file_seq) ||
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen hdr->log_file_seq < log_file_seq)
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen return TRUE;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen if (index->need_recreate)
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen return TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen /* already synced */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return mail_cache_need_compress(index->cache);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmail_index_sync_set_log_view(struct mail_index_view *view,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uint32_t start_file_seq, uoff_t start_file_offset)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen uint32_t log_seq;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen uoff_t log_offset;
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen bool reset;
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen int ret;
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen mail_transaction_log_get_head(view->index->log, &log_seq, &log_offset);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen ret = mail_transaction_log_view_set(view->log_view,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen start_file_seq, start_file_offset,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen log_seq, log_offset, &reset);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ret <= 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* either corrupted or the file was deleted for
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen some reason. either way, we can't go forward */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_set_error(view->index,
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen "Unexpected transaction log desync with index %s",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen view->index->filepath);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainenint mail_index_sync_begin(struct mail_index *index,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_index_sync_ctx **ctx_r,
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen struct mail_index_view **view_r,
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen struct mail_index_transaction **trans_r,
f519e4c2ad4ef826f1b08f3e0138b9b287a52c80Timo Sirainen enum mail_index_sync_flags flags)
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen{
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen int ret;
d565eaa943f29a49b97230ced57eec40ee65b4f9Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen ret = mail_index_sync_begin_to(index, ctx_r, view_r, trans_r,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (uint32_t)-1, (uoff_t)-1, flags);
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen i_assert(ret != 0 ||
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen (flags & MAIL_INDEX_SYNC_FLAG_REQUIRE_CHANGES) != 0);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainenmail_index_sync_begin_init(struct mail_index *index,
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen enum mail_index_sync_flags flags,
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen uint32_t log_file_seq, uoff_t log_file_offset)
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen{
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen const struct mail_index_header *hdr;
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen uint32_t seq;
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen uoff_t offset;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen bool locked = FALSE;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen int ret;
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* if we require changes, don't lock transaction log yet. first check
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if there's anything to sync. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((flags & MAIL_INDEX_SYNC_FLAG_REQUIRE_CHANGES) == 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mail_transaction_log_sync_lock(index->log,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen &seq, &offset) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen locked = TRUE;
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen }
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* The view must contain what we expect the mailbox to look like
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen currently. That allows the backend to update external flag
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen changes (etc.) if the view doesn't match the mailbox.
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen We'll update the view to contain everything that exist in the
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen transaction log except for expunges. They're synced in
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen mail_index_sync_commit(). */
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen if ((ret = mail_index_map(index, MAIL_INDEX_SYNC_HANDLER_HEAD)) <= 0) {
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen if (ret == 0) {
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen if (locked)
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen mail_transaction_log_sync_unlock(index->log);
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen return -1;
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen }
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen /* let's try again */
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen if (mail_index_map(index, MAIL_INDEX_SYNC_HANDLER_HEAD) <= 0) {
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen if (locked)
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen mail_transaction_log_sync_unlock(index->log);
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!mail_index_need_sync(index, flags,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen log_file_seq, log_file_offset)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (locked)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_transaction_log_sync_unlock(index->log);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen
a835194f9a9dae88528367a791cbc282589f6c01Timo Sirainen if (!locked) {
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen /* it looks like we have something to sync. lock the file and
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen check again. */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen flags &= ~MAIL_INDEX_SYNC_FLAG_REQUIRE_CHANGES;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return mail_index_sync_begin_init(index, flags, log_file_seq,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen log_file_offset);
8887bf3757d51d73887dd20b1db3334d867d3817Timo Sirainen }
8da095519878426b012058e6f331a669f327f47fTimo Sirainen
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen hdr = &index->map->hdr;
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen if (hdr->log_file_tail_offset > hdr->log_file_head_offset ||
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen hdr->log_file_seq > seq ||
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen (hdr->log_file_seq == seq && hdr->log_file_tail_offset > offset)) {
ce19e80b5a907d51a7cdf081e09699af8367dbfaTimo Sirainen /* broken sync positions. fix them. */
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen mail_index_set_error(index,
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen "broken sync positions in index file %s",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index->filepath);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen mail_index_fsck_locked(index);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return 1;
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen}
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenint mail_index_sync_begin_to(struct mail_index *index,
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen struct mail_index_sync_ctx **ctx_r,
9315dd69233d554452df0c12bc57002d2042a8f4Timo Sirainen struct mail_index_view **view_r,
9315dd69233d554452df0c12bc57002d2042a8f4Timo Sirainen struct mail_index_transaction **trans_r,
69bd816e46fdee6182d0cb2e4c6be32399a555c8Timo Sirainen uint32_t log_file_seq, uoff_t log_file_offset,
69bd816e46fdee6182d0cb2e4c6be32399a555c8Timo Sirainen enum mail_index_sync_flags flags)
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen{
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen const struct mail_index_header *hdr;
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen struct mail_index_sync_ctx *ctx;
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen struct mail_index_view *sync_view;
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen enum mail_index_transaction_flags trans_flags;
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen int ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(!index->syncing);
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen if (log_file_seq != (uint32_t)-1)
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen flags |= MAIL_INDEX_SYNC_FLAG_REQUIRE_CHANGES;
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen ret = mail_index_sync_begin_init(index, flags, log_file_seq,
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen log_file_offset);
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen if (ret <= 0)
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen return ret;
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen hdr = &index->map->hdr;
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen ctx = i_new(struct mail_index_sync_ctx, 1);
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen ctx->index = index;
5196f9ea42d02000f9c3d22f20aa816140af4422Timo Sirainen ctx->last_tail_seq = hdr->log_file_seq;
5196f9ea42d02000f9c3d22f20aa816140af4422Timo Sirainen ctx->last_tail_offset = hdr->log_file_tail_offset;
5196f9ea42d02000f9c3d22f20aa816140af4422Timo Sirainen ctx->flags = flags;
5196f9ea42d02000f9c3d22f20aa816140af4422Timo Sirainen
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen ctx->view = mail_index_view_open(index);
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen sync_view = mail_index_dummy_view_open(index);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen ctx->sync_trans = mail_index_transaction_begin(sync_view,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen mail_index_view_close(&sync_view);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen /* we wish to see all the changes from last mailbox sync position to
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen the end of the transaction log */
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen if (mail_index_sync_set_log_view(ctx->view, hdr->log_file_seq,
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen hdr->log_file_tail_offset) < 0) {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen /* if a log file is missing, there's nothing we can do except
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen to skip over it. fix the problem with fsck and try again. */
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen mail_index_fsck_locked(index);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen mail_index_sync_rollback(&ctx);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen return mail_index_sync_begin_to(index, ctx_r, view_r, trans_r,
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen log_file_seq, log_file_offset,
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen flags);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
ba00293b85c7fb4e7a2d100991c716e17b9daaaeTimo Sirainen /* we need to have all the transactions sorted to optimize
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen caller's mailbox access patterns */
0cea9b1f4fa0495a48f5f097e40492517d67e1baTimo Sirainen if (mail_index_sync_read_and_sort(ctx) < 0) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen mail_index_sync_rollback(&ctx);
0cea9b1f4fa0495a48f5f097e40492517d67e1baTimo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->view->index_sync_view = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen /* create the transaction after the view has been updated with
2af769daebd83719ac696a440e06f6020471cec0Timo Sirainen external transactions and marked as sync view */
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen trans_flags = MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL;
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen if ((ctx->flags & MAIL_INDEX_SYNC_FLAG_AVOID_FLAG_UPDATES) != 0)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen trans_flags |= MAIL_INDEX_TRANSACTION_FLAG_AVOID_FLAG_UPDATES;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen ctx->ext_trans = mail_index_transaction_begin(ctx->view, trans_flags);
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen ctx->ext_trans->sync_transaction = TRUE;
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen
cc833a7a4e2258afdc834ace4bfe6579820a1df3Timo Sirainen index->syncing = TRUE;
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen *ctx_r = ctx;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen *view_r = ctx->view;
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen *trans_r = ctx->ext_trans;
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen return 1;
5bdad39213d28ab35e615a7f4ea1712ab25b6a80Timo Sirainen}
5bdad39213d28ab35e615a7f4ea1712ab25b6a80Timo Sirainen
5bdad39213d28ab35e615a7f4ea1712ab25b6a80Timo Sirainenstatic bool mail_index_sync_view_have_any(struct mail_index_view *view,
5bdad39213d28ab35e615a7f4ea1712ab25b6a80Timo Sirainen enum mail_index_sync_flags flags)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen{
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen const struct mail_transaction_header *hdr;
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen const void *data;
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen uint32_t log_seq;
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen uoff_t log_offset;
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen bool reset;
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen int ret;
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen if (view->map->hdr.first_recent_uid < view->map->hdr.next_uid &&
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen (flags & MAIL_INDEX_SYNC_FLAG_DROP_RECENT) != 0)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen return TRUE;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen if ((view->map->hdr.flags & MAIL_INDEX_HDR_FLAG_HAVE_DIRTY) &&
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen (flags & MAIL_INDEX_SYNC_FLAG_FLUSH_DIRTY) != 0)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen return TRUE;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
2af769daebd83719ac696a440e06f6020471cec0Timo Sirainen mail_transaction_log_get_head(view->index->log, &log_seq, &log_offset);
2af769daebd83719ac696a440e06f6020471cec0Timo Sirainen if (mail_transaction_log_view_set(view->log_view,
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen view->map->hdr.log_file_seq,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen view->map->hdr.log_file_tail_offset,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen log_seq, log_offset, &reset) <= 0) {
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen /* let the actual syncing handle the error */
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen return TRUE;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen while ((ret = mail_transaction_log_view_next(view->log_view,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen &hdr, &data)) > 0) {
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXTERNAL) != 0)
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen continue;
6a8a4c9f530668cd8961b73d702856ed94f05f80Timo Sirainen
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen case MAIL_TRANSACTION_EXT_REC_UPDATE:
ba482d3624ca4f1b3d638e6e8470ba5134f21493Timo Sirainen /* extension record updates aren't exactly needed
ba482d3624ca4f1b3d638e6e8470ba5134f21493Timo Sirainen to be synced, but cache syncing relies on tail
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen offsets being updated. */
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen case MAIL_TRANSACTION_EXPUNGE:
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen case MAIL_TRANSACTION_FLAG_UPDATE:
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen case MAIL_TRANSACTION_KEYWORD_UPDATE:
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen case MAIL_TRANSACTION_KEYWORD_RESET:
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen return TRUE;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen default:
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen break;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen return ret < 0;
cf3bea6d9b57f8608bec22d98ad547a507b05f66Timo Sirainen}
cf3bea6d9b57f8608bec22d98ad547a507b05f66Timo Sirainen
cf3bea6d9b57f8608bec22d98ad547a507b05f66Timo Sirainenbool mail_index_sync_have_any(struct mail_index *index,
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen enum mail_index_sync_flags flags)
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen{
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen struct mail_index_view *view;
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen bool ret;
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen (void)mail_index_refresh(index);
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainen
cf3bea6d9b57f8608bec22d98ad547a507b05f66Timo Sirainen view = mail_index_view_open(index);
e6e43b396799aa5704c679a3017d6c7195f9347dTimo Sirainen ret = mail_index_sync_view_have_any(view, flags);
cf3bea6d9b57f8608bec22d98ad547a507b05f66Timo Sirainen mail_index_view_close(&view);
cf3bea6d9b57f8608bec22d98ad547a507b05f66Timo Sirainen return ret;
cf3bea6d9b57f8608bec22d98ad547a507b05f66Timo Sirainen}
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen
2af769daebd83719ac696a440e06f6020471cec0Timo Sirainenstatic void
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainenmail_index_sync_get_expunge(struct mail_index_sync_rec *rec,
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen const struct mail_transaction_expunge *exp)
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen{
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen rec->type = MAIL_INDEX_SYNC_TYPE_EXPUNGE;
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen rec->uid1 = exp->uid1;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen rec->uid2 = exp->uid2;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainenstatic void
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainenmail_index_sync_get_update(struct mail_index_sync_rec *rec,
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen const struct mail_transaction_flag_update *update)
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen rec->type = MAIL_INDEX_SYNC_TYPE_FLAGS;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen rec->uid1 = update->uid1;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen rec->uid2 = update->uid2;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen
114a0f74e0f825c6bd8aeadfafb248a030762a1fTimo Sirainen rec->add_flags = update->add_flags;
114a0f74e0f825c6bd8aeadfafb248a030762a1fTimo Sirainen rec->remove_flags = update->remove_flags;
114a0f74e0f825c6bd8aeadfafb248a030762a1fTimo Sirainen}
114a0f74e0f825c6bd8aeadfafb248a030762a1fTimo Sirainen
7981779f9aebd25728d3c26555d598ff842cf2e2Timo Sirainenstatic void
7981779f9aebd25728d3c26555d598ff842cf2e2Timo Sirainenmail_index_sync_get_keyword_update(struct mail_index_sync_rec *rec,
7981779f9aebd25728d3c26555d598ff842cf2e2Timo Sirainen const struct uid_range *range,
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen struct mail_index_sync_list *sync_list)
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen{
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen rec->type = !sync_list->keyword_remove ?
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD :
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE;
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen rec->uid1 = range->uid1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen rec->uid2 = range->uid2;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen rec->keyword_idx = sync_list->keyword_idx;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void mail_index_sync_get_keyword_reset(struct mail_index_sync_rec *rec,
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen const struct uid_range *range)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen{
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen rec->type = MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen rec->uid1 = range->uid1;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen rec->uid2 = range->uid2;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen}
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
1a21e7049796c98d6d998fcf7a438d7a97193dc4Timo Sirainenbool mail_index_sync_next(struct mail_index_sync_ctx *ctx,
1a21e7049796c98d6d998fcf7a438d7a97193dc4Timo Sirainen struct mail_index_sync_rec *sync_rec)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen{
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen struct mail_index_transaction *sync_trans = ctx->sync_trans;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen struct mail_index_sync_list *sync_list;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct uid_range *uid_range = NULL;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen unsigned int i, count, next_i;
1a21e7049796c98d6d998fcf7a438d7a97193dc4Timo Sirainen uint32_t next_found_uid;
1a21e7049796c98d6d998fcf7a438d7a97193dc4Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen next_i = (unsigned int)-1;
1a21e7049796c98d6d998fcf7a438d7a97193dc4Timo Sirainen next_found_uid = (uint32_t)-1;
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* FIXME: replace with a priority queue so we don't have to go
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen through the whole list constantly. and remember to make sure that
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen keyword resets are sent before adds! */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen sync_list = array_get_modifiable(&ctx->sync_list, &count);
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen for (i = 0; i < count; i++) {
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen if (!array_is_created(sync_list[i].array) ||
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen sync_list[i].idx == array_count(sync_list[i].array))
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen continue;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen uid_range = array_idx(sync_list[i].array, sync_list[i].idx);
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen if (uid_range->uid1 == ctx->next_uid) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen /* use this one. */
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen break;
62cfc346eb7b0a4fd9e1ab6edd63b98711161229Timo Sirainen }
62cfc346eb7b0a4fd9e1ab6edd63b98711161229Timo Sirainen if (uid_range->uid1 < next_found_uid) {
62cfc346eb7b0a4fd9e1ab6edd63b98711161229Timo Sirainen next_i = i;
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen next_found_uid = uid_range->uid1;
62cfc346eb7b0a4fd9e1ab6edd63b98711161229Timo Sirainen }
62cfc346eb7b0a4fd9e1ab6edd63b98711161229Timo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (i == count) {
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen if (next_i == (unsigned int)-1) {
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen /* nothing left in sync_list */
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen if (ctx->sync_appends) {
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen ctx->sync_appends = FALSE;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen sync_rec->type = MAIL_INDEX_SYNC_TYPE_APPEND;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen sync_rec->uid1 = ctx->append_uid_first;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen sync_rec->uid2 = ctx->append_uid_last;
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen return TRUE;
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen }
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen return FALSE;
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen }
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen ctx->next_uid = next_found_uid;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen i = next_i;
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen uid_range = array_idx(sync_list[i].array, sync_list[i].idx);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen if (sync_list[i].array == (void *)&sync_trans->expunges) {
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen mail_index_sync_get_expunge(sync_rec,
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen (const struct mail_transaction_expunge *)uid_range);
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen } else if (sync_list[i].array == (void *)&sync_trans->updates) {
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen mail_index_sync_get_update(sync_rec,
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen (const struct mail_transaction_flag_update *)uid_range);
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen } else if (sync_list[i].array == (void *)&sync_trans->keyword_resets) {
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen mail_index_sync_get_keyword_reset(sync_rec, uid_range);
9566c1b4506d49778659e3dc65997f3c0399cb7eTimo Sirainen } else {
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen mail_index_sync_get_keyword_update(sync_rec, uid_range,
9566c1b4506d49778659e3dc65997f3c0399cb7eTimo Sirainen &sync_list[i]);
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen }
9566c1b4506d49778659e3dc65997f3c0399cb7eTimo Sirainen sync_list[i].idx++;
9566c1b4506d49778659e3dc65997f3c0399cb7eTimo Sirainen return TRUE;
9566c1b4506d49778659e3dc65997f3c0399cb7eTimo Sirainen}
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainenbool mail_index_sync_have_more(struct mail_index_sync_ctx *ctx)
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct mail_index_sync_list *sync_list;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int i, count;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ctx->sync_appends)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen sync_list = array_get(&ctx->sync_list, &count);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (i = 0; i < count; i++) {
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen if (array_is_created(sync_list[i].array) &&
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen sync_list[i].idx != array_count(sync_list[i].array))
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return TRUE;
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_index_sync_reset(struct mail_index_sync_ctx *ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
6f73af3a3a6ee900c7e736874587968d76a20bc0Timo Sirainen struct mail_index_sync_list *sync_list;
6f73af3a3a6ee900c7e736874587968d76a20bc0Timo Sirainen unsigned int i, count;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen ctx->next_uid = 0;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen sync_list = array_get_modifiable(&ctx->sync_list, &count);
0f66f12eb4cdbf47670975044c88d8f388bf92dfTimo Sirainen for (i = 0; i < count; i++)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen sync_list[i].idx = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainenstatic void mail_index_sync_end(struct mail_index_sync_ctx **_ctx)
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen{
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen struct mail_index_sync_ctx *ctx = *_ctx;
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen i_assert(ctx->index->syncing);
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen *_ctx = NULL;
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen ctx->index->syncing = FALSE;
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen mail_transaction_log_sync_unlock(ctx->index->log);
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen mail_index_view_close(&ctx->view);
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen mail_index_transaction_rollback(&ctx->sync_trans);
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen if (array_is_created(&ctx->sync_list))
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen array_free(&ctx->sync_list);
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen i_free(ctx);
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen}
static void
mail_index_sync_update_mailbox_offset(struct mail_index_sync_ctx *ctx)
{
uint32_t seq;
uoff_t offset;
mail_transaction_log_view_get_prev_pos(ctx->view->log_view,
&seq, &offset);
mail_transaction_log_set_mailbox_sync_pos(ctx->index->log, seq, offset);
/* If tail offset has changed, make sure it gets written to
transaction log. */
if (ctx->last_tail_offset != offset)
ctx->ext_trans->log_updates = TRUE;
}
static bool mail_index_sync_want_index_write(struct mail_index *index)
{
uint32_t log_diff;
log_diff = index->map->hdr.log_file_tail_offset -
index->last_read_log_file_tail_offset;
if (log_diff > MAIL_INDEX_MAX_WRITE_BYTES ||
(index->index_min_write && log_diff > MAIL_INDEX_MIN_WRITE_BYTES))
return TRUE;
if (index->need_recreate)
return TRUE;
return FALSE;
}
int mail_index_sync_commit(struct mail_index_sync_ctx **_ctx)
{
struct mail_index_sync_ctx *ctx = *_ctx;
struct mail_index *index = ctx->index;
uint32_t seq, next_uid;
uoff_t offset;
bool want_rotate;
int ret = 0;
mail_index_sync_update_mailbox_offset(ctx);
if (mail_cache_need_compress(index->cache)) {
/* if cache compression fails, we don't really care.
the cache offsets are updated only if the compression was
successful. */
(void)mail_cache_compress(index->cache, ctx->ext_trans);
}
if ((ctx->flags & MAIL_INDEX_SYNC_FLAG_DROP_RECENT) != 0) {
next_uid = mail_index_transaction_get_next_uid(ctx->ext_trans);
if (index->map->hdr.first_recent_uid < next_uid) {
mail_index_update_header(ctx->ext_trans,
offsetof(struct mail_index_header,
first_recent_uid),
&next_uid, sizeof(next_uid), FALSE);
}
}
if (mail_index_transaction_commit(&ctx->ext_trans, &seq, &offset) < 0) {
mail_index_sync_end(&ctx);
return -1;
}
/* refresh the mapping with newly committed external transactions
and the synced expunges. sync using file handler here so that the
expunge handlers get called. */
if (mail_index_map(ctx->index, MAIL_INDEX_SYNC_HANDLER_FILE) <= 0)
ret = -1;
want_rotate = mail_transaction_log_want_rotate(index->log);
if (ret == 0 &&
(want_rotate || mail_index_sync_want_index_write(index))) {
index->need_recreate = FALSE;
index->index_min_write = FALSE;
mail_index_write(index, want_rotate);
}
mail_index_sync_end(_ctx);
return ret;
}
void mail_index_sync_rollback(struct mail_index_sync_ctx **ctx)
{
if ((*ctx)->ext_trans != NULL)
mail_index_transaction_rollback(&(*ctx)->ext_trans);
mail_index_sync_end(ctx);
}
void mail_index_sync_flags_apply(const struct mail_index_sync_rec *sync_rec,
uint8_t *flags)
{
i_assert(sync_rec->type == MAIL_INDEX_SYNC_TYPE_FLAGS);
*flags = (*flags & ~sync_rec->remove_flags) | sync_rec->add_flags;
}
bool mail_index_sync_keywords_apply(const struct mail_index_sync_rec *sync_rec,
ARRAY_TYPE(keyword_indexes) *keywords)
{
const unsigned int *keyword_indexes;
unsigned int idx = sync_rec->keyword_idx;
unsigned int i, count;
keyword_indexes = array_get(keywords, &count);
switch (sync_rec->type) {
case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
for (i = 0; i < count; i++) {
if (keyword_indexes[i] == idx)
return FALSE;
}
array_append(keywords, &idx, 1);
return TRUE;
case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
for (i = 0; i < count; i++) {
if (keyword_indexes[i] == idx) {
array_delete(keywords, i, 1);
return TRUE;
}
}
return FALSE;
case MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET:
if (array_count(keywords) == 0)
return FALSE;
array_clear(keywords);
return TRUE;
default:
i_unreached();
return FALSE;
}
}
void mail_index_sync_set_corrupted(struct mail_index_sync_map_ctx *ctx,
const char *fmt, ...)
{
va_list va;
uint32_t seq;
uoff_t offset;
ctx->errors = TRUE;
mail_transaction_log_view_get_prev_pos(ctx->view->log_view,
&seq, &offset);
if (seq < ctx->view->index->fsck_log_head_file_seq ||
(seq == ctx->view->index->fsck_log_head_file_seq &&
offset < ctx->view->index->fsck_log_head_file_offset)) {
/* be silent */
return;
}
va_start(va, fmt);
T_BEGIN {
mail_index_set_error(ctx->view->index,
"Log synchronization error at "
"seq=%u,offset=%"PRIuUOFF_T" for %s: %s",
seq, offset, ctx->view->index->filepath,
t_strdup_vprintf(fmt, va));
} T_END;
va_end(va);
}