mail-index-sync.c revision a24f6b02ed8d0dde933a715be1c86f01977bf610
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "lib.h"
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainen#include "buffer.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "mail-index-view-private.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "mail-index-sync-private.h"
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen#include "mail-transaction-log.h"
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen#include "mail-transaction-util.h"
bfef6891565ff9018ac92add6eae401e9352c657Timo Sirainen
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen#include <stdlib.h>
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainenstatic void mail_index_sync_sort_flags(struct mail_index_sync_ctx *ctx)
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen{
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen const struct mail_transaction_flag_update *src, *src_end;
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen const struct mail_transaction_flag_update *dest;
dff32d11a411a24f3b76003c1ae22c5a960f180eTimo Sirainen struct mail_transaction_flag_update new_update;
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen uint32_t last;
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen size_t i, dest_count;
eb209d12e3b1cfed564c35cf19fdb1bf7fcc6811Timo Sirainen
eb209d12e3b1cfed564c35cf19fdb1bf7fcc6811Timo Sirainen src = ctx->data;
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen src_end = PTR_OFFSET(src, ctx->hdr->size);
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen if (src == src_end)
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen return;
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen
ae32667c54480d329eed994b3defab89cd76c077Timo Sirainen dest = buffer_get_data(ctx->updates_buf, &dest_count);
ae32667c54480d329eed994b3defab89cd76c077Timo Sirainen dest_count /= sizeof(*dest);
bfef6891565ff9018ac92add6eae401e9352c657Timo Sirainen
bfef6891565ff9018ac92add6eae401e9352c657Timo Sirainen for (i = 0; src != src_end; src++) {
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen new_update = *src;
8c2b4a45f17a5cb13bb01058ca37798cf48d91baTimo Sirainen
8c2b4a45f17a5cb13bb01058ca37798cf48d91baTimo Sirainen /* insert it into buffer, split it in multiple parts if needed
8c2b4a45f17a5cb13bb01058ca37798cf48d91baTimo Sirainen to make sure the ordering stays the same */
8c2b4a45f17a5cb13bb01058ca37798cf48d91baTimo Sirainen for (; i < dest_count; i++) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (dest[i].uid1 <= new_update.uid1)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen continue;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
b44033e45e9f48f8a6e1ac5905234fec5de6d6ccAki Tuomi if (dest[i].uid1 > new_update.uid2)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen break;
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen /* partial */
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen last = new_update.uid2;
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen new_update.uid2 = dest[i].uid1-1;
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen buffer_insert(ctx->updates_buf, i * sizeof(new_update),
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen &new_update, sizeof(new_update));
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen dest = buffer_get_data(ctx->updates_buf, NULL);
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen dest_count++;
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen new_update.uid1 = new_update.uid2+1;
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen new_update.uid2 = last;
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen }
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen buffer_insert(ctx->updates_buf, i * sizeof(new_update),
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen &new_update, sizeof(new_update));
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen dest = buffer_get_data(ctx->updates_buf, NULL);
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen dest_count++;
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen }
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen}
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainenstatic void mail_index_sync_sort_transaction(struct mail_index_sync_ctx *ctx)
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen{
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen switch (ctx->hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen case MAIL_TRANSACTION_EXPUNGE:
c13fce16374a6fa8d127742c527498d38e777789Timo Sirainen if (buffer_get_used_size(ctx->expunges_buf) == 0) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen buffer_append(ctx->expunges_buf, ctx->data,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen ctx->hdr->size);
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen } else {
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen mail_transaction_log_sort_expunges(ctx->expunges_buf,
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen ctx->data,
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen ctx->hdr->size);
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen }
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen break;
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen case MAIL_TRANSACTION_FLAG_UPDATE:
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen if (buffer_get_used_size(ctx->expunges_buf) == 0 &&
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen buffer_get_used_size(ctx->updates_buf) == 0) {
b44033e45e9f48f8a6e1ac5905234fec5de6d6ccAki Tuomi buffer_append(ctx->updates_buf, ctx->data,
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen ctx->hdr->size);
b93ec4e5b569e1216d0c7a6f28cbdccfe4fb32caTimo Sirainen } else {
cdc7ca129c3433d3e4b9d5e90f4c209e4546dfe9Timo Sirainen mail_index_sync_sort_flags(ctx);
cdc7ca129c3433d3e4b9d5e90f4c209e4546dfe9Timo Sirainen }
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen break;
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen case MAIL_TRANSACTION_APPEND:
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen buffer_append(ctx->appends_buf, ctx->data, ctx->hdr->size);
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen ctx->sync_appends = TRUE;
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen break;
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen }
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen}
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainenstatic int mail_index_sync_read_and_sort(struct mail_index_sync_ctx *ctx,
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen int external)
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen{
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen enum mail_transaction_type flag;
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen size_t size;
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen int ret;
1b7cd57585d8c2f133dd612d2d5d9c775595659fTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen flag = external ? MAIL_TRANSACTION_EXTERNAL : 0;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen while ((ret = mail_transaction_log_view_next(ctx->view->log_view,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen &ctx->hdr,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen &ctx->data, NULL)) > 0) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if ((ctx->hdr->type & MAIL_TRANSACTION_EXTERNAL) == flag)
009217abb57a24a4076092e8e4e165545747839eStephan Bosch mail_index_sync_sort_transaction(ctx);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
009217abb57a24a4076092e8e4e165545747839eStephan Bosch
00e7c3010f7da4a49881a7feb05e413af353af0aTimo Sirainen ctx->expunges = buffer_get_data(ctx->expunges_buf, &size);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen ctx->expunges_count = size / sizeof(*ctx->expunges);
5f5713d6468dca1acf3d350dd8a33057331f78c5Timo Sirainen ctx->updates = buffer_get_data(ctx->updates_buf, &size);
5f5713d6468dca1acf3d350dd8a33057331f78c5Timo Sirainen ctx->updates_count = size / sizeof(*ctx->updates);
5f5713d6468dca1acf3d350dd8a33057331f78c5Timo Sirainen
5f5713d6468dca1acf3d350dd8a33057331f78c5Timo Sirainen return ret;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainenstatic int mail_index_need_lock(struct mail_index *index,
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen uint32_t log_file_seq, uoff_t log_file_offset)
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen{
3ee8a7ee6912c7caa4e83d3ce5a5db1590a7ffcdTimo Sirainen if (index->hdr->log_file_seq > log_file_seq ||
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen (index->hdr->log_file_seq == log_file_seq &&
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen index->hdr->log_file_offset >= log_file_offset)) {
cf9d67e4a9bfee31cf3be05244555d51a3d1b9feTimo Sirainen /* already synced */
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen return 0;
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen }
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen
d3bae1f9d2448e5c398145ea250849ec12583845Timo Sirainen return 1;
d3bae1f9d2448e5c398145ea250849ec12583845Timo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenint mail_index_sync_begin(struct mail_index *index,
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen struct mail_index_sync_ctx **ctx_r,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct mail_index_view **view_r,
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen uint32_t log_file_seq, uoff_t log_file_offset)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct mail_index_sync_ctx *ctx;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen uint32_t seq;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen uoff_t offset;
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen unsigned int lock_id;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (mail_transaction_log_sync_lock(index->log, &seq, &offset) < 0)
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen return -1;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
58b8a301b7b36047f10a592751094fbed86d6f0cTimo Sirainen if (mail_index_lock_shared(index, TRUE, &lock_id) < 0) {
58b8a301b7b36047f10a592751094fbed86d6f0cTimo Sirainen mail_transaction_log_sync_unlock(index->log);
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen return -1;
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen }
152db3f90f298b7fb2dbbd4276f0fc30a9bc30f6Timo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (mail_index_map(index, FALSE) <= 0) {
89d6cd658eabf46e07e40037b0e641ed9be1a2a3Timo Sirainen mail_transaction_log_sync_unlock(index->log);
89d6cd658eabf46e07e40037b0e641ed9be1a2a3Timo Sirainen mail_index_unlock(index, lock_id);
ece0a20249ce26208db3415ba2e79423678856f8Timo Sirainen return -1;
ece0a20249ce26208db3415ba2e79423678856f8Timo Sirainen }
ece0a20249ce26208db3415ba2e79423678856f8Timo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (!mail_index_need_lock(index, log_file_seq, log_file_offset)) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen mail_index_unlock(index, lock_id);
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen mail_transaction_log_sync_unlock(index->log);
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen return 0;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen }
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen ctx = i_new(struct mail_index_sync_ctx, 1);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen ctx->index = index;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen ctx->lock_id = lock_id;
1df39b899804fd1dbc560f75382364822935c857Timo Sirainen
1df39b899804fd1dbc560f75382364822935c857Timo Sirainen ctx->view = mail_index_view_open(index);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen ctx->view->external = TRUE;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (mail_transaction_log_view_set(ctx->view->log_view,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen index->hdr->log_file_seq,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen index->hdr->log_file_offset,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen seq, offset,
009217abb57a24a4076092e8e4e165545747839eStephan Bosch MAIL_TRANSACTION_TYPE_MASK) < 0) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen mail_index_sync_end(ctx);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return -1;
c4900d31385344bfadaee53a897daeafdb3063d8Timo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* we need to have all the transactions sorted to optimize
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen caller's mailbox access patterns */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen ctx->expunges_buf = buffer_create_dynamic(default_pool,
4aab01f4eade3d278b61471516c062ce30a84b5fTimo Sirainen 1024, (size_t)-1);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen ctx->updates_buf = buffer_create_dynamic(default_pool,
152db3f90f298b7fb2dbbd4276f0fc30a9bc30f6Timo Sirainen 1024, (size_t)-1);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen ctx->appends_buf = buffer_create_dynamic(default_pool,
aa797403d51ff047727b77d64532001d6b6cc21aTimo Sirainen 1024, (size_t)-1);
468c28dfb03613ab8d487b5aebc985a969193aceTimo Sirainen if (mail_index_sync_read_and_sort(ctx, FALSE) < 0) {
abe29107f5dce932d28a00912d2d75a01021bef1Timo Sirainen mail_index_sync_end(ctx);
433f5c9cc560a8cbff47257513d0bacb1cf250f4Timo Sirainen return -1;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen
027f58ea63a1822bbf13d99ee5572e5f8b9e8d8bTimo Sirainen *ctx_r = ctx;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen *view_r = ctx->view;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen return 1;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainenvoid
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainenmail_index_sync_get_expunge(struct mail_index_sync_rec *rec,
abe29107f5dce932d28a00912d2d75a01021bef1Timo Sirainen const struct mail_transaction_expunge *exp)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen rec->type = MAIL_INDEX_SYNC_TYPE_EXPUNGE;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen rec->uid1 = exp->uid1;
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen rec->uid2 = exp->uid2;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen}
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenvoid
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenmail_index_sync_get_update(struct mail_index_sync_rec *rec,
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen const struct mail_transaction_flag_update *update)
ab779efe68458cf6fdcaa4f99527685d5563df0aTimo Sirainen{
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen rec->type = MAIL_INDEX_SYNC_TYPE_FLAGS;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen rec->uid1 = update->uid1;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen rec->uid2 = update->uid2;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen rec->add_flags = update->add_flags;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen memcpy(rec->add_keywords, update->add_keywords,
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen sizeof(rec->add_keywords));
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen rec->remove_flags = update->remove_flags;
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen memcpy(rec->remove_keywords, update->remove_keywords,
bfef6891565ff9018ac92add6eae401e9352c657Timo Sirainen sizeof(rec->remove_keywords));
bfef6891565ff9018ac92add6eae401e9352c657Timo Sirainen}
bfef6891565ff9018ac92add6eae401e9352c657Timo Sirainen
bfef6891565ff9018ac92add6eae401e9352c657Timo Sirainenstatic int mail_index_sync_rec_check(struct mail_index_view *view,
36e091dc733c6cd690c5aae6e411e41adb1eca73Timo Sirainen struct mail_index_sync_rec *rec)
36e091dc733c6cd690c5aae6e411e41adb1eca73Timo Sirainen{
36e091dc733c6cd690c5aae6e411e41adb1eca73Timo Sirainen switch (rec->type) {
36e091dc733c6cd690c5aae6e411e41adb1eca73Timo Sirainen case MAIL_INDEX_SYNC_TYPE_EXPUNGE:
36e091dc733c6cd690c5aae6e411e41adb1eca73Timo Sirainen case MAIL_INDEX_SYNC_TYPE_FLAGS:
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen if (rec->uid1 > rec->uid2 || rec->uid1 == 0) {
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen mail_transaction_log_view_set_corrupted(view->log_view,
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen "Broken UID range: %u..%u (type 0x%x)",
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen rec->uid1, rec->uid2, rec->type);
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen return FALSE;
b6b9c99fefbbc662bd9a0006566133c4480bf0e8Timo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen break;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen case MAIL_INDEX_SYNC_TYPE_APPEND:
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen break;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return TRUE;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainenint mail_index_sync_next(struct mail_index_sync_ctx *ctx,
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen struct mail_index_sync_rec *sync_rec)
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen{
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen const struct mail_transaction_expunge *next_exp;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen const struct mail_transaction_flag_update *next_update;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen next_exp = ctx->expunge_idx == ctx->expunges_count ? NULL :
de92873c366becfaea1554642f89b9169d7955e2Timo Sirainen &ctx->expunges[ctx->expunge_idx];
de92873c366becfaea1554642f89b9169d7955e2Timo Sirainen next_update = ctx->update_idx == ctx->updates_count ? NULL :
de92873c366becfaea1554642f89b9169d7955e2Timo Sirainen &ctx->updates[ctx->update_idx];
de92873c366becfaea1554642f89b9169d7955e2Timo Sirainen
c3a2a487e23a282e59254b82deb9344ed0306bb2Timo Sirainen // FIXME: return dirty flagged records as flag updates
c3a2a487e23a282e59254b82deb9344ed0306bb2Timo Sirainen
c3a2a487e23a282e59254b82deb9344ed0306bb2Timo Sirainen /* the ugliness here is to avoid returning overlapping expunge
1df39b899804fd1dbc560f75382364822935c857Timo Sirainen and update areas. For example:
1df39b899804fd1dbc560f75382364822935c857Timo Sirainen
1f7f4294207557edf83171642ef62ce4922ffc9dTimo Sirainen updates[] = A { 1, 7 }, B { 1, 3 }
1f7f4294207557edf83171642ef62ce4922ffc9dTimo Sirainen expunges[] = { 5, 6 }
1f7f4294207557edf83171642ef62ce4922ffc9dTimo Sirainen
1f7f4294207557edf83171642ef62ce4922ffc9dTimo Sirainen will make us return
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
update A: 1, 4
update B: 1, 3
expunge : 5, 6
update A: 7, 7
*/
while (next_update != NULL &&
(next_exp == NULL || next_update->uid1 < next_exp->uid1)) {
if (next_update->uid2 >= ctx->next_uid) {
mail_index_sync_get_update(sync_rec, next_update);
if (next_exp != NULL &&
next_exp->uid1 <= next_update->uid2) {
/* it's overlapping.. */
sync_rec->uid2 = next_exp->uid1-1;
}
if (sync_rec->uid1 < ctx->next_uid)
sync_rec->uid1 = ctx->next_uid;
i_assert(sync_rec->uid1 <= sync_rec->uid2);
ctx->update_idx++;
return mail_index_sync_rec_check(ctx->view, sync_rec);
}
if (++ctx->update_idx == ctx->updates_count)
break;
next_update++;
}
if (next_exp != NULL) {
mail_index_sync_get_expunge(sync_rec, next_exp);
if (mail_index_sync_rec_check(ctx->view, sync_rec) < 0)
return -1;
ctx->expunge_idx++;
/* scan updates again from the beginning */
ctx->update_idx = 0;
ctx->next_uid = next_exp->uid2+1;
return 1;
}
if (ctx->sync_appends) {
ctx->sync_appends = FALSE;
sync_rec->type = MAIL_INDEX_SYNC_TYPE_APPEND;
sync_rec->appends = buffer_get_data(ctx->appends_buf,
&sync_rec->appends_count);
sync_rec->appends_count /= sizeof(*sync_rec->appends);
sync_rec->uid1 = sync_rec->uid2 = 0;
return 1;
}
return 0;
}
int mail_index_sync_have_more(struct mail_index_sync_ctx *ctx)
{
return (ctx->update_idx != ctx->updates_count) ||
(ctx->expunge_idx != ctx->expunges_count) ||
ctx->sync_appends;
}
int mail_index_sync_end(struct mail_index_sync_ctx *ctx)
{
const struct mail_index_header *hdr;
uint32_t seq;
uoff_t offset;
int ret = 0;
if (mail_transaction_log_view_is_corrupted(ctx->view->log_view))
ret = -1;
mail_transaction_log_get_head(ctx->index->log, &seq, &offset);
if (ret == 0) {
hdr = ctx->index->hdr;
if (mail_transaction_log_view_set(ctx->view->log_view,
hdr->log_file_seq, hdr->log_file_offset,
seq, offset, MAIL_TRANSACTION_TYPE_MASK) < 0)
ret = -1;
}
if (ret == 0) {
mail_index_sync_read_and_sort(ctx, TRUE);
if (mail_transaction_log_view_set(ctx->view->log_view,
hdr->log_file_seq, hdr->log_file_offset,
seq, offset, MAIL_TRANSACTION_TYPE_MASK) < 0)
ret = -1;
if (mail_index_sync_update_index(ctx) < 0)
ret = -1;
}
mail_index_unlock(ctx->index, ctx->lock_id);
mail_transaction_log_sync_unlock(ctx->index->log);
mail_index_view_close(ctx->view);
if (ctx->expunges_buf != NULL)
buffer_free(ctx->expunges_buf);
if (ctx->updates_buf != NULL)
buffer_free(ctx->updates_buf);
if (ctx->appends_buf != NULL)
buffer_free(ctx->appends_buf);
i_free(ctx);
return ret;
}
void mail_index_sync_flags_apply(const struct mail_index_sync_rec *sync_rec,
uint8_t *flags, keywords_mask_t keywords)
{
int i;
i_assert(sync_rec->type == MAIL_INDEX_SYNC_TYPE_FLAGS);
*flags = (*flags & ~sync_rec->remove_flags) | sync_rec->add_flags;
for (i = 0; i < INDEX_KEYWORDS_BYTE_COUNT; i++) {
keywords[i] = (keywords[i] & ~sync_rec->remove_keywords[i]) |
sync_rec->add_keywords[i];
}
}