bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2003-2018 Dovecot authors, see the included COPYING file */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen#include "lib.h"
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen#include "array.h"
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen#include "mail-index-private.h"
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen#include "mail-index-modseq.h"
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen#include "mail-transaction-log-private.h"
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen#include "mail-index-transaction-private.h"
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstruct mail_index_export_context {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_index_transaction *trans;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_transaction_log_append_ctx *append_ctx;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen};
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainenstatic void
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainenlog_append_buffer(struct mail_index_export_context *ctx,
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen const buffer_t *buf, enum mail_transaction_type type)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
40a5aeebf6b4858b93f0ddff0bf12fba769cf903Timo Sirainen mail_transaction_log_append_add(ctx->append_ctx, type,
40a5aeebf6b4858b93f0ddff0bf12fba769cf903Timo Sirainen buf->data, buf->used);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainenstatic void log_append_flag_updates(struct mail_index_export_context *ctx,
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen struct mail_index_transaction *t)
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen{
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen ARRAY(struct mail_transaction_flag_update) log_updates;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen const struct mail_index_flag_update *updates;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen struct mail_transaction_flag_update *log_update;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen unsigned int i, count;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen updates = array_get(&t->updates, &count);
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen if (count == 0)
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen return;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen i_array_init(&log_updates, count);
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen for (i = 0; i < count; i++) {
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen log_update = array_append_space(&log_updates);
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen log_update->uid1 = updates[i].uid1;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen log_update->uid2 = updates[i].uid2;
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_update->modseq_inc_flag = 1;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen }
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen log_append_buffer(ctx, log_updates.arr.buffer,
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen MAIL_TRANSACTION_FLAG_UPDATE);
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen array_free(&log_updates);
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen}
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic const buffer_t *
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenlog_get_hdr_update_buffer(struct mail_index_transaction *t, bool prepend)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen buffer_t *buf;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen const unsigned char *data, *mask;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_transaction_header_update u;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen uint16_t offset;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen int state = 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&u);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
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
c147bff818798a979d93537f72f5c1f68f5d5ba8Aki Tuomi buf = t_buffer_create(256);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen for (offset = 0; offset <= sizeof(t->pre_hdr_change); offset++) {
23bdbb7b1831785c6ba6df190f6369da882d2b9dTimo Sirainen if (offset < sizeof(t->pre_hdr_change) && mask[offset] != 0) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (state == 0) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen u.offset = offset;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen state++;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen } else {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (state > 0) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen u.size = offset - u.offset;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen buffer_append(buf, &u, sizeof(u));
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen buffer_append(buf, data + u.offset, u.size);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen state = 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return buf;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainenstatic unsigned int
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainenext_hdr_update_get_size(const struct mail_index_transaction_ext_hdr_update *hu)
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen{
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen unsigned int i;
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen for (i = hu->alloc_size; i > 0; i--) {
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen if (hu->mask[i-1] != 0)
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen return i;
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen }
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen return 0;
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen}
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic void log_append_ext_intro(struct mail_index_export_context *ctx,
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen uint32_t ext_id, uint32_t reset_id,
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen unsigned int *hdr_size_r)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_index_transaction *t = ctx->trans;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen const struct mail_index_registered_ext *rext;
930d6db2ee2bbafd3c7cdaa39855ddccb999522fTimo Sirainen const struct mail_index_ext *ext;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_transaction_ext_intro *intro, *resizes;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen buffer_t *buf;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen uint32_t idx;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen unsigned int count;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen i_assert(ext_id != (uint32_t)-1);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (t->reset ||
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen !mail_index_map_get_ext_idx(t->view->index->map, ext_id, &idx)) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* new extension */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen idx = (uint32_t)-1;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen rext = array_idx(&t->view->index->extensions, ext_id);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (!array_is_created(&t->ext_resizes)) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen resizes = NULL;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen count = 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen } else {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen resizes = array_get_modifiable(&t->ext_resizes, &count);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
c147bff818798a979d93537f72f5c1f68f5d5ba8Aki Tuomi buf = t_buffer_create(128);
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 intro = &resizes[ext_id];
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
b8864211b88ed7521e9af514590639344af38910Timo Sirainen if (idx != (uint32_t)-1) {
b8864211b88ed7521e9af514590639344af38910Timo Sirainen intro->ext_id = idx;
c3cb859d93a77d52d6af054d358b55d45b4a5188Timo Sirainen intro->name_size = 0;
b8864211b88ed7521e9af514590639344af38910Timo Sirainen } else {
c3cb859d93a77d52d6af054d358b55d45b4a5188Timo Sirainen intro->ext_id = (uint32_t)-1;
c3cb859d93a77d52d6af054d358b55d45b4a5188Timo Sirainen intro->name_size = strlen(rext->name);
c3cb859d93a77d52d6af054d358b55d45b4a5188Timo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen buffer_append(buf, intro, sizeof(*intro));
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen } else {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* generate a new intro structure */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen intro = buffer_append_space_unsafe(buf, sizeof(*intro));
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen intro->ext_id = idx;
3403e054eacf125e757bf6c66abf0ea9f086a4b6Timo Sirainen intro->record_size = rext->record_size;
3403e054eacf125e757bf6c66abf0ea9f086a4b6Timo Sirainen intro->record_align = rext->record_align;
930d6db2ee2bbafd3c7cdaa39855ddccb999522fTimo Sirainen if (idx == (uint32_t)-1) {
930d6db2ee2bbafd3c7cdaa39855ddccb999522fTimo Sirainen intro->hdr_size = rext->hdr_size;
930d6db2ee2bbafd3c7cdaa39855ddccb999522fTimo Sirainen intro->name_size = strlen(rext->name);
930d6db2ee2bbafd3c7cdaa39855ddccb999522fTimo Sirainen } else {
930d6db2ee2bbafd3c7cdaa39855ddccb999522fTimo Sirainen ext = array_idx(&t->view->index->map->extensions, idx);
930d6db2ee2bbafd3c7cdaa39855ddccb999522fTimo Sirainen intro->hdr_size = ext->hdr_size;
930d6db2ee2bbafd3c7cdaa39855ddccb999522fTimo Sirainen intro->name_size = 0;
930d6db2ee2bbafd3c7cdaa39855ddccb999522fTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen intro->flags = MAIL_TRANSACTION_EXT_INTRO_FLAG_NO_SHRINK;
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen /* handle increasing header size automatically */
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen if (array_is_created(&t->ext_hdr_updates) &&
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen ext_id < array_count(&t->ext_hdr_updates)) {
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen const struct mail_index_transaction_ext_hdr_update *hu;
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen unsigned int hdr_update_size;
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen hu = array_idx(&t->ext_hdr_updates, ext_id);
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen hdr_update_size = ext_hdr_update_get_size(hu);
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen if (intro->hdr_size < hdr_update_size)
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen intro->hdr_size = hdr_update_size;
aa938aea66562ca3f3c5965a79b3b27ebcbe04efTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
01e29d9d23a1844b4582592a473a3b3eac56b36bTimo Sirainen i_assert(intro->record_size != 0 || intro->hdr_size != 0);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (reset_id != 0) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* we're going to reset this extension in this transaction */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen intro->reset_id = reset_id;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen } else if (idx != (uint32_t)-1) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* use the existing reset_id */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen const struct mail_index_ext *map_ext =
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen array_idx(&t->view->index->map->extensions, idx);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen intro->reset_id = map_ext->reset_id;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen } else {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* new extension, reset_id defaults to 0 */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen buffer_append(buf, rext->name, intro->name_size);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if ((buf->used % 4) != 0)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen buffer_append_zero(buf, 4 - (buf->used % 4));
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
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 */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen ctx->append_ctx->new_highest_modseq = 1;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen log_append_buffer(ctx, buf, MAIL_TRANSACTION_EXT_INTRO);
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen *hdr_size_r = intro->hdr_size;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic void
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenlog_append_ext_hdr_update(struct mail_index_export_context *ctx,
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen const struct mail_index_transaction_ext_hdr_update *hdr,
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen unsigned int ext_hdr_size)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen buffer_t *buf;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen const unsigned char *data, *mask;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_transaction_ext_hdr_update u;
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen struct mail_transaction_ext_hdr_update32 u32;
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen size_t offset;
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen bool started = FALSE, use_32 = hdr->alloc_size >= 65536;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&u);
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&u32);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen data = hdr->data;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mask = hdr->mask;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
c147bff818798a979d93537f72f5c1f68f5d5ba8Aki Tuomi buf = t_buffer_create(256);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen for (offset = 0; offset <= hdr->alloc_size; offset++) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (offset < hdr->alloc_size && mask[offset] != 0) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (!started) {
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen u32.offset = offset;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen started = TRUE;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen } else {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (started) {
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen u32.size = offset - u32.offset;
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen if (use_32)
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen buffer_append(buf, &u32, sizeof(u32));
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen else {
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen u.offset = u32.offset;
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen u.size = u32.size;
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen buffer_append(buf, &u, sizeof(u));
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen }
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen i_assert(u32.offset + u32.size <= ext_hdr_size);
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen buffer_append(buf, data + u32.offset, u32.size);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen started = FALSE;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (buf->used % 4 != 0)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen buffer_append_zero(buf, 4 - buf->used % 4);
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen log_append_buffer(ctx, buf, use_32 ? MAIL_TRANSACTION_EXT_HDR_UPDATE32 :
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen MAIL_TRANSACTION_EXT_HDR_UPDATE);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic void
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenmail_transaction_log_append_ext_intros(struct mail_index_export_context *ctx)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
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;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_transaction_ext_reset ext_reset;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen unsigned int resize_count, ext_count = 0;
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen unsigned int hdrs_count, reset_id_count, reset_count, hdr_size;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen uint32_t ext_id, reset_id;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen const struct mail_transaction_ext_reset *reset;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen const uint32_t *reset_ids;
8e361d2906b0e44f7175a20981f8d2280645b58bTimo Sirainen buffer_t reset_buf;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (!array_is_created(&t->ext_resizes)) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen resize = NULL;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen resize_count = 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen } else {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen resize = array_get(&t->ext_resizes, &resize_count);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (ext_count < resize_count)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen ext_count = resize_count;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (!array_is_created(&t->ext_reset_ids)) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen reset_ids = NULL;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen reset_id_count = 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen } else {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen reset_ids = array_get(&t->ext_reset_ids, &reset_id_count);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (!array_is_created(&t->ext_resets)) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen reset = NULL;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen reset_count = 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen } else {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen reset = array_get(&t->ext_resets, &reset_count);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (ext_count < reset_count)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen ext_count = reset_count;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (!array_is_created(&t->ext_hdr_updates)) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen hdrs = NULL;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen hdrs_count = 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen } else {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen hdrs = array_get(&t->ext_hdr_updates, &hdrs_count);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (ext_count < hdrs_count)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen ext_count = hdrs_count;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&ext_reset);
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
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen for (ext_id = 0; ext_id < ext_count; ext_id++) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (ext_id < reset_count)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen ext_reset = reset[ext_id];
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen else
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen ext_reset.new_reset_id = 0;
23bdbb7b1831785c6ba6df190f6369da882d2b9dTimo Sirainen if ((ext_id < resize_count && resize[ext_id].name_size > 0) ||
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen ext_reset.new_reset_id != 0 ||
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen (ext_id < hdrs_count && hdrs[ext_id].alloc_size > 0)) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (ext_reset.new_reset_id != 0) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* we're going to reset this extension
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen immediately after the intro */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen reset_id = 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen } else {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen reset_id = ext_id < reset_id_count ?
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen reset_ids[ext_id] : 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen log_append_ext_intro(ctx, ext_id, reset_id, &hdr_size);
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen } else {
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen hdr_size = 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (ext_reset.new_reset_id != 0) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen i_assert(ext_id < reset_id_count &&
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen ext_reset.new_reset_id == reset_ids[ext_id]);
8e361d2906b0e44f7175a20981f8d2280645b58bTimo Sirainen log_append_buffer(ctx, &reset_buf,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen MAIL_TRANSACTION_EXT_RESET);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (ext_id < hdrs_count && hdrs[ext_id].alloc_size > 0) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen T_BEGIN {
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen log_append_ext_hdr_update(ctx, &hdrs[ext_id],
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen hdr_size);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen } T_END;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic void log_append_ext_recs(struct mail_index_export_context *ctx,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen const ARRAY_TYPE(seq_array_array) *arr,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen enum mail_transaction_type type)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_index_transaction *t = ctx->trans;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen const ARRAY_TYPE(seq_array) *updates;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen const uint32_t *reset_ids;
3b8a19184c37851d9794178dd7a612ed8ed1c4f8Timo Sirainen unsigned int ext_id, count, reset_id_count, hdr_size;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen uint32_t reset_id;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (!array_is_created(&t->ext_reset_ids)) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen reset_ids = NULL;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen reset_id_count = 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen } else {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen reset_ids = array_get_modifiable(&t->ext_reset_ids,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen &reset_id_count);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen updates = array_get(arr, &count);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen for (ext_id = 0; ext_id < count; ext_id++) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (!array_is_created(&updates[ext_id]))
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen continue;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
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);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen log_append_buffer(ctx, updates[ext_id].arr.buffer, type);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic void
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{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_transaction_keyword_update kt_hdr;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
fad068d459cc7b04fedade4e0bb343be62e6d310Timo Sirainen i_assert(uid_buffer->used > 0);
fad068d459cc7b04fedade4e0bb343be62e6d310Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&kt_hdr);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen kt_hdr.modify_type = modify_type;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen kt_hdr.name_size = strlen(keyword);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen buffer_set_used_size(tmp_buf, 0);
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen buffer_append(tmp_buf, &kt_hdr, sizeof(kt_hdr));
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen buffer_append(tmp_buf, keyword, kt_hdr.name_size);
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen if ((tmp_buf->used % 4) != 0)
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen buffer_append_zero(tmp_buf, 4 - (tmp_buf->used % 4));
fad068d459cc7b04fedade4e0bb343be62e6d310Timo Sirainen buffer_append(tmp_buf, uid_buffer->data, uid_buffer->used);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen log_append_buffer(ctx, tmp_buf, MAIL_TRANSACTION_KEYWORD_UPDATE);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
4fbf718a46e608d0f67180cae3e6773a39149e20Timo Sirainenstatic bool
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenlog_append_keyword_updates(struct mail_index_export_context *ctx)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen const struct mail_index_transaction_keyword_update *updates;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen const char *const *keywords;
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen buffer_t *tmp_buf;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen unsigned int i, count, keywords_count;
4fbf718a46e608d0f67180cae3e6773a39149e20Timo Sirainen bool changed = FALSE;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
c147bff818798a979d93537f72f5c1f68f5d5ba8Aki Tuomi tmp_buf = t_buffer_create(64);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen keywords = array_get_modifiable(&ctx->trans->view->index->keywords,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen &keywords_count);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen updates = array_get_modifiable(&ctx->trans->keyword_updates, &count);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen i_assert(count <= keywords_count);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen for (i = 0; i < count; i++) {
fad068d459cc7b04fedade4e0bb343be62e6d310Timo Sirainen if (array_is_created(&updates[i].add_seq) &&
fad068d459cc7b04fedade4e0bb343be62e6d310Timo Sirainen array_count(&updates[i].add_seq) > 0) {
4fbf718a46e608d0f67180cae3e6773a39149e20Timo Sirainen changed = TRUE;
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen log_append_keyword_update(ctx, tmp_buf,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen MODIFY_ADD, keywords[i],
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen updates[i].add_seq.arr.buffer);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
fad068d459cc7b04fedade4e0bb343be62e6d310Timo Sirainen if (array_is_created(&updates[i].remove_seq) &&
fad068d459cc7b04fedade4e0bb343be62e6d310Timo Sirainen array_count(&updates[i].remove_seq) > 0) {
4fbf718a46e608d0f67180cae3e6773a39149e20Timo Sirainen changed = TRUE;
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen log_append_keyword_update(ctx, tmp_buf,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen MODIFY_REMOVE, keywords[i],
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen updates[i].remove_seq.arr.buffer);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
4fbf718a46e608d0f67180cae3e6773a39149e20Timo Sirainen return changed;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
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)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen static uint8_t null4[4] = { 0, 0, 0, 0 };
724b7fcf28c2547eb9c837d0e99241c0501dccf3Timo Sirainen enum mail_index_fsync_mask change_mask = 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_index_export_context ctx;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen *changes_r = 0;
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&ctx);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen ctx.trans = t;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen ctx.append_ctx = append_ctx;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen if (t->index_undeleted) {
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen i_assert(!t->index_deleted);
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen mail_transaction_log_append_add(ctx.append_ctx,
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen MAIL_TRANSACTION_INDEX_UNDELETED, &null4, 4);
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen }
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* send all extension introductions and resizes before appends
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen to avoid resize overhead as much as possible */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_transaction_log_append_ext_intros(&ctx);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (t->pre_hdr_changed) {
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen log_append_buffer(&ctx, log_get_hdr_update_buffer(t, TRUE),
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen MAIL_TRANSACTION_HEADER_UPDATE);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen if (append_ctx->output->used > 0)
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen *changes_r |= MAIL_INDEX_TRANSACTION_CHANGE_OTHERS;
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen if (t->attribute_updates != NULL) {
35e4905f732e1d25c71c47be3dbd747bc28cf642Timo Sirainen buffer_append_c(t->attribute_updates, '\0');
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen /* need to have 32bit alignment */
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen if (t->attribute_updates->used % 4 != 0) {
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen buffer_append_zero(t->attribute_updates,
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen 4 - t->attribute_updates->used % 4);
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen }
238812433b4f7965fd662dce0f4efccb092630a8Timo Sirainen /* append the timestamp and value lengths */
238812433b4f7965fd662dce0f4efccb092630a8Timo Sirainen buffer_append(t->attribute_updates,
238812433b4f7965fd662dce0f4efccb092630a8Timo Sirainen t->attribute_updates_suffix->data,
238812433b4f7965fd662dce0f4efccb092630a8Timo Sirainen t->attribute_updates_suffix->used);
238812433b4f7965fd662dce0f4efccb092630a8Timo Sirainen i_assert(t->attribute_updates->used % 4 == 0);
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen *changes_r |= MAIL_INDEX_TRANSACTION_CHANGE_ATTRIBUTE;
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen log_append_buffer(&ctx, t->attribute_updates,
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen MAIL_TRANSACTION_ATTRIBUTE_UPDATE);
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen }
de9d79337eca11a7f9c1cd476c74dfe4f09a4bd7Timo Sirainen if (array_is_created(&t->appends)) {
724b7fcf28c2547eb9c837d0e99241c0501dccf3Timo Sirainen change_mask |= MAIL_INDEX_FSYNC_MASK_APPENDS;
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen *changes_r |= MAIL_INDEX_TRANSACTION_CHANGE_APPEND;
de9d79337eca11a7f9c1cd476c74dfe4f09a4bd7Timo Sirainen log_append_buffer(&ctx, t->appends.arr.buffer,
de9d79337eca11a7f9c1cd476c74dfe4f09a4bd7Timo Sirainen MAIL_TRANSACTION_APPEND);
de9d79337eca11a7f9c1cd476c74dfe4f09a4bd7Timo Sirainen }
d1baa8c6f97cdb1b3c2c44a73cc21f9dfc7a963fTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (array_is_created(&t->updates)) {
724b7fcf28c2547eb9c837d0e99241c0501dccf3Timo Sirainen change_mask |= MAIL_INDEX_FSYNC_MASK_FLAGS;
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen *changes_r |= MAIL_INDEX_TRANSACTION_CHANGE_FLAGS;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen log_append_flag_updates(&ctx, t);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (array_is_created(&t->ext_rec_updates)) {
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen *changes_r |= MAIL_INDEX_TRANSACTION_CHANGE_OTHERS;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen log_append_ext_recs(&ctx, &t->ext_rec_updates,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen MAIL_TRANSACTION_EXT_REC_UPDATE);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (array_is_created(&t->ext_rec_atomics)) {
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen *changes_r |= MAIL_INDEX_TRANSACTION_CHANGE_OTHERS;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen log_append_ext_recs(&ctx, &t->ext_rec_atomics,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen MAIL_TRANSACTION_EXT_ATOMIC_INC);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
4fbf718a46e608d0f67180cae3e6773a39149e20Timo Sirainen if (array_is_created(&t->keyword_updates)) {
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen if (log_append_keyword_updates(&ctx)) {
4fbf718a46e608d0f67180cae3e6773a39149e20Timo Sirainen change_mask |= MAIL_INDEX_FSYNC_MASK_KEYWORDS;
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen *changes_r |= MAIL_INDEX_TRANSACTION_CHANGE_KEYWORDS;
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen }
4fbf718a46e608d0f67180cae3e6773a39149e20Timo Sirainen }
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen /* keep modseq updates almost last */
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen if (array_is_created(&t->modseq_updates)) {
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen *changes_r |= MAIL_INDEX_TRANSACTION_CHANGE_MODSEQ;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen log_append_buffer(&ctx, t->modseq_updates.arr.buffer,
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen MAIL_TRANSACTION_MODSEQ_UPDATE);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (array_is_created(&t->expunges)) {
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 } else {
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen *changes_r |= MAIL_INDEX_TRANSACTION_CHANGE_OTHERS;
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen }
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen log_append_buffer(&ctx, t->expunges.arr.buffer,
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen MAIL_TRANSACTION_EXPUNGE_GUID);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (t->post_hdr_changed) {
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen *changes_r |= MAIL_INDEX_TRANSACTION_CHANGE_OTHERS;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen log_append_buffer(&ctx, log_get_hdr_update_buffer(t, FALSE),
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen MAIL_TRANSACTION_HEADER_UPDATE);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
651fc0f1e43fef3e02e0e7b5f498973b05f641d7Timo Sirainen if (t->index_deleted) {
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen i_assert(!t->index_undeleted);
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen *changes_r |= MAIL_INDEX_TRANSACTION_CHANGE_OTHERS;
651fc0f1e43fef3e02e0e7b5f498973b05f641d7Timo Sirainen mail_transaction_log_append_add(ctx.append_ctx,
651fc0f1e43fef3e02e0e7b5f498973b05f641d7Timo Sirainen MAIL_TRANSACTION_INDEX_DELETED,
651fc0f1e43fef3e02e0e7b5f498973b05f641d7Timo Sirainen &null4, 4);
651fc0f1e43fef3e02e0e7b5f498973b05f641d7Timo Sirainen }
651fc0f1e43fef3e02e0e7b5f498973b05f641d7Timo Sirainen
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen i_assert((append_ctx->output->used > 0) == (*changes_r != 0));
6a0855a04d75bce3c0a2f68517d02f86ae72087fTimo Sirainen
082e82792b8ac33ad42beac510441b37a3c50737Timo Sirainen append_ctx->index_sync_transaction = t->sync_transaction;
082e82792b8ac33ad42beac510441b37a3c50737Timo Sirainen append_ctx->tail_offset_changed = t->tail_offset_changed;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen append_ctx->want_fsync =
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen (t->view->index->fsync_mask & change_mask) != 0 ||
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen (t->flags & MAIL_INDEX_TRANSACTION_FLAG_FSYNC) != 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainenstatic unsigned int
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainencount_modseq_incs_with(struct mail_index_transaction *t,
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen ARRAY_TYPE(seq_range) *tmp_seqs,
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen const ARRAY_TYPE(seq_range) *orig_seqs)
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen{
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen if (!array_is_created(orig_seqs))
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen return 0;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen array_clear(tmp_seqs);
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen array_append_array(tmp_seqs, orig_seqs);
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen mail_index_transaction_seq_range_to_uid(t, tmp_seqs);
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen return array_count(tmp_seqs) > 0 ? 1 : 0;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen}
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainenstatic unsigned int
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainenmail_index_transaction_keywords_count_modseq_incs(struct mail_index_transaction *t)
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen{
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen const struct mail_index_transaction_keyword_update *update;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen ARRAY_TYPE(seq_range) tmp_seqs;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen unsigned int count = 0;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen i_array_init(&tmp_seqs, 64);
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);
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen }
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen array_free(&tmp_seqs);
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen return count;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen}
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainenstatic bool
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainentransaction_flag_updates_have_non_internal(struct mail_index_transaction *t)
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen{
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen struct mail_transaction_log_file *file = t->view->index->log->head;
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen const uint8_t internal_flags =
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen MAIL_INDEX_MAIL_FLAG_BACKEND | MAIL_INDEX_MAIL_FLAG_DIRTY;
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen const struct mail_index_flag_update *u;
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen const unsigned int hdr_version =
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen MAIL_TRANSACTION_LOG_HDR_VERSION(&file->hdr);
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen
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 return array_count(&t->updates) > 0;
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen }
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen array_foreach(&t->updates, u) {
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen uint8_t changed_flags = u->add_flags | u->remove_flags;
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen if ((changed_flags & ~internal_flags) != 0)
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen return TRUE;
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen }
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen return FALSE;
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen}
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainenuint64_t mail_index_transaction_get_highest_modseq(struct mail_index_transaction *t)
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen{
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
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen i_assert(file->locked);
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen if (new_highest_modseq == 0) {
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 "(this shouldn't happen)", file->filepath);
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen return 0;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen }
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen /* finish everything that can affect highest-modseq */
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen mail_index_transaction_finish_so_far(t);
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen
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, */
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen new_highest_modseq++;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen }
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen if (array_is_created(&t->updates) &&
af0a12ae492d79e27b29d63ff0f289f9034fecc9Stephan Bosch transaction_flag_updates_have_non_internal(t))
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen new_highest_modseq++;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen if (array_is_created(&t->keyword_updates)) {
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen new_highest_modseq +=
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen mail_index_transaction_keywords_count_modseq_incs(t);
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen }
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen if (t->attribute_updates != NULL)
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen new_highest_modseq++;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen /* NOTE: the order of modseq_updates and everything following it
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen must match mail_index_transaction_export(). */
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen if (array_is_created(&t->modseq_updates)) {
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen const struct mail_transaction_modseq_update *mu;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen /* mail_index_update_highest_modseq() is handled here also,
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen as a special case of uid==0. */
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen array_foreach(&t->modseq_updates, mu) {
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen uint64_t modseq = ((uint64_t)mu->modseq_high32 << 32) |
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen mu->modseq_low32;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen if (new_highest_modseq < modseq)
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen new_highest_modseq = modseq;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen }
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen }
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen if (array_is_created(&t->expunges) && array_count(&t->expunges) > 0 &&
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen (t->flags & MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL) != 0)
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen new_highest_modseq++;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen return new_highest_modseq;
9e6d83a3ef6abb393eeebca423cfd0d8cb08d430Timo Sirainen}