static void log_append_flag_updates(struct mail_index_export_context *ctx, struct mail_index_transaction *t) { ARRAY(struct mail_transaction_flag_update) log_updates; const struct mail_index_flag_update *updates; struct mail_transaction_flag_update *log_update; unsigned int i, count; updates = array_get(&t->updates, &count); if (count == 0) return; i_array_init(&log_updates, count); for (i = 0; i < count; i++) { log_update = array_append_space(&log_updates); log_update->uid1 = updates[i].uid1; log_update->uid2 = updates[i].uid2; log_update->add_flags = updates[i].add_flags & 0xff; log_update->remove_flags = updates[i].remove_flags & 0xff; if ((updates[i].add_flags & MAIL_INDEX_MAIL_FLAG_UPDATE_MODSEQ) != 0) log_update->modseq_inc_flag = 1; } log_append_buffer(ctx, log_updates.arr.buffer, MAIL_TRANSACTION_FLAG_UPDATE); array_free(&log_updates); }
static void log_append_ext_hdr_update(struct mail_index_export_context *ctx, const struct mail_index_transaction_ext_hdr_update *hdr) { buffer_t *buf; const unsigned char *data, *mask; struct mail_transaction_ext_hdr_update u; struct mail_transaction_ext_hdr_update32 u32; size_t offset; bool started = FALSE, use_32 = hdr->alloc_size >= 65536; memset(&u, 0, sizeof(u)); memset(&u32, 0, sizeof(u32)); data = hdr->data; mask = hdr->mask; buf = buffer_create_dynamic(pool_datastack_create(), 256); for (offset = 0; offset <= hdr->alloc_size; offset++) { if (offset < hdr->alloc_size && mask[offset] != 0) { if (!started) { u32.offset = offset; started = TRUE; } } else { if (started) { u32.size = offset - u32.offset; if (use_32) buffer_append(buf, &u32, sizeof(u32)); else { u.offset = u32.offset; u.size = u32.size; buffer_append(buf, &u, sizeof(u)); } buffer_append(buf, data + u32.offset, u32.size); started = FALSE; } } } if (buf->used % 4 != 0) buffer_append_zero(buf, 4 - buf->used % 4); log_append_buffer(ctx, buf, use_32 ? MAIL_TRANSACTION_EXT_HDR_UPDATE32 : MAIL_TRANSACTION_EXT_HDR_UPDATE); }
static void log_append_ext_intro(struct mail_index_export_context *ctx, uint32_t ext_id, uint32_t reset_id) { struct mail_index_transaction *t = ctx->trans; const struct mail_index_registered_ext *rext; struct mail_transaction_ext_intro *intro, *resizes; buffer_t *buf; uint32_t idx; unsigned int count; i_assert(ext_id != (uint32_t)-1); if (t->reset || !mail_index_map_get_ext_idx(t->view->index->map, ext_id, &idx)) { /* new extension */ idx = (uint32_t)-1; } rext = array_idx(&t->view->index->extensions, ext_id); if (!array_is_created(&t->ext_resizes)) { resizes = NULL; count = 0; } else { resizes = array_get_modifiable(&t->ext_resizes, &count); } buf = buffer_create_dynamic(pool_datastack_create(), 128); if (ext_id < count && resizes[ext_id].name_size != 0) { /* we're resizing the extension. use the resize struct. */ intro = &resizes[ext_id]; i_assert(intro->ext_id == idx); intro->name_size = idx != (uint32_t)-1 ? 0 : strlen(rext->name); buffer_append(buf, intro, sizeof(*intro)); } else { /* generate a new intro structure */ intro = buffer_append_space_unsafe(buf, sizeof(*intro)); intro->ext_id = idx; intro->hdr_size = rext->hdr_size; intro->record_size = rext->record_size; intro->record_align = rext->record_align; intro->flags = MAIL_TRANSACTION_EXT_INTRO_FLAG_NO_SHRINK; intro->name_size = idx != (uint32_t)-1 ? 0 : strlen(rext->name); } if (reset_id != 0) { /* we're going to reset this extension in this transaction */ intro->reset_id = reset_id; } else if (idx != (uint32_t)-1) { /* use the existing reset_id */ const struct mail_index_ext *map_ext = array_idx(&t->view->index->map->extensions, idx); intro->reset_id = map_ext->reset_id; } else { /* new extension, reset_id defaults to 0 */ } buffer_append(buf, rext->name, intro->name_size); if ((buf->used % 4) != 0) buffer_append_zero(buf, 4 - (buf->used % 4)); if (ctx->append_ctx->new_highest_modseq == 0 && strcmp(rext->name, MAIL_INDEX_MODSEQ_EXT_NAME) == 0) { /* modseq tracking started */ ctx->append_ctx->new_highest_modseq = 1; } log_append_buffer(ctx, buf, MAIL_TRANSACTION_EXT_INTRO); }
static void mail_transaction_log_append_ext_intros(struct mail_index_export_context *ctx) { struct mail_index_transaction *t = ctx->trans; const struct mail_transaction_ext_intro *resize; const struct mail_index_transaction_ext_hdr_update *hdrs; struct mail_transaction_ext_reset ext_reset; unsigned int resize_count, ext_count = 0; unsigned int hdrs_count, reset_id_count, reset_count; uint32_t ext_id, reset_id; const struct mail_transaction_ext_reset *reset; const uint32_t *reset_ids; buffer_t reset_buf; if (!array_is_created(&t->ext_resizes)) { resize = NULL; resize_count = 0; } else { resize = array_get(&t->ext_resizes, &resize_count); if (ext_count < resize_count) ext_count = resize_count; } if (!array_is_created(&t->ext_reset_ids)) { reset_ids = NULL; reset_id_count = 0; } else { reset_ids = array_get(&t->ext_reset_ids, &reset_id_count); } if (!array_is_created(&t->ext_resets)) { reset = NULL; reset_count = 0; } else { reset = array_get(&t->ext_resets, &reset_count); if (ext_count < reset_count) ext_count = reset_count; } if (!array_is_created(&t->ext_hdr_updates)) { hdrs = NULL; hdrs_count = 0; } else { hdrs = array_get(&t->ext_hdr_updates, &hdrs_count); if (ext_count < hdrs_count) ext_count = hdrs_count; } memset(&ext_reset, 0, sizeof(ext_reset)); buffer_create_data(&reset_buf, &ext_reset, sizeof(ext_reset)); buffer_set_used_size(&reset_buf, sizeof(ext_reset)); for (ext_id = 0; ext_id < ext_count; ext_id++) { if (ext_id < reset_count) ext_reset = reset[ext_id]; else ext_reset.new_reset_id = 0; if ((ext_id < resize_count && resize[ext_id].name_size) || ext_reset.new_reset_id != 0 || (ext_id < hdrs_count && hdrs[ext_id].alloc_size > 0)) { if (ext_reset.new_reset_id != 0) { /* we're going to reset this extension immediately after the intro */ reset_id = 0; } else { reset_id = ext_id < reset_id_count ? reset_ids[ext_id] : 0; } log_append_ext_intro(ctx, ext_id, reset_id); } if (ext_reset.new_reset_id != 0) { i_assert(ext_id < reset_id_count && ext_reset.new_reset_id == reset_ids[ext_id]); log_append_buffer(ctx, &reset_buf, MAIL_TRANSACTION_EXT_RESET); } if (ext_id < hdrs_count && hdrs[ext_id].alloc_size > 0) { T_BEGIN { log_append_ext_hdr_update(ctx, &hdrs[ext_id]); } T_END; } }