Mercurial > dovecot > original-hg > dovecot-1.2
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 |