From 24fc71a693331ffe77e2b6d81c70aca6fa055e47 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Tue, 22 Jun 2004 10:36:33 +0300 Subject: [PATCH] Added mail_index_transaction_get_updated_view() which can be used to access uncommitted messages. --HG-- branch : HEAD --- src/lib-index/Makefile.am | 1 + src/lib-index/mail-cache-lookup.c | 5 - src/lib-index/mail-cache-transaction.c | 13 +- .../mail-index-transaction-private.h | 7 +- src/lib-index/mail-index-transaction-view.c | 165 ++++++++++++++ src/lib-index/mail-index-transaction.c | 37 ++- src/lib-index/mail-index-view-private.h | 20 ++ src/lib-index/mail-index-view.c | 215 ++++++++++++------ src/lib-index/mail-index.h | 11 +- src/lib-storage/index/index-fetch.c | 2 +- src/lib-storage/index/index-mail-headers.c | 18 +- src/lib-storage/index/index-mail.c | 39 ++-- src/lib-storage/index/index-search.c | 24 +- src/lib-storage/index/index-storage.c | 4 - src/lib-storage/index/index-storage.h | 8 +- src/lib-storage/index/index-transaction.c | 19 +- .../index/maildir/maildir-transaction.c | 10 +- src/lib-storage/index/mbox/mbox-mail.c | 2 +- src/lib-storage/index/mbox/mbox-save.c | 4 +- src/lib-storage/index/mbox/mbox-transaction.c | 10 +- 20 files changed, 434 insertions(+), 180 deletions(-) create mode 100644 src/lib-index/mail-index-transaction-view.c diff --git a/src/lib-index/Makefile.am b/src/lib-index/Makefile.am index 9860919d79..f2bae4cefe 100644 --- a/src/lib-index/Makefile.am +++ b/src/lib-index/Makefile.am @@ -12,6 +12,7 @@ libindex_a_SOURCES = \ mail-index-fsck.c \ mail-index-lock.c \ mail-index-transaction.c \ + mail-index-transaction-view.c \ mail-index-sync.c \ mail-index-sync-update.c \ mail-index-view.c \ diff --git a/src/lib-index/mail-cache-lookup.c b/src/lib-index/mail-cache-lookup.c index 8ad0050c02..c28ccedc49 100644 --- a/src/lib-index/mail-cache-lookup.c +++ b/src/lib-index/mail-cache-lookup.c @@ -175,11 +175,6 @@ mail_cache_lookup(struct mail_cache_view *view, uint32_t seq, if (view->cache->disabled) return NULL; - if (seq > mail_index_view_get_message_count(view->view)) { - /* it's being appended in some transaction */ - return NULL; - } - if (mail_index_lookup_full(view->view, seq, &map, &rec) < 0) return NULL; diff --git a/src/lib-index/mail-cache-transaction.c b/src/lib-index/mail-cache-transaction.c index 3c63de017c..251ff9dfa7 100644 --- a/src/lib-index/mail-cache-transaction.c +++ b/src/lib-index/mail-cache-transaction.c @@ -220,7 +220,7 @@ static int mail_cache_write(struct mail_cache_transaction_ctx *ctx) struct mail_cache_record *cache_rec, *next; const struct mail_index_record *rec; struct mail_index_map *map; - uint32_t messages_count, write_offset, update_offset; + uint32_t write_offset, update_offset; const void *buf; size_t size, buf_size; int ret; @@ -230,15 +230,8 @@ static int mail_cache_write(struct mail_cache_transaction_ctx *ctx) size = sizeof(*cache_rec) + buf_size; ctx->cache_rec.size = uint32_to_nbo(size); - messages_count = mail_index_view_get_message_count(ctx->view->view); - if (ctx->prev_seq <= messages_count) { - ret = mail_index_lookup_full(ctx->view->view, ctx->prev_seq, - &map, &rec); - } else { - ret = mail_index_transaction_lookup(ctx->trans, - ctx->prev_seq, &rec); - map = cache->index->map; - } + ret = mail_index_lookup_full(ctx->view->view, ctx->prev_seq, + &map, &rec); if (ret < 0) return -1; diff --git a/src/lib-index/mail-index-transaction-private.h b/src/lib-index/mail-index-transaction-private.h index d0efb4e31c..f22ac491ca 100644 --- a/src/lib-index/mail-index-transaction-private.h +++ b/src/lib-index/mail-index-transaction-private.h @@ -1,8 +1,10 @@ #ifndef __MAIL_INDEX_TRANSACTION_PRIVATE_H #define __MAIL_INDEX_TRANSACTION_PRIVATE_H +#include "mail-transaction-log.h" + struct mail_index_transaction { - struct mail_index_view *view; + struct mail_index_view *view, *updated_view; buffer_t *appends; uint32_t first_new_seq, last_new_seq; @@ -24,4 +26,7 @@ struct mail_index_transaction { unsigned int hdr_changed:1; }; +struct mail_index_record * +mail_index_transaction_lookup(struct mail_index_transaction *t, uint32_t seq); + #endif diff --git a/src/lib-index/mail-index-transaction-view.c b/src/lib-index/mail-index-transaction-view.c new file mode 100644 index 0000000000..30c1bb022e --- /dev/null +++ b/src/lib-index/mail-index-transaction-view.c @@ -0,0 +1,165 @@ +/* Copyright (C) 2004 Timo Sirainen */ + +#include "lib.h" +#include "buffer.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_methods *parent; + struct mail_index_transaction *t; +}; + +static void _tview_close(struct mail_index_view *view) +{ + struct mail_index_view_transaction *tview = + (struct mail_index_view_transaction *)view; + + tview->t->updated_view = NULL; + + return tview->parent->close(view); +} + +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->messages_count + + (tview->t->last_new_seq == 0 ? 0 : + tview->t->last_new_seq - tview->t->first_new_seq); +} + +static int _tview_get_header(struct mail_index_view *view, + const struct mail_index_header **hdr_r) +{ + struct mail_index_view_transaction *tview = + (struct mail_index_view_transaction *)view; + + if (tview->parent->get_header(view, hdr_r) < 0) + return -1; + + if ((*hdr_r)->messages_count != view->messages_count) { + /* messages_count differs, use a modified copy. + FIXME: same problems as with _view_get_header().. */ + view->tmp_hdr_copy = **hdr_r; + view->tmp_hdr_copy.messages_count = view->messages_count; + *hdr_r = &view->tmp_hdr_copy; + } + return 0; +} + +static int _tview_lookup_full(struct mail_index_view *view, uint32_t seq, + struct mail_index_map **map_r, + const struct mail_index_record **rec_r) +{ + struct mail_index_view_transaction *tview = + (struct mail_index_view_transaction *)view; + + 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; + *rec_r = mail_index_transaction_lookup(tview->t, seq); + return 1; + } else { + return tview->parent->lookup_full(view, seq, map_r, rec_r); + } +} + +static int _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; + return 0; + } else { + return tview->parent->lookup_uid(view, seq, uid_r); + } +} + +static int _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; + + if (tview->parent->lookup_uid_range(view, first_uid, last_uid, + first_seq_r, last_seq_r) < 0) + return -1; + + /* FIXME: we don't need this function yet.. new UIDs might be 0 as + well.. */ + + if (*first_seq_r == 0) { + /* nothing found, either doesn't exist or it's completely + newly appended. */ + } else if (*last_seq_r + 1 == tview->t->first_new_seq) { + /* last_seq_r may be growed from transactions */ + } + + return 0; +} + +static int _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; + uint32_t seq, message_count; + + if (tview->parent->lookup_first(view, flags, flags_mask, seq_r) < 0) + return -1; + + if (*seq_r != 0) + return 0; + + rec = buffer_get_data(tview->t->appends, NULL); + seq = tview->t->first_new_seq; + message_count = tview->t->last_new_seq; + for (; seq <= message_count; seq++) { + if ((rec->flags & flags_mask) == (uint8_t)flags) { + *seq_r = seq; + break; + } + rec = CONST_PTR_OFFSET(rec, view->index->record_size); + } + + return 0; +} + +static struct mail_index_view_methods view_methods = { + _tview_close, + _tview_get_message_count, + _tview_get_header, + _tview_lookup_full, + _tview_lookup_uid, + _tview_lookup_uid_range, + _tview_lookup_first +}; + +struct mail_index_view * +mail_index_transaction_get_updated_view(struct mail_index_transaction *t) +{ + struct mail_index_view_transaction *tview; + + if (t->updated_view == NULL) { + tview = i_new(struct mail_index_view_transaction, 1); + mail_index_view_clone(&tview->view, t->view); + tview->view.methods = view_methods; + tview->parent = &t->view->methods; + tview->t = t; + + t->updated_view = &tview->view; + } + + return t->updated_view; +} diff --git a/src/lib-index/mail-index-transaction.c b/src/lib-index/mail-index-transaction.c index 35a003990a..58e7766388 100644 --- a/src/lib-index/mail-index-transaction.c +++ b/src/lib-index/mail-index-transaction.c @@ -25,6 +25,7 @@ mail_index_transaction_begin(struct mail_index_view *view, int hide) t = i_new(struct mail_index_transaction, 1); t->view = view; t->hide_transaction = hide; + t->first_new_seq = mail_index_view_get_message_count(t->view)+1; return t; } @@ -47,6 +48,8 @@ static void mail_index_transaction_free(struct mail_index_transaction *t) buffer_free(t->updates); if (t->cache_updates != NULL) buffer_free(t->cache_updates); + if (t->updated_view != NULL) + mail_index_view_close(t->updated_view); i_free(t); } @@ -136,8 +139,8 @@ void mail_index_transaction_rollback(struct mail_index_transaction *t) mail_index_transaction_free(t); } -static struct mail_index_record * -mail_index_lookup_append(struct mail_index_transaction *t, uint32_t seq) +struct mail_index_record * +mail_index_transaction_lookup(struct mail_index_transaction *t, uint32_t seq) { size_t pos; @@ -148,18 +151,6 @@ mail_index_lookup_append(struct mail_index_transaction *t, uint32_t seq) t->view->index->record_size); } -int mail_index_transaction_lookup(struct mail_index_transaction *t, - uint32_t seq, - const struct mail_index_record **rec_r) -{ - if (t->first_new_seq != 0 && seq >= t->first_new_seq) { - *rec_r = mail_index_lookup_append(t, seq); - return 1; - } else { - return mail_index_lookup(t->view, seq, rec_r); - } -} - void mail_index_append(struct mail_index_transaction *t, uint32_t uid, uint32_t *seq_r) { @@ -174,10 +165,8 @@ void mail_index_append(struct mail_index_transaction *t, uint32_t uid, so let it generate it */ if (t->last_new_seq != 0) *seq_r = ++t->last_new_seq; - else { - *seq_r = t->first_new_seq = t->last_new_seq = - mail_index_view_get_message_count(t->view)+1; - } + else + *seq_r = t->last_new_seq = t->first_new_seq; rec = buffer_append_space_unsafe(t->appends, t->view->index->record_size); @@ -313,9 +302,9 @@ void mail_index_update_flags(struct mail_index_transaction *t, uint32_t seq, { struct mail_index_record *rec; - if (t->first_new_seq != 0 && seq >= t->first_new_seq) { + if (seq >= t->first_new_seq) { /* just appended message, modify it directly */ - rec = mail_index_lookup_append(t, seq); + rec = mail_index_transaction_lookup(t, seq); mail_index_record_modify_flags(rec, modify_type, flags, keywords); return; @@ -497,9 +486,9 @@ void mail_index_update_cache(struct mail_index_transaction *t, { struct mail_index_record *rec; - if (t->first_new_seq != 0 && seq >= t->first_new_seq) { + if (seq >= t->first_new_seq) { /* just appended message, modify it directly */ - rec = mail_index_lookup_append(t, seq); + rec = mail_index_transaction_lookup(t, seq); rec->cache_offset = offset; } else { mail_index_update_seq_buffer(&t->cache_updates, seq, @@ -516,10 +505,10 @@ void mail_index_update_extra_rec(struct mail_index_transaction *t, i_assert(data_id < index->extra_records_count); - if (t->first_new_seq != 0 && seq >= t->first_new_seq) { + if (seq >= t->first_new_seq) { /* just appended message, modify it directly */ /* FIXME: do data_id mapping conversion */ - rec = mail_index_lookup_append(t, seq); + rec = mail_index_transaction_lookup(t, seq); memcpy(PTR_OFFSET(rec, index->extra_records[data_id].offset), data, index->extra_records[data_id].size); } else { diff --git a/src/lib-index/mail-index-view-private.h b/src/lib-index/mail-index-view-private.h index 7dba3058ce..15de0963ae 100644 --- a/src/lib-index/mail-index-view-private.h +++ b/src/lib-index/mail-index-view-private.h @@ -3,7 +3,25 @@ #include "mail-index-private.h" +struct mail_index_view_methods { + void (*close)(struct mail_index_view *view); + uint32_t (*get_message_count)(struct mail_index_view *view); + int (*get_header)(struct mail_index_view *view, + const struct mail_index_header **hdr_r); + int (*lookup_full)(struct mail_index_view *view, uint32_t seq, + struct mail_index_map **map_r, + const struct mail_index_record **rec_r); + int (*lookup_uid)(struct mail_index_view *view, uint32_t seq, + uint32_t *uid_r); + int (*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); + int (*lookup_first)(struct mail_index_view *view, enum mail_flags flags, + uint8_t flags_mask, uint32_t *seq_r); +}; + struct mail_index_view { + struct mail_index_view_methods methods; struct mail_index *index; struct mail_transaction_log_view *log_view; @@ -27,6 +45,8 @@ struct mail_index_view { unsigned int map_protected:1; }; +void mail_index_view_clone(struct mail_index_view *dest, + const struct mail_index_view *src); int mail_index_view_lock(struct mail_index_view *view); int mail_index_view_lock_head(struct mail_index_view *view, int update_index); void mail_index_view_add_synced_transaction(struct mail_index_view *view, diff --git a/src/lib-index/mail-index-view.c b/src/lib-index/mail-index-view.c index 3d8fc5d924..479249a13e 100644 --- a/src/lib-index/mail-index-view.c +++ b/src/lib-index/mail-index-view.c @@ -6,25 +6,24 @@ #include "mail-index-view-private.h" #include "mail-transaction-log.h" -struct mail_index_view *mail_index_view_open(struct mail_index *index) +void mail_index_view_clone(struct mail_index_view *dest, + const struct mail_index_view *src) { - struct mail_index_view *view; - - view = i_new(struct mail_index_view, 1); - view->index = index; - view->log_view = mail_transaction_log_view_open(index->log); - - view->indexid = index->indexid; - view->map = index->map; - view->map->refcount++; - view->messages_count = view->map->records_count; - - view->log_file_seq = view->map->log_file_seq; - view->log_file_offset = view->map->log_file_offset; - return view; + memset(dest, 0, sizeof(dest)); + dest->methods = src->methods; + dest->index = src->index; + dest->log_view = mail_transaction_log_view_open(src->index->log); + + dest->indexid = src->indexid; + dest->map = src->map; + dest->map->refcount++; + dest->messages_count = src->messages_count; + + dest->log_file_seq = src->log_file_seq; + dest->log_file_offset = src->log_file_offset; } -void mail_index_view_close(struct mail_index_view *view) +static void _view_close(struct mail_index_view *view) { mail_index_view_unlock(view); mail_transaction_log_view_close(view->log_view); @@ -117,11 +116,6 @@ void mail_index_view_unlock(struct mail_index_view *view) } } -uint32_t mail_index_view_get_message_count(struct mail_index_view *view) -{ - return view->messages_count; -} - int mail_index_view_is_inconsistent(struct mail_index_view *view) { if (view->index->indexid != view->indexid) @@ -146,8 +140,13 @@ void mail_index_view_transaction_unref(struct mail_index_view *view) view->transactions--; } -int mail_index_get_header(struct mail_index_view *view, - const struct mail_index_header **hdr_r) +static uint32_t _view_get_message_count(struct mail_index_view *view) +{ + return view->messages_count; +} + +static int _view_get_header(struct mail_index_view *view, + const struct mail_index_header **hdr_r) { if (mail_index_view_lock(view) < 0) return -1; @@ -155,7 +154,10 @@ int mail_index_get_header(struct mail_index_view *view, if (view->map->hdr->messages_count == view->messages_count) *hdr_r = view->map->hdr; else { - /* messages_count differs, use a modified copy */ + /* messages_count differs, use a modified copy. + FIXME: so might seen_messages_count, etc. and they're + more difficult to fix. maybe grab a copy of the header + when opening the view initially?.. */ view->tmp_hdr_copy = *view->map->hdr; view->tmp_hdr_copy.messages_count = view->messages_count; *hdr_r = &view->tmp_hdr_copy; @@ -163,16 +165,15 @@ int mail_index_get_header(struct mail_index_view *view, return 0; } -int mail_index_lookup_full(struct mail_index_view *view, uint32_t seq, - struct mail_index_map **map_r, - const struct mail_index_record **rec_r) +static int _view_lookup_full(struct mail_index_view *view, uint32_t seq, + struct mail_index_map **map_r, + const struct mail_index_record **rec_r) { struct mail_index_map *map; const struct mail_index_record *rec, *n_rec; uint32_t uid; - i_assert(seq > 0); - i_assert(seq <= view->messages_count); + i_assert(seq > 0 && seq <= mail_index_view_get_message_count(view)); if (mail_index_view_lock(view) < 0) return -1; @@ -216,19 +217,10 @@ int mail_index_lookup_full(struct mail_index_view *view, uint32_t seq, } } -int mail_index_lookup(struct mail_index_view *view, uint32_t seq, - const struct mail_index_record **rec_r) -{ - struct mail_index_map *map; - - return mail_index_lookup_full(view, seq, &map, rec_r); -} - -int mail_index_lookup_uid(struct mail_index_view *view, uint32_t seq, - uint32_t *uid_r) +static int _view_lookup_uid(struct mail_index_view *view, uint32_t seq, + uint32_t *uid_r) { - i_assert(seq > 0); - i_assert(seq <= view->messages_count); + i_assert(seq > 0 && seq <= mail_index_view_get_message_count(view)); if (mail_index_view_lock(view) < 0) return -1; @@ -237,29 +229,6 @@ int mail_index_lookup_uid(struct mail_index_view *view, uint32_t seq, return 0; } -int mail_index_lookup_extra(struct mail_index_view *view, uint32_t seq, - uint32_t data_id, const void **data_r) -{ - const struct mail_index_record *rec; - struct mail_index_map *map; - uint32_t offset; - int ret; - - if ((ret = mail_index_lookup_full(view, seq, &map, &rec)) < 0) - return -1; - - if (rec == NULL) { - *data_r = NULL; - return ret; - } - - /* FIXME: do data_id mapping conversion */ - - offset = view->index->extra_records[data_id].offset; - *data_r = CONST_PTR_OFFSET(rec, offset); - return ret; -} - static uint32_t mail_index_bsearch_uid(struct mail_index_view *view, uint32_t uid, uint32_t *left_idx_p, int nearest_side) @@ -267,6 +236,8 @@ static uint32_t mail_index_bsearch_uid(struct mail_index_view *view, const struct mail_index_record *rec_base, *rec; uint32_t idx, left_idx, right_idx, record_size; + i_assert(view->messages_count <= view->map->records_count); + rec_base = view->map->records; record_size = view->index->record_size; @@ -306,9 +277,9 @@ static uint32_t mail_index_bsearch_uid(struct mail_index_view *view, return idx+1; } -int mail_index_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) +static int _view_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) { uint32_t left_idx; @@ -347,8 +318,9 @@ int mail_index_lookup_uid_range(struct mail_index_view *view, return 0; } -int mail_index_lookup_first(struct mail_index_view *view, enum mail_flags flags, - uint8_t flags_mask, uint32_t *seq_r) +static int _view_lookup_first(struct mail_index_view *view, + enum mail_flags flags, uint8_t flags_mask, + uint32_t *seq_r) { #define LOW_UPDATE(x) \ STMT_START { if ((x) > low_uid) low_uid = x; } STMT_END @@ -378,7 +350,7 @@ int mail_index_lookup_first(struct mail_index_view *view, enum mail_flags flags, return 0; } - for (; seq <= view->messages_count; seq++, rec++) { + for (; seq <= view->messages_count; seq++) { rec = MAIL_INDEX_MAP_IDX(view->index, view->map, seq-1); if ((rec->flags & flags_mask) == (uint8_t)flags) { *seq_r = seq; @@ -388,3 +360,106 @@ int mail_index_lookup_first(struct mail_index_view *view, enum mail_flags flags, return 0; } + +void mail_index_view_close(struct mail_index_view *view) +{ + view->methods.close(view); +} + +uint32_t mail_index_view_get_message_count(struct mail_index_view *view) +{ + return view->messages_count; +} + +int mail_index_get_header(struct mail_index_view *view, + const struct mail_index_header **hdr_r) +{ + return view->methods.get_header(view, hdr_r); +} + +int mail_index_lookup(struct mail_index_view *view, uint32_t seq, + const struct mail_index_record **rec_r) +{ + struct mail_index_map *map; + + return mail_index_lookup_full(view, seq, &map, rec_r); +} + +int mail_index_lookup_uid(struct mail_index_view *view, uint32_t seq, + uint32_t *uid_r) +{ + return view->methods.lookup_uid(view, seq, uid_r); +} + +int mail_index_lookup_extra(struct mail_index_view *view, uint32_t seq, + uint32_t data_id, const void **data_r) +{ + const struct mail_index_record *rec; + struct mail_index_map *map; + uint32_t offset; + int ret; + + if ((ret = mail_index_lookup_full(view, seq, &map, &rec)) < 0) + return -1; + + if (rec == NULL) { + *data_r = NULL; + return ret; + } + + /* FIXME: do data_id mapping conversion */ + + offset = view->index->extra_records[data_id].offset; + *data_r = CONST_PTR_OFFSET(rec, offset); + return ret; +} + +int mail_index_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) +{ + return view->methods.lookup_uid_range(view, first_uid, last_uid, + first_seq_r, last_seq_r); +} + +int mail_index_lookup_first(struct mail_index_view *view, enum mail_flags flags, + uint8_t flags_mask, uint32_t *seq_r) +{ + return view->methods.lookup_first(view, flags, flags_mask, seq_r); +} + +int mail_index_lookup_full(struct mail_index_view *view, uint32_t seq, + struct mail_index_map **map_r, + const struct mail_index_record **rec_r) +{ + return view->methods.lookup_full(view, seq, map_r, rec_r); +} + +static struct mail_index_view_methods view_methods = { + _view_close, + _view_get_message_count, + _view_get_header, + _view_lookup_full, + _view_lookup_uid, + _view_lookup_uid_range, + _view_lookup_first +}; + +struct mail_index_view *mail_index_view_open(struct mail_index *index) +{ + struct mail_index_view *view; + + view = i_new(struct mail_index_view, 1); + view->methods = view_methods; + view->index = index; + view->log_view = mail_transaction_log_view_open(index->log); + + view->indexid = index->indexid; + view->map = index->map; + view->map->refcount++; + view->messages_count = view->map->records_count; + + view->log_file_seq = view->map->log_file_seq; + view->log_file_offset = view->map->log_file_offset; + return view; +} diff --git a/src/lib-index/mail-index.h b/src/lib-index/mail-index.h index e6aad4b0a1..365de0fc63 100644 --- a/src/lib-index/mail-index.h +++ b/src/lib-index/mail-index.h @@ -178,6 +178,12 @@ int mail_index_transaction_commit(struct mail_index_transaction *t, uoff_t *log_file_offset_r); void mail_index_transaction_rollback(struct mail_index_transaction *t); +/* Returns a view to transaction. Currently this differs from normal view only + in that it contains newly appended messages in transaction. The view is + destroyed when the transaction is destroyed. */ +struct mail_index_view * +mail_index_transaction_get_updated_view(struct mail_index_transaction *t); + /* Begin synchronizing mailbox with index file. This call locks the index exclusively against other modifications. Returns 1 if ok, -1 if error. @@ -278,11 +284,6 @@ void mail_index_update_header(struct mail_index_transaction *t, void mail_index_update_extra_rec(struct mail_index_transaction *t, uint32_t seq, uint32_t data_id, const void *data); -/* Like mail_index_lookup(), but if seq > view's message count, it's referring - to message appended with given transaction. */ -int mail_index_transaction_lookup(struct mail_index_transaction *t, - uint32_t seq, - const struct mail_index_record **rec_r); /* Returns the last error code. */ enum mail_index_error mail_index_get_last_error(struct mail_index *index); diff --git a/src/lib-storage/index/index-fetch.c b/src/lib-storage/index/index-fetch.c index 1adff6d193..a4d4ebe428 100644 --- a/src/lib-storage/index/index-fetch.c +++ b/src/lib-storage/index/index-fetch.c @@ -12,7 +12,7 @@ index_storage_fetch(struct mailbox_transaction_context *_t, uint32_t seq, (struct index_transaction_context *)_t; const struct mail_index_record *rec; - if (mail_index_lookup(t->ibox->view, seq, &rec) < 0) { + if (mail_index_lookup(t->trans_view, seq, &rec) < 0) { mail_storage_set_index_error(t->ibox); return NULL; } diff --git a/src/lib-storage/index/index-mail-headers.c b/src/lib-storage/index/index-mail-headers.c index b4428f3ba0..76a4dd17ca 100644 --- a/src/lib-storage/index/index-mail-headers.c +++ b/src/lib-storage/index/index-mail-headers.c @@ -186,7 +186,7 @@ static int mail_find_wanted_headers(struct index_mail *mail, { int idx; - idx = find_wanted_headers(mail->ibox->cache_view, wanted_headers); + idx = find_wanted_headers(mail->trans->cache_view, wanted_headers); if (idx < 0) return -1; @@ -434,7 +434,7 @@ static int parse_cached_headers(struct index_mail *mail, int idx) data->header_stream = istream; } else { str = mail_cache_lookup_string_field( - mail->ibox->cache_view, data->seq, + mail->trans->cache_view, data->seq, mail_cache_header_fields[idx]); if (str == NULL) { /* broken - we expected the header to exist */ @@ -447,7 +447,7 @@ static int parse_cached_headers(struct index_mail *mail, int idx) str, strlen(str)); } - idx_headers = mail_cache_get_header_fields(mail->ibox->cache_view, + idx_headers = mail_cache_get_header_fields(mail->trans->cache_view, idx); if (idx_headers == NULL) { mail_cache_set_corrupted(mail->ibox->cache, @@ -511,7 +511,7 @@ int index_mail_parse_headers(struct index_mail *mail) idx = data->header_data_cached; max = idx-1; for (; idx < MAIL_CACHE_HEADERS_COUNT; idx++) { str = mail_cache_lookup_string_field( - mail->ibox->cache_view, mail->data.seq, + mail->trans->cache_view, mail->data.seq, mail_cache_header_fields[idx]); if (str == NULL) continue; @@ -526,7 +526,7 @@ int index_mail_parse_headers(struct index_mail *mail) /* make sure we cache everything */ for (idx = MAIL_CACHE_HEADERS_COUNT-1; idx >= 0; idx--) { headers = mail_cache_get_header_fields( - mail->ibox->cache_view, idx); + mail->trans->cache_view, idx); if (headers != NULL) break; } @@ -655,7 +655,7 @@ struct istream *index_mail_get_headers(struct mail *_mail, } for (i = data->header_data_cached; i <= idx; i++) { str = mail_cache_lookup_string_field( - mail->ibox->cache_view, data->seq, + mail->trans->cache_view, data->seq, mail_cache_header_fields[i]); if (str == NULL) continue; @@ -687,7 +687,7 @@ struct istream *index_mail_get_headers(struct mail *_mail, void index_mail_headers_init(struct index_mail *mail) { - struct mail_cache_view *cache_view = mail->ibox->cache_view; + struct mail_cache_view *cache_view = mail->trans->cache_view; int idx = -2, idx2 = -2; if (mail->wanted_headers != NULL && *mail->wanted_headers != NULL) @@ -769,7 +769,7 @@ void index_mail_headers_close(struct index_mail *mail) accessing headers from same message. index_mails should probably be shared.. */ headers = cached_header_get_names(mail); - idx = find_wanted_headers(mail->ibox->cache_view, headers); + idx = find_wanted_headers(mail->trans->cache_view, headers); if (idx >= 0) { /* all headers found */ if (idx != mail->data.header_save_idx) { @@ -779,7 +779,7 @@ void index_mail_headers_close(struct index_mail *mail) } } else { /* there's some new headers */ - idx = find_unused_header_idx(mail->ibox->cache_view); + idx = find_unused_header_idx(mail->trans->cache_view); if (idx < 0) return; diff --git a/src/lib-storage/index/index-mail.c b/src/lib-storage/index/index-mail.c index ff7f6d1449..5b6eb48cca 100644 --- a/src/lib-storage/index/index-mail.c +++ b/src/lib-storage/index/index-mail.c @@ -23,12 +23,12 @@ static struct message_part *get_cached_parts(struct index_mail *mail) size_t part_size; if ((mail->data.cached_fields & MAIL_CACHE_MESSAGEPART) == 0) { - mail_cache_mark_missing(mail->ibox->cache_view, + mail_cache_mark_missing(mail->trans->cache_view, MAIL_CACHE_MESSAGEPART); return NULL; } - if (!mail_cache_lookup_field(mail->ibox->cache_view, mail->data.seq, + if (!mail_cache_lookup_field(mail->trans->cache_view, mail->data.seq, MAIL_CACHE_MESSAGEPART, &part_data, &part_size)) { /* unexpected - must be an error */ @@ -61,11 +61,11 @@ char *index_mail_get_cached_string(struct index_mail *mail, const char *ret; if ((mail->data.cached_fields & field) == 0) { - mail_cache_mark_missing(mail->ibox->cache_view, field); + mail_cache_mark_missing(mail->trans->cache_view, field); return NULL; } - ret = mail_cache_lookup_string_field(mail->ibox->cache_view, + ret = mail_cache_lookup_string_field(mail->trans->cache_view, mail->data.seq, field); return p_strdup(mail->pool, ret); } @@ -75,9 +75,10 @@ uoff_t index_mail_get_cached_uoff_t(struct index_mail *mail, { uoff_t uoff; - if (!mail_cache_copy_fixed_field(mail->ibox->cache_view, mail->data.seq, - field, &uoff, sizeof(uoff))) { - mail_cache_mark_missing(mail->ibox->cache_view, field); + if (!mail_cache_copy_fixed_field(mail->trans->cache_view, + mail->data.seq, field, + &uoff, sizeof(uoff))) { + mail_cache_mark_missing(mail->trans->cache_view, field); uoff = (uoff_t)-1; } @@ -93,10 +94,11 @@ time_t index_mail_get_cached_received_date(struct index_mail *mail) { time_t t; - if (!mail_cache_copy_fixed_field(mail->ibox->cache_view, mail->data.seq, + if (!mail_cache_copy_fixed_field(mail->trans->cache_view, + mail->data.seq, MAIL_CACHE_RECEIVED_DATE, &t, sizeof(t))) { - mail_cache_mark_missing(mail->ibox->cache_view, + mail_cache_mark_missing(mail->trans->cache_view, MAIL_CACHE_RECEIVED_DATE); t = (time_t)-1; } @@ -107,10 +109,11 @@ time_t index_mail_get_cached_received_date(struct index_mail *mail) static void get_cached_sent_date(struct index_mail *mail, struct mail_sent_date *sent_date) { - if (!mail_cache_copy_fixed_field(mail->ibox->cache_view, mail->data.seq, + if (!mail_cache_copy_fixed_field(mail->trans->cache_view, + mail->data.seq, MAIL_CACHE_SENT_DATE, sent_date, sizeof(*sent_date))) { - mail_cache_mark_missing(mail->ibox->cache_view, + mail_cache_mark_missing(mail->trans->cache_view, MAIL_CACHE_SENT_DATE); sent_date->time = (time_t)-1; @@ -123,13 +126,13 @@ int index_mail_cache_transaction_begin(struct index_mail *mail) if (mail->trans->cache_trans != NULL) return TRUE; - if (mail_cache_transaction_begin(mail->ibox->cache_view, TRUE, + if (mail_cache_transaction_begin(mail->trans->cache_view, TRUE, mail->trans->trans, &mail->trans->cache_trans) <= 0) return FALSE; - mail->data.cached_fields = mail_cache_get_fields(mail->ibox->cache_view, - mail->data.seq); + mail->data.cached_fields = + mail_cache_get_fields(mail->trans->cache_view, mail->data.seq); return TRUE; } @@ -351,14 +354,14 @@ static void index_mail_parse_body(struct index_mail *mail) return; /* update cache_flags */ - cache_flags = mail_cache_get_record_flags(mail->ibox->cache_view, + cache_flags = mail_cache_get_record_flags(mail->trans->cache_view, mail->data.seq); if (mail->mail.has_nuls) cache_flags |= MAIL_INDEX_FLAG_HAS_NULS; else cache_flags |= MAIL_INDEX_FLAG_HAS_NO_NULS; - if (!mail_cache_update_record_flags(mail->ibox->cache_view, + if (!mail_cache_update_record_flags(mail->trans->cache_view, mail->data.seq, cache_flags)) return; @@ -542,9 +545,9 @@ int index_mail_next(struct index_mail *mail, p_clear(mail->pool); data->cached_fields = - mail_cache_get_fields(mail->ibox->cache_view, seq); + mail_cache_get_fields(mail->trans->cache_view, seq); cache_flags = (data->cached_fields & MAIL_CACHE_INDEX_FLAGS) == 0 ? 0 : - mail_cache_get_record_flags(mail->ibox->cache_view, seq); + mail_cache_get_record_flags(mail->trans->cache_view, seq); mail->mail.seq = seq; mail->mail.uid = rec->uid; diff --git a/src/lib-storage/index/index-search.c b/src/lib-storage/index/index-search.c index 8c938f12d5..046a5f1e6a 100644 --- a/src/lib-storage/index/index-search.c +++ b/src/lib-storage/index/index-search.c @@ -21,7 +21,7 @@ struct index_search_context { struct mail_search_context mail_ctx; - struct index_transaction_context *trans; + struct mail_index_view *view; struct index_mailbox *ibox; char *charset; struct mail_search_arg *args; @@ -601,7 +601,7 @@ static int search_parse_msgset_args(struct index_mailbox *ibox, return 0; } -static int search_limit_lowwater(struct index_mailbox *ibox, +static int search_limit_lowwater(struct index_search_context *ctx, uint32_t uid_lowwater, uint32_t *first_seq) { uint32_t seq1, seq2; @@ -609,9 +609,9 @@ static int search_limit_lowwater(struct index_mailbox *ibox, if (uid_lowwater == 0) return 0; - if (mail_index_lookup_uid_range(ibox->view, uid_lowwater, (uint32_t)-1, - &seq1, &seq2) < 0) { - mail_storage_set_index_error(ibox); + if (mail_index_lookup_uid_range(ctx->view, uid_lowwater, + (uint32_t)-1, &seq1, &seq2) < 0) { + mail_storage_set_index_error(ctx->ibox); return -1; } @@ -620,7 +620,7 @@ static int search_limit_lowwater(struct index_mailbox *ibox, return 0; } -static int search_limit_by_flags(struct index_mailbox *ibox, +static int search_limit_by_flags(struct index_search_context *ctx, const struct mail_index_header *hdr, struct mail_search_arg *args, uint32_t *seq1, uint32_t *seq2) @@ -640,7 +640,7 @@ static int search_limit_by_flags(struct index_mailbox *ibox, args->match_always = TRUE; } else if (args->not) { /* UNSEEN with lowwater limiting */ - if (search_limit_lowwater(ibox, + if (search_limit_lowwater(ctx, hdr->first_unseen_uid_lowwater, seq1) < 0) return -1; @@ -662,7 +662,7 @@ static int search_limit_by_flags(struct index_mailbox *ibox, args->match_always = TRUE; } else if (!args->not) { /* DELETED with lowwater limiting */ - if (search_limit_lowwater(ibox, + if (search_limit_lowwater(ctx, hdr->first_deleted_uid_lowwater, seq1) < 0) return -1; @@ -678,7 +678,7 @@ static int search_get_seqset(struct index_search_context *ctx, { const struct mail_index_header *hdr; - if (mail_index_get_header(ctx->ibox->view, &hdr) < 0) { + if (mail_index_get_header(ctx->view, &hdr) < 0) { mail_storage_set_index_error(ctx->ibox); return -1; } @@ -701,7 +701,7 @@ static int search_get_seqset(struct index_search_context *ctx, i_assert(ctx->seq1 <= ctx->seq2); /* UNSEEN and DELETED in root search level may limit the range */ - if (search_limit_by_flags(ctx->ibox, hdr, args, + if (search_limit_by_flags(ctx, hdr, args, &ctx->seq1, &ctx->seq2) < 0) return -1; return 0; @@ -733,8 +733,8 @@ index_storage_search_init(struct mailbox_transaction_context *_t, ctx = i_new(struct index_search_context, 1); ctx->mail_ctx.box = &t->ibox->box; - ctx->trans = t; ctx->ibox = t->ibox; + ctx->view = t->trans_view; ctx->charset = i_strdup(charset); ctx->args = args; @@ -815,7 +815,7 @@ struct mail *index_storage_search_next(struct mail_search_context *_ctx) ret = 0; while (ctx->seq1 <= ctx->seq2) { - if (mail_index_lookup(ctx->ibox->view, ctx->seq1, &rec) < 0) { + if (mail_index_lookup(ctx->view, ctx->seq1, &rec) < 0) { ctx->failed = TRUE; mail_storage_set_index_error(ctx->ibox); return NULL; diff --git a/src/lib-storage/index/index-storage.c b/src/lib-storage/index/index-storage.c index 812aa8bad6..e2dab12929 100644 --- a/src/lib-storage/index/index-storage.c +++ b/src/lib-storage/index/index-storage.c @@ -350,8 +350,6 @@ index_storage_mailbox_init(struct index_storage *storage, struct mailbox *box, } ibox->view = mail_index_view_open(index); - ibox->cache_view = - mail_cache_view_open(ibox->cache, ibox->view); return ibox; } while (0); @@ -364,8 +362,6 @@ void index_storage_mailbox_free(struct mailbox *box) { struct index_mailbox *ibox = (struct index_mailbox *) box; - if (ibox->cache_view != NULL) - mail_cache_view_close(ibox->cache_view); if (ibox->view != NULL) mail_index_view_close(ibox->view); diff --git a/src/lib-storage/index/index-storage.h b/src/lib-storage/index/index-storage.h index f4e803aff6..74b786c40b 100644 --- a/src/lib-storage/index/index-storage.h +++ b/src/lib-storage/index/index-storage.h @@ -58,7 +58,6 @@ struct index_mailbox { struct mail_index *index; struct mail_index_view *view; struct mail_cache *cache; - struct mail_cache_view *cache_view; struct mail *mail_interface; uint32_t (*get_recent_count)(struct index_mailbox *ibox); @@ -112,7 +111,10 @@ struct index_mailbox { struct index_transaction_context { struct mailbox_transaction_context mailbox_ctx; struct index_mailbox *ibox; + struct mail_index_transaction *trans; + struct mail_index_view *trans_view; + struct mail_cache_view *cache_view; struct mail_cache_transaction_ctx *cache_trans; struct index_mail fetch_mail; /* for index_storage_fetch() */ @@ -182,8 +184,8 @@ index_storage_search_init(struct mailbox_transaction_context *t, int index_storage_search_deinit(struct mail_search_context *ctx); struct mail *index_storage_search_next(struct mail_search_context *ctx); -struct mailbox_transaction_context * -index_transaction_begin(struct mailbox *box); +void index_transaction_init(struct index_transaction_context *t, + struct index_mailbox *ibox, int hide); int index_transaction_commit(struct mailbox_transaction_context *t); void index_transaction_rollback(struct mailbox_transaction_context *t); diff --git a/src/lib-storage/index/index-transaction.c b/src/lib-storage/index/index-transaction.c index e32d930757..b8364e73b0 100644 --- a/src/lib-storage/index/index-transaction.c +++ b/src/lib-storage/index/index-transaction.c @@ -3,8 +3,22 @@ #include "lib.h" #include "index-storage.h" +void index_transaction_init(struct index_transaction_context *t, + struct index_mailbox *ibox, int hide) +{ + t->mailbox_ctx.box = &ibox->box; + t->ibox = ibox; + t->trans = mail_index_transaction_begin(ibox->view, hide); + t->trans_view = mail_index_transaction_get_updated_view(t->trans); + t->cache_view = mail_cache_view_open(ibox->cache, t->trans_view); +} + static void index_transaction_free(struct index_transaction_context *t) { + if (t->cache_trans != NULL) + (void)mail_cache_transaction_end(t->cache_trans); + + mail_cache_view_close(t->cache_view); mail_index_view_unlock(t->ibox->view); if (t->fetch_mail.pool != NULL) @@ -20,11 +34,8 @@ int index_transaction_commit(struct mailbox_transaction_context *_t) uoff_t offset; int ret; - if (t->cache_trans != NULL) { + if (t->cache_trans != NULL) (void)mail_cache_transaction_commit(t->cache_trans); - (void)mail_cache_transaction_end(t->cache_trans); - t->cache_trans = NULL; - } ret = mail_index_transaction_commit(t->trans, &seq, &offset); if (ret < 0) diff --git a/src/lib-storage/index/maildir/maildir-transaction.c b/src/lib-storage/index/maildir/maildir-transaction.c index 6fbb584f2e..2d717e16ef 100644 --- a/src/lib-storage/index/maildir/maildir-transaction.c +++ b/src/lib-storage/index/maildir/maildir-transaction.c @@ -7,13 +7,11 @@ struct mailbox_transaction_context * maildir_transaction_begin(struct mailbox *box, int hide) { struct index_mailbox *ibox = (struct index_mailbox *)box; - struct maildir_transaction_context *ctx; + struct maildir_transaction_context *t; - ctx = i_new(struct maildir_transaction_context, 1); - ctx->ictx.mailbox_ctx.box = box; - ctx->ictx.ibox = ibox; - ctx->ictx.trans = mail_index_transaction_begin(ibox->view, hide); - return &ctx->ictx.mailbox_ctx; + t = i_new(struct maildir_transaction_context, 1); + index_transaction_init(&t->ictx, ibox, hide); + return &t->ictx.mailbox_ctx; } int maildir_transaction_commit(struct mailbox_transaction_context *_t) diff --git a/src/lib-storage/index/mbox/mbox-mail.c b/src/lib-storage/index/mbox/mbox-mail.c index 6e5f03c0ac..b215618013 100644 --- a/src/lib-storage/index/mbox/mbox-mail.c +++ b/src/lib-storage/index/mbox/mbox-mail.c @@ -31,7 +31,7 @@ static int mbox_mail_seek(struct index_mail *mail) if (mbox_file_open_stream(ibox) < 0) return -1; - ret = mail_index_lookup_extra(ibox->view, mail->mail.seq, + ret = mail_index_lookup_extra(mail->trans->trans_view, mail->mail.seq, ibox->mbox_extra_idx, &data); if (ret <= 0) { if (ret < 0) diff --git a/src/lib-storage/index/mbox/mbox-save.c b/src/lib-storage/index/mbox/mbox-save.c index a65bfe96bb..da20fa2327 100644 --- a/src/lib-storage/index/mbox/mbox-save.c +++ b/src/lib-storage/index/mbox/mbox-save.c @@ -179,7 +179,7 @@ static int mbox_save_init_sync(struct mbox_transaction_context *t) struct mbox_save_context *ctx = t->save_ctx; const struct mail_index_header *hdr; - if (mail_index_get_header(ctx->ibox->view, &hdr) < 0) { + if (mail_index_get_header(t->ictx.trans_view, &hdr) < 0) { mail_storage_set_index_error(ctx->ibox); return -1; } @@ -345,7 +345,7 @@ int mbox_save(struct mailbox_transaction_context *_t, if (mail_r != NULL) { const struct mail_index_record *rec; - if (mail_index_transaction_lookup(ctx->trans, seq, &rec) < 0) + if (mail_index_lookup(t->ictx.trans_view, seq, &rec) < 0) return -1; if (index_mail_next(&ctx->mail, rec, seq, FALSE) <= 0) return -1; diff --git a/src/lib-storage/index/mbox/mbox-transaction.c b/src/lib-storage/index/mbox/mbox-transaction.c index eaff99995a..8a13a664b1 100644 --- a/src/lib-storage/index/mbox/mbox-transaction.c +++ b/src/lib-storage/index/mbox/mbox-transaction.c @@ -12,9 +12,7 @@ mbox_transaction_begin(struct mailbox *box, int hide) struct mbox_transaction_context *t; t = i_new(struct mbox_transaction_context, 1); - t->ictx.mailbox_ctx.box = box; - t->ictx.ibox = ibox; - t->ictx.trans = mail_index_transaction_begin(ibox->view, hide); + index_transaction_init(&t->ictx, ibox, hide); return &t->ictx.mailbox_ctx; } @@ -24,10 +22,11 @@ int mbox_transaction_commit(struct mailbox_transaction_context *_t) (struct mbox_transaction_context *)_t; struct index_mailbox *ibox = t->ictx.ibox; unsigned int lock_id = t->mbox_lock_id; - int ret = 0; + int mbox_modified, ret = 0; if (t->save_ctx != NULL) ret = mbox_save_commit(t->save_ctx); + mbox_modified = t->mbox_modified; if (ret == 0) { if (index_transaction_commit(_t) < 0) @@ -35,9 +34,10 @@ int mbox_transaction_commit(struct mailbox_transaction_context *_t) } else { index_transaction_rollback(_t); } + t = NULL; if (ret == 0) { - if (mbox_sync(ibox, TRUE, t->mbox_modified, FALSE) < 0) + if (mbox_sync(ibox, TRUE, mbox_modified, FALSE) < 0) ret = -1; } -- 2.47.3