From: Timo Sirainen Date: Mon, 14 Nov 2016 16:41:23 +0000 (+0100) Subject: lib-index: Added mail_index_transaction_get_highest_modseq() X-Git-Tag: 2.2.27~122 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c04a8e72620641deafccd19f5e2107913a8ba67a;p=thirdparty%2Fdovecot%2Fcore.git lib-index: Added mail_index_transaction_get_highest_modseq() --- diff --git a/src/lib-index/mail-index-transaction-export.c b/src/lib-index/mail-index-transaction-export.c index f846c891f1..fa690e1ec8 100644 --- a/src/lib-index/mail-index-transaction-export.c +++ b/src/lib-index/mail-index-transaction-export.c @@ -505,3 +505,90 @@ void mail_index_transaction_export(struct mail_index_transaction *t, (t->view->index->fsync_mask & change_mask) != 0 || (t->flags & MAIL_INDEX_TRANSACTION_FLAG_FSYNC) != 0; } + +static unsigned int +count_modseq_incs_with(struct mail_index_transaction *t, + ARRAY_TYPE(seq_range) *tmp_seqs, + const ARRAY_TYPE(seq_range) *orig_seqs) +{ + if (!array_is_created(orig_seqs)) + return 0; + + array_clear(tmp_seqs); + array_append_array(tmp_seqs, orig_seqs); + mail_index_transaction_seq_range_to_uid(t, tmp_seqs); + return array_count(tmp_seqs) > 0 ? 1 : 0; +} + +static unsigned int +mail_index_transaction_keywords_count_modseq_incs(struct mail_index_transaction *t) +{ + const struct mail_index_transaction_keyword_update *update; + ARRAY_TYPE(seq_range) tmp_seqs; + unsigned int count = 0; + + i_array_init(&tmp_seqs, 64); + array_foreach_modifiable(&t->keyword_updates, update) { + count += count_modseq_incs_with(t, &tmp_seqs, &update->add_seq); + count += count_modseq_incs_with(t, &tmp_seqs, &update->remove_seq); + } + array_free(&tmp_seqs); + return count; +} + +uint64_t mail_index_transaction_get_highest_modseq(struct mail_index_transaction *t) +{ + struct mail_transaction_log_file *file = t->view->index->log->head; + uint64_t new_highest_modseq = file->sync_highest_modseq; + + i_assert(file->locked); + + if (new_highest_modseq == 0) { + /* highest-modseq tracking isn't enabled in this transaction + log file. This shouldn't happen with logs created since + v2.2.26+, because initial_modseq is always set. We don't + also bother checking if this transaction itself enables the + highest-modseq tracking, because it's always done as a + standalone transaction in mail_index_modseq_enable(), + which doesn't care about this function. */ + i_warning("%s: Requested highest-modseq for transaction, " + "but modseq tracking isn't enabled for the file " + "(this shouldn't happen)", file->filepath); + return 0; + } + + /* finish everything that can affect highest-modseq */ + mail_index_transaction_finish_so_far(t); + + /* NOTE: keep in sync with mail_transaction_update_modseq() */ + if (array_is_created(&t->appends) && array_count(&t->appends) > 0) { + /* sorting may change the order of keyword_updates, */ + new_highest_modseq++; + } + if (array_is_created(&t->updates) && array_count(&t->updates) > 0) + new_highest_modseq++; + if (array_is_created(&t->keyword_updates)) { + new_highest_modseq += + mail_index_transaction_keywords_count_modseq_incs(t); + } + if (t->attribute_updates != NULL) + new_highest_modseq++; + /* NOTE: the order of modseq_updates and everything following it + must match mail_index_transaction_export(). */ + if (array_is_created(&t->modseq_updates)) { + const struct mail_transaction_modseq_update *mu; + + /* mail_index_update_highest_modseq() is handled here also, + as a special case of uid==0. */ + array_foreach(&t->modseq_updates, mu) { + uint64_t modseq = ((uint64_t)mu->modseq_high32 << 32) | + mu->modseq_low32; + if (new_highest_modseq < modseq) + new_highest_modseq = modseq; + } + } + if (array_is_created(&t->expunges) && array_count(&t->expunges) > 0 && + (t->flags & MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL) != 0) + new_highest_modseq++; + return new_highest_modseq; +} diff --git a/src/lib-index/mail-index-transaction-finish.c b/src/lib-index/mail-index-transaction-finish.c index 0e47c254d3..e182afec3c 100644 --- a/src/lib-index/mail-index-transaction-finish.c +++ b/src/lib-index/mail-index-transaction-finish.c @@ -218,9 +218,8 @@ get_nonexpunged_uid2(struct mail_index_transaction *t, return uid1; } -static void -mail_index_convert_to_uid_ranges(struct mail_index_transaction *t, - ARRAY_TYPE(seq_range) *array) +void mail_index_transaction_seq_range_to_uid(struct mail_index_transaction *t, + ARRAY_TYPE(seq_range) *array) { struct seq_range *range, *new_range; unsigned int i, count; @@ -268,8 +267,8 @@ static void keyword_updates_convert_to_uids(struct mail_index_transaction *t) return; array_foreach_modifiable(&t->keyword_updates, update) { - mail_index_convert_to_uid_ranges(t, &update->add_seq); - mail_index_convert_to_uid_ranges(t, &update->remove_seq); + mail_index_transaction_seq_range_to_uid(t, &update->add_seq); + mail_index_transaction_seq_range_to_uid(t, &update->remove_seq); } } @@ -320,7 +319,7 @@ mail_index_transaction_convert_to_uids(struct mail_index_transaction *t) keyword_updates_convert_to_uids(t); expunges_convert_to_uids(t); mail_index_convert_to_uids(t, (void *)&t->modseq_updates); - mail_index_convert_to_uid_ranges(t, (void *)&t->updates); + mail_index_transaction_seq_range_to_uid(t, (void *)&t->updates); } void mail_index_transaction_finish_so_far(struct mail_index_transaction *t) diff --git a/src/lib-index/mail-index-transaction-private.h b/src/lib-index/mail-index-transaction-private.h index 44120f2c43..755480c0a0 100644 --- a/src/lib-index/mail-index-transaction-private.h +++ b/src/lib-index/mail-index-transaction-private.h @@ -137,6 +137,12 @@ bool mail_index_cancel_flag_updates(struct mail_index_transaction *t, bool mail_index_cancel_keyword_updates(struct mail_index_transaction *t, uint32_t seq); +/* As input the array's each element starts with struct seq_range where + uid1..uid2 are actually sequences within the transaction view. This function + changes the sequences into UIDs. If the transaction has any appends, they + must have already been assigned UIDs. */ +void mail_index_transaction_seq_range_to_uid(struct mail_index_transaction *t, + ARRAY_TYPE(seq_range) *array); void mail_index_transaction_finish_so_far(struct mail_index_transaction *t); void mail_index_transaction_finish(struct mail_index_transaction *t); void mail_index_transaction_export(struct mail_index_transaction *t, diff --git a/src/lib-index/mail-index-transaction.c b/src/lib-index/mail-index-transaction.c index d401638cb2..492615bbdd 100644 --- a/src/lib-index/mail-index-transaction.c +++ b/src/lib-index/mail-index-transaction.c @@ -161,6 +161,10 @@ mail_index_transaction_commit_real(struct mail_index_transaction *t, if (mail_transaction_log_append_begin(log->index, trans_flags, &ctx) < 0) return -1; ret = mail_transaction_log_file_refresh(t, ctx); +#ifdef DEBUG + uint64_t expected_highest_modseq = + mail_index_transaction_get_highest_modseq(t); +#endif if (ret > 0) T_BEGIN { mail_index_transaction_finish(t); mail_index_transaction_export(t, ctx); @@ -172,6 +176,10 @@ mail_index_transaction_commit_real(struct mail_index_transaction *t, mail_transaction_log_get_head(log, &log_seq2, &log_offset2); i_assert(log_seq1 == log_seq2); +#ifdef DEBUG + i_assert(expected_highest_modseq == log->head->sync_highest_modseq); +#endif + if (t->reset) { /* get rid of the old index. it might just confuse readers, especially if it's broken. */ diff --git a/src/lib-index/mail-index.h b/src/lib-index/mail-index.h index 2ead84827f..c519adae4f 100644 --- a/src/lib-index/mail-index.h +++ b/src/lib-index/mail-index.h @@ -309,6 +309,11 @@ void mail_index_transaction_reset(struct mail_index_transaction *t); void mail_index_transaction_set_max_modseq(struct mail_index_transaction *t, uint64_t max_modseq, ARRAY_TYPE(seq_range) *seqs); +/* Returns the resulting highest-modseq after this commit. This can be called + only if transaction log is locked, which normally means only during mail + index syncing. If there are any appends, they all must have been assigned + UIDs before calling this. */ +uint64_t mail_index_transaction_get_highest_modseq(struct mail_index_transaction *t); /* Returns the view transaction was created for. */ struct mail_index_view * diff --git a/src/lib-index/mail-transaction-log-file.c b/src/lib-index/mail-transaction-log-file.c index 36d519b0bb..ed073b5130 100644 --- a/src/lib-index/mail-transaction-log-file.c +++ b/src/lib-index/mail-transaction-log-file.c @@ -1021,6 +1021,7 @@ void mail_transaction_update_modseq(const struct mail_transaction_header *hdr, return; } + /* NOTE: keep in sync with mail_index_transaction_get_highest_modseq() */ switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) { case MAIL_TRANSACTION_EXPUNGE | MAIL_TRANSACTION_EXPUNGE_PROT: case MAIL_TRANSACTION_EXPUNGE_GUID | MAIL_TRANSACTION_EXPUNGE_PROT: