mail-index-transaction-export.c revision fee561b9d9162b130e662914fcebc9dd99b5c320
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (c) 2003-2013 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 unsigned int i, count;
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 memset(&u, 0, sizeof(u));
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 buf = buffer_create_dynamic(pool_datastack_create(), 256);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen for (offset = 0; offset <= sizeof(t->pre_hdr_change); offset++) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (offset < sizeof(t->pre_hdr_change) && mask[offset]) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic void log_append_ext_intro(struct mail_index_export_context *ctx,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_index_transaction *t = ctx->trans;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_transaction_ext_intro *intro, *resizes;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen unsigned int count;
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 buf = buffer_create_dynamic(pool_datastack_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 /* generate a new intro structure */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen intro = buffer_append_space_unsafe(buf, sizeof(*intro));
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen intro->flags = MAIL_TRANSACTION_EXT_INTRO_FLAG_NO_SHRINK;
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,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen const struct mail_index_transaction_ext_hdr_update *hdr)
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen bool started = FALSE, use_32 = hdr->alloc_size >= 65536;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen memset(&u, 0, sizeof(u));
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen buf = buffer_create_dynamic(pool_datastack_create(), 256);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen for (offset = 0; offset <= hdr->alloc_size; offset++) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (offset < hdr->alloc_size && mask[offset] != 0) {
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;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen unsigned int hdrs_count, reset_id_count, reset_count;
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++) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if ((ext_id < resize_count && resize[ext_id].name_size) ||
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 */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (ext_id < hdrs_count && hdrs[ext_id].alloc_size > 0) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen log_append_ext_hdr_update(ctx, &hdrs[ext_id]);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic void log_append_ext_recs(struct mail_index_export_context *ctx,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_index_transaction *t = ctx->trans;
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;
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 const char *const *keywords;
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen tmp_buf = buffer_create_dynamic(pool_datastack_create(), 64);
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++) {
724b7fcf28c2547eb9c837d0e99241c0501dccf3Timo Sirainen change_mask |= MAIL_INDEX_FSYNC_MASK_KEYWORDS;
fad068d459cc7b04fedade4e0bb343be62e6d310Timo Sirainen if (array_is_created(&updates[i].remove_seq) &&
724b7fcf28c2547eb9c837d0e99241c0501dccf3Timo Sirainen change_mask |= MAIL_INDEX_FSYNC_MASK_KEYWORDS;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenvoid mail_index_transaction_export(struct mail_index_transaction *t,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_transaction_log_append_ctx *append_ctx)
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),
fee561b9d9162b130e662914fcebc9dd99b5c320Timo Sirainen /* need to have 32bit alignment */
de9d79337eca11a7f9c1cd476c74dfe4f09a4bd7Timo Sirainen log_append_buffer(&ctx, t->appends.arr.buffer,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen log_append_ext_recs(&ctx, &t->ext_rec_updates,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen log_append_ext_recs(&ctx, &t->ext_rec_atomics,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen change_mask |= log_append_keyword_updates(&ctx);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen /* keep modseq updates almost last */
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 */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if ((t->flags & MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL) != 0)
724b7fcf28c2547eb9c837d0e99241c0501dccf3Timo Sirainen change_mask |= MAIL_INDEX_FSYNC_MASK_EXPUNGES;
77bc2bda5b781c4ffddc8a74b175cf32e9e2c2ecTimo Sirainen log_append_buffer(&ctx, t->expunges.arr.buffer,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen log_append_buffer(&ctx, log_get_hdr_update_buffer(t, FALSE),
651fc0f1e43fef3e02e0e7b5f498973b05f641d7Timo Sirainen mail_transaction_log_append_add(ctx.append_ctx,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* Update the tail offsets only when committing the sync transaction.
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen Other transactions may not know the latest tail offset and might
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen end up shrinking it. (Alternatively the shrinking tail offsets could
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen just be ignored, which would probably work fine too.) */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen append_ctx->append_sync_offset = t->sync_transaction;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen (t->view->index->fsync_mask & change_mask) != 0 ||