uncommitted messages.
--HG--
branch : HEAD
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 \
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;
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;
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;
#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;
unsigned int hdr_changed:1;
};
+struct mail_index_record *
+mail_index_transaction_lookup(struct mail_index_transaction *t, uint32_t seq);
+
#endif
--- /dev/null
+/* 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;
+}
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;
}
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);
}
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;
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)
{
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);
{
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;
{
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,
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 {
#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;
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,
#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);
}
}
-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)
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;
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;
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;
}
}
-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;
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)
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;
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;
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
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;
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;
+}
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.
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);
(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;
}
{
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;
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 */
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,
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;
/* 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;
}
}
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;
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)
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) {
}
} 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;
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 */
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);
}
{
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;
}
{
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;
}
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;
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;
}
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;
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;
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;
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;
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;
}
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)
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;
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;
{
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;
}
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;
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;
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;
}
ibox->view = mail_index_view_open(index);
- ibox->cache_view =
- mail_cache_view_open(ibox->cache, ibox->view);
return ibox;
} while (0);
{
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);
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);
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() */
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);
#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)
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)
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)
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)
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;
}
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;
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;
}
(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)
} 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;
}