Mercurial > dovecot > core-2.2
view src/lib-index/mail-index-transaction-view.c @ 6429:65c69a53a7be HEAD
Replaced my Copyright notices. The year range always ends with 2007 now.
My name was replaced with "Dovecot authors". In many cases I didn't really
even own the copyright, so this is more correct.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 16 Sep 2007 14:34:22 +0300 |
parents | a8b515e1a26f |
children | 90bcf480312d |
line wrap: on
line source
/* Copyright (c) 2004-2007 Dovecot authors, see the included COPYING file */ #include "lib.h" #include "array.h" #include "buffer.h" #include "seq-range-array.h" #include "mail-index-private.h" #include "mail-index-view-private.h" #include "mail-index-transaction-private.h" struct mail_index_view_transaction { struct mail_index_view view; struct mail_index_view_vfuncs *super; struct mail_index_transaction *t; struct mail_index_map *lookup_map; struct mail_index_header hdr; }; static void tview_close(struct mail_index_view *view) { struct mail_index_view_transaction *tview = (struct mail_index_view_transaction *)view; struct mail_index_transaction *t = tview->t; if (tview->lookup_map != NULL) mail_index_unmap(&tview->lookup_map); tview->super->close(view); mail_index_transaction_unref(&t); } static uint32_t tview_get_message_count(struct mail_index_view *view) { struct mail_index_view_transaction *tview = (struct mail_index_view_transaction *)view; return view->map->hdr.messages_count + (tview->t->last_new_seq == 0 ? 0 : tview->t->last_new_seq - tview->t->first_new_seq); } static const struct mail_index_header * tview_get_header(struct mail_index_view *view) { struct mail_index_view_transaction *tview = (struct mail_index_view_transaction *)view; const struct mail_index_header *hdr; uint32_t next_uid; /* FIXME: header counters may not be correct */ hdr = tview->super->get_header(view); next_uid = mail_index_transaction_get_next_uid(tview->t); if (next_uid != hdr->next_uid) { tview->hdr = *hdr; tview->hdr.next_uid = next_uid; hdr = &tview->hdr; } return hdr; } 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) { struct mail_index_view_transaction *tview = (struct mail_index_view_transaction *)view; const struct mail_index_record *rec; if (seq >= tview->t->first_new_seq) { /* FIXME: is this right to return index map..? it's not there yet. */ *map_r = view->index->map; *expunged_r = FALSE; return mail_index_transaction_lookup(tview->t, seq); } rec = tview->super->lookup_full(view, seq, map_r, expunged_r); /* 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; return rec; } static void tview_lookup_uid(struct mail_index_view *view, uint32_t seq, uint32_t *uid_r) { struct mail_index_view_transaction *tview = (struct mail_index_view_transaction *)view; if (seq >= tview->t->first_new_seq) *uid_r = mail_index_transaction_lookup(tview->t, seq)->uid; else tview->super->lookup_uid(view, seq, uid_r); } static void tview_lookup_uid_range(struct mail_index_view *view, uint32_t first_uid, uint32_t last_uid, uint32_t *first_seq_r, uint32_t *last_seq_r) { struct mail_index_view_transaction *tview = (struct mail_index_view_transaction *)view; const struct mail_index_record *rec; uint32_t seq; tview->super->lookup_uid_range(view, first_uid, last_uid, first_seq_r, last_seq_r); if (tview->t->last_new_seq == 0) { /* no new messages, the results are final. */ return; } rec = mail_index_transaction_lookup(tview->t, tview->t->first_new_seq); if (rec->uid == 0) { /* new messages don't have UIDs */ return; } if (last_uid < rec->uid) { /* all wanted messages were existing */ return; } /* at least some of the wanted messages are newly created */ if (*first_seq_r == 0) *first_seq_r = tview->t->first_new_seq; seq = tview->t->last_new_seq; for (; seq >= tview->t->first_new_seq; seq--) { rec = mail_index_transaction_lookup(tview->t, seq); if (rec->uid <= last_uid) { *last_seq_r = seq; break; } } i_assert(seq >= tview->t->first_new_seq); } static void tview_lookup_first(struct mail_index_view *view, enum mail_flags flags, uint8_t flags_mask, uint32_t *seq_r) { struct mail_index_view_transaction *tview = (struct mail_index_view_transaction *)view; const struct mail_index_record *rec; unsigned int append_count; uint32_t seq, message_count; tview->super->lookup_first(view, flags, flags_mask, seq_r); if (*seq_r != 0) return; rec = array_get(&tview->t->appends, &append_count); seq = tview->t->first_new_seq; message_count = tview->t->last_new_seq; i_assert(append_count == message_count - seq + 1); for (; seq <= message_count; seq++, rec++) { if ((rec->flags & flags_mask) == (uint8_t)flags) { *seq_r = seq; break; } } } static struct mail_index_map * tview_get_lookup_map(struct mail_index_view_transaction *tview) { if (tview->lookup_map == NULL) { tview->lookup_map = mail_index_map_clone(tview->view.index->map); } return tview->lookup_map; } static void tview_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) { struct mail_index_view_transaction *tview = (struct mail_index_view_transaction *)view; const ARRAY_TYPE(seq_array) *ext_buf; const void *data; unsigned int idx; i_assert(ext_id < array_count(&view->index->extensions)); *expunged_r = FALSE; if (array_is_created(&tview->t->ext_rec_updates) && ext_id < array_count(&tview->t->ext_rec_updates)) { /* there are some ext updates in transaction. see if there's any for this sequence. */ ext_buf = array_idx(&tview->t->ext_rec_updates, ext_id); if (array_is_created(ext_buf) && mail_index_seq_array_lookup(ext_buf, seq, &idx)) { data = array_idx(ext_buf, idx); *map_r = tview_get_lookup_map(tview); *data_r = CONST_PTR_OFFSET(data, sizeof(uint32_t)); return; } } /* not updated, return the existing value */ if (seq < tview->t->first_new_seq) { tview->super->lookup_ext_full(view, seq, ext_id, map_r, data_r, expunged_r); } else { *map_r = view->index->map; *data_r = NULL; } } static void tview_get_header_ext(struct mail_index_view *view, struct mail_index_map *map, uint32_t ext_id, const void **data_r, size_t *data_size_r) { struct mail_index_view_transaction *tview = (struct mail_index_view_transaction *)view; /* FIXME: check updates */ tview->super->get_header_ext(view, map, ext_id, data_r, data_size_r); } static bool tview_ext_get_reset_id(struct mail_index_view *view, struct mail_index_map *map, uint32_t ext_id, uint32_t *reset_id_r) { struct mail_index_view_transaction *tview = (struct mail_index_view_transaction *)view; const uint32_t *reset_id_p; if (array_is_created(&tview->t->ext_reset_ids) && ext_id < array_count(&tview->t->ext_reset_ids) && map == tview->lookup_map) { reset_id_p = array_idx(&tview->t->ext_reset_ids, ext_id); *reset_id_r = *reset_id_p; return TRUE; } return tview->super->ext_get_reset_id(view, map, ext_id, reset_id_r); } static struct mail_index_view_vfuncs trans_view_vfuncs = { tview_close, tview_get_message_count, tview_get_header, tview_lookup_full, tview_lookup_uid, tview_lookup_uid_range, tview_lookup_first, tview_lookup_ext_full, tview_get_header_ext, tview_ext_get_reset_id }; struct mail_index_view * mail_index_transaction_open_updated_view(struct mail_index_transaction *t) { struct mail_index_view_transaction *tview; if (t->view->syncing) { /* transaction view is being synced. while it's done, it's not possible to add new messages, but the view itself might change. so we can't make a copy of the view. */ mail_index_view_ref(t->view); return t->view; } tview = i_new(struct mail_index_view_transaction, 1); mail_index_view_clone(&tview->view, t->view); tview->view.v = trans_view_vfuncs; tview->super = &t->view->v; tview->t = t; mail_index_transaction_ref(t); return &tview->view; }