Mercurial > dovecot > original-hg > dovecot-1.2
changeset 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 | 613151990b79 |
files | src/lib-index/mail-index-dummy-view.c src/lib-index/mail-index-transaction-private.h src/lib-index/mail-index-transaction-view.c src/lib-index/mail-index-transaction.c src/lib-index/mail-index-view-private.h src/lib-index/mail-index-view.c src/lib-storage/index/index-mail.c src/lib-storage/index/index-mail.h src/plugins/virtual/virtual-mail.c |
diffstat | 9 files changed, 210 insertions(+), 74 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-index/mail-index-dummy-view.c Sun Dec 14 06:51:04 2008 +0200 +++ b/src/lib-index/mail-index-dummy-view.c Sun Dec 14 07:19:48 2008 +0200 @@ -29,6 +29,7 @@ NULL, NULL, NULL, + NULL, NULL };
--- a/src/lib-index/mail-index-transaction-private.h Sun Dec 14 06:51:04 2008 +0200 +++ b/src/lib-index/mail-index-transaction-private.h Sun Dec 14 07:19:48 2008 +0200 @@ -100,6 +100,12 @@ void mail_index_transaction_convert_to_uids(struct mail_index_transaction *t); void mail_index_transaction_check_conflicts(struct mail_index_transaction *t); +unsigned int +mail_index_transaction_get_flag_update_pos(struct mail_index_transaction *t, + unsigned int left_idx, + unsigned int right_idx, + uint32_t seq); + bool mail_index_seq_array_lookup(const ARRAY_TYPE(seq_array) *array, uint32_t seq, unsigned int *idx_r);
--- a/src/lib-index/mail-index-transaction-view.c Sun Dec 14 06:51:04 2008 +0200 +++ b/src/lib-index/mail-index-transaction-view.c Sun Dec 14 07:19:48 2008 +0200 @@ -15,8 +15,12 @@ struct mail_index_map *lookup_map; struct mail_index_header hdr; + buffer_t *lookup_return_data; uint32_t lookup_prev_seq; + + unsigned int recs_count; + struct mail_index_record *recs; }; static void tview_close(struct mail_index_view *view) @@ -29,6 +33,7 @@ mail_index_unmap(&tview->lookup_map); if (tview->lookup_return_data != NULL) buffer_free(&tview->lookup_return_data); + i_free(tview->recs); tview->super->close(view); mail_index_transaction_unref(&t); @@ -65,6 +70,42 @@ } static const struct mail_index_record * +tview_apply_flag_updates(struct mail_index_view_transaction *tview, + const struct mail_index_record *rec, uint32_t seq) +{ + struct mail_index_transaction *t = tview->t; + const struct mail_transaction_flag_update *updates; + unsigned int idx, count; + + /* see if there are any flag updates */ + if (seq < t->min_flagupdate_seq || seq > t->max_flagupdate_seq || + !array_is_created(&t->updates)) + return rec; + + updates = array_get(&t->updates, &count); + idx = mail_index_transaction_get_flag_update_pos(t, 0, count, seq); + if (seq < updates[idx].uid1 || seq > updates[idx].uid2) + return rec; + + /* yes, we have flag updates. since we can't modify rec directly and + we want to be able to handle multiple mail_index_lookup() calls + without the second one overriding the first one's data, we'll + create a records array and return data from there */ + if (tview->recs == NULL) { + tview->recs_count = t->first_new_seq; + tview->recs = i_new(struct mail_index_record, + tview->recs_count); + } + i_assert(tview->recs_count == t->first_new_seq); + i_assert(seq > 0 && seq <= tview->recs_count); + + tview->recs[seq-1] = *rec; + tview->recs[seq-1].flags |= updates[idx].add_flags; + tview->recs[seq-1].flags &= ~updates[idx].remove_flags; + return &tview->recs[seq-1]; +} + +static const struct mail_index_record * tview_lookup_full(struct mail_index_view *view, uint32_t seq, struct mail_index_map **map_r, bool *expunged_r) { @@ -81,8 +122,8 @@ } rec = tview->super->lookup_full(view, seq, map_r, expunged_r); + rec = tview_apply_flag_updates(tview, rec, seq); - /* if we're expunged within this transaction, return 0 */ if (array_is_created(&tview->t->expunges) && seq_range_exists(&tview->t->expunges, seq)) *expunged_r = TRUE; @@ -190,6 +231,73 @@ } } +static void keyword_index_add(ARRAY_TYPE(keyword_indexes) *keywords, + unsigned int idx) +{ + const unsigned int *indexes; + unsigned int i, count; + + indexes = array_get(keywords, &count); + for (i = 0; i < count; i++) { + if (indexes[i] == idx) + return; + } + array_append(keywords, &idx, 1); +} + +static void keyword_index_remove(ARRAY_TYPE(keyword_indexes) *keywords, + unsigned int idx) +{ + const unsigned int *indexes; + unsigned int i, count; + + indexes = array_get(keywords, &count); + for (i = 0; i < count; i++) { + if (indexes[i] == idx) { + array_delete(keywords, i, 1); + break; + } + } +} + +static void tview_lookup_keywords(struct mail_index_view *view, uint32_t seq, + ARRAY_TYPE(keyword_indexes) *keyword_idx) +{ + struct mail_index_view_transaction *tview = + (struct mail_index_view_transaction *)view; + struct mail_index_transaction *t = tview->t; + const struct mail_index_transaction_keyword_update *updates; + unsigned int i, count; + + tview->super->lookup_keywords(view, seq, keyword_idx); + + if (seq < t->min_flagupdate_seq || seq > t->max_flagupdate_seq) { + /* no keyword updates for this sequence */ + return; + } + + /* apply any keyword updates in this transaction */ + if (array_is_created(&t->keyword_resets)) { + if (seq_range_exists(&t->keyword_resets, seq)) + array_clear(keyword_idx); + } + + if (array_is_created(&t->keyword_updates)) + updates = array_get(&t->keyword_updates, &count); + else { + updates = NULL; + count = 0; + } + for (i = 0; i < count; i++) { + if (array_is_created(&updates[i].add_seq) && + seq_range_exists(&updates[i].add_seq, seq)) + keyword_index_add(keyword_idx, i); + else if (array_is_created(&updates[i].remove_seq) && + seq_range_exists(&updates[i].remove_seq, seq)) + keyword_index_remove(keyword_idx, i); + } +} + static struct mail_index_map * tview_get_lookup_map(struct mail_index_view_transaction *tview) { @@ -336,6 +444,7 @@ tview_lookup_uid, tview_lookup_seq_range, tview_lookup_first, + tview_lookup_keywords, tview_lookup_ext_full, tview_get_header_ext, tview_ext_get_reset_id
--- a/src/lib-index/mail-index-transaction.c Sun Dec 14 06:51:04 2008 +0200 +++ b/src/lib-index/mail-index-transaction.c Sun Dec 14 07:19:48 2008 +0200 @@ -805,10 +805,11 @@ return FALSE; } -static uint32_t -mail_index_find_update_insert_pos(struct mail_index_transaction *t, - unsigned int left_idx, unsigned int right_idx, - uint32_t seq) +unsigned int +mail_index_transaction_get_flag_update_pos(struct mail_index_transaction *t, + unsigned int left_idx, + unsigned int right_idx, + uint32_t seq) { const struct mail_transaction_flag_update *updates; unsigned int idx, count; @@ -1038,8 +1039,8 @@ first_idx = 0; count = t->last_update_idx + 1; } - idx = mail_index_find_update_insert_pos(t, first_idx, count, - u.uid1); + idx = mail_index_transaction_get_flag_update_pos(t, first_idx, + count, u.uid1); mail_index_insert_flag_update(t, u, idx); } } @@ -1567,7 +1568,7 @@ return ret; updates = array_get_modifiable(&t->updates, &count); - i = mail_index_find_update_insert_pos(t, 0, count, seq); + i = mail_index_transaction_get_flag_update_pos(t, 0, count, seq); if (i < count && updates[i].uid1 <= seq && updates[i].uid2 >= seq) { /* exists */ ret = TRUE;
--- a/src/lib-index/mail-index-view-private.h Sun Dec 14 06:51:04 2008 +0200 +++ b/src/lib-index/mail-index-view-private.h Sun Dec 14 07:19:48 2008 +0200 @@ -26,6 +26,8 @@ void (*lookup_first)(struct mail_index_view *view, enum mail_flags flags, uint8_t flags_mask, uint32_t *seq_r); + void (*lookup_keywords)(struct mail_index_view *view, uint32_t seq, + ARRAY_TYPE(keyword_indexes) *keyword_idx); void (*lookup_ext_full)(struct mail_index_view *view, uint32_t seq, uint32_t ext_id, struct mail_index_map **map_r, const void **data_r, bool *expunged_r);
--- a/src/lib-index/mail-index-view.c Sun Dec 14 06:51:04 2008 +0200 +++ b/src/lib-index/mail-index-view.c Sun Dec 14 07:19:48 2008 +0200 @@ -333,6 +333,62 @@ } static void +mail_index_data_lookup_keywords(struct mail_index_map *map, + const unsigned char *data, + ARRAY_TYPE(keyword_indexes) *keyword_idx) +{ + const unsigned int *keyword_idx_map; + unsigned int i, j, keyword_count, index_idx; + uint32_t idx; + uint16_t record_size; + + array_clear(keyword_idx); + if (data == NULL) { + /* no keywords at all in index */ + return; + } + (void)mail_index_ext_get_size(NULL, map->index->keywords_ext_id, + map, NULL, &record_size, NULL); + + /* keyword_idx_map[] contains file => index keyword mapping */ + if (!array_is_created(&map->keyword_idx_map)) + return; + + keyword_idx_map = array_get(&map->keyword_idx_map, &keyword_count); + for (i = 0, idx = 0; i < record_size; i++) { + /* first do the quick check to see if there's keywords at all */ + if (data[i] == 0) + continue; + + idx = i * CHAR_BIT; + for (j = 0; j < CHAR_BIT; j++, idx++) { + if ((data[i] & (1 << j)) == 0) + continue; + + if (idx >= keyword_count) { + /* extra bits set in keyword bytes. + shouldn't happen, but just ignore. */ + break; + } + + index_idx = keyword_idx_map[idx]; + array_append(keyword_idx, &index_idx, 1); + } + } +} + +static void view_lookup_keywords(struct mail_index_view *view, uint32_t seq, + ARRAY_TYPE(keyword_indexes) *keyword_idx) +{ + struct mail_index_map *map; + const void *data; + + mail_index_lookup_ext_full(view, seq, view->index->keywords_ext_id, + &map, &data, NULL); + mail_index_data_lookup_keywords(map, data, keyword_idx); +} + +static void view_lookup_ext_full(struct mail_index_view *view, uint32_t seq, uint32_t ext_id, struct mail_index_map **map_r, const void **data_r, bool *expunged_r) @@ -442,51 +498,6 @@ return expunged; } -static void -mail_index_data_lookup_keywords(struct mail_index_map *map, - const unsigned char *data, - ARRAY_TYPE(keyword_indexes) *keyword_idx) -{ - const unsigned int *keyword_idx_map; - unsigned int i, j, keyword_count, index_idx; - uint32_t idx; - uint16_t record_size; - - array_clear(keyword_idx); - if (data == NULL) { - /* no keywords at all in index */ - return; - } - (void)mail_index_ext_get_size(NULL, map->index->keywords_ext_id, - map, NULL, &record_size, NULL); - - /* keyword_idx_map[] contains file => index keyword mapping */ - if (!array_is_created(&map->keyword_idx_map)) - return; - - keyword_idx_map = array_get(&map->keyword_idx_map, &keyword_count); - for (i = 0, idx = 0; i < record_size; i++) { - /* first do the quick check to see if there's keywords at all */ - if (data[i] == 0) - continue; - - idx = i * CHAR_BIT; - for (j = 0; j < CHAR_BIT; j++, idx++) { - if ((data[i] & (1 << j)) == 0) - continue; - - if (idx >= keyword_count) { - /* extra bits set in keyword bytes. - shouldn't happen, but just ignore. */ - break; - } - - index_idx = keyword_idx_map[idx]; - array_append(keyword_idx, &index_idx, 1); - } - } -} - void mail_index_map_lookup_keywords(struct mail_index_map *map, uint32_t seq, ARRAY_TYPE(keyword_indexes) *keyword_idx) { @@ -509,12 +520,7 @@ void mail_index_lookup_keywords(struct mail_index_view *view, uint32_t seq, ARRAY_TYPE(keyword_indexes) *keyword_idx) { - struct mail_index_map *map; - const void *data; - - mail_index_lookup_ext_full(view, seq, view->index->keywords_ext_id, - &map, &data, NULL); - mail_index_data_lookup_keywords(map, data, keyword_idx); + view->v.lookup_keywords(view, seq, keyword_idx); } void mail_index_lookup_uid(struct mail_index_view *view, uint32_t seq, @@ -625,6 +631,7 @@ view_lookup_uid, view_lookup_seq_range, view_lookup_first, + view_lookup_keywords, view_lookup_ext_full, view_get_header_ext, view_ext_get_reset_id
--- a/src/lib-storage/index/index-mail.c Sun Dec 14 06:51:04 2008 +0200 +++ b/src/lib-storage/index/index-mail.c Sun Dec 14 07:19:48 2008 +0200 @@ -122,12 +122,17 @@ enum mail_flags index_mail_get_flags(struct mail *_mail) { struct index_mail *mail = (struct index_mail *)_mail; - struct index_mail_data *data = &mail->data; + const struct mail_index_record *rec; + enum mail_flags flags; + + rec = mail_index_lookup(mail->trans->trans_view, _mail->seq); + flags = rec->flags & (MAIL_FLAGS_NONRECENT | + MAIL_INDEX_MAIL_FLAG_BACKEND); if (index_mailbox_is_recent(mail->ibox, _mail->uid)) - data->flags |= MAIL_RECENT; + flags |= MAIL_RECENT; - return data->flags; + return flags; } uint64_t index_mail_get_modseq(struct mail *_mail) @@ -180,7 +185,8 @@ if (!array_is_created(&data->keyword_indexes)) { p_array_init(&data->keyword_indexes, mail->data_pool, 32); - mail_index_lookup_keywords(mail->ibox->view, mail->data.seq, + mail_index_lookup_keywords(mail->trans->trans_view, + mail->data.seq, &data->keyword_indexes); } return &data->keyword_indexes; @@ -1176,7 +1182,6 @@ struct index_mail_data *data = &mail->data; struct mail_cache_field *cache_fields = mail->ibox->cache_fields; struct mail_cache_view *cache_view = mail->trans->cache_view; - const struct mail_index_record *rec; struct istream *input; if (data->seq == seq) @@ -1184,13 +1189,11 @@ index_mail_reset(mail); - rec = mail_index_lookup(mail->trans->trans_view, seq); data->seq = seq; - data->flags = rec->flags & (MAIL_FLAGS_NONRECENT | - MAIL_INDEX_MAIL_FLAG_BACKEND); mail->mail.mail.seq = seq; - mail->mail.mail.uid = rec->uid; + mail_index_lookup_uid(mail->trans->trans_view, seq, + &mail->mail.mail.uid); if (mail_index_view_is_inconsistent(mail->trans->trans_view)) { mail_set_expunged(&mail->mail.mail); @@ -1395,6 +1398,18 @@ { struct index_mail *imail = (struct index_mail *)mail; + if (array_is_created(&imail->data.keyword_indexes)) + array_free(&imail->data.keyword_indexes); + if (array_is_created(&imail->data.keywords)) { + /* clear the keywords array so the next mail_get_keywords() + returns the updated keywords. don't free the array, because + then any existing mail_get_keywords() return values would + point to broken data. this won't leak memory because the + array is allocated from mail's memory pool. */ + memset(&imail->data.keywords, 0, + sizeof(imail->data.keywords)); + } + mail_index_update_keywords(imail->trans->trans, mail->seq, modify_type, keywords); }
--- a/src/lib-storage/index/index-mail.h Sun Dec 14 06:51:04 2008 +0200 +++ b/src/lib-storage/index/index-mail.h Sun Dec 14 07:19:48 2008 +0200 @@ -69,7 +69,6 @@ struct message_header_line; struct index_mail_data { - enum mail_flags flags; time_t date, received_date, save_date; uoff_t virtual_size, physical_size;
--- a/src/plugins/virtual/virtual-mail.c Sun Dec 14 06:51:04 2008 +0200 +++ b/src/plugins/virtual/virtual-mail.c Sun Dec 14 07:19:48 2008 +0200 @@ -83,7 +83,6 @@ struct mailbox_transaction_context *backend_trans; struct mailbox_header_lookup_ctx *backend_headers; const struct virtual_mail_index_record *vrec; - const struct mail_index_record *rec; const void *data; bool expunged; @@ -112,12 +111,9 @@ memset(&vmail->imail.data, 0, sizeof(vmail->imail.data)); p_clear(vmail->imail.data_pool); - rec = mail_index_lookup(mbox->ibox.view, seq); vmail->imail.data.seq = seq; - vmail->imail.data.flags = rec->flags & MAIL_FLAGS_NONRECENT; - mail->seq = seq; - mail->uid = rec->uid; + mail_index_lookup_uid(mbox->ibox.view, seq, &mail->uid); mail->expunged = vmail->backend_mail->expunged; mail->has_nuls = vmail->backend_mail->has_nuls;