mail-index-transaction-finish.c revision eab880d75fd73a80c7803289796d13e08e4b52cb
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen/* Copyright (c) 2003-2010 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-index-transaction-private.h"
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainenint mail_transaction_expunge_guid_cmp(const struct mail_transaction_expunge_guid *e1,
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen const struct mail_transaction_expunge_guid *e2)
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen{
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if (e1->uid < e2->uid)
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen return -1;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen else if (e1->uid > e2->uid)
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen return 1;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen else
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen return 0;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen}
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainenvoid mail_index_transaction_sort_expunges(struct mail_index_transaction *t)
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen{
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if (!t->expunges_nonsorted)
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen return;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen array_sort(&t->expunges, mail_transaction_expunge_guid_cmp);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen t->expunges_nonsorted = FALSE;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen}
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic void
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenext_reset_update_atomic(struct mail_index_transaction *t,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen uint32_t ext_id, uint32_t expected_reset_id)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen const struct mail_index_ext *map_ext;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_transaction_ext_reset *reset;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen uint32_t idx, reset_id;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (!mail_index_map_get_ext_idx(t->view->index->map, ext_id, &idx)) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* new extension */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen reset_id = 1;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen } else {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen map_ext = array_idx(&t->view->index->map->extensions, idx);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen reset_id = map_ext->reset_id + 1;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (reset_id != expected_reset_id) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* ignore this extension update */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_index_ext_set_reset_id(t, ext_id, 0);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (reset_id == 0)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen reset_id++;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen array_idx_set(&t->ext_reset_ids, ext_id, &reset_id);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* reseting existing data is optional */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (array_is_created(&t->ext_resets)) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen reset = array_idx_modifiable(&t->ext_resets, ext_id);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (reset->new_reset_id == (uint32_t)-1)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen reset->new_reset_id = reset_id;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic void
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainentransaction_update_atomic_reset_ids(struct mail_index_transaction *t)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen const uint32_t *expected_reset_ids;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen unsigned int ext_id, count;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (!array_is_created(&t->ext_reset_atomic))
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen expected_reset_ids = array_get(&t->ext_reset_atomic, &count);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen for (ext_id = 0; ext_id < count; ext_id++) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (expected_reset_ids[ext_id] != 0) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen ext_reset_update_atomic(t, ext_id,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen expected_reset_ids[ext_id]);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainenstatic unsigned int
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainenmail_transaction_drop_range(struct mail_index_transaction *t,
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen struct mail_transaction_flag_update update,
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen unsigned int update_idx,
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen ARRAY_TYPE(seq_range) *keeps)
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen{
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen const struct seq_range *keep_range;
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen unsigned int i, keep_count;
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen keep_range = array_get(keeps, &keep_count);
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen if (keep_count == 1 &&
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen update.uid1 == keep_range[0].seq1 &&
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen update.uid2 == keep_range[0].seq2) {
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen /* evereything is kept */
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen return update_idx + 1;
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen }
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen array_delete(&t->updates, update_idx, 1);
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen /* add back all the updates we want to keep */
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen for (i = 0; i < keep_count; i++, update_idx++) {
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen update.uid1 = keep_range[i].seq1;
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen update.uid2 = keep_range[i].seq2;
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen array_insert(&t->updates, update_idx, &update, 1);
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen }
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen return update_idx;
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen}
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainenstatic void
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainenmail_index_transaction_finish_flag_updates(struct mail_index_transaction *t)
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen{
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen const struct mail_transaction_flag_update *updates, *u;
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen const struct mail_index_record *rec;
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen unsigned int i, count;
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen ARRAY_TYPE(seq_range) keeps;
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen uint32_t seq;
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen if (!t->drop_unnecessary_flag_updates || !array_is_created(&t->updates))
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen return;
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen t_array_init(&keeps, 64);
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen updates = array_get(&t->updates, &count);
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen for (i = 0; i < count; ) {
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen /* first get the list of changes to drop */
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen u = &updates[i];
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen array_clear(&keeps);
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen for (seq = u->uid1; seq <= u->uid2; seq++) {
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen rec = mail_index_lookup(t->view, seq);
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen if ((rec->flags & u->add_flags) != u->add_flags ||
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen (rec->flags & u->remove_flags) != 0) {
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen /* keep this change */
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen seq_range_array_add(&keeps, 0, seq);
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen }
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen }
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen i = mail_transaction_drop_range(t, updates[i], i, &keeps);
bed3fcccce6a15dfd7491e82df10acd5f5c0bc9bTimo Sirainen updates = array_get(&t->updates, &count);
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen }
e06147cec0f68a6a9d08b38785c36d00ef73868aTimo Sirainen
e06147cec0f68a6a9d08b38785c36d00ef73868aTimo Sirainen if (array_count(&t->updates) == 0)
e06147cec0f68a6a9d08b38785c36d00ef73868aTimo Sirainen array_free(&t->updates);
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen}
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic void
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenmail_index_transaction_check_conflicts(struct mail_index_transaction *t)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen uint32_t seq;
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen bool ret1, ret2;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen i_assert(t->max_modseq != 0);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen i_assert(t->conflict_seqs != NULL);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (t->max_modseq == mail_index_modseq_get_highest(t->view)) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* no conflicts possible */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (t->min_flagupdate_seq == 0) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* no flag updates */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen for (seq = t->min_flagupdate_seq; seq <= t->max_flagupdate_seq; seq++) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (mail_index_modseq_lookup(t->view, seq) > t->max_modseq) {
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen ret1 = mail_index_cancel_flag_updates(t, seq);
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen ret2 = mail_index_cancel_keyword_updates(t, seq);
02bb8313a711dfe50c7f01e8132e13ca93ecfb42Timo Sirainen if (ret1 || ret2)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen seq_range_array_add(t->conflict_seqs, 0, seq);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_index_transaction_set_log_updates(t);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic uint32_t
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenmail_index_transaction_get_uid(struct mail_index_transaction *t, uint32_t seq)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen const struct mail_index_record *rec;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen i_assert(seq > 0);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (seq >= t->first_new_seq)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen rec = mail_index_transaction_lookup(t, seq);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen else {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen i_assert(seq <= t->view->map->hdr.messages_count);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen rec = MAIL_INDEX_MAP_IDX(t->view->map, seq - 1);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen i_assert(rec->uid != 0);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return rec->uid;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic void
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenmail_index_convert_to_uids(struct mail_index_transaction *t,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen ARRAY_TYPE(seq_array) *array)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen uint32_t *seq;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen unsigned int i, count;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (!array_is_created(array))
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen count = array_count(array);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen for (i = 0; i < count; i++) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen seq = array_idx_modifiable(array, i);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen *seq = mail_index_transaction_get_uid(t, *seq);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic uint32_t
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenget_nonexpunged_uid2(struct mail_index_transaction *t,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen uint32_t uid1, uint32_t seq1)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen seq1++;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen while (mail_index_transaction_get_uid(t, seq1) == uid1 + 1) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen seq1++;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen uid1++;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return uid1;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic void
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenmail_index_convert_to_uid_ranges(struct mail_index_transaction *t,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen ARRAY_TYPE(seq_range) *array)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct seq_range *range, *new_range;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen unsigned int i, count;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen uint32_t uid1, uid2;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (!array_is_created(array))
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen count = array_count(array);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen for (i = 0; i < count; i++) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen range = array_idx_modifiable(array, i);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen uid1 = mail_index_transaction_get_uid(t, range->seq1);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen uid2 = mail_index_transaction_get_uid(t, range->seq2);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (uid2 - uid1 == range->seq2 - range->seq1) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* simple conversion */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen range->seq1 = uid1;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen range->seq2 = uid2;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen } else {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* remove expunged UIDs */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen new_range = array_insert_space(array, i);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen range = array_idx_modifiable(array, i + 1);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen count++;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen memcpy(new_range, range, array->arr.element_size);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen new_range->seq1 = uid1;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen new_range->seq2 = get_nonexpunged_uid2(t, uid1,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen range->seq1);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* continue the range without the inserted seqs */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen range->seq1 += new_range->seq2 - new_range->seq1 + 1;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic void keyword_updates_convert_to_uids(struct mail_index_transaction *t)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen struct mail_index_transaction_keyword_update *update;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (!array_is_created(&t->keyword_updates))
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen array_foreach_modifiable(&t->keyword_updates, update) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_index_convert_to_uid_ranges(t, &update->add_seq);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_index_convert_to_uid_ranges(t, &update->remove_seq);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainenstatic void expunges_convert_to_uids(struct mail_index_transaction *t)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen struct mail_transaction_expunge_guid *expunges;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen unsigned int src, dest, count;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if (!array_is_created(&t->expunges))
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen return;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen mail_index_transaction_sort_expunges(t);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen expunges = array_get_modifiable(&t->expunges, &count);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if (count == 0)
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen return;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen /* convert uids and drop duplicates */
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen expunges[0].uid = mail_index_transaction_get_uid(t, expunges[0].uid);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen for (src = dest = 1; src < count; src++) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen expunges[dest].uid =
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen mail_index_transaction_get_uid(t, expunges[src].uid);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if (expunges[dest-1].uid != expunges[dest].uid) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen memcpy(expunges[dest].guid_128, expunges[src].guid_128,
3a017aa592823edf0363d77f13458d569637915eTimo Sirainen sizeof(expunges[dest].guid_128));
3a017aa592823edf0363d77f13458d569637915eTimo Sirainen dest++;
3a017aa592823edf0363d77f13458d569637915eTimo Sirainen }
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen }
3a017aa592823edf0363d77f13458d569637915eTimo Sirainen array_delete(&t->expunges, dest, count-dest);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen}
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainenstatic void
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainenmail_index_transaction_convert_to_uids(struct mail_index_transaction *t)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen ARRAY_TYPE(seq_array) *update;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (array_is_created(&t->ext_rec_updates)) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen array_foreach_modifiable(&t->ext_rec_updates, update)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_index_convert_to_uids(t, update);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (array_is_created(&t->ext_rec_atomics)) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen array_foreach_modifiable(&t->ext_rec_atomics, update)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_index_convert_to_uids(t, update);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen keyword_updates_convert_to_uids(t);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen expunges_convert_to_uids(t);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_index_convert_to_uids(t, (void *)&t->modseq_updates);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_index_convert_to_uid_ranges(t, (void *)&t->updates);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_index_convert_to_uid_ranges(t, &t->keyword_resets);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainenint mail_index_transaction_finish(struct mail_index_transaction *t)
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen{
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (array_is_created(&t->appends)) {
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_index_update_day_headers(t);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_index_transaction_sort_appends(t);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_index_transaction_finish_flag_updates(t);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
b346610430690398b8c840006004a2df4aa8ce92Timo Sirainen if (array_is_created(&t->ext_reset_atomic) || t->max_modseq != 0) {
b346610430690398b8c840006004a2df4aa8ce92Timo Sirainen if (mail_index_map(t->view->index,
b346610430690398b8c840006004a2df4aa8ce92Timo Sirainen MAIL_INDEX_SYNC_HANDLER_HEAD) <= 0)
b346610430690398b8c840006004a2df4aa8ce92Timo Sirainen return -1;
54b51a9c2705a19dfb1639647bc7e9378e37f881Timo Sirainen }
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (array_is_created(&t->ext_reset_atomic))
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen transaction_update_atomic_reset_ids(t);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (t->max_modseq != 0)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_index_transaction_check_conflicts(t);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* finally convert all sequences to UIDs before we write them,
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen but after we've checked and removed conflicts */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_index_transaction_convert_to_uids(t);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen /* and kind of ugly way to update highest modseq */
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen if (t->min_highest_modseq != 0)
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen mail_index_update_modseq(t, 0, t->min_highest_modseq);
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen return 0;
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen}
1279090ba03f9c176976a69ab7718f0ed77b19afTimo Sirainen