mail-index-transaction.c revision 287ba82a8da3eaa473b5735d4eeac2fb4c5d8117
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
659fe5d24825b160cae512538088020d97a60239Timo Sirainen/* Inside transaction we keep messages stored in sequences in uid fields.
659fe5d24825b160cae512538088020d97a60239Timo Sirainen Before they're written to transaction log the sequences are changed to
659fe5d24825b160cae512538088020d97a60239Timo Sirainen UIDs. This is because we're able to compress sequence ranges better. */
659fe5d24825b160cae512538088020d97a60239Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "buffer.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-index-view-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-transaction-log.h"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#include "mail-cache-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-index-transaction-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen#include <stddef.h>
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen#include <stdlib.h>
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct mail_index_transaction *
7c95b03620a03a43dd72d39608cea5fc77393ad6Timo Sirainenmail_index_transaction_begin(struct mail_index_view *view,
7c95b03620a03a43dd72d39608cea5fc77393ad6Timo Sirainen int hide, int external)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_index_transaction *t;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* don't allow syncing view while there's ongoing transactions */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_view_transaction_ref(view);
e8acc691a14a6d0884c5ca9aa4d8507f1e082040Timo Sirainen mail_index_view_ref(view);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen t = i_new(struct mail_index_transaction, 1);
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen t->refcount = 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen t->view = view;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen t->hide_transaction = hide;
7c95b03620a03a43dd72d39608cea5fc77393ad6Timo Sirainen t->external = external;
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen t->first_new_seq = mail_index_view_get_messages_count(t->view)+1;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen if (view->syncing) {
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen /* transaction view cannot work if new records are being added
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen in two places. make sure it doesn't happen. */
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen t->no_appends = TRUE;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen }
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return t;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void mail_index_transaction_free(struct mail_index_transaction *t)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_t *recs;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen unsigned i, count;
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (array_is_created(&t->ext_rec_updates)) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen recs = array_get_modifyable(&t->ext_rec_updates, &count);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen for (i = 0; i < count; i++) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (array_is_created(&recs[i]))
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_free(&recs[i]);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_free(&t->ext_rec_updates);
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen }
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (array_is_created(&t->keyword_updates)) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen recs = array_get_modifyable(&t->keyword_updates, &count);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen for (i = 0; i < count; i++) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (array_is_created(&recs[i]))
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_free(&recs[i]);
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen }
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_free(&t->keyword_updates);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen }
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (array_is_created(&t->keyword_resets))
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_free(&t->keyword_resets);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (array_is_created(&t->appends))
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_free(&t->appends);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (array_is_created(&t->expunges))
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_free(&t->expunges);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (array_is_created(&t->updates))
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_free(&t->updates);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (array_is_created(&t->ext_resizes))
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_free(&t->ext_resizes);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (array_is_created(&t->ext_resets))
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_free(&t->ext_resets);
e8acc691a14a6d0884c5ca9aa4d8507f1e082040Timo Sirainen
e8acc691a14a6d0884c5ca9aa4d8507f1e082040Timo Sirainen mail_index_view_transaction_unref(t->view);
e8acc691a14a6d0884c5ca9aa4d8507f1e082040Timo Sirainen mail_index_view_close(t->view);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_free(t);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainenvoid mail_index_transaction_ref(struct mail_index_transaction *t)
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen{
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen t->refcount++;
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen}
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainenvoid mail_index_transaction_unref(struct mail_index_transaction *t)
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen{
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen if (--t->refcount == 0)
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen mail_index_transaction_free(t);
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen}
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen
659fe5d24825b160cae512538088020d97a60239Timo Sirainenstatic void
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenmail_index_buffer_convert_to_uids(struct mail_index_transaction *t,
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_t *array, int range)
659fe5d24825b160cae512538088020d97a60239Timo Sirainen{
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen ARRAY_ARG_SET_TYPE(array, uint32_t);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen struct mail_index_view *view = t->view;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen const struct mail_index_record *rec;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen uint32_t *seq;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen unsigned int i, count;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen int j;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (!array_is_created(array))
659fe5d24825b160cae512538088020d97a60239Timo Sirainen return;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen count = array_count(array);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen for (i = 0; i < count; i++) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen seq = array_modifyable_idx(array, i);
659fe5d24825b160cae512538088020d97a60239Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen for (j = 0; j <= range; j++, seq++) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (*seq >= t->first_new_seq) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen rec = mail_index_transaction_lookup(t, *seq);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen *seq = rec->uid;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen } else {
9d8d1efcc1274ef4d8413c3687549b297d81da10Timo Sirainen i_assert(*seq <= view->map->records_count);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen *seq = MAIL_INDEX_MAP_IDX(view->map,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen *seq - 1)->uid;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen i_assert(*seq != 0);
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen }
659fe5d24825b160cae512538088020d97a60239Timo Sirainen }
659fe5d24825b160cae512538088020d97a60239Timo Sirainen}
659fe5d24825b160cae512538088020d97a60239Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainenstatic void arrays_convert_to_uids(struct mail_index_transaction *t,
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_t *array)
659fe5d24825b160cae512538088020d97a60239Timo Sirainen{
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen ARRAY_ARG_SET_TYPE(array, array_t);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_t *updates;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen unsigned int i, count;
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (!array_is_created(array))
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen return;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen updates = array_get_modifyable(array, &count);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen for (i = 0; i < count; i++) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (array_is_created(&updates[i])) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen mail_index_buffer_convert_to_uids(t, &updates[i],
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen FALSE);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen }
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen}
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainenstatic int
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainenmail_index_transaction_convert_to_uids(struct mail_index_transaction *t)
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen{
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (mail_index_view_lock(t->view) < 0)
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen return -1;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen arrays_convert_to_uids(t, &t->ext_rec_updates);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen arrays_convert_to_uids(t, &t->keyword_updates);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen mail_index_buffer_convert_to_uids(t, &t->expunges, TRUE);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen mail_index_buffer_convert_to_uids(t, &t->updates, TRUE);
659fe5d24825b160cae512538088020d97a60239Timo Sirainen return 0;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen}
659fe5d24825b160cae512538088020d97a60239Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mail_index_transaction_commit(struct mail_index_transaction *t,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uint32_t *log_file_seq_r,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uoff_t *log_file_offset_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mail_index_view_is_inconsistent(t->view)) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen mail_index_transaction_rollback(t);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (t->cache_trans_ctx != NULL) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen mail_cache_transaction_commit(t->cache_trans_ctx);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen t->cache_trans_ctx = NULL;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
659fe5d24825b160cae512538088020d97a60239Timo Sirainen if (mail_index_transaction_convert_to_uids(t) < 0)
659fe5d24825b160cae512538088020d97a60239Timo Sirainen ret = -1;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen else {
659fe5d24825b160cae512538088020d97a60239Timo Sirainen ret = mail_transaction_log_append(t, log_file_seq_r,
659fe5d24825b160cae512538088020d97a60239Timo Sirainen log_file_offset_r);
659fe5d24825b160cae512538088020d97a60239Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen mail_index_transaction_unref(t);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_index_transaction_rollback(struct mail_index_transaction *t)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (t->cache_trans_ctx != NULL) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen mail_cache_transaction_rollback(t->cache_trans_ctx);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen t->cache_trans_ctx = NULL;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen }
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen mail_index_transaction_unref(t);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainenstruct mail_index_record *
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainenmail_index_transaction_lookup(struct mail_index_transaction *t, uint32_t seq)
b44a50ea4123f21dfc8e1b6c602f690fd9721b67Timo Sirainen{
b44a50ea4123f21dfc8e1b6c602f690fd9721b67Timo Sirainen i_assert(seq >= t->first_new_seq && seq <= t->last_new_seq);
b44a50ea4123f21dfc8e1b6c602f690fd9721b67Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen return array_modifyable_idx(&t->appends, seq - t->first_new_seq);
b44a50ea4123f21dfc8e1b6c602f690fd9721b67Timo Sirainen}
b44a50ea4123f21dfc8e1b6c602f690fd9721b67Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_index_append(struct mail_index_transaction *t, uint32_t uid,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uint32_t *seq_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_index_record *rec;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen i_assert(!t->no_appends);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen
73e7998716853b5b7621c06aea0022dccda70ad1Timo Sirainen t->log_updates = TRUE;
73e7998716853b5b7621c06aea0022dccda70ad1Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (!array_is_created(&t->appends)) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen ARRAY_CREATE(&t->appends, default_pool,
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen struct mail_index_record, 32);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* sequence number is visible only inside given view,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen so let it generate it */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (t->last_new_seq != 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *seq_r = ++t->last_new_seq;
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen else
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen *seq_r = t->last_new_seq = t->first_new_seq;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen rec = array_modifyable_append(&t->appends);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen rec->uid = uid;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainenvoid mail_index_append_assign_uids(struct mail_index_transaction *t,
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen uint32_t first_uid, uint32_t *next_uid_r)
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen{
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen struct mail_index_record *recs;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen unsigned int i, count;
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (!array_is_created(&t->appends))
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen return;
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen recs = array_get_modifyable(&t->appends, &count);
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen /* find the first mail with uid = 0 */
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen for (i = 0; i < count; i++) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (recs[i].uid == 0)
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen break;
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen }
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen for (; i < count; i++) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen i_assert(recs[i].uid == 0);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen recs[i].uid = first_uid++;
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen }
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen *next_uid_r = first_uid;
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen}
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenstruct seq_range {
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen uint32_t seq1, seq2;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen};
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainenstatic void
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainenmail_index_seq_range_array_add(array_t *array, unsigned int init_count,
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen uint32_t seq)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen ARRAY_ARG_SET_TYPE(array, struct seq_range);
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen struct seq_range *data, value;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen unsigned int idx, left_idx, right_idx, count;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen value.seq1 = value.seq2 = seq;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (!array_is_created(array)) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_create(array, default_pool,
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen sizeof(struct seq_range), init_count);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_append(array, &value, 1);
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen return;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen }
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen data = array_get_modifyable(array, &count);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen i_assert(count > 0);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* quick checks */
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (data[count-1].seq2 == seq-1) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* grow last range */
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen data[count-1].seq2 = seq;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (data[count-1].seq2 < seq) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_append(array, &value, 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (data[0].seq1 == seq+1) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* grow down first range */
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen data[0].seq1 = seq;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (data[0].seq1 > seq) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_insert(array, 0, &value, 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* somewhere in the middle, array is sorted so find it with
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen binary search */
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen idx = 0; left_idx = 0; right_idx = count;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen while (left_idx < right_idx) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen idx = (left_idx + right_idx) / 2;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (data[idx].seq1 <= seq) {
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (data[idx].seq2 >= seq) {
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen /* it's already in the range */
47d1fae2fa2964faa70d9e656d6c3995a1066eaeTimo Sirainen return;
47d1fae2fa2964faa70d9e656d6c3995a1066eaeTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen left_idx = idx+1;
47d1fae2fa2964faa70d9e656d6c3995a1066eaeTimo Sirainen } else {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen right_idx = idx;
47d1fae2fa2964faa70d9e656d6c3995a1066eaeTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (data[idx].seq2 < seq)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen idx++;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen /* idx == count couldn't happen because we already handle it above */
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen i_assert(idx < count && data[idx].seq1 >= seq);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen i_assert(data[idx].seq1 > seq || data[idx].seq2 < seq);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (data[idx].seq1 == seq+1) {
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen data[idx].seq1 = seq;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (idx > 0 && data[idx-1].seq2 == seq-1) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* merge */
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen data[idx-1].seq2 = data[idx].seq2;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_delete(array, idx, 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen } else if (data[idx].seq2 == seq-1) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen i_assert(idx+1 < count); /* already handled above */
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen data[idx].seq2 = seq;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (data[idx+1].seq1 == seq+1) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* merge */
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen data[idx+1].seq1 = data[idx].seq1;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_delete(array, idx, 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } else {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_insert(array, idx, &value, 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainenstatic void mail_index_seq_range_array_remove(array_t *array, uint32_t seq)
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen{
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen ARRAY_ARG_SET_TYPE(array, struct seq_range);
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen struct seq_range *data, value;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen unsigned int idx, left_idx, right_idx, count;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (!array_is_created(array))
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen return;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen data = array_get_modifyable(array, &count);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen i_assert(count > 0);
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen /* quick checks */
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (seq > data[count-1].seq2 || seq < data[0].seq1) {
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen /* outside the range */
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen return;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen }
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (data[count-1].seq2 == seq) {
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen /* shrink last range */
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen data[count-1].seq2--;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen return;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen }
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen if (data[0].seq1 == seq) {
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen /* shrink up first range */
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen data[0].seq1++;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen return;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen }
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen /* somewhere in the middle, array is sorted so find it with
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen binary search */
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen idx = 0; left_idx = 0; right_idx = count;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen while (left_idx < right_idx) {
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen idx = (left_idx + right_idx) / 2;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen if (data[idx].seq1 > seq)
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen right_idx = idx;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen else if (data[idx].seq2 < seq)
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen left_idx = idx+1;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen else {
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen /* found it */
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen if (data[idx].seq1 == seq) {
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen if (data[idx].seq1 == data[idx].seq2) {
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen /* a single sequence range.
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen remove it entirely */
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_delete(array, idx, 1);
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen } else {
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen /* shrink the range */
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen data[idx].seq1++;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen }
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen } else if (data[idx].seq2 == seq) {
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen /* shrink the range */
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen data[idx].seq2--;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen } else {
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen /* split the sequence range */
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen value.seq1 = seq + 1;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen value.seq2 = data[idx].seq2;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen data[idx].seq2 = seq - 1;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_insert(array, idx, &value, 1);
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen }
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen break;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen }
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen }
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen}
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenvoid mail_index_expunge(struct mail_index_transaction *t, uint32_t seq)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen{
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen i_assert(seq > 0 && seq <= mail_index_view_get_messages_count(t->view));
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen t->log_updates = TRUE;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen /* expunges is a sorted array of {seq1, seq2, ..}, .. */
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen mail_index_seq_range_array_add(&t->expunges, 128, seq);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen}
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainenstatic void
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainenmail_index_insert_flag_update(struct mail_index_transaction *t,
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen struct mail_transaction_flag_update u,
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen uint32_t left_idx, uint32_t right_idx)
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen{
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen struct mail_transaction_flag_update *updates, tmp_update;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen unsigned int count;
3127020d0ae64cd75bb428bdee42391376b9dd74Timo Sirainen uint32_t idx, move;
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen updates = array_get_modifyable(&t->updates, &count);
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen i_assert(left_idx <= right_idx && right_idx <= count);
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen /* find the first update with either overlapping range,
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen or the update which will come after our insert */
f84ef9754f697526ee11a2fb0e99fc6d390e0619Timo Sirainen idx = left_idx;
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen while (left_idx < right_idx) {
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen idx = (left_idx + right_idx) / 2;
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen
ba665db60cf64cbe6e3ac67822de72101ec6fd36Timo Sirainen if (updates[idx].uid2 < u.uid1)
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen left_idx = idx+1;
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen else if (updates[idx].uid1 > u.uid1)
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen right_idx = idx;
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen else
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen break;
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen }
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (idx < count && updates[idx].uid2 < u.uid1)
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen idx++;
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen /* overlapping ranges, split/merge them */
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen i_assert(idx == 0 || updates[idx-1].uid2 < u.uid1);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen i_assert(idx == count || updates[idx].uid2 >= u.uid1);
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen for (; idx < count && u.uid2 >= updates[idx].uid1; idx++) {
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen if (u.uid1 != updates[idx].uid1 &&
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen (updates[idx].add_flags != u.add_flags ||
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen updates[idx].remove_flags != u.remove_flags)) {
3127020d0ae64cd75bb428bdee42391376b9dd74Timo Sirainen if (u.uid1 < updates[idx].uid1) {
3127020d0ae64cd75bb428bdee42391376b9dd74Timo Sirainen /* insert new update */
3127020d0ae64cd75bb428bdee42391376b9dd74Timo Sirainen tmp_update = u;
3127020d0ae64cd75bb428bdee42391376b9dd74Timo Sirainen tmp_update.uid2 = updates[idx].uid1 - 1;
3127020d0ae64cd75bb428bdee42391376b9dd74Timo Sirainen move = 0;
3127020d0ae64cd75bb428bdee42391376b9dd74Timo Sirainen } else {
3127020d0ae64cd75bb428bdee42391376b9dd74Timo Sirainen /* split existing update from beginning */
3127020d0ae64cd75bb428bdee42391376b9dd74Timo Sirainen tmp_update = updates[idx];
3127020d0ae64cd75bb428bdee42391376b9dd74Timo Sirainen tmp_update.uid2 = u.uid1 - 1;
3127020d0ae64cd75bb428bdee42391376b9dd74Timo Sirainen updates[idx].uid1 = u.uid1;
3127020d0ae64cd75bb428bdee42391376b9dd74Timo Sirainen move = 1;
3127020d0ae64cd75bb428bdee42391376b9dd74Timo Sirainen }
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen i_assert(tmp_update.uid1 <= tmp_update.uid2);
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen i_assert(updates[idx].uid1 <= updates[idx].uid2);
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_insert(&t->updates, idx, &tmp_update, 1);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen updates = array_get_modifyable(&t->updates, &count);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen idx += move;
3127020d0ae64cd75bb428bdee42391376b9dd74Timo Sirainen } else if (u.uid1 < updates[idx].uid1) {
3127020d0ae64cd75bb428bdee42391376b9dd74Timo Sirainen updates[idx].uid1 = u.uid1;
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen }
3127020d0ae64cd75bb428bdee42391376b9dd74Timo Sirainen
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen if (u.uid2 < updates[idx].uid2 &&
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen (updates[idx].add_flags != u.add_flags ||
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen updates[idx].remove_flags != u.remove_flags)) {
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen /* split existing update from end */
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen tmp_update = updates[idx];
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen tmp_update.uid2 = u.uid2;
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen updates[idx].uid1 = u.uid2 + 1;
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen i_assert(tmp_update.uid1 <= tmp_update.uid2);
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen i_assert(updates[idx].uid1 <= updates[idx].uid2);
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_insert(&t->updates, idx, &tmp_update, 1);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen updates = array_get_modifyable(&t->updates, &count);
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen }
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen updates[idx].add_flags =
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen (updates[idx].add_flags | u.add_flags) &
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen ~u.remove_flags;
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen updates[idx].remove_flags =
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen (updates[idx].remove_flags | u.remove_flags) &
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen ~u.add_flags;
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen u.uid1 = updates[idx].uid2 + 1;
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen if (u.uid1 > u.uid2) {
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen /* break here before idx++ so last_update_idx is set
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen correctly */
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen break;
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen }
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen }
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen i_assert(idx <= count);
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen if (u.uid1 <= u.uid2) {
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen i_assert(idx == 0 || updates[idx-1].uid2 < u.uid1);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen i_assert(idx == count || updates[idx].uid1 > u.uid2);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_insert(&t->updates, idx, &u, 1);
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen }
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen t->last_update_idx = idx;
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen}
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void mail_index_record_modify_flags(struct mail_index_record *rec,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen enum modify_type modify_type,
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen enum mail_flags flags)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen switch (modify_type) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen case MODIFY_REPLACE:
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen rec->flags = flags;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen case MODIFY_ADD:
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen rec->flags |= flags;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen case MODIFY_REMOVE:
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen rec->flags &= ~flags;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainenvoid mail_index_update_flags_range(struct mail_index_transaction *t,
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen uint32_t seq1, uint32_t seq2,
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen enum modify_type modify_type,
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen enum mail_flags flags)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_index_record *rec;
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen struct mail_transaction_flag_update u, *last_update;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen unsigned int count;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
73e7998716853b5b7621c06aea0022dccda70ad1Timo Sirainen t->log_updates = TRUE;
73e7998716853b5b7621c06aea0022dccda70ad1Timo Sirainen
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen if (seq2 >= t->first_new_seq) {
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen /* updates for appended messages, modify them directly */
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen uint32_t seq;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen for (seq = I_MAX(t->first_new_seq, seq1); seq <= seq2; seq++) {
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen rec = mail_index_transaction_lookup(t, seq);
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen mail_index_record_modify_flags(rec, modify_type, flags);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen if (seq1 >= t->first_new_seq)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return;
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen /* range contains also existing messages. update them next. */
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen seq2 = t->first_new_seq - 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen i_assert(seq1 <= seq2 && seq1 > 0);
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen i_assert(seq2 <= mail_index_view_get_messages_count(t->view));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen memset(&u, 0, sizeof(u));
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen u.uid1 = seq1;
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen u.uid2 = seq2;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen switch (modify_type) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen case MODIFY_REPLACE:
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen u.add_flags = flags;
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen u.remove_flags = ~flags & MAIL_INDEX_FLAGS_MASK;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen case MODIFY_ADD:
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen u.add_flags = flags;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen case MODIFY_REMOVE:
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen u.remove_flags = flags;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (!array_is_created(&t->updates)) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen ARRAY_CREATE(&t->updates, default_pool,
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen struct mail_transaction_flag_update, 256);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_append(&t->updates, &u, 1);
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen return;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen last_update = array_get_modifyable(&t->updates, &count);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (t->last_update_idx < count) {
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen /* fast path - hopefully we're updating the next message,
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen or a message that is to be appended as last update */
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen last_update += t->last_update_idx;
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen if (seq1 - 1 == last_update->uid2) {
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen if (u.add_flags == last_update->add_flags &&
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen u.remove_flags == last_update->remove_flags &&
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen (t->last_update_idx + 1 == count ||
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen last_update[1].uid1 > seq2)) {
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen /* we can just update the UID range */
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen last_update->uid2 = seq2;
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen return;
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen }
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen } else if (seq1 > last_update->uid2) {
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen /* hopefully we can just append it */
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen t->last_update_idx++;
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen last_update++;
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen }
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (t->last_update_idx == count) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_append(&t->updates, &u, 1);
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen return;
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen }
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen /* slow path */
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen if (seq1 > last_update->uid2) {
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen /* added after this */
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen mail_index_insert_flag_update(t, u, t->last_update_idx + 1,
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen count);
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen } else {
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen /* added before this or on top of this */
42739a4203faffcea3ecf60dbf7ee9a8c0f24337Timo Sirainen mail_index_insert_flag_update(t, u, 0, t->last_update_idx + 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainenvoid mail_index_update_flags(struct mail_index_transaction *t, uint32_t seq,
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen enum modify_type modify_type,
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen enum mail_flags flags)
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen{
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen mail_index_update_flags_range(t, seq, seq, modify_type, flags);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainenint mail_index_seq_array_lookup(const array_t *array, uint32_t seq,
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen unsigned int *idx_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen ARRAY_ARG_SET_TYPE(array, uint32_t);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen unsigned int idx, left_idx, right_idx, count;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen const uint32_t *seq_p;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen count = array_count(array);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (count == 0) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen *idx_r = 0;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen return FALSE;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* we're probably appending it, check */
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen seq_p = array_idx(array, count-1);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (*seq_p < seq)
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen idx = count;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen idx = 0; left_idx = 0; right_idx = count;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen while (left_idx < right_idx) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen idx = (left_idx + right_idx) / 2;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen seq_p = array_idx(array, idx);
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen if (*seq_p < seq)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen left_idx = idx+1;
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen else if (*seq_p > seq)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen right_idx = idx;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen *idx_r = idx;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen *idx_r = idx;
ca316aeb7648d3f1bcf45231f73ddeb1b67a6961Timo Sirainen return FALSE;
ca316aeb7648d3f1bcf45231f73ddeb1b67a6961Timo Sirainen}
ca316aeb7648d3f1bcf45231f73ddeb1b67a6961Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainenstatic int mail_index_seq_array_add(array_t *array, uint32_t seq,
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen const void *record, size_t record_size,
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen void *old_record)
ca316aeb7648d3f1bcf45231f73ddeb1b67a6961Timo Sirainen{
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen ARRAY_ARG_SET_TYPE(array, void *);
ca316aeb7648d3f1bcf45231f73ddeb1b67a6961Timo Sirainen void *p;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen unsigned int idx;
ca316aeb7648d3f1bcf45231f73ddeb1b67a6961Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (!array_is_created(array)) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_create(array, default_pool,
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen sizeof(seq) + record_size,
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen 1024 / (sizeof(seq) + record_size));
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen }
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen i_assert(array->element_size == sizeof(seq) + record_size);
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (mail_index_seq_array_lookup(array, seq, &idx)) {
ca316aeb7648d3f1bcf45231f73ddeb1b67a6961Timo Sirainen /* already there, update */
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen p = array_modifyable_idx(array, idx);
ca316aeb7648d3f1bcf45231f73ddeb1b67a6961Timo Sirainen if (old_record != NULL)
ca316aeb7648d3f1bcf45231f73ddeb1b67a6961Timo Sirainen memcpy(old_record, p, record_size);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen memcpy(PTR_OFFSET(p, sizeof(seq)), record, record_size);
ca316aeb7648d3f1bcf45231f73ddeb1b67a6961Timo Sirainen return TRUE;
ca316aeb7648d3f1bcf45231f73ddeb1b67a6961Timo Sirainen } else {
ca316aeb7648d3f1bcf45231f73ddeb1b67a6961Timo Sirainen /* insert */
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen p = array_modifyable_insert(array, idx);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen memcpy(p, &seq, sizeof(seq));
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen memcpy(PTR_OFFSET(p, sizeof(seq)), record, record_size);
ca316aeb7648d3f1bcf45231f73ddeb1b67a6961Timo Sirainen return FALSE;
ca316aeb7648d3f1bcf45231f73ddeb1b67a6961Timo Sirainen }
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen}
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenvoid mail_index_update_header(struct mail_index_transaction *t,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen size_t offset, const void *data, size_t size)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen{
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen i_assert(offset < sizeof(t->hdr_change));
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen i_assert(size <= sizeof(t->hdr_change) - offset);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen t->hdr_changed = TRUE;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen t->log_updates = TRUE;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen memcpy(t->hdr_change + offset, data, size);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen for (; size > 0; size--)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen t->hdr_mask[offset++] = 1;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen}
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenvoid mail_index_ext_resize(struct mail_index_transaction *t, uint32_t ext_id,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen uint32_t hdr_size, uint16_t record_size,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen uint16_t record_align)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen{
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen struct mail_transaction_ext_intro intro;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen const struct mail_index_ext *ext;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen memset(&intro, 0, sizeof(intro));
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (!mail_index_map_get_ext_idx(t->view->map, ext_id, &intro.ext_id)) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen intro.ext_id = (uint32_t)-1;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen ext = array_idx(&t->view->index->extensions, ext_id);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen } else {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen ext = array_idx(&t->view->map->extensions, ext_id);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen /* allow only header size changes if extension records have already
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen been changed in transaction */
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen i_assert(!array_is_created(&t->ext_rec_updates) ||
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen (ext->record_size == record_size &&
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen ext->record_align == record_align));
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen t->log_updates = TRUE;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (!array_is_created(&t->ext_resizes)) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen ARRAY_CREATE(&t->ext_resizes, default_pool,
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen struct mail_transaction_ext_intro, ext_id + 2);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen intro.hdr_size = hdr_size;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen intro.record_size = record_size;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen intro.record_align = record_align;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen intro.name_size = 1;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_idx_set(&t->ext_resizes, ext_id, &intro);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen}
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenvoid mail_index_ext_reset(struct mail_index_transaction *t, uint32_t ext_id,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen uint32_t reset_id)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen{
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen i_assert(reset_id != 0);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen t->log_updates = TRUE;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (array_is_created(&t->ext_rec_updates) &&
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen ext_id < array_count(&t->ext_rec_updates)) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen /* if extension records have been updated, clear them */
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_t *array;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array = array_modifyable_idx(&t->ext_rec_updates, ext_id);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (array_is_created(array))
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_clear(array);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (!array_is_created(&t->ext_resets)) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen ARRAY_CREATE(&t->ext_resets, default_pool,
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen uint32_t, ext_id + 2);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_idx_set(&t->ext_resets, ext_id, &reset_id);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen}
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenvoid mail_index_update_header_ext(struct mail_index_transaction *t,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen uint32_t ext_id, size_t offset,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen const void *data, size_t size)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen{
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen // FIXME
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen}
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenvoid mail_index_update_ext(struct mail_index_transaction *t, uint32_t seq,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen uint32_t ext_id, const void *data, void *old_data_r)
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen{
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen struct mail_index *index = t->view->index;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen const struct mail_index_ext *ext;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen const struct mail_transaction_ext_intro *intro;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen uint16_t record_size;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_t *array;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen unsigned int count;
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen
6b817c545d810e583c6f5bf8a14aafca2d28e7dcTimo Sirainen i_assert(seq > 0 &&
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen (seq <= mail_index_view_get_messages_count(t->view) ||
6b817c545d810e583c6f5bf8a14aafca2d28e7dcTimo Sirainen seq <= t->last_new_seq));
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen i_assert(ext_id < array_count(&index->extensions));
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen
73e7998716853b5b7621c06aea0022dccda70ad1Timo Sirainen t->log_updates = TRUE;
73e7998716853b5b7621c06aea0022dccda70ad1Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (!array_is_created(&t->ext_resizes)) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen intro = NULL;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen count = 0;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen } else {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen intro = array_get(&t->ext_resizes, &count);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (ext_id < count && intro[ext_id].name_size != 0) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* resized record */
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen record_size = intro[ext_id].record_size;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen } else {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen ext = array_idx(&index->extensions, ext_id);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen record_size = ext->record_size;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (!array_is_created(&t->ext_rec_updates)) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen ARRAY_CREATE(&t->ext_rec_updates, default_pool,
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_t, ext_id + 2);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen }
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array = array_modifyable_idx(&t->ext_rec_updates, ext_id);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen /* @UNSAFE */
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (!mail_index_seq_array_add(array, seq, data, record_size,
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen old_data_r)) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (old_data_r != NULL)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen memset(old_data_r, 0, record_size);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen}
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainenstruct mail_keywords *
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainenmail_index_keywords_create(struct mail_index_transaction *t,
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen const char *const keywords[])
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen{
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen /* @UNSAFE */
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen struct mail_index *index = t->view->index;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen struct mail_keywords *k;
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen const char **missing_keywords, *keyword;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen unsigned int count, i, j, k_pos = 0, missing_count = 0;
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen size_t size;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
ae6ead56ef1ca592e6d4e446d7d5d43c70fd9915Timo Sirainen if (keywords == NULL) {
ae6ead56ef1ca592e6d4e446d7d5d43c70fd9915Timo Sirainen k = i_new(struct mail_keywords, 1);
ae6ead56ef1ca592e6d4e446d7d5d43c70fd9915Timo Sirainen k->index = index;
ae6ead56ef1ca592e6d4e446d7d5d43c70fd9915Timo Sirainen return k;
ae6ead56ef1ca592e6d4e446d7d5d43c70fd9915Timo Sirainen }
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen count = strarray_length(keywords);
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen k = i_malloc(sizeof(struct mail_keywords) +
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen (sizeof(k->idx) * (count-1)));
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen k->index = t->view->index;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen k->count = count;
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen t_push();
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen missing_keywords = t_new(const char *, count + 1);
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen /* look up the keywords from index. they're never removed from there
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen so we can permanently store indexes to them. */
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen for (i = 0; i < count; i++) {
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen for (j = 0; index->keywords[j] != NULL; j++) {
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen if (strcasecmp(keywords[i], index->keywords[j]) == 0)
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen break;
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen }
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen if (index->keywords[j] != NULL)
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen k->idx[k_pos++] = j;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen else
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen missing_keywords[missing_count++] = keywords[i];
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen }
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen if (missing_count > 0) {
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen /* add missing keywords. first drop the trailing NULL. */
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen size = index->keywords_buf->used - sizeof(const char *);
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen buffer_set_used_size(index->keywords_buf, size);
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen j = size / sizeof(const char *);
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen for (; *missing_keywords != NULL; missing_keywords++, j++) {
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen keyword = p_strdup(index->keywords_pool,
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen *missing_keywords);
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen buffer_append(index->keywords_buf,
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen &keyword, sizeof(keyword));
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen k->idx[k_pos++] = j;
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen }
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen buffer_append_zero(index->keywords_buf, sizeof(const char *));
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen index->keywords = index->keywords_buf->data;
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen }
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen i_assert(k_pos == count);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen t_pop();
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen return k;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen}
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainenvoid mail_index_keywords_free(struct mail_keywords *keywords)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen{
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen i_free(keywords);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen}
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenvoid mail_index_update_keywords(struct mail_index_transaction *t, uint32_t seq,
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen enum modify_type modify_type,
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen struct mail_keywords *keywords)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen{
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_t *arr;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen unsigned int i, idx;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen i_assert(seq > 0 &&
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen (seq <= mail_index_view_get_messages_count(t->view) ||
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen seq <= t->last_new_seq));
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen i_assert(keywords->count > 0 || modify_type == MODIFY_REPLACE);
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen i_assert(keywords->index == t->view->index);
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen /* keyword_updates is an array of
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen { buffer_t *add_seq; buffer_t *remove_seq; }
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen which is why there's the multiplication by 2.
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen If t->keyword_resets is set for the sequence, there's no need to
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen update remove_seq as it will remove all keywords. */
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (!array_is_created(&t->keyword_updates)) {
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen uint32_t max_idx = keywords->idx[keywords->count-1];
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen ARRAY_CREATE(&t->keyword_updates, default_pool,
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_t, max_idx * 2);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen }
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen switch (modify_type) {
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen case MODIFY_ADD:
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen for (i = 0; i < keywords->count; i++) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen idx = keywords->idx[i] * 2;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen arr = array_modifyable_idx(&t->keyword_updates, idx);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen mail_index_seq_range_array_add(arr, 16, seq);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen arr = array_modifyable_idx(&t->keyword_updates, idx+1);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen mail_index_seq_range_array_remove(arr, seq);
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen }
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen break;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen case MODIFY_REMOVE:
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen for (i = 0; i < keywords->count; i++) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen idx = keywords->idx[i] * 2;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen arr = array_modifyable_idx(&t->keyword_updates, idx);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen mail_index_seq_range_array_remove(arr, seq);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen arr = array_modifyable_idx(&t->keyword_updates, idx+1);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen mail_index_seq_range_array_add(arr, 16, seq);
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen }
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen break;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen case MODIFY_REPLACE:
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen for (i = 0; i < keywords->count; i++) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen idx = keywords->idx[i] * 2;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen arr = array_modifyable_idx(&t->keyword_updates, idx);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen mail_index_seq_range_array_add(arr, 16, seq);
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen }
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen mail_index_seq_range_array_add(&t->keyword_resets, 16, seq);
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen break;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen }
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen t->log_updates = TRUE;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen}