mail-index-view-sync.c revision 14c474d9f4591c397ed0b5206af6537c7b52c924
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenmail_transaction_log_sort_expunges(ARRAY_TYPE(seq_range) *expunges,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* Note that all the sequences are actually still UIDs at this point */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* @UNSAFE */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen dest = array_get_modifiable(expunges, &dest_count);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen array_append(expunges, src, src_size / sizeof(*src));
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* src[] must be sorted. */
cf9d67e4a9bfee31cf3be05244555d51a3d1b9feTimo Sirainen (src+1 != src_end && src->seq2 >= src[1].seq1))
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen for (; i < dest_count; i++) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen while (i < dest_count && src->seq2 >= dest[i].seq1-1) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* we can/must merge with next record */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (first > 0 && new_exp.seq1 <= dest[first-1].seq2+1) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* continue previous record */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen } else if (i == first) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen dest = array_get_modifiable(expunges, &dest_count);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* use next record */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen dest = array_get_modifiable(expunges, &dest_count);
cf9d67e4a9bfee31cf3be05244555d51a3d1b9feTimo Sirainenview_sync_set_log_view_range(struct mail_index_view *view, bool sync_expunges)
cf9d67e4a9bfee31cf3be05244555d51a3d1b9feTimo Sirainen const struct mail_index_header *hdr = &view->index->map->hdr;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* the view begins from the first non-synced transaction */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen ret = mail_transaction_log_view_set(view->log_view,
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen /* FIXME: use the new index to get needed
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen "Transaction log got desynced for index %s",
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen /* we can't do this. sync only up to reset. */
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen mail_transaction_log_view_get_prev_pos(view->log_view,
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen /* we have only this reset log */
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen mail_transaction_log_view_clear(view->log_view);
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainenview_sync_get_expunges(struct mail_index_view *view,
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen unsigned int count;
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen if (view_sync_set_log_view_range(view, TRUE) < 0)
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen /* get a list of expunge transactions. there may be some that we have
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen already synced, but it doesn't matter because they'll get dropped
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen out when converting to sequences */
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen while ((ret = mail_transaction_log_view_next(view->log_view,
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXPUNGE) == 0)
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen if ((hdr->type & MAIL_TRANSACTION_EXTERNAL) == 0) {
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen /* this is simply a request for expunge */
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen if (mail_transaction_log_sort_expunges(expunges_r, data,
242abe3ad2423776e9cf05e1304eb8fda4831b23Timo Sirainen mail_transaction_log_view_set_corrupted(view->log_view,
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen "Corrupted expunge record");
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen /* convert UIDs to sequences */
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen src = dest = array_get_modifiable(expunges_r, &count);
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen ret = mail_index_lookup_uid_range(view, src->seq1,
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen array_delete(expunges_r, count, array_count(expunges_r) - count);
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainenstatic void mail_index_view_check(struct mail_index_view *view)
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen i_assert(view->hdr.messages_count == view->map->hdr.messages_count);
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen#define VIEW_IS_SYNCED_TO_SAME(hdr, tail_seq, tail_offset) \
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainenint mail_index_view_sync_begin(struct mail_index_view *view,
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen if (mail_index_map_lock(view->index->map) < 0)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen sync_expunges = (flags & MAIL_INDEX_VIEW_SYNC_FLAG_NOEXPUNGES) == 0;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* get list of all expunges first */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (view_sync_get_expunges(view, &expunges) < 0)
d2cadbf5445156fc12988506279d51d0e53b0449Timo Sirainen if (view_sync_set_log_view_range(view, sync_expunges) < 0) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen ctx = i_new(struct mail_index_view_sync_ctx, 1);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen mail_index_sync_map_init(&ctx->sync_map_ctx, view,
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen /* keep the old mapping without expunges until we're
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen fully synced */
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen /* We need a private copy of the map if we don't want to
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen sync expunges.
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen If view's map is the head map, it means that it contains
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen already all the latest changes and there's no need for us
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen to apply any changes to it. This can only happen if there
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen hadn't been any expunges. */
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen /* Using non-head mapping. We have to apply
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen transactions to it to get latest changes into it. */
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen /* Unless map was synced at the exact same position as
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen view, the message flags can't be reliably used to
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen update flag counters. note that map->hdr may contain
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen old information if another process updated the
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen index file since. */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen // FIXME: locking should do this..?..
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen i_assert(map->records_count == map->hdr.messages_count);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* Syncing the view invalidates all previous looked up records.
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen Unreference the mappings this view keeps because of them. */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenview_sync_is_hidden(struct mail_index_view *view, uint32_t seq, uoff_t offset)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen const struct mail_index_view_log_sync_area *syncs;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen unsigned int i, count;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen syncs = array_get(&view->syncs_hidden, &count);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen for (i = 0; i < count; i++) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen offset - syncs[i].log_file_offset < syncs[i].length &&
return FALSE;
return FALSE;
return FALSE;
return TRUE;
int ret;
bool synced_to_map;
if (ret <= 0) {
if (ret < 0)
store +flags.silent command) */
#define FLAG_UPDATE_IS_INTERNAL(u) \
case MAIL_TRANSACTION_APPEND: {
case MAIL_TRANSACTION_EXPUNGE: {
case MAIL_TRANSACTION_FLAG_UPDATE: {
case MAIL_TRANSACTION_KEYWORD_UPDATE: {
case MAIL_TRANSACTION_KEYWORD_RESET: {
return FALSE;
return TRUE;
int ret;
if (ret <= 0)
return ret;
unsigned int i, count;
for (i = 0; i < count; i++) {
#ifdef DEBUG
unsigned int length)