comparison src/lib-index/mail-index-transaction-view.c @ 8549:7b16388a3bb0 HEAD

mail_get_flags/keywords() now returns updated values if they've been changed within transaction.
author Timo Sirainen <tss@iki.fi>
date Sun, 14 Dec 2008 07:19:48 +0200
parents 6a6a3bfea547
children b9faf4db2a9f
comparison
equal deleted inserted replaced
8548:6a6a3bfea547 8549:7b16388a3bb0
13 struct mail_index_view_vfuncs *super; 13 struct mail_index_view_vfuncs *super;
14 struct mail_index_transaction *t; 14 struct mail_index_transaction *t;
15 15
16 struct mail_index_map *lookup_map; 16 struct mail_index_map *lookup_map;
17 struct mail_index_header hdr; 17 struct mail_index_header hdr;
18
18 buffer_t *lookup_return_data; 19 buffer_t *lookup_return_data;
19 uint32_t lookup_prev_seq; 20 uint32_t lookup_prev_seq;
21
22 unsigned int recs_count;
23 struct mail_index_record *recs;
20 }; 24 };
21 25
22 static void tview_close(struct mail_index_view *view) 26 static void tview_close(struct mail_index_view *view)
23 { 27 {
24 struct mail_index_view_transaction *tview = 28 struct mail_index_view_transaction *tview =
27 31
28 if (tview->lookup_map != NULL) 32 if (tview->lookup_map != NULL)
29 mail_index_unmap(&tview->lookup_map); 33 mail_index_unmap(&tview->lookup_map);
30 if (tview->lookup_return_data != NULL) 34 if (tview->lookup_return_data != NULL)
31 buffer_free(&tview->lookup_return_data); 35 buffer_free(&tview->lookup_return_data);
36 i_free(tview->recs);
32 37
33 tview->super->close(view); 38 tview->super->close(view);
34 mail_index_transaction_unref(&t); 39 mail_index_transaction_unref(&t);
35 } 40 }
36 41
60 tview->hdr = *hdr; 65 tview->hdr = *hdr;
61 tview->hdr.next_uid = next_uid; 66 tview->hdr.next_uid = next_uid;
62 hdr = &tview->hdr; 67 hdr = &tview->hdr;
63 } 68 }
64 return hdr; 69 return hdr;
70 }
71
72 static const struct mail_index_record *
73 tview_apply_flag_updates(struct mail_index_view_transaction *tview,
74 const struct mail_index_record *rec, uint32_t seq)
75 {
76 struct mail_index_transaction *t = tview->t;
77 const struct mail_transaction_flag_update *updates;
78 unsigned int idx, count;
79
80 /* see if there are any flag updates */
81 if (seq < t->min_flagupdate_seq || seq > t->max_flagupdate_seq ||
82 !array_is_created(&t->updates))
83 return rec;
84
85 updates = array_get(&t->updates, &count);
86 idx = mail_index_transaction_get_flag_update_pos(t, 0, count, seq);
87 if (seq < updates[idx].uid1 || seq > updates[idx].uid2)
88 return rec;
89
90 /* yes, we have flag updates. since we can't modify rec directly and
91 we want to be able to handle multiple mail_index_lookup() calls
92 without the second one overriding the first one's data, we'll
93 create a records array and return data from there */
94 if (tview->recs == NULL) {
95 tview->recs_count = t->first_new_seq;
96 tview->recs = i_new(struct mail_index_record,
97 tview->recs_count);
98 }
99 i_assert(tview->recs_count == t->first_new_seq);
100 i_assert(seq > 0 && seq <= tview->recs_count);
101
102 tview->recs[seq-1] = *rec;
103 tview->recs[seq-1].flags |= updates[idx].add_flags;
104 tview->recs[seq-1].flags &= ~updates[idx].remove_flags;
105 return &tview->recs[seq-1];
65 } 106 }
66 107
67 static const struct mail_index_record * 108 static const struct mail_index_record *
68 tview_lookup_full(struct mail_index_view *view, uint32_t seq, 109 tview_lookup_full(struct mail_index_view *view, uint32_t seq,
69 struct mail_index_map **map_r, bool *expunged_r) 110 struct mail_index_map **map_r, bool *expunged_r)
79 *expunged_r = FALSE; 120 *expunged_r = FALSE;
80 return mail_index_transaction_lookup(tview->t, seq); 121 return mail_index_transaction_lookup(tview->t, seq);
81 } 122 }
82 123
83 rec = tview->super->lookup_full(view, seq, map_r, expunged_r); 124 rec = tview->super->lookup_full(view, seq, map_r, expunged_r);
84 125 rec = tview_apply_flag_updates(tview, rec, seq);
85 /* if we're expunged within this transaction, return 0 */ 126
86 if (array_is_created(&tview->t->expunges) && 127 if (array_is_created(&tview->t->expunges) &&
87 seq_range_exists(&tview->t->expunges, seq)) 128 seq_range_exists(&tview->t->expunges, seq))
88 *expunged_r = TRUE; 129 *expunged_r = TRUE;
89 return rec; 130 return rec;
90 } 131 }
185 for (; seq <= message_count; seq++, rec++) { 226 for (; seq <= message_count; seq++, rec++) {
186 if ((rec->flags & flags_mask) == (uint8_t)flags) { 227 if ((rec->flags & flags_mask) == (uint8_t)flags) {
187 *seq_r = seq; 228 *seq_r = seq;
188 break; 229 break;
189 } 230 }
231 }
232 }
233
234 static void keyword_index_add(ARRAY_TYPE(keyword_indexes) *keywords,
235 unsigned int idx)
236 {
237 const unsigned int *indexes;
238 unsigned int i, count;
239
240 indexes = array_get(keywords, &count);
241 for (i = 0; i < count; i++) {
242 if (indexes[i] == idx)
243 return;
244 }
245 array_append(keywords, &idx, 1);
246 }
247
248 static void keyword_index_remove(ARRAY_TYPE(keyword_indexes) *keywords,
249 unsigned int idx)
250 {
251 const unsigned int *indexes;
252 unsigned int i, count;
253
254 indexes = array_get(keywords, &count);
255 for (i = 0; i < count; i++) {
256 if (indexes[i] == idx) {
257 array_delete(keywords, i, 1);
258 break;
259 }
260 }
261 }
262
263 static void tview_lookup_keywords(struct mail_index_view *view, uint32_t seq,
264 ARRAY_TYPE(keyword_indexes) *keyword_idx)
265 {
266 struct mail_index_view_transaction *tview =
267 (struct mail_index_view_transaction *)view;
268 struct mail_index_transaction *t = tview->t;
269 const struct mail_index_transaction_keyword_update *updates;
270 unsigned int i, count;
271
272 tview->super->lookup_keywords(view, seq, keyword_idx);
273
274 if (seq < t->min_flagupdate_seq || seq > t->max_flagupdate_seq) {
275 /* no keyword updates for this sequence */
276 return;
277 }
278
279 /* apply any keyword updates in this transaction */
280 if (array_is_created(&t->keyword_resets)) {
281 if (seq_range_exists(&t->keyword_resets, seq))
282 array_clear(keyword_idx);
283 }
284
285 if (array_is_created(&t->keyword_updates))
286 updates = array_get(&t->keyword_updates, &count);
287 else {
288 updates = NULL;
289 count = 0;
290 }
291 for (i = 0; i < count; i++) {
292 if (array_is_created(&updates[i].add_seq) &&
293 seq_range_exists(&updates[i].add_seq, seq))
294 keyword_index_add(keyword_idx, i);
295 else if (array_is_created(&updates[i].remove_seq) &&
296 seq_range_exists(&updates[i].remove_seq, seq))
297 keyword_index_remove(keyword_idx, i);
190 } 298 }
191 } 299 }
192 300
193 static struct mail_index_map * 301 static struct mail_index_map *
194 tview_get_lookup_map(struct mail_index_view_transaction *tview) 302 tview_get_lookup_map(struct mail_index_view_transaction *tview)
334 tview_get_header, 442 tview_get_header,
335 tview_lookup_full, 443 tview_lookup_full,
336 tview_lookup_uid, 444 tview_lookup_uid,
337 tview_lookup_seq_range, 445 tview_lookup_seq_range,
338 tview_lookup_first, 446 tview_lookup_first,
447 tview_lookup_keywords,
339 tview_lookup_ext_full, 448 tview_lookup_ext_full,
340 tview_get_header_ext, 449 tview_get_header_ext,
341 tview_ext_get_reset_id 450 tview_ext_get_reset_id
342 }; 451 };
343 452