mail-index-sync-update.c revision 2ebfb5c0608e2323b73271208f4036a7ea7d7f3a
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (C) 2004 Timo Sirainen */
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen/* If we have less than this many bytes to sync from log file, don't bother
9cf4bb70f014849735aab4226691edcdf56b3271Timo Sirainen reading the main index */
9cf4bb70f014849735aab4226691edcdf56b3271Timo Sirainen#define MAIL_INDEX_SYNC_MIN_READ_INDEX_SIZE 2048
e09c7dc961cb9cab04ec7cc79215c2f6318fbde0Timo Sirainenmail_index_sync_update_log_offset(struct mail_index_sync_map_ctx *ctx,
e09c7dc961cb9cab04ec7cc79215c2f6318fbde0Timo Sirainen mail_transaction_log_view_get_prev_pos(ctx->view->log_view,
bada94029be451d716948d6e03a4fc329447486aTimo Sirainen if (prev_offset == ctx->ext_intro_end_offset &&
bada94029be451d716948d6e03a4fc329447486aTimo Sirainen /* previous transaction was an extension introduction.
bada94029be451d716948d6e03a4fc329447486aTimo Sirainen we probably came here from
bada94029be451d716948d6e03a4fc329447486aTimo Sirainen mail_index_sync_ext_reset(). if there are any more
bada94029be451d716948d6e03a4fc329447486aTimo Sirainen views which want to continue syncing it needs the
3e1cc04de22e3c564644562897b0a5212bd6ee46Timo Sirainen intro. so back up a bit more.
3e1cc04de22e3c564644562897b0a5212bd6ee46Timo Sirainen don't do this in case the last transaction in the
3e1cc04de22e3c564644562897b0a5212bd6ee46Timo Sirainen log is the extension intro, so we don't keep trying
2a9af9ae38a33b93e10ee01b42f5612b175418baTimo Sirainen to sync it over and over again. */
9cf4bb70f014849735aab4226691edcdf56b3271Timo Sirainen i_assert(ctx->view->index->log->head->hdr.file_seq == prev_seq);
e09c7dc961cb9cab04ec7cc79215c2f6318fbde0Timo Sirainenstatic void mail_index_sync_replace_map(struct mail_index_sync_map_ctx *ctx,
c220c8cd341ee9ba78979397c5d33ccd98b5d19fAki Tuomi mail_index_sync_update_log_offset(ctx, view->map, FALSE);
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen if (ctx->type != MAIL_INDEX_SYNC_HANDLER_VIEW)
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainenmail_index_sync_move_to_private_memory(struct mail_index_sync_map_ctx *ctx)
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen if (!MAIL_INDEX_MAP_IS_IN_MEMORY(ctx->view->map))
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen mail_index_map_move_to_memory(ctx->view->map);
e09c7dc961cb9cab04ec7cc79215c2f6318fbde0Timo Sirainenmail_index_sync_get_atomic_map(struct mail_index_sync_map_ctx *ctx)
e09c7dc961cb9cab04ec7cc79215c2f6318fbde0Timo Sirainen mail_index_record_map_move_to_private(ctx->view->map);
05093f69a5ac540a569c4e675686ed96e61667c6Timo Sirainenmail_index_header_update_counts(struct mail_index_header *hdr,
e09c7dc961cb9cab04ec7cc79215c2f6318fbde0Timo Sirainen const char **error_r)
e09c7dc961cb9cab04ec7cc79215c2f6318fbde0Timo Sirainen if (((old_flags ^ new_flags) & MAIL_SEEN) != 0) {
e09c7dc961cb9cab04ec7cc79215c2f6318fbde0Timo Sirainen /* different seen-flag */
e09c7dc961cb9cab04ec7cc79215c2f6318fbde0Timo Sirainen if (hdr->seen_messages_count >= hdr->messages_count) {
e09c7dc961cb9cab04ec7cc79215c2f6318fbde0Timo Sirainen if (++hdr->seen_messages_count == hdr->messages_count)
e09c7dc961cb9cab04ec7cc79215c2f6318fbde0Timo Sirainen hdr->first_unseen_uid_lowwater = hdr->next_uid;
4ca6f6e2ae7be7c5f04ea5ef176a7c4a47ea3d33Timo Sirainen if (((old_flags ^ new_flags) & MAIL_DELETED) != 0) {
4ca6f6e2ae7be7c5f04ea5ef176a7c4a47ea3d33Timo Sirainen /* different deleted-flag */
4ca6f6e2ae7be7c5f04ea5ef176a7c4a47ea3d33Timo Sirainen if (hdr->deleted_messages_count > hdr->messages_count) {
4ca6f6e2ae7be7c5f04ea5ef176a7c4a47ea3d33Timo Sirainen hdr->deleted_messages_count > hdr->messages_count) {
e09c7dc961cb9cab04ec7cc79215c2f6318fbde0Timo Sirainen hdr->first_deleted_uid_lowwater = hdr->next_uid;
05093f69a5ac540a569c4e675686ed96e61667c6Timo Sirainenmail_index_sync_header_update_counts_all(struct mail_index_sync_map_ctx *ctx,
05093f69a5ac540a569c4e675686ed96e61667c6Timo Sirainen unsigned int i, count;
05093f69a5ac540a569c4e675686ed96e61667c6Timo Sirainen maps = array_get(&ctx->view->map->rec_map->maps, &count);
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen for (i = 0; i < count; i++) {
402e999a878e0cc41a0afb830fea0a93afc75f0dTimo Sirainen if (mail_index_header_update_counts(&maps[i]->hdr,
402e999a878e0cc41a0afb830fea0a93afc75f0dTimo Sirainen mail_index_sync_set_corrupted(ctx, "%s", error);
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainenmail_index_sync_header_update_counts(struct mail_index_sync_map_ctx *ctx,
9cf4bb70f014849735aab4226691edcdf56b3271Timo Sirainen mail_index_sync_header_update_counts_all(ctx, uid, old_flags,
9cf4bb70f014849735aab4226691edcdf56b3271Timo Sirainen if (mail_index_header_update_counts(&ctx->view->map->hdr,
b8b085f7bc6f1c0367802a9f00062bbbd981690dTimo Sirainen mail_index_sync_set_corrupted(ctx, "%s", error);
b1e46e840dae172f61140dc260eede4f124ebb31Timo Sirainenmail_index_header_update_lowwaters(struct mail_index_sync_map_ctx *ctx,
9cf4bb70f014849735aab4226691edcdf56b3271Timo Sirainen unsigned int i, count;
b8b085f7bc6f1c0367802a9f00062bbbd981690dTimo Sirainen maps = array_get(&ctx->view->map->rec_map->maps, &count);
9cf4bb70f014849735aab4226691edcdf56b3271Timo Sirainen for (i = 0; i < count; i++) {
b8b085f7bc6f1c0367802a9f00062bbbd981690dTimo Sirainen uid < maps[i]->hdr.first_deleted_uid_lowwater)
b8b085f7bc6f1c0367802a9f00062bbbd981690dTimo Sirainen maps[i]->hdr.first_deleted_uid_lowwater = uid;
b8b085f7bc6f1c0367802a9f00062bbbd981690dTimo Sirainensync_expunge_call_handlers(struct mail_index_sync_map_ctx *ctx,
23878bd03d1de531e3261a25598beec621351910Timo Sirainen unsigned int i, count;
57434d8add2f13b6d6dbd39b941e9e80c64be74eTimo Sirainen /* call expunge handlers only when syncing index file */
57434d8add2f13b6d6dbd39b941e9e80c64be74eTimo Sirainen if (ctx->type != MAIL_INDEX_SYNC_HANDLER_FILE)
57434d8add2f13b6d6dbd39b941e9e80c64be74eTimo Sirainen if (!array_is_created(&ctx->expunge_handlers))
23878bd03d1de531e3261a25598beec621351910Timo Sirainen eh = array_get(&ctx->expunge_handlers, &count);
1db62753d9e3b5d71018889c8ef0a3722a307455Timo Sirainen rec = MAIL_INDEX_MAP_IDX(ctx->view->map, seq1-1);
9cf4bb70f014849735aab4226691edcdf56b3271Timo Sirainensync_expunge(const struct mail_transaction_expunge *e, unsigned int count,
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen unsigned int i;
9cf4bb70f014849735aab4226691edcdf56b3271Timo Sirainen for (i = 0; i < count; i++, e++) {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen mail_index_lookup_uid_range(ctx->view, e->uid1, e->uid2,
9cf4bb70f014849735aab4226691edcdf56b3271Timo Sirainen /* everything expunged already */
9cf4bb70f014849735aab4226691edcdf56b3271Timo Sirainen mail_index_sync_header_update_counts(ctx, rec->uid,
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi if (sync_expunge_call_handlers(ctx, seq1, seq2) < 0)
9cf4bb70f014849735aab4226691edcdf56b3271Timo Sirainen /* @UNSAFE */
9cf4bb70f014849735aab4226691edcdf56b3271Timo Sirainenvoid mail_index_sync_write_seq_update(struct mail_index_sync_map_ctx *ctx,
9cf4bb70f014849735aab4226691edcdf56b3271Timo Sirainenstatic int sync_append(const struct mail_index_record *rec,
bada94029be451d716948d6e03a4fc329447486aTimo Sirainen "Append with UID %u, but next_uid = %u",
2df92c5bbd42ff42a1a38d688a6b11f1d326cb78Timo Sirainen /* move to memory. the mapping is written when unlocking so we don't
2df92c5bbd42ff42a1a38d688a6b11f1d326cb78Timo Sirainen waste time re-mmap()ing multiple times or waste space growing index
2df92c5bbd42ff42a1a38d688a6b11f1d326cb78Timo Sirainen file too large */
bada94029be451d716948d6e03a4fc329447486aTimo Sirainen if (rec->uid <= map->rec_map->last_appended_uid) {
bada94029be451d716948d6e03a4fc329447486aTimo Sirainen i_assert(map->hdr.messages_count < map->rec_map->records_count);
bada94029be451d716948d6e03a4fc329447486aTimo Sirainen /* the flags may have changed since it was added to map.
23878bd03d1de531e3261a25598beec621351910Timo Sirainen use the updated flags already, so flag counters won't get
23878bd03d1de531e3261a25598beec621351910Timo Sirainen MAIL_INDEX_MAP_IDX(map, map->hdr.messages_count)->flags;
1db62753d9e3b5d71018889c8ef0a3722a307455Timo Sirainen /* don't rely on buffer->used being at the correct position.
1db62753d9e3b5d71018889c8ef0a3722a307455Timo Sirainen at least expunges can move it */
bada94029be451d716948d6e03a4fc329447486aTimo Sirainen append_pos = map->rec_map->records_count * map->hdr.record_size;
2df92c5bbd42ff42a1a38d688a6b11f1d326cb78Timo Sirainen dest = buffer_get_space_unsafe(map->rec_map->buffer, append_pos,
9cf4bb70f014849735aab4226691edcdf56b3271Timo Sirainen buffer_get_modifiable_data(map->rec_map->buffer, NULL);
28c669e01da03d36cef8f64a0eddc000c47befd8Timo Sirainen if ((new_flags & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0)
28c669e01da03d36cef8f64a0eddc000c47befd8Timo Sirainen map->hdr.flags |= MAIL_INDEX_HDR_FLAG_HAVE_DIRTY;
3e1cc04de22e3c564644562897b0a5212bd6ee46Timo Sirainen mail_index_header_update_lowwaters(ctx, rec->uid, new_flags);
3e1cc04de22e3c564644562897b0a5212bd6ee46Timo Sirainen mail_index_sync_header_update_counts(ctx, rec->uid,
3e1cc04de22e3c564644562897b0a5212bd6ee46Timo Sirainenstatic int sync_flag_update(const struct mail_transaction_flag_update *u,
9cf4bb70f014849735aab4226691edcdf56b3271Timo Sirainen mail_index_lookup_uid_range(view, u->uid1, u->uid2, &seq1, &seq2);
3e1cc04de22e3c564644562897b0a5212bd6ee46Timo Sirainen mail_index_sync_write_seq_update(ctx, seq1, seq2);
2a9af9ae38a33b93e10ee01b42f5612b175418baTimo Sirainen if ((u->add_flags & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0)
3e1cc04de22e3c564644562897b0a5212bd6ee46Timo Sirainen view->map->hdr.flags |= MAIL_INDEX_HDR_FLAG_HAVE_DIRTY;
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen /* we're not modifying any counted/lowwatered flags */
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen rec->flags = (rec->flags & flag_mask) | u->add_flags;
3e1cc04de22e3c564644562897b0a5212bd6ee46Timo Sirainen rec->flags = (rec->flags & flag_mask) | u->add_flags;
3e1cc04de22e3c564644562897b0a5212bd6ee46Timo Sirainen mail_index_header_update_lowwaters(ctx, rec->uid,
9cf4bb70f014849735aab4226691edcdf56b3271Timo Sirainen mail_index_sync_header_update_counts(ctx, rec->uid,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenstatic int sync_header_update(const struct mail_transaction_header_update *u,
9cf4bb70f014849735aab4226691edcdf56b3271Timo Sirainen uint32_t orig_log_file_tail_offset = map->hdr.log_file_tail_offset;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen u->offset + u->size > map->hdr.base_header_size) {
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen "Header update outside range: %u + %u > %u",
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen u->offset, u->size, map->hdr.base_header_size);
9cf4bb70f014849735aab4226691edcdf56b3271Timo Sirainen buffer_write(map->hdr_copy_buf, u->offset, u + 1, u->size);
23878bd03d1de531e3261a25598beec621351910Timo Sirainen /* @UNSAFE */
23878bd03d1de531e3261a25598beec621351910Timo Sirainen if ((uint32_t)(u->offset + u->size) <= sizeof(map->hdr)) {
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen /* the tail offset updates are intended for internal transaction
9cf4bb70f014849735aab4226691edcdf56b3271Timo Sirainen log handling. we'll update the offset in the header only when
9cf4bb70f014849735aab4226691edcdf56b3271Timo Sirainen the sync is finished. */
e09c7dc961cb9cab04ec7cc79215c2f6318fbde0Timo Sirainen map->hdr.log_file_tail_offset = orig_log_file_tail_offset;
23878bd03d1de531e3261a25598beec621351910Timo Sirainenint mail_index_sync_record(struct mail_index_sync_map_ctx *ctx,
3e1cc04de22e3c564644562897b0a5212bd6ee46Timo Sirainen switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
3e1cc04de22e3c564644562897b0a5212bd6ee46Timo Sirainen case MAIL_TRANSACTION_EXPUNGE|MAIL_TRANSACTION_EXPUNGE_PROT: {
3e1cc04de22e3c564644562897b0a5212bd6ee46Timo Sirainen const struct mail_transaction_expunge *rec = data, *end;
3e1cc04de22e3c564644562897b0a5212bd6ee46Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXTERNAL) == 0) {
3e1cc04de22e3c564644562897b0a5212bd6ee46Timo Sirainen /* this is simply a request for expunge */
1db62753d9e3b5d71018889c8ef0a3722a307455Timo Sirainen const struct mail_transaction_flag_update *rec, *end;
9cf4bb70f014849735aab4226691edcdf56b3271Timo Sirainen const struct mail_transaction_header_update *rec;
9cf4bb70f014849735aab4226691edcdf56b3271Timo Sirainen unsigned int i;
9cf4bb70f014849735aab4226691edcdf56b3271Timo Sirainen if ((i % 4) != 0)
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen const struct mail_transaction_ext_intro *rec = data;
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen unsigned int i;
05093f69a5ac540a569c4e675686ed96e61667c6Timo Sirainen mail_transaction_log_view_get_prev_pos(ctx->view->log_view,
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen /* should be just extra padding */
9cf4bb70f014849735aab4226691edcdf56b3271Timo Sirainen if (i + sizeof(*rec) + rec->name_size > hdr->size) {
9cf4bb70f014849735aab4226691edcdf56b3271Timo Sirainen "ext intro: name_size too large");
9cf4bb70f014849735aab4226691edcdf56b3271Timo Sirainen if ((i % 4) != 0)
23878bd03d1de531e3261a25598beec621351910Timo Sirainen const struct mail_transaction_ext_reset *rec = data;
1db62753d9e3b5d71018889c8ef0a3722a307455Timo Sirainen "ext reset: invalid record size");
ecbbdf594f9329fc15a182bd6c7c4a7fb144ed74Timo Sirainen const struct mail_transaction_ext_hdr_update *rec = data;
ecbbdf594f9329fc15a182bd6c7c4a7fb144ed74Timo Sirainen unsigned int i;
ecbbdf594f9329fc15a182bd6c7c4a7fb144ed74Timo Sirainen "ext hdr update: invalid record size");
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen ret = mail_index_sync_ext_hdr_update(ctx, rec);
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen if ((i % 4) != 0)
ecbbdf594f9329fc15a182bd6c7c4a7fb144ed74Timo Sirainen const struct mail_transaction_ext_rec_update *rec;
ecbbdf594f9329fc15a182bd6c7c4a7fb144ed74Timo Sirainen unsigned int i, record_size;
ecbbdf594f9329fc15a182bd6c7c4a7fb144ed74Timo Sirainen "Extension record updated "
ecbbdf594f9329fc15a182bd6c7c4a7fb144ed74Timo Sirainen "without intro prefix");
ecbbdf594f9329fc15a182bd6c7c4a7fb144ed74Timo Sirainen /* the record is padded to 32bits in the transaction log */
ecbbdf594f9329fc15a182bd6c7c4a7fb144ed74Timo Sirainen record_size = (sizeof(*rec) + ext->record_size + 3) & ~3;
ecbbdf594f9329fc15a182bd6c7c4a7fb144ed74Timo Sirainen for (i = 0; i < hdr->size; i += record_size) {
ecbbdf594f9329fc15a182bd6c7c4a7fb144ed74Timo Sirainen "ext rec update: invalid record size");
ecbbdf594f9329fc15a182bd6c7c4a7fb144ed74Timo Sirainen ret = mail_index_sync_ext_rec_update(ctx, rec);
ecbbdf594f9329fc15a182bd6c7c4a7fb144ed74Timo Sirainen const struct mail_transaction_keyword_update *rec = data;
ecbbdf594f9329fc15a182bd6c7c4a7fb144ed74Timo Sirainen ret = mail_index_sync_keywords(ctx, hdr, rec);
ecbbdf594f9329fc15a182bd6c7c4a7fb144ed74Timo Sirainen const struct mail_transaction_keyword_reset *rec = data;
c220c8cd341ee9ba78979397c5d33ccd98b5d19fAki Tuomi ret = mail_index_sync_keywords_reset(ctx, hdr, rec);
c220c8cd341ee9ba78979397c5d33ccd98b5d19fAki Tuomivoid mail_index_sync_map_init(struct mail_index_sync_map_ctx *sync_map_ctx,
c220c8cd341ee9ba78979397c5d33ccd98b5d19fAki Tuomivoid mail_index_sync_map_deinit(struct mail_index_sync_map_ctx *sync_map_ctx)
c220c8cd341ee9ba78979397c5d33ccd98b5d19fAki Tuomi mail_index_sync_deinit_expunge_handlers(sync_map_ctx);
c220c8cd341ee9ba78979397c5d33ccd98b5d19fAki Tuomistatic void mail_index_sync_update_hdr_dirty_flag(struct mail_index_map *map)
c220c8cd341ee9ba78979397c5d33ccd98b5d19fAki Tuomi unsigned int i;
c220c8cd341ee9ba78979397c5d33ccd98b5d19fAki Tuomi if ((map->hdr.flags & MAIL_INDEX_HDR_FLAG_HAVE_DIRTY) != 0)
c220c8cd341ee9ba78979397c5d33ccd98b5d19fAki Tuomi /* do we have dirty flags anymore? */
c220c8cd341ee9ba78979397c5d33ccd98b5d19fAki Tuomi for (i = 0; i < map->rec_map->records_count; i++) {
c220c8cd341ee9ba78979397c5d33ccd98b5d19fAki Tuomi if ((rec->flags & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0) {
c220c8cd341ee9ba78979397c5d33ccd98b5d19fAki Tuomivoid mail_index_map_check(struct mail_index_map *map)
c220c8cd341ee9ba78979397c5d33ccd98b5d19fAki Tuomi i_assert(hdr->messages_count <= map->rec_map->records_count);
c220c8cd341ee9ba78979397c5d33ccd98b5d19fAki Tuomi i_assert(rec->uid >= hdr->first_deleted_uid_lowwater);
61cf001f1944d92eb25f113ba4c08985d6e30d53Timo Sirainen i_assert(rec->uid >= hdr->first_unseen_uid_lowwater);
c220c8cd341ee9ba78979397c5d33ccd98b5d19fAki Tuomiint mail_index_sync_map(struct mail_index_map **_map,
c220c8cd341ee9ba78979397c5d33ccd98b5d19fAki Tuomi enum mail_index_sync_handler_type type, bool force)
c220c8cd341ee9ba78979397c5d33ccd98b5d19fAki Tuomi const void *tdata;
c220c8cd341ee9ba78979397c5d33ccd98b5d19fAki Tuomi i_assert(index->map == map || type == MAIL_INDEX_SYNC_HANDLER_VIEW);
c220c8cd341ee9ba78979397c5d33ccd98b5d19fAki Tuomi /* see if we'd prefer to reopen the index file instead of
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen syncing the current map from the transaction log */
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen /* we don't know the index's size, so use the
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen smallest index size we're willing to read */
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen index_size = MAIL_INDEX_SYNC_MIN_READ_INDEX_SIZE;
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen /* this isn't necessary correct currently, but it should be
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen close enough */
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen if (log_size > map->hdr.log_file_tail_offset &&
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen log_size - map->hdr.log_file_tail_offset > index_size)
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen start_offset = type == MAIL_INDEX_SYNC_HANDLER_FILE ?
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen map->hdr.log_file_tail_offset : map->hdr.log_file_head_offset;
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen view = mail_index_view_open_with_map(index, map);
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen ret = mail_transaction_log_view_set(view->log_view,
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen /* the seq/offset is probably broken */
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen /* can't use it. sync by re-reading index. */
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen /* view referenced the map. avoid unnecessary map cloning by
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen unreferencing the map while view exists. */
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen had_dirty = (map->hdr.flags & MAIL_INDEX_HDR_FLAG_HAVE_DIRTY) != 0;
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen map->hdr.flags &= ~MAIL_INDEX_HDR_FLAG_HAVE_DIRTY;
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen if (map->hdr_base != map->hdr_copy_buf->data) {
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen /* if syncing updates the header, it updates hdr_copy_buf
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen and updates hdr_base to hdr_copy_buf. so the buffer must
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen initially contain a valid header or we'll break it when
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen writing it. */
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen buffer_append(map->hdr_copy_buf, map->hdr_base,
d4847b921058734e0668bc7690465c91523d9ec0Martti Rannanjärvi mail_index_sync_map_init(&sync_map_ctx, view, type);
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen /* Reset the entire index. Leave only indexid and
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen log_file_seq. */
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen mail_transaction_log_view_get_prev_pos(view->log_view,
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen mail_index_sync_replace_map(&sync_map_ctx, map);
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen /* FIXME: when transaction sync lock is removed, we'll need to handle
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen the case when a transaction is committed while mailbox is being
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen synced ([synced transactions][new transaction][ext transaction]).
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen this means int_offset contains [synced] and ext_offset contains
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen while ((ret = mail_transaction_log_view_next(view->log_view, &thdr,
209d29ccf7550b0731147c53a0419749270fc501Timo Sirainen mail_transaction_log_view_get_prev_pos(view->log_view,
0368f3b0ae3fc1ea892da5c5ec02c05c0c3989afAki Tuomi /* this has been synced already. we're here only to call
0368f3b0ae3fc1ea892da5c5ec02c05c0c3989afAki Tuomi expunge handlers and extension update handlers. */
14102a0c5db8828ca8c7751ec96587fadc97a0bcTimo Sirainen i_assert(type == MAIL_INDEX_SYNC_HANDLER_FILE);
14102a0c5db8828ca8c7751ec96587fadc97a0bcTimo Sirainen if ((thdr->type & MAIL_TRANSACTION_EXTERNAL) != 0)
0368f3b0ae3fc1ea892da5c5ec02c05c0c3989afAki Tuomi if ((thdr->type & MAIL_TRANSACTION_EXT_MASK) == 0)
0368f3b0ae3fc1ea892da5c5ec02c05c0c3989afAki Tuomi /* we'll just skip over broken entries */
0368f3b0ae3fc1ea892da5c5ec02c05c0c3989afAki Tuomi (void)mail_index_sync_record(&sync_map_ctx, thdr, tdata);
0368f3b0ae3fc1ea892da5c5ec02c05c0c3989afAki Tuomi mail_index_sync_update_log_offset(&sync_map_ctx, view->map, TRUE);
5f7f5baf6ce0b9428793b590ca286cdb24f67a11Aki Tuomi i_assert(map->hdr.indexid == index->indexid || map->hdr.indexid == 0);
0368f3b0ae3fc1ea892da5c5ec02c05c0c3989afAki Tuomi /* transaction log tracks internally the current tail offset.
0368f3b0ae3fc1ea892da5c5ec02c05c0c3989afAki Tuomi besides using header updates, it also updates the offset to skip
2a9af9ae38a33b93e10ee01b42f5612b175418baTimo Sirainen over following external transactions to avoid extra unneeded log
4b5a2e923b61c3512dec0fcb32653fbd652bdc32Aki Tuomi map->hdr.log_file_tail_offset = index->log->head->max_tail_offset;
14102a0c5db8828ca8c7751ec96587fadc97a0bcTimo Sirainen buffer_write(map->hdr_copy_buf, 0, &map->hdr, sizeof(map->hdr));
23878bd03d1de531e3261a25598beec621351910Timo Sirainen memcpy(map->rec_map->mmap_base, map->hdr_copy_buf->data,
c45a841bee3f42ec6524b8f62c3fd457115c3f97Timo Sirainen /* avoid the same syncing errors the next time */
a18da4410dcd47ab8d9b40c09a76a54fa55b9c86Timo Sirainen /* restore refcount before closing the view. this is necessary also
a18da4410dcd47ab8d9b40c09a76a54fa55b9c86Timo Sirainen if map got cloned, because view closing would otherwise destroy it */
0368f3b0ae3fc1ea892da5c5ec02c05c0c3989afAki Tuomi i_assert(index->map == map || type == MAIL_INDEX_SYNC_HANDLER_VIEW);
0368f3b0ae3fc1ea892da5c5ec02c05c0c3989afAki Tuomi "Synchronization corrupted index header: %s",