bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2003-2018 Dovecot authors, see the included COPYING file */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_transaction_log_append_ctx *append_ctx;
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainenlog_append_buffer(struct mail_index_export_context *ctx,
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen const buffer_t *buf, enum mail_transaction_type type)
40a5aeebf6b4858b93f0ddff0bf12fba769cf903Timo Sirainen mail_transaction_log_append_add(ctx->append_ctx, type,
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainenstatic void log_append_flag_updates(struct mail_index_export_context *ctx,
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen ARRAY(struct mail_transaction_flag_update) log_updates;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen struct mail_transaction_flag_update *log_update;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen for (i = 0; i < count; i++) {
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen log_update = array_append_space(&log_updates);
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen log_update->add_flags = updates[i].add_flags & 0xff;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen log_update->remove_flags = updates[i].remove_flags & 0xff;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen if ((updates[i].add_flags & MAIL_INDEX_MAIL_FLAG_UPDATE_MODSEQ) != 0)
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen log_append_buffer(ctx, log_updates.arr.buffer,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenlog_get_hdr_update_buffer(struct mail_index_transaction *t, bool prepend)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen data = prepend ? t->pre_hdr_change : t->post_hdr_change;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mask = prepend ? t->pre_hdr_mask : t->post_hdr_mask;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen for (offset = 0; offset <= sizeof(t->pre_hdr_change); offset++) {
23bdbb7b1831785c6ba6df190f6369da882d2b9dTimo Sirainen if (offset < sizeof(t->pre_hdr_change) && mask[offset] != 0) {
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainenstatic unsigned int
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainenext_hdr_update_get_size(const struct mail_index_transaction_ext_hdr_update *hu)
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen unsigned int i;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic void log_append_ext_intro(struct mail_index_export_context *ctx,
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen unsigned int *hdr_size_r)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_index_transaction *t = ctx->trans;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_transaction_ext_intro *intro, *resizes;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen !mail_index_map_get_ext_idx(t->view->index->map, ext_id, &idx)) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* new extension */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen rext = array_idx(&t->view->index->extensions, ext_id);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen resizes = array_get_modifiable(&t->ext_resizes, &count);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (ext_id < count && resizes[ext_id].name_size != 0) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* we're resizing the extension. use the resize struct. */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* generate a new intro structure */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen intro = buffer_append_space_unsafe(buf, sizeof(*intro));
930d6db2ee2bbafd3c7cdaa39855ddccb999522fTimo Sirainen ext = array_idx(&t->view->index->map->extensions, idx);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen intro->flags = MAIL_TRANSACTION_EXT_INTRO_FLAG_NO_SHRINK;
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen /* handle increasing header size automatically */
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen const struct mail_index_transaction_ext_hdr_update *hu;
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen hdr_update_size = ext_hdr_update_get_size(hu);
01e29d9d23a1844b4582592a473a3b3eac56b36bTimo Sirainen i_assert(intro->record_size != 0 || intro->hdr_size != 0);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* we're going to reset this extension in this transaction */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* use the existing reset_id */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen array_idx(&t->view->index->map->extensions, idx);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* new extension, reset_id defaults to 0 */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen buffer_append(buf, rext->name, intro->name_size);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (ctx->append_ctx->new_highest_modseq == 0 &&
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen strcmp(rext->name, MAIL_INDEX_MODSEQ_EXT_NAME) == 0) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* modseq tracking started */
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen log_append_buffer(ctx, buf, MAIL_TRANSACTION_EXT_INTRO);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenlog_append_ext_hdr_update(struct mail_index_export_context *ctx,
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen const struct mail_index_transaction_ext_hdr_update *hdr,
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen bool started = FALSE, use_32 = hdr->alloc_size >= 65536;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen for (offset = 0; offset <= hdr->alloc_size; offset++) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (offset < hdr->alloc_size && mask[offset] != 0) {
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen i_assert(u32.offset + u32.size <= ext_hdr_size);
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen buffer_append(buf, data + u32.offset, u32.size);
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen log_append_buffer(ctx, buf, use_32 ? MAIL_TRANSACTION_EXT_HDR_UPDATE32 :
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenmail_transaction_log_append_ext_intros(struct mail_index_export_context *ctx)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_index_transaction *t = ctx->trans;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen const struct mail_transaction_ext_intro *resize;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen const struct mail_index_transaction_ext_hdr_update *hdrs;
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen unsigned int hdrs_count, reset_id_count, reset_count, hdr_size;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen const struct mail_transaction_ext_reset *reset;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen resize = array_get(&t->ext_resizes, &resize_count);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen reset_ids = array_get(&t->ext_reset_ids, &reset_id_count);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen reset = array_get(&t->ext_resets, &reset_count);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen hdrs = array_get(&t->ext_hdr_updates, &hdrs_count);
3281669db44d09a087a203201248abbc81b3cc1aTimo Sirainen buffer_create_from_data(&reset_buf, &ext_reset, sizeof(ext_reset));
8e361d2906b0e44f7175a20981f8d2280645b58bTimo Sirainen buffer_set_used_size(&reset_buf, sizeof(ext_reset));
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen for (ext_id = 0; ext_id < ext_count; ext_id++) {
23bdbb7b1831785c6ba6df190f6369da882d2b9dTimo Sirainen if ((ext_id < resize_count && resize[ext_id].name_size > 0) ||
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen (ext_id < hdrs_count && hdrs[ext_id].alloc_size > 0)) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* we're going to reset this extension
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen immediately after the intro */
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen log_append_ext_intro(ctx, ext_id, reset_id, &hdr_size);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (ext_id < hdrs_count && hdrs[ext_id].alloc_size > 0) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic void log_append_ext_recs(struct mail_index_export_context *ctx,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_index_transaction *t = ctx->trans;
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen unsigned int ext_id, count, reset_id_count, hdr_size;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen reset_ids = array_get_modifiable(&t->ext_reset_ids,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen reset_id = ext_id < reset_id_count ? reset_ids[ext_id] : 0;
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen log_append_ext_intro(ctx, ext_id, reset_id, &hdr_size);
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen log_append_buffer(ctx, updates[ext_id].arr.buffer, type);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenlog_append_keyword_update(struct mail_index_export_context *ctx,
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen buffer_t *tmp_buf, enum modify_type modify_type,
fad068d459cc7b04fedade4e0bb343be62e6d310Timo Sirainen const char *keyword, const buffer_t *uid_buffer)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_transaction_keyword_update kt_hdr;
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen buffer_append(tmp_buf, &kt_hdr, sizeof(kt_hdr));
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen buffer_append(tmp_buf, keyword, kt_hdr.name_size);
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen buffer_append_zero(tmp_buf, 4 - (tmp_buf->used % 4));
fad068d459cc7b04fedade4e0bb343be62e6d310Timo Sirainen buffer_append(tmp_buf, uid_buffer->data, uid_buffer->used);
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen log_append_buffer(ctx, tmp_buf, MAIL_TRANSACTION_KEYWORD_UPDATE);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenlog_append_keyword_updates(struct mail_index_export_context *ctx)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen const struct mail_index_transaction_keyword_update *updates;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen keywords = array_get_modifiable(&ctx->trans->view->index->keywords,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen updates = array_get_modifiable(&ctx->trans->keyword_updates, &count);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen for (i = 0; i < count; i++) {
fad068d459cc7b04fedade4e0bb343be62e6d310Timo Sirainen if (array_is_created(&updates[i].remove_seq) &&
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenvoid mail_index_transaction_export(struct mail_index_transaction *t,
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen struct mail_transaction_log_append_ctx *append_ctx,
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen enum mail_index_transaction_change *changes_r)
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen mail_transaction_log_append_add(ctx.append_ctx,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* send all extension introductions and resizes before appends
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen to avoid resize overhead as much as possible */
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen log_append_buffer(&ctx, log_get_hdr_update_buffer(t, TRUE),
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen *changes_r |= MAIL_INDEX_TRANSACTION_CHANGE_OTHERS;
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen /* need to have 32bit alignment */
238812433b4f7965fd662dce0f4efccb092630a8Timo Sirainen /* append the timestamp and value lengths */
238812433b4f7965fd662dce0f4efccb092630a8Timo Sirainen i_assert(t->attribute_updates->used % 4 == 0);
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen *changes_r |= MAIL_INDEX_TRANSACTION_CHANGE_ATTRIBUTE;
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen *changes_r |= MAIL_INDEX_TRANSACTION_CHANGE_APPEND;
de9d79337eca11a7f9c1cd476c74dfe4f09a4bd7Timo Sirainen log_append_buffer(&ctx, t->appends.arr.buffer,
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen *changes_r |= MAIL_INDEX_TRANSACTION_CHANGE_FLAGS;
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen *changes_r |= MAIL_INDEX_TRANSACTION_CHANGE_OTHERS;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen log_append_ext_recs(&ctx, &t->ext_rec_updates,
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen *changes_r |= MAIL_INDEX_TRANSACTION_CHANGE_OTHERS;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen log_append_ext_recs(&ctx, &t->ext_rec_atomics,
4fbf718a46e608d0f67180cae3e6773a39149e20Timo Sirainen change_mask |= MAIL_INDEX_FSYNC_MASK_KEYWORDS;
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen *changes_r |= MAIL_INDEX_TRANSACTION_CHANGE_KEYWORDS;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen /* keep modseq updates almost last */
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen *changes_r |= MAIL_INDEX_TRANSACTION_CHANGE_MODSEQ;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen log_append_buffer(&ctx, t->modseq_updates.arr.buffer,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* non-external expunges are only requests, ignore them when
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen checking fsync_mask */
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen if ((t->flags & MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL) != 0) {
724b7fcf28c2547eb9c837d0e99241c0501dccf3Timo Sirainen change_mask |= MAIL_INDEX_FSYNC_MASK_EXPUNGES;
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen *changes_r |= MAIL_INDEX_TRANSACTION_CHANGE_EXPUNGE;
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen *changes_r |= MAIL_INDEX_TRANSACTION_CHANGE_OTHERS;
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen log_append_buffer(&ctx, t->expunges.arr.buffer,
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen *changes_r |= MAIL_INDEX_TRANSACTION_CHANGE_OTHERS;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen log_append_buffer(&ctx, log_get_hdr_update_buffer(t, FALSE),
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen *changes_r |= MAIL_INDEX_TRANSACTION_CHANGE_OTHERS;
651fc0f1e43fef3e02e0e7b5f498973b05f641d7Timo Sirainen mail_transaction_log_append_add(ctx.append_ctx,
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen i_assert((append_ctx->output->used > 0) == (*changes_r != 0));
082e82792b8ac33ad42beac510441b37a3c50737Timo Sirainen append_ctx->index_sync_transaction = t->sync_transaction;
082e82792b8ac33ad42beac510441b37a3c50737Timo Sirainen append_ctx->tail_offset_changed = t->tail_offset_changed;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen (t->view->index->fsync_mask & change_mask) != 0 ||
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen (t->flags & MAIL_INDEX_TRANSACTION_FLAG_FSYNC) != 0;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainenstatic unsigned int
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainencount_modseq_incs_with(struct mail_index_transaction *t,
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen mail_index_transaction_seq_range_to_uid(t, tmp_seqs);
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainenstatic unsigned int
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainenmail_index_transaction_keywords_count_modseq_incs(struct mail_index_transaction *t)
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen const struct mail_index_transaction_keyword_update *update;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen array_foreach_modifiable(&t->keyword_updates, update) {
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen count += count_modseq_incs_with(t, &tmp_seqs, &update->add_seq);
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen count += count_modseq_incs_with(t, &tmp_seqs, &update->remove_seq);
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainentransaction_flag_updates_have_non_internal(struct mail_index_transaction *t)
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen struct mail_transaction_log_file *file = t->view->index->log->head;
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen MAIL_INDEX_MAIL_FLAG_BACKEND | MAIL_INDEX_MAIL_FLAG_DIRTY;
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen if (!MAIL_TRANSACTION_LOG_VERSION_HAVE(hdr_version, HIDE_INTERNAL_MODSEQS)) {
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen /* this check can be a bit racy if the call isn't done while
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen transaction log is locked. practically it won't matter
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen now though. */
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen uint8_t changed_flags = u->add_flags | u->remove_flags;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainenuint64_t mail_index_transaction_get_highest_modseq(struct mail_index_transaction *t)
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen struct mail_transaction_log_file *file = t->view->index->log->head;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen uint64_t new_highest_modseq = file->sync_highest_modseq;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen /* highest-modseq tracking isn't enabled in this transaction
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen log file. This shouldn't happen with logs created since
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen v2.2.26+, because initial_modseq is always set. We don't
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen also bother checking if this transaction itself enables the
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen highest-modseq tracking, because it's always done as a
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen standalone transaction in mail_index_modseq_enable(),
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen which doesn't care about this function. */
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen i_warning("%s: Requested highest-modseq for transaction, "
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen "but modseq tracking isn't enabled for the file "
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen /* finish everything that can affect highest-modseq */
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen /* NOTE: keep in sync with mail_transaction_update_modseq() */
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen if (array_is_created(&t->appends) && array_count(&t->appends) > 0) {
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen /* sorting may change the order of keyword_updates, */
af0a12ae492d79e27b29d63ff0f289f9034fecc9Stephan Bosch transaction_flag_updates_have_non_internal(t))
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen mail_index_transaction_keywords_count_modseq_incs(t);
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen /* NOTE: the order of modseq_updates and everything following it
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen must match mail_index_transaction_export(). */
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen const struct mail_transaction_modseq_update *mu;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen /* mail_index_update_highest_modseq() is handled here also,
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen as a special case of uid==0. */
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen uint64_t modseq = ((uint64_t)mu->modseq_high32 << 32) |
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen if (array_is_created(&t->expunges) && array_count(&t->expunges) > 0 &&