16
16
struct mail_index_map *lookup_map;
17
17
struct mail_index_header hdr;
18
19
buffer_t *lookup_return_data;
20
uint32_t lookup_prev_seq;
22
unsigned int record_size;
23
unsigned int recs_count;
25
ARRAY_DEFINE(all_recs, void *);
21
28
static void tview_close(struct mail_index_view *view)
23
30
struct mail_index_view_transaction *tview =
24
31
(struct mail_index_view_transaction *)view;
25
32
struct mail_index_transaction *t = tview->t;
34
unsigned int i, count;
27
36
if (tview->lookup_map != NULL)
28
37
mail_index_unmap(&tview->lookup_map);
29
38
if (tview->lookup_return_data != NULL)
30
39
buffer_free(&tview->lookup_return_data);
41
if (array_is_created(&tview->all_recs)) {
42
recs = array_get_modifiable(&tview->all_recs, &count);
43
for (i = 0; i < count; i++)
45
array_free(&tview->all_recs);
32
48
tview->super->close(view);
33
49
mail_index_transaction_unref(&t);
66
82
static const struct mail_index_record *
83
tview_apply_flag_updates(struct mail_index_view_transaction *tview,
84
struct mail_index_map *map,
85
const struct mail_index_record *rec, uint32_t seq)
87
struct mail_index_transaction *t = tview->t;
88
const struct mail_transaction_flag_update *updates;
89
struct mail_index_record *trec;
90
unsigned int idx, count;
92
/* see if there are any flag updates */
93
if (seq < t->min_flagupdate_seq || seq > t->max_flagupdate_seq ||
94
!array_is_created(&t->updates))
97
updates = array_get(&t->updates, &count);
98
idx = mail_index_transaction_get_flag_update_pos(t, 0, count, seq);
99
if (seq < updates[idx].uid1 || seq > updates[idx].uid2)
102
/* yes, we have flag updates. since we can't modify rec directly and
103
we want to be able to handle multiple mail_index_lookup() calls
104
without the second one overriding the first one's data, we'll
105
create a records array and return data from there.
107
it's also possible that the record size increases, so we potentially
108
have to create multiple arrays. they all get eventually freed when
109
the view gets freed. */
110
if (map->hdr.record_size > tview->record_size) {
111
if (!array_is_created(&tview->all_recs))
112
i_array_init(&tview->all_recs, 4);
113
tview->recs_count = t->first_new_seq;
114
tview->record_size = I_MAX(map->hdr.record_size,
115
tview->view.map->hdr.record_size);
116
tview->recs = i_malloc(tview->record_size *
118
array_append(&tview->all_recs, &tview->recs, 1);
120
i_assert(tview->recs_count == t->first_new_seq);
121
i_assert(seq > 0 && seq <= tview->recs_count);
123
trec = PTR_OFFSET(tview->recs, (seq-1) * tview->record_size);
124
memcpy(trec, rec, map->hdr.record_size);
125
trec->flags |= updates[idx].add_flags;
126
trec->flags &= ~updates[idx].remove_flags;
130
static const struct mail_index_record *
67
131
tview_lookup_full(struct mail_index_view *view, uint32_t seq,
68
132
struct mail_index_map **map_r, bool *expunged_r)
82
146
rec = tview->super->lookup_full(view, seq, map_r, expunged_r);
147
rec = tview_apply_flag_updates(tview, *map_r, rec, seq);
84
/* if we're expunged within this transaction, return 0 */
85
149
if (array_is_created(&tview->t->expunges) &&
86
150
seq_range_exists(&tview->t->expunges, seq))
87
151
*expunged_r = TRUE;
256
static void keyword_index_add(ARRAY_TYPE(keyword_indexes) *keywords,
259
const unsigned int *indexes;
260
unsigned int i, count;
262
indexes = array_get(keywords, &count);
263
for (i = 0; i < count; i++) {
264
if (indexes[i] == idx)
267
array_append(keywords, &idx, 1);
270
static void keyword_index_remove(ARRAY_TYPE(keyword_indexes) *keywords,
273
const unsigned int *indexes;
274
unsigned int i, count;
276
indexes = array_get(keywords, &count);
277
for (i = 0; i < count; i++) {
278
if (indexes[i] == idx) {
279
array_delete(keywords, i, 1);
285
static void tview_lookup_keywords(struct mail_index_view *view, uint32_t seq,
286
ARRAY_TYPE(keyword_indexes) *keyword_idx)
288
struct mail_index_view_transaction *tview =
289
(struct mail_index_view_transaction *)view;
290
struct mail_index_transaction *t = tview->t;
291
const struct mail_index_transaction_keyword_update *updates;
292
unsigned int i, count;
294
tview->super->lookup_keywords(view, seq, keyword_idx);
296
if (seq < t->min_flagupdate_seq || seq > t->max_flagupdate_seq) {
297
/* no keyword updates for this sequence */
301
/* apply any keyword updates in this transaction */
302
if (array_is_created(&t->keyword_resets)) {
303
if (seq_range_exists(&t->keyword_resets, seq))
304
array_clear(keyword_idx);
307
if (array_is_created(&t->keyword_updates))
308
updates = array_get(&t->keyword_updates, &count);
313
for (i = 0; i < count; i++) {
314
if (array_is_created(&updates[i].add_seq) &&
315
seq_range_exists(&updates[i].add_seq, seq))
316
keyword_index_add(keyword_idx, i);
317
else if (array_is_created(&updates[i].remove_seq) &&
318
seq_range_exists(&updates[i].remove_seq, seq))
319
keyword_index_remove(keyword_idx, i);
192
323
static struct mail_index_map *
193
324
tview_get_lookup_map(struct mail_index_view_transaction *tview)
202
333
static const void *
203
334
tview_return_updated_ext(struct mail_index_view_transaction *tview,
204
const void *data, uint32_t ext_id)
335
uint32_t seq, const void *data, uint32_t ext_id)
206
337
const struct mail_index_ext *ext;
207
338
const struct mail_index_registered_ext *rext;
208
339
const struct mail_transaction_ext_intro *intro;
209
340
unsigned int record_align, record_size;
210
341
uint32_t ext_idx;
212
344
/* data begins with a 32bit sequence, followed by the actual
213
345
extension data */
244
376
tview->lookup_return_data =
245
377
buffer_create_dynamic(default_pool,
246
378
record_size + 64);
379
} else if (seq != tview->lookup_prev_seq) {
380
/* clear the buffer between lookups for different
382
buffer_set_used_size(tview->lookup_return_data, 0);
248
buffer_write(tview->lookup_return_data, 0, data, record_size);
249
return tview->lookup_return_data->data;
384
tview->lookup_prev_seq = seq;
385
pos = tview->lookup_return_data->used;
386
buffer_append(tview->lookup_return_data, data, record_size);
387
return CONST_PTR_OFFSET(tview->lookup_return_data->data, pos);
274
412
mail_index_seq_array_lookup(ext_buf, seq, &idx)) {
275
413
data = array_idx(ext_buf, idx);
276
414
*map_r = tview_get_lookup_map(tview);
277
*data_r = tview_return_updated_ext(tview, data,
415
*data_r = tview_return_updated_ext(tview, seq, data,