mail-index-transaction.c revision 287ba82a8da3eaa473b5735d4eeac2fb4c5d8117
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (C) 2003-2004 Timo 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. */
7c95b03620a03a43dd72d39608cea5fc77393ad6Timo Sirainenmail_index_transaction_begin(struct mail_index_view *view,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* don't allow syncing view while there's ongoing transactions */
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen t->first_new_seq = mail_index_view_get_messages_count(t->view)+1;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen /* transaction view cannot work if new records are being added
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen in two places. make sure it doesn't happen. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void mail_index_transaction_free(struct mail_index_transaction *t)
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen recs = array_get_modifyable(&t->ext_rec_updates, &count);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen for (i = 0; i < count; i++) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen recs = array_get_modifyable(&t->keyword_updates, &count);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen for (i = 0; i < count; i++) {
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainenvoid mail_index_transaction_ref(struct mail_index_transaction *t)
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainenvoid mail_index_transaction_unref(struct mail_index_transaction *t)
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen if (--t->refcount == 0)
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenmail_index_buffer_convert_to_uids(struct mail_index_transaction *t,
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen unsigned int i, count;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen for (i = 0; i < count; i++) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainenstatic void arrays_convert_to_uids(struct mail_index_transaction *t,
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen unsigned int i, count;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen updates = array_get_modifyable(array, &count);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen for (i = 0; i < count; i++) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen mail_index_buffer_convert_to_uids(t, &updates[i],
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainenmail_index_transaction_convert_to_uids(struct mail_index_transaction *t)
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen arrays_convert_to_uids(t, &t->ext_rec_updates);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen arrays_convert_to_uids(t, &t->keyword_updates);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen mail_index_buffer_convert_to_uids(t, &t->expunges, TRUE);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen mail_index_buffer_convert_to_uids(t, &t->updates, TRUE);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mail_index_transaction_commit(struct mail_index_transaction *t,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mail_index_view_is_inconsistent(t->view)) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen mail_cache_transaction_commit(t->cache_trans_ctx);
659fe5d24825b160cae512538088020d97a60239Timo Sirainen if (mail_index_transaction_convert_to_uids(t) < 0)
659fe5d24825b160cae512538088020d97a60239Timo Sirainen ret = mail_transaction_log_append(t, log_file_seq_r,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_index_transaction_rollback(struct mail_index_transaction *t)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen mail_cache_transaction_rollback(t->cache_trans_ctx);
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainenmail_index_transaction_lookup(struct mail_index_transaction *t, uint32_t seq)
b44a50ea4123f21dfc8e1b6c602f690fd9721b67Timo Sirainen i_assert(seq >= t->first_new_seq && seq <= t->last_new_seq);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen return array_modifyable_idx(&t->appends, seq - t->first_new_seq);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_index_append(struct mail_index_transaction *t, uint32_t uid,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* sequence number is visible only inside given view,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen so let it generate it */
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainenvoid mail_index_append_assign_uids(struct mail_index_transaction *t,
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen unsigned int i, count;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen recs = array_get_modifyable(&t->appends, &count);
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen /* find the first mail with uid = 0 */
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen for (i = 0; i < count; i++) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen for (; i < count; i++) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainenmail_index_seq_range_array_add(array_t *array, unsigned int init_count,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* quick checks */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* grow last range */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* grow down first range */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* somewhere in the middle, array is sorted so find it with
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen binary search */
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen /* it's already in the range */
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);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen i_assert(idx+1 < count); /* already handled above */
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainenstatic void mail_index_seq_range_array_remove(array_t *array, uint32_t seq)
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen /* quick checks */
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (seq > data[count-1].seq2 || seq < data[0].seq1) {
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen /* outside the range */
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen /* shrink last range */
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen /* shrink up first range */
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen /* somewhere in the middle, array is sorted so find it with
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen binary search */
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen /* found it */
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen /* a single sequence range.
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen remove it entirely */
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen /* shrink the range */
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen /* shrink the range */
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen /* split the sequence range */
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenvoid mail_index_expunge(struct mail_index_transaction *t, uint32_t seq)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen i_assert(seq > 0 && seq <= mail_index_view_get_messages_count(t->view));
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen /* expunges is a sorted array of {seq1, seq2, ..}, .. */
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen mail_index_seq_range_array_add(&t->expunges, 128, seq);
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainenmail_index_insert_flag_update(struct mail_index_transaction *t,
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen struct mail_transaction_flag_update *updates, tmp_update;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen unsigned int count;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen updates = array_get_modifyable(&t->updates, &count);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen i_assert(left_idx <= right_idx && right_idx <= count);
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen /* find the first update with either overlapping range,
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen or the update which will come after our insert */
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (idx < count && updates[idx].uid2 < u.uid1)
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);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen for (; idx < count && u.uid2 >= updates[idx].uid1; idx++) {
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen updates[idx].remove_flags != u.remove_flags)) {
3127020d0ae64cd75bb428bdee42391376b9dd74Timo Sirainen /* insert new update */
3127020d0ae64cd75bb428bdee42391376b9dd74Timo Sirainen /* split existing update from beginning */
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen i_assert(updates[idx].uid1 <= updates[idx].uid2);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_insert(&t->updates, idx, &tmp_update, 1);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen updates = array_get_modifyable(&t->updates, &count);
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen updates[idx].remove_flags != u.remove_flags)) {
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen /* split existing update from end */
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen i_assert(updates[idx].uid1 <= updates[idx].uid2);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_insert(&t->updates, idx, &tmp_update, 1);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen updates = array_get_modifyable(&t->updates, &count);
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen (updates[idx].remove_flags | u.remove_flags) &
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen /* break here before idx++ so last_update_idx is set
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen i_assert(idx == 0 || updates[idx-1].uid2 < u.uid1);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen i_assert(idx == count || updates[idx].uid1 > u.uid2);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void mail_index_record_modify_flags(struct mail_index_record *rec,
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainenvoid mail_index_update_flags_range(struct mail_index_transaction *t,
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen struct mail_transaction_flag_update u, *last_update;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen unsigned int count;
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen /* updates for appended messages, modify them directly */
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen for (seq = I_MAX(t->first_new_seq, seq1); seq <= seq2; seq++) {
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen mail_index_record_modify_flags(rec, modify_type, flags);
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen /* range contains also existing messages. update them next. */
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen i_assert(seq2 <= mail_index_view_get_messages_count(t->view));
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen memset(&u, 0, sizeof(u));
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen u.remove_flags = ~flags & MAIL_INDEX_FLAGS_MASK;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen last_update = array_get_modifyable(&t->updates, &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 u.remove_flags == last_update->remove_flags &&
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen /* we can just update the UID range */
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen /* hopefully we can just append it */
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen /* slow path */
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen /* added after this */
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen mail_index_insert_flag_update(t, u, t->last_update_idx + 1,
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);
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainenvoid mail_index_update_flags(struct mail_index_transaction *t, uint32_t seq,
c251a38df327599a62d341bf5c2282f31352faa5Timo Sirainen mail_index_update_flags_range(t, seq, seq, modify_type, flags);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainenint mail_index_seq_array_lookup(const array_t *array, uint32_t seq,
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen unsigned int *idx_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* we're probably appending it, check */
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainenstatic int mail_index_seq_array_add(array_t *array, uint32_t seq,
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen unsigned int idx;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen i_assert(array->element_size == sizeof(seq) + record_size);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (mail_index_seq_array_lookup(array, seq, &idx)) {
ca316aeb7648d3f1bcf45231f73ddeb1b67a6961Timo Sirainen /* already there, update */
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen memcpy(PTR_OFFSET(p, sizeof(seq)), record, record_size);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen memcpy(PTR_OFFSET(p, sizeof(seq)), record, record_size);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenvoid mail_index_update_header(struct mail_index_transaction *t,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen i_assert(size <= sizeof(t->hdr_change) - offset);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenvoid mail_index_ext_resize(struct mail_index_transaction *t, uint32_t ext_id,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (!mail_index_map_get_ext_idx(t->view->map, ext_id, &intro.ext_id)) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen ext = array_idx(&t->view->index->extensions, ext_id);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen ext = array_idx(&t->view->map->extensions, ext_id);
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) ||
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen struct mail_transaction_ext_intro, ext_id + 2);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_idx_set(&t->ext_resizes, ext_id, &intro);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenvoid mail_index_ext_reset(struct mail_index_transaction *t, uint32_t ext_id,
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen /* if extension records have been updated, clear them */
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array = array_modifyable_idx(&t->ext_rec_updates, ext_id);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array_idx_set(&t->ext_resets, ext_id, &reset_id);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenvoid mail_index_update_header_ext(struct mail_index_transaction *t,
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)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen const struct mail_transaction_ext_intro *intro;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen unsigned int count;
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen (seq <= mail_index_view_get_messages_count(t->view) ||
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen i_assert(ext_id < array_count(&index->extensions));
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (ext_id < count && intro[ext_id].name_size != 0) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* resized record */
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen ARRAY_CREATE(&t->ext_rec_updates, default_pool,
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen array = array_modifyable_idx(&t->ext_rec_updates, ext_id);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen /* @UNSAFE */
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (!mail_index_seq_array_add(array, seq, data, record_size,
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainenmail_index_keywords_create(struct mail_index_transaction *t,
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen const char *const keywords[])
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen /* @UNSAFE */
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen unsigned int count, i, j, k_pos = 0, missing_count = 0;
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen missing_keywords = t_new(const char *, count + 1);
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 missing_keywords[missing_count++] = keywords[i];
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 j = size / sizeof(const char *);
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen for (; *missing_keywords != NULL; missing_keywords++, j++) {
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen buffer_append_zero(index->keywords_buf, sizeof(const char *));
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainenvoid mail_index_keywords_free(struct mail_keywords *keywords)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenvoid mail_index_update_keywords(struct mail_index_transaction *t, uint32_t seq,
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen unsigned int i, idx;
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen (seq <= mail_index_view_get_messages_count(t->view) ||
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen i_assert(keywords->count > 0 || modify_type == MODIFY_REPLACE);
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 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 uint32_t max_idx = keywords->idx[keywords->count-1];
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen ARRAY_CREATE(&t->keyword_updates, default_pool,
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen arr = array_modifyable_idx(&t->keyword_updates, idx);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen arr = array_modifyable_idx(&t->keyword_updates, idx+1);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen arr = array_modifyable_idx(&t->keyword_updates, idx);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen arr = array_modifyable_idx(&t->keyword_updates, idx+1);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen arr = array_modifyable_idx(&t->keyword_updates, idx);