mail-index-sync-update.c revision 76b43e4417bab52e913da39b5f5bc2a130d3f149
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (c) 2004-2008 Dovecot authors, see the included COPYING file */
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen/* If we have less than this many bytes to sync from log file, don't bother
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen reading the main index */
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen#define MAIL_INDEX_SYNC_MIN_READ_INDEX_SIZE 2048
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainenmail_index_sync_update_log_offset(struct mail_index_sync_map_ctx *ctx,
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen mail_transaction_log_view_get_prev_pos(ctx->view->log_view,
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen if (prev_offset == ctx->ext_intro_end_offset &&
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen /* previous transaction was an extension introduction.
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen we probably came here from
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen mail_index_sync_ext_reset(). if there are any more
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen views which want to continue syncing it needs the
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen intro. so back up a bit more.
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen don't do this in case the last transaction in the
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen log is the extension intro, so we don't keep trying
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen to sync it over and over again. */
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen i_assert(ctx->view->index->log->head->hdr.file_seq == prev_seq);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic void mail_index_sync_replace_map(struct mail_index_sync_map_ctx *ctx,
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen mail_index_sync_update_log_offset(ctx, view->map, FALSE);
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen if (ctx->type != MAIL_INDEX_SYNC_HANDLER_VIEW)
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainenmail_index_sync_move_to_private_memory(struct mail_index_sync_map_ctx *ctx)
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen if (!MAIL_INDEX_MAP_IS_IN_MEMORY(ctx->view->map))
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen mail_index_map_move_to_memory(ctx->view->map);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenmail_index_sync_get_atomic_map(struct mail_index_sync_map_ctx *ctx)
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen mail_index_record_map_move_to_private(ctx->view->map);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainenmail_index_header_update_counts(struct mail_index_header *hdr,
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen const char **error_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (((old_flags ^ new_flags) & MAIL_SEEN) != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* different seen-flag */
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen if (hdr->seen_messages_count >= hdr->messages_count) {
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen if (++hdr->seen_messages_count == hdr->messages_count)
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen hdr->first_unseen_uid_lowwater = hdr->next_uid;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (((old_flags ^ new_flags) & MAIL_DELETED) != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* different deleted-flag */
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen if (hdr->deleted_messages_count > hdr->messages_count) {
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen hdr->deleted_messages_count > hdr->messages_count) {
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen hdr->first_deleted_uid_lowwater = hdr->next_uid;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainenmail_index_sync_header_update_counts_all(struct mail_index_sync_map_ctx *ctx,
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen unsigned int i, count;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen maps = array_get(&ctx->view->map->rec_map->maps, &count);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen for (i = 0; i < count; i++) {
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if (mail_index_header_update_counts(&maps[i]->hdr,
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen mail_index_sync_set_corrupted(ctx, "%s", error);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenmail_index_sync_header_update_counts(struct mail_index_sync_map_ctx *ctx,
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen mail_index_sync_header_update_counts_all(ctx, uid, old_flags,
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if (mail_index_header_update_counts(&ctx->view->map->hdr,
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen mail_index_sync_set_corrupted(ctx, "%s", error);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainenmail_index_header_update_lowwaters(struct mail_index_sync_map_ctx *ctx,
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen unsigned int i, count;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen maps = array_get(&ctx->view->map->rec_map->maps, &count);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen for (i = 0; i < count; i++) {
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen uid < maps[i]->hdr.first_deleted_uid_lowwater)
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen maps[i]->hdr.first_deleted_uid_lowwater = uid;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainensync_expunge_call_handlers(struct mail_index_sync_map_ctx *ctx,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen unsigned int i, count;
9315dd69233d554452df0c12bc57002d2042a8f4Timo Sirainen /* call expunge handlers only when syncing index file */
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (ctx->type != MAIL_INDEX_SYNC_HANDLER_FILE)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (!array_is_created(&ctx->expunge_handlers))
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen eh = array_get(&ctx->expunge_handlers, &count);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen rec = MAIL_INDEX_MAP_IDX(ctx->view->map, seq1-1);
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen /* FIXME: does expunge handler's return value matter?
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen we probably shouldn't disallow expunges if the
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen handler returns failure.. should it be just changed
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen to return void? */
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainensync_expunge(const struct mail_transaction_expunge *e, unsigned int count,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen unsigned int i;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen for (i = 0; i < count; i++, e++) {
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen if (!mail_index_lookup_seq_range(ctx->view, e->uid1, e->uid2,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* everything expunged already */
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen mail_index_sync_header_update_counts(ctx, rec->uid,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* @UNSAFE */
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenvoid mail_index_sync_write_seq_update(struct mail_index_sync_map_ctx *ctx,
cd5ee8630497fdbd853ef588a858b4ef619a5e03Timo Sirainenstatic int sync_append(const struct mail_index_record *rec,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen "Append with UID %u, but next_uid = %u",
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* move to memory. the mapping is written when unlocking so we don't
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen waste time re-mmap()ing multiple times or waste space growing index
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen file too large */
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen if (rec->uid <= map->rec_map->last_appended_uid) {
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen i_assert(map->hdr.messages_count < map->rec_map->records_count);
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen /* the flags may have changed since it was added to map.
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen use the updated flags already, so flag counters won't get
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen MAIL_INDEX_MAP_IDX(map, map->hdr.messages_count)->flags;
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen /* don't rely on buffer->used being at the correct position.
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen at least expunges can move it */
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen append_pos = map->rec_map->records_count * map->hdr.record_size;
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen dest = buffer_get_space_unsafe(map->rec_map->buffer, append_pos,
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen buffer_get_modifiable_data(map->rec_map->buffer, NULL);
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen if ((new_flags & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0)
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen map->hdr.flags |= MAIL_INDEX_HDR_FLAG_HAVE_DIRTY;
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen mail_index_header_update_lowwaters(ctx, rec->uid, new_flags);
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen mail_index_sync_header_update_counts(ctx, rec->uid,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenstatic int sync_flag_update(const struct mail_transaction_flag_update *u,
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen if (!mail_index_lookup_seq_range(view, u->uid1, u->uid2, &seq1, &seq2))
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen mail_index_sync_write_seq_update(ctx, seq1, seq2);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if ((u->add_flags & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen view->map->hdr.flags |= MAIL_INDEX_HDR_FLAG_HAVE_DIRTY;
51920d00fa50edf7b2e9b1019288d64b7abee7f3Timo Sirainen /* we're not modifying any counted/lowwatered flags */
21ec6628c567eeff025af35d8027be01044b0b1aTimo Sirainen rec->flags = (rec->flags & flag_mask) | u->add_flags;
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen rec->flags = (rec->flags & flag_mask) | u->add_flags;
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen mail_index_header_update_lowwaters(ctx, rec->uid,
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen mail_index_sync_header_update_counts(ctx, rec->uid,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenstatic int sync_header_update(const struct mail_transaction_header_update *u,
5a7b52012bf77132bb8f466d07e0e88c63fdba42Timo Sirainen uint32_t orig_log_file_tail_offset = map->hdr.log_file_tail_offset;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen u->offset + u->size > map->hdr.base_header_size) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen "Header update outside range: %u + %u > %u",
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen u->offset, u->size, map->hdr.base_header_size);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen buffer_write(map->hdr_copy_buf, u->offset, u + 1, u->size);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen /* @UNSAFE */
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen if ((uint32_t)(u->offset + u->size) <= sizeof(map->hdr)) {
5a7b52012bf77132bb8f466d07e0e88c63fdba42Timo Sirainen /* the tail offset updates are intended for internal transaction
5a7b52012bf77132bb8f466d07e0e88c63fdba42Timo Sirainen log handling. we'll update the offset in the header only when
5a7b52012bf77132bb8f466d07e0e88c63fdba42Timo Sirainen the sync is finished. */
5a7b52012bf77132bb8f466d07e0e88c63fdba42Timo Sirainen map->hdr.log_file_tail_offset = orig_log_file_tail_offset;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainenint mail_index_sync_record(struct mail_index_sync_map_ctx *ctx,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen case MAIL_TRANSACTION_EXPUNGE|MAIL_TRANSACTION_EXPUNGE_PROT: {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen const struct mail_transaction_expunge *rec = data, *end;
e063aca6bc2f08bec516d4b631052ea9191f011dTimo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXTERNAL) == 0) {
e063aca6bc2f08bec516d4b631052ea9191f011dTimo Sirainen /* this is simply a request for expunge */
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen const struct mail_transaction_flag_update *rec, *end;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen const struct mail_transaction_header_update *rec;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen unsigned int i;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if ((i % 4) != 0)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen const struct mail_transaction_ext_intro *rec = data;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen unsigned int i;
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen mail_transaction_log_view_get_prev_pos(ctx->view->log_view,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen /* should be just extra padding */
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen if (i + sizeof(*rec) + rec->name_size > hdr->size) {
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen "ext intro: name_size too large");
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if ((i % 4) != 0)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen const struct mail_transaction_ext_reset *rec = data;
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen "ext reset: invalid record size");
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen const struct mail_transaction_ext_hdr_update *rec = data;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen unsigned int i;
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen "ext hdr update: invalid record size");
a0d34d3982507f513a9d800082481e9faeb9a943Timo Sirainen ret = mail_index_sync_ext_hdr_update(ctx, rec);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if ((i % 4) != 0)
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen const struct mail_transaction_ext_rec_update *rec;
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen unsigned int i, record_size;
86d52f310fe939090c66b780a3b6ffe5d10dc8faTimo Sirainen "Extension record updated "
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen "without intro prefix");
2d79e603e20a32bdae4c2b516ead5c5c9169545aTimo Sirainen /* the record is padded to 32bits in the transaction log */
2d79e603e20a32bdae4c2b516ead5c5c9169545aTimo Sirainen record_size = (sizeof(*rec) + ext->record_size + 3) & ~3;
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen for (i = 0; i < hdr->size; i += record_size) {
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen "ext rec update: invalid record size");
a0d34d3982507f513a9d800082481e9faeb9a943Timo Sirainen ret = mail_index_sync_ext_rec_update(ctx, rec);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen const struct mail_transaction_keyword_update *rec = data;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen ret = mail_index_sync_keywords(ctx, hdr, rec);
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen const struct mail_transaction_keyword_reset *rec = data;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen ret = mail_index_sync_keywords_reset(ctx, hdr, rec);
20261d71760e4199cb8d906ab9704a4561d954d7Timo Sirainen "Unknown transaction record type 0x%x",
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenvoid mail_index_sync_map_init(struct mail_index_sync_map_ctx *sync_map_ctx,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen memset(sync_map_ctx, 0, sizeof(*sync_map_ctx));
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainenvoid mail_index_sync_map_deinit(struct mail_index_sync_map_ctx *sync_map_ctx)
0f66f12eb4cdbf47670975044c88d8f388bf92dfTimo Sirainen buffer_free(&sync_map_ctx->unknown_extensions);
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen mail_index_sync_deinit_expunge_handlers(sync_map_ctx);
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen mail_index_sync_deinit_handlers(sync_map_ctx);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic void mail_index_sync_update_hdr_dirty_flag(struct mail_index_map *map)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen unsigned int i;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if ((map->hdr.flags & MAIL_INDEX_HDR_FLAG_HAVE_DIRTY) != 0)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* do we have dirty flags anymore? */
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen for (i = 0; i < map->rec_map->records_count; i++) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if ((rec->flags & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen map->hdr.flags |= MAIL_INDEX_HDR_FLAG_HAVE_DIRTY;
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainenvoid mail_index_map_check(struct mail_index_map *map)
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen const struct mail_index_header *hdr = &map->hdr;
d12f05c7c391786d0d9795ec3aa4377280bbfaeaTimo Sirainen i_assert(hdr->messages_count <= map->rec_map->records_count);
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen i_assert(rec->uid >= hdr->first_deleted_uid_lowwater);
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen i_assert(rec->uid >= hdr->first_unseen_uid_lowwater);
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainenint mail_index_sync_map(struct mail_index_map **_map,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen enum mail_index_sync_handler_type type, bool force)
5c7aa03f959b8b9cab3eba8a585a90f4b50a4cdfTimo Sirainen i_assert(index->map == map || type == MAIL_INDEX_SYNC_HANDLER_VIEW);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* see if we'd prefer to reopen the index file instead of
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen syncing the current map from the transaction log */
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen /* we don't know the index's size, so use the
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen smallest index size we're willing to read */
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen index_size = MAIL_INDEX_SYNC_MIN_READ_INDEX_SIZE;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* this isn't necessary correct currently, but it should be
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen close enough */
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen if (log_size > map->hdr.log_file_tail_offset &&
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen log_size - map->hdr.log_file_tail_offset > index_size)
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen start_offset = type == MAIL_INDEX_SYNC_HANDLER_FILE ?
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen map->hdr.log_file_tail_offset : map->hdr.log_file_head_offset;
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainen view = mail_index_view_open_with_map(index, map);
1dec807061d7d428dba5c5a92cd2a5ff843a2039Timo Sirainen ret = mail_transaction_log_view_set(view->log_view,
1dec807061d7d428dba5c5a92cd2a5ff843a2039Timo Sirainen /* the seq/offset is probably broken */
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* can't use it. sync by re-reading index. */
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* view referenced the map. avoid unnecessary map cloning by
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen unreferencing the map while view exists. */
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen had_dirty = (map->hdr.flags & MAIL_INDEX_HDR_FLAG_HAVE_DIRTY) != 0;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen map->hdr.flags &= ~MAIL_INDEX_HDR_FLAG_HAVE_DIRTY;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen if (map->hdr_base != map->hdr_copy_buf->data) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* if syncing updates the header, it updates hdr_copy_buf
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen and updates hdr_base to hdr_copy_buf. so the buffer must
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen initially contain a valid header or we'll break it when
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen writing it. */
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen buffer_append(map->hdr_copy_buf, map->hdr_base,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen mail_index_sync_map_init(&sync_map_ctx, view, type);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen /* Reset the entire index. Leave only indexid and
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen log_file_seq. */
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen mail_transaction_log_view_get_prev_pos(view->log_view,
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen mail_index_sync_replace_map(&sync_map_ctx, map);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* FIXME: when transaction sync lock is removed, we'll need to handle
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen the case when a transaction is committed while mailbox is being
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen synced ([synced transactions][new transaction][ext transaction]).
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen this means int_offset contains [synced] and ext_offset contains
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen while ((ret = mail_transaction_log_view_next(view->log_view, &thdr,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen mail_transaction_log_view_get_prev_pos(view->log_view,
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen /* this has been synced already. we're here only to call
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen expunge handlers and extension update handlers. */
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen i_assert(type == MAIL_INDEX_SYNC_HANDLER_FILE);
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen if ((thdr->type & MAIL_TRANSACTION_EXTERNAL) != 0)
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen if ((thdr->type & MAIL_TRANSACTION_EXT_MASK) == 0)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* we'll just skip over broken entries */
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen mail_index_sync_update_log_offset(&sync_map_ctx, view->map, TRUE);
9ae24544b49e9cbf12bfa888279988a97235e10dTimo Sirainen i_assert(map->hdr.indexid == index->indexid || map->hdr.indexid == 0);
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen /* transaction log tracks internally the current tail offset.
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen besides using header updates, it also updates the offset to skip
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen over following external transactions to avoid extra unneeded log
88b6f36ef1b453c08e8d9cadb229b39fc9bb4a1cTimo Sirainen i_assert(map->hdr.log_file_seq == index->log->head->hdr.file_seq);
88b6f36ef1b453c08e8d9cadb229b39fc9bb4a1cTimo Sirainen if (map->hdr.log_file_tail_offset < index->log->head->max_tail_offset) {
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen buffer_write(map->hdr_copy_buf, 0, &map->hdr, sizeof(map->hdr));
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen memcpy(map->rec_map->mmap_base, map->hdr_copy_buf->data,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* restore refcount before closing the view. this is necessary also
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if map got cloned, because view closing would otherwise destroy it */
5c7aa03f959b8b9cab3eba8a585a90f4b50a4cdfTimo Sirainen i_assert(index->map == map || type == MAIL_INDEX_SYNC_HANDLER_VIEW);
f7656d7bc15510a4259ed74ddda3c560de8a51c1Timo Sirainen "Synchronization corrupted index header: %s",
f31720ad5ece28ca3fa793920f1501165ad9603fTimo Sirainen /* make sure the index looks valid now */