421
426
mail_index_insert_flag_update(struct mail_index_transaction *t,
422
struct mail_transaction_flag_update u,
427
struct mail_index_flag_update u,
423
428
unsigned int idx)
425
struct mail_transaction_flag_update *updates, tmp_update;
430
struct mail_index_flag_update *updates, tmp_update;
426
431
unsigned int count, first_idx, max;
428
433
updates = array_get_modifiable(&t->updates, &count);
648
653
mail_index_update_flags_range(t, seq, seq, modify_type, flags);
657
mail_index_attribute_set_full(struct mail_index_transaction *t,
658
const char *key, bool pvt, char prefix,
659
time_t timestamp, uint32_t value_len)
661
uint32_t ts = timestamp;
663
if (t->attribute_updates == NULL) {
664
t->attribute_updates = buffer_create_dynamic(default_pool, 64);
665
t->attribute_updates_suffix = buffer_create_dynamic(default_pool, 64);
667
buffer_append_c(t->attribute_updates, prefix);
668
buffer_append_c(t->attribute_updates, pvt ? 'p' : 's');
669
buffer_append(t->attribute_updates, key, strlen(key)+1);
671
buffer_append(t->attribute_updates_suffix, &ts, sizeof(ts));
673
buffer_append(t->attribute_updates_suffix,
674
&value_len, sizeof(value_len));
676
t->log_updates = TRUE;
679
void mail_index_attribute_set(struct mail_index_transaction *t,
680
bool pvt, const char *key,
681
time_t timestamp, uint32_t value_len)
683
mail_index_attribute_set_full(t, key, pvt, '+', timestamp, value_len);
686
void mail_index_attribute_unset(struct mail_index_transaction *t,
687
bool pvt, const char *key,
690
mail_index_attribute_set_full(t, key, pvt, '-', timestamp, 0);
651
693
void mail_index_update_header(struct mail_index_transaction *t,
652
694
size_t offset, const void *data, size_t size,
688
730
rext = array_idx(&t->view->index->extensions, ext_id);
689
731
old_record_size = rext->record_size;
690
732
old_record_align = rext->record_align;
733
old_header_size = rext->hdr_size;
692
735
const struct mail_index_ext *ext;
694
737
ext = array_idx(&t->view->map->extensions, intro.ext_id);
695
738
old_record_size = ext->record_size;
696
739
old_record_align = ext->record_align;
740
old_header_size = ext->hdr_size;
699
743
/* allow only header size changes if extension records have already
700
744
been changed in transaction */
701
745
i_assert(!array_is_created(&t->ext_rec_updates) ||
746
record_size == (uint16_t)-1 ||
702
747
(old_record_size == record_size &&
703
748
old_record_align == record_align));
707
752
if (!array_is_created(&t->ext_resizes))
708
753
i_array_init(&t->ext_resizes, ext_id + 2);
710
intro.hdr_size = hdr_size;
711
intro.record_size = record_size;
712
intro.record_align = record_align;
755
intro.hdr_size = hdr_size != (uint32_t)-1 ? hdr_size : old_header_size;
756
if (record_size != (uint16_t)-1) {
757
i_assert(record_align != (uint16_t)-1);
758
intro.record_size = record_size;
759
intro.record_align = record_align;
761
i_assert(record_align == (uint16_t)-1);
762
intro.record_size = old_record_size;
763
intro.record_align = old_record_align;
713
765
intro.name_size = 1;
714
766
array_idx_set(&t->ext_resizes, ext_id, &intro);
769
void mail_index_ext_resize_hdr(struct mail_index_transaction *t,
770
uint32_t ext_id, uint32_t hdr_size)
772
mail_index_ext_resize(t, ext_id, hdr_size, (uint16_t)-1, (uint16_t)-1);
717
775
void mail_index_ext_reset(struct mail_index_transaction *t, uint32_t ext_id,
718
776
uint32_t reset_id, bool clear_data)
1065
static struct mail_keywords *
1066
keyword_update_remove_existing(struct mail_index_transaction *t, uint32_t seq)
1068
ARRAY_TYPE(keyword_indexes) keywords;
1069
uint32_t i, keywords_count;
1071
t_array_init(&keywords, 32);
1072
if (t->view->v.lookup_full == NULL) {
1073
/* syncing is saving a list of changes into this transaction.
1074
the seq is actual an uid, so we can't lookup the existing
1075
keywords. we shouldn't get here unless we're reading
1076
pre-v2.2 keyword-reset records from .log files. so we don't
1077
really care about performance that much here, */
1078
keywords_count = array_count(&t->view->index->keywords);
1079
for (i = 0; i < keywords_count; i++)
1080
array_append(&keywords, &i, 1);
1082
mail_index_transaction_lookup_latest_keywords(t, seq, &keywords);
1084
if (array_count(&keywords) == 0)
1086
return mail_index_keywords_create_from_indexes(t->view->index,
1015
1090
void mail_index_update_keywords(struct mail_index_transaction *t, uint32_t seq,
1016
1091
enum modify_type modify_type,
1017
1092
struct mail_keywords *keywords)
1019
1094
struct mail_index_transaction_keyword_update *u;
1095
struct mail_keywords *add_keywords = NULL, *remove_keywords = NULL;
1096
struct mail_keywords *unref_keywords = NULL;
1020
1097
unsigned int i;
1125
switch (modify_type) {
1126
case MODIFY_REPLACE:
1127
/* split this into add+remove. remove all existing keywords not
1128
included in the keywords list */
1129
if (seq < t->first_new_seq) {
1130
/* remove the ones currently in index */
1131
remove_keywords = keyword_update_remove_existing(t, seq);
1132
unref_keywords = remove_keywords;
1134
/* remove from all changes we've done in this transaction */
1135
array_foreach_modifiable(&t->keyword_updates, u)
1136
seq_range_array_remove(&u->add_seq, seq);
1137
add_keywords = keywords;
1140
add_keywords = keywords;
1143
remove_keywords = keywords;
1047
1147
/* Update add_seq and remove_seq arrays which describe the keyword
1048
changes. Don't bother updating remove_seq or keyword resets for
1049
newly added messages since they default to not having any
1051
switch (modify_type) {
1053
for (i = 0; i < keywords->count; i++) {
1054
u = array_idx_modifiable(&t->keyword_updates,
1056
seq_range_array_add(&u->add_seq, 16, seq);
1148
changes. First do the removes, since replace removes everything
1150
if (remove_keywords != NULL) {
1151
for (i = 0; i < remove_keywords->count; i++) {
1152
u = array_idx_modifiable(&t->keyword_updates,
1153
remove_keywords->idx[i]);
1154
seq_range_array_remove(&u->add_seq, seq);
1155
/* Don't bother updating remove_seq for new messages,
1156
since their initial state is "no keyword" anyway */
1157
if (seq < t->first_new_seq) {
1158
seq_range_array_add_with_init(&u->remove_seq,
1163
if (add_keywords != NULL) {
1164
for (i = 0; i < add_keywords->count; i++) {
1165
u = array_idx_modifiable(&t->keyword_updates,
1166
add_keywords->idx[i]);
1167
seq_range_array_add_with_init(&u->add_seq, 16, seq);
1057
1168
seq_range_array_remove(&u->remove_seq, seq);
1061
for (i = 0; i < keywords->count; i++) {
1062
u = array_idx_modifiable(&t->keyword_updates,
1064
seq_range_array_remove(&u->add_seq, seq);
1065
if (seq < t->first_new_seq)
1066
seq_range_array_add(&u->remove_seq, 16, seq);
1069
case MODIFY_REPLACE:
1070
/* Remove sequence from all add/remove arrays */
1071
if (array_is_created(&t->keyword_updates)) {
1072
array_foreach_modifiable(&t->keyword_updates, u) {
1073
seq_range_array_remove(&u->add_seq, seq);
1074
seq_range_array_remove(&u->remove_seq, seq);
1077
/* Add the wanted keyword back */
1078
for (i = 0; i < keywords->count; i++) {
1079
u = array_idx_modifiable(&t->keyword_updates,
1081
seq_range_array_add(&u->add_seq, 16, seq);
1084
if (seq < t->first_new_seq)
1085
seq_range_array_add(&t->keyword_resets, 16, seq);
1171
if (unref_keywords != NULL)
1172
mail_index_keywords_unref(&unref_keywords);
1089
1174
t->log_updates = TRUE;
1146
1231
struct mail_index_transaction_keyword_update *kw;
1147
bool ret, have_kw_changes = FALSE;
1232
bool ret = FALSE, have_kw_changes = FALSE;
1149
ret = mail_index_cancel_array(&t->keyword_resets, seq);
1150
1234
if (!array_is_created(&t->keyword_updates))
1153
1237
array_foreach_modifiable(&t->keyword_updates, kw) {
1154
1238
if (mail_index_cancel_array(&kw->add_seq, seq))