[dovecot-cvs] dovecot/src/lib-index Makefile.am, 1.21,
1.22 mail-cache-compress.c, 1.23, 1.24 mail-cache-lookup.c,
1.24, 1.25 mail-cache-private.h, 1.16,
1.17 mail-cache-sync-update.c, NONE,
1.1 mail-cache-transaction.c, 1.30, 1.31 mail-cache.c, 1.50,
1.51 mail-index-private.h, 1.33,
1.34 mail-index-sync-private.h, 1.14,
1.15 mail-index-sync-update.c, 1.52,
1.53 mail-index-transaction-private.h, 1.15,
1.16 mail-index-transaction-view.c, 1.6,
1.7 mail-index-transaction.c, 1.32,
1.33 mail-index-view-private.h, 1.11,
1.12 mail-index-view-sync.c, 1.26, 1.27 mail-index-view.c,
1.26, 1.27 mail-index.c, 1.160, 1.161 mail-index.h, 1.133,
1.134 mail-transaction-log.c, 1.69,
1.70 mail-transaction-log.h, 1.20,
1.21 mail-transaction-util.c, 1.20, 1.21
cras at dovecot.org
cras at dovecot.org
Sat Nov 6 19:20:22 EET 2004
Update of /var/lib/cvs/dovecot/src/lib-index
In directory talvi:/tmp/cvs-serv6738/src/lib-index
Modified Files:
Makefile.am mail-cache-compress.c mail-cache-lookup.c
mail-cache-private.h mail-cache-transaction.c mail-cache.c
mail-index-private.h mail-index-sync-private.h
mail-index-sync-update.c mail-index-transaction-private.h
mail-index-transaction-view.c mail-index-transaction.c
mail-index-view-private.h mail-index-view-sync.c
mail-index-view.c mail-index.c mail-index.h
mail-transaction-log.c mail-transaction-log.h
mail-transaction-util.c
Added Files:
mail-cache-sync-update.c
Log Message:
Removed cache_offset from mail_index_record and changed it to use extension
instead. Added possibility to register sync and expunge handlers for
extensions. Changed the way extension resets work: all extension updates
which were committed without having seen the reset are ignored.
Index: Makefile.am
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/Makefile.am,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- Makefile.am 20 Oct 2004 23:05:55 -0000 1.21
+++ Makefile.am 6 Nov 2004 17:20:18 -0000 1.22
@@ -11,6 +11,7 @@
mail-cache-fields.c \
mail-cache-lookup.c \
mail-cache-transaction.c \
+ mail-cache-sync-update.c \
mail-index.c \
mail-index-fsck.c \
mail-index-lock.c \
Index: mail-cache-compress.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-cache-compress.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- mail-cache-compress.c 8 Oct 2004 17:51:48 -0000 1.23
+++ mail-cache-compress.c 6 Nov 2004 17:20:18 -0000 1.24
@@ -94,6 +94,17 @@
return 1;
}
+static uint32_t
+get_next_file_seq(struct mail_cache *cache, struct mail_index_view *view)
+{
+ const struct mail_index_ext *ext;
+ uint32_t file_seq;
+
+ ext = mail_index_view_get_ext(view, cache->ext_id);
+ file_seq = ext != NULL ? ext->reset_id + 1 : (uint32_t)ioloop_time;
+ return file_seq != 0 ? file_seq : 1;
+}
+
static int
mail_cache_copy(struct mail_cache *cache, struct mail_index_view *view, int fd)
{
@@ -131,7 +142,7 @@
memset(&hdr, 0, sizeof(hdr));
hdr.version = MAIL_CACHE_VERSION;
hdr.indexid = idx_hdr->indexid;
- hdr.file_seq = idx_hdr->cache_file_seq + 1;
+ hdr.file_seq = get_next_file_seq(cache, view);
o_stream_send(output, &hdr, sizeof(hdr));
memset(&ctx, 0, sizeof(ctx));
@@ -139,7 +150,7 @@
ctx.field_seen = buffer_create_dynamic(default_pool, 64);
ctx.field_seen_value = 0;
- mail_index_reset_cache(t, hdr.file_seq);
+ mail_index_ext_reset(t, cache->ext_id, hdr.file_seq);
for (seq = 1; seq <= message_count; seq++) {
ctx.new_msg = seq >= first_new_seq;
@@ -161,12 +172,11 @@
if (cache_rec.size == sizeof(cache_rec))
continue;
- mail_index_update_cache(t, seq, hdr.file_seq,
- output->offset, &old_offset);
+ mail_index_update_ext(t, seq, cache->ext_id, &output->offset,
+ &old_offset);
buffer_write(ctx.buffer, 0, &cache_rec, sizeof(cache_rec));
- o_stream_send(output, buffer_get_data(ctx.buffer, NULL),
- cache_rec.size);
+ o_stream_send(output, ctx.buffer->data, cache_rec.size);
}
if (cache->fields_count != 0) {
Index: mail-cache-lookup.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-cache-lookup.c,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -d -r1.24 -r1.25
--- mail-cache-lookup.c 8 Oct 2004 17:51:48 -0000 1.24
+++ mail-cache-lookup.c 6 Nov 2004 17:20:18 -0000 1.25
@@ -45,23 +45,37 @@
return cache_rec;
}
-static int mail_cache_lookup_offset(struct mail_cache_view *view, uint32_t seq,
- uint32_t *offset_r)
+static int
+mail_cache_lookup_offset(struct mail_cache *cache, struct mail_index_view *view,
+ uint32_t seq, uint32_t *offset_r)
{
- const struct mail_index_record *rec;
struct mail_index_map *map;
+ const struct mail_index_ext *ext;
+ const void *data;
+ uint32_t idx;
int i, ret;
- for (i = 0; i < 2; i++) {
- if (mail_index_lookup_full(view->view, seq, &map, &rec) < 0)
- return -1;
+ if (mail_index_lookup_ext_full(view, seq, cache->ext_id,
+ &map, &data) < 0)
+ return -1;
+ if (data == NULL)
+ return 0;
- if (map->hdr->cache_file_seq == view->cache->hdr->file_seq) {
- *offset_r = rec->cache_offset;
+ if (!mail_index_map_get_ext_idx(map, cache->ext_id, &idx)) {
+ /* no cache */
+ return 0;
+ }
+
+ ext = map->extensions->data;
+ ext += idx;
+
+ for (i = 0; i < 2; i++) {
+ if (cache->hdr->file_seq == ext->reset_id) {
+ *offset_r = *((const uint32_t *)data);
return 1;
}
- if ((ret = mail_cache_reopen(view->cache)) <= 0)
+ if ((ret = mail_cache_reopen(cache)) <= 0)
return ret;
}
@@ -170,7 +184,8 @@
if (view->cached_offset_seq == seq)
offset = view->cached_offset;
else {
- if ((ret = mail_cache_lookup_offset(view, seq, &offset)) <= 0)
+ if ((ret = mail_cache_lookup_offset(view->cache, view->view,
+ seq, &offset)) <= 0)
return ret;
view->cached_offset_seq = seq;
@@ -191,7 +206,8 @@
}
if (ret > 0 && view->trans_seq1 <= seq && view->trans_seq2 >= seq &&
- mail_cache_transaction_lookup(view->transaction, seq, &offset)) {
+ mail_cache_lookup_offset(view->cache, view->trans_view,
+ seq, &offset)) {
buffer_set_used_size(view->offsets_buf, 0);
while (offset != 0 && ret > 0) {
if (buffer_find_offset(view->offsets_buf, offset)) {
Index: mail-cache-private.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-cache-private.h,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- mail-cache-private.h 16 Sep 2004 14:33:16 -0000 1.16
+++ mail-cache-private.h 6 Nov 2004 17:20:18 -0000 1.17
@@ -115,6 +115,7 @@
struct mail_cache {
struct mail_index *index;
+ uint32_t ext_id;
char *filepath;
int fd;
@@ -142,7 +143,7 @@
struct mail_cache_view {
struct mail_cache *cache;
- struct mail_index_view *view;
+ struct mail_index_view *view, *trans_view;
struct mail_cache_transaction_ctx *transaction;
uint32_t trans_seq1, trans_seq2;
@@ -183,9 +184,6 @@
int mail_cache_transaction_commit(struct mail_cache_transaction_ctx *ctx);
void mail_cache_transaction_rollback(struct mail_cache_transaction_ctx *ctx);
-int mail_cache_transaction_lookup(struct mail_cache_transaction_ctx *ctx,
- uint32_t seq, uint32_t *offset_r);
-
int mail_cache_map(struct mail_cache *cache, size_t offset, size_t size);
void mail_cache_file_close(struct mail_cache *cache);
int mail_cache_reopen(struct mail_cache *cache);
@@ -201,6 +199,12 @@
void mail_cache_decision_add(struct mail_cache_view *view, uint32_t seq,
uint32_t field);
+int mail_cache_expunge_handler(struct mail_index_sync_map_ctx *sync_ctx,
+ uint32_t seq, const void *data, void **context);
+int mail_cache_sync_handler(struct mail_index_sync_map_ctx *sync_ctx,
+ uint32_t seq, void *old_data, const void *new_data,
+ void **context);
+
void mail_cache_set_syscall_error(struct mail_cache *cache,
const char *function);
--- NEW FILE: mail-cache-sync-update.c ---
/* Copyright (C) 2004 Timo Sirainen */
#include "lib.h"
#include "mail-cache-private.h"
#include "mail-index-view-private.h"
#include "mail-index-sync-private.h"
struct mail_cache_sync_context {
unsigned int locked:1;
unsigned int lock_failed:1;
};
static void mail_cache_handler_deinit(struct mail_index_sync_map_ctx *sync_ctx,
struct mail_cache_sync_context *ctx)
{
if (ctx == NULL)
return;
if (ctx->locked)
mail_cache_unlock(sync_ctx->view->index->cache);
i_free(ctx);
}
static int mail_cache_handler_init(struct mail_cache_sync_context **ctx_r,
struct mail_cache *cache)
{
struct mail_cache_sync_context *ctx = *ctx_r;
int ret;
if (ctx == NULL)
ctx = *ctx_r = i_new(struct mail_cache_sync_context, 1);
if (ctx->locked || ctx->lock_failed)
return 1;
if (!ctx->locked) {
if ((ret = mail_cache_lock(cache)) <= 0) {
ctx->lock_failed = TRUE;
return ret;
}
ctx->locked = TRUE;
}
return 1;
}
static int get_cache_file_seq(struct mail_index_view *view,
uint32_t *cache_file_seq_r)
{
const struct mail_index_ext *ext;
ext = mail_index_view_get_ext(view, view->index->cache->ext_id);
if (ext == NULL)
return 0;
*cache_file_seq_r = ext->reset_id;
return 1;
}
int mail_cache_expunge_handler(struct mail_index_sync_map_ctx *sync_ctx,
uint32_t seq __attr_unused__,
const void *data, void **context)
{
struct mail_index_view *view = sync_ctx->view;
struct mail_cache_sync_context *ctx = *context;
struct mail_cache *cache = view->index->cache;
const uint32_t *cache_offset = data;
uint32_t cache_file_seq;
int ret;
if (data == NULL) {
mail_cache_handler_deinit(sync_ctx, ctx);
*context = NULL;
return 1;
}
if (*cache_offset == 0)
return 1;
ret = mail_cache_handler_init(&ctx, cache);
*context = ctx;
if (ret <= 0)
return ret < 0 ? -1 : 1;
if (!get_cache_file_seq(view, &cache_file_seq))
return 1;
if (!MAIL_CACHE_IS_UNUSABLE(cache) &&
cache_file_seq != cache->hdr->file_seq)
(void)mail_cache_delete(cache, *cache_offset);
return 1;
}
int mail_cache_sync_handler(struct mail_index_sync_map_ctx *sync_ctx,
uint32_t seq __attr_unused__,
void *old_data, const void *new_data,
void **context)
{
struct mail_index_view *view = sync_ctx->view;
struct mail_cache_sync_context *ctx = *context;
const uint32_t *old_cache_offset = old_data;
const uint32_t *new_cache_offset = new_data;
uint32_t cache_file_seq;
int ret;
if (new_cache_offset == NULL) {
mail_cache_handler_deinit(sync_ctx, ctx);
*context = NULL;
return 1;
}
if (*old_cache_offset == 0)
return 1;
/* we'll need to link the old and new cache records */
ret = mail_cache_handler_init(&ctx, view->index->cache);
*context = ctx;
if (ret <= 0)
return ret < 0 ? -1 : 1;
if (!get_cache_file_seq(view, &cache_file_seq))
return 1;
if (cache_file_seq != view->index->cache->hdr->file_seq) {
/* cache has been compressed, don't modify it */
return 1;
}
if (mail_cache_link(view->index->cache,
*old_cache_offset, *new_cache_offset) < 0)
return -1;
return 1;
}
Index: mail-cache-transaction.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-cache-transaction.c,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -d -r1.30 -r1.31
--- mail-cache-transaction.c 14 Oct 2004 23:06:49 -0000 1.30
+++ mail-cache-transaction.c 6 Nov 2004 17:20:18 -0000 1.31
@@ -52,6 +52,7 @@
i_assert(view->transaction == NULL);
view->transaction = ctx;
+ view->trans_view = mail_index_transaction_open_updated_view(t);
t->cache_trans_ctx = ctx;
return ctx;
@@ -436,9 +437,9 @@
is updated to point to old cache record when index is being
synced. */
for (; seq_idx < seq_limit; seq_idx++) {
- mail_index_update_cache(ctx->trans, seq[seq_idx],
- cache->hdr->file_seq,
- write_offset, &old_offset);
+ mail_index_update_ext(ctx->trans, seq[seq_idx],
+ cache->ext_id, &write_offset,
+ &old_offset);
if (old_offset != 0) {
/* we added records for this message multiple
times in this same uncommitted transaction.
@@ -689,12 +690,6 @@
buffer_append(ctx->cache_data, null4, 4 - (data_size & 3));
}
-int mail_cache_transaction_lookup(struct mail_cache_transaction_ctx *ctx,
- uint32_t seq, uint32_t *offset_r)
-{
- return mail_index_update_cache_lookup(ctx->trans, seq, offset_r);
-}
-
static int mail_cache_link_unlocked(struct mail_cache *cache,
uint32_t old_offset, uint32_t new_offset)
{
Index: mail-cache.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-cache.c,v
retrieving revision 1.50
retrieving revision 1.51
diff -u -d -r1.50 -r1.51
--- mail-cache.c 25 Oct 2004 21:23:33 -0000 1.50
+++ mail-cache.c 6 Nov 2004 17:20:18 -0000 1.51
@@ -59,6 +59,9 @@
int mail_cache_reopen(struct mail_cache *cache)
{
+ struct mail_index_view *view;
+ const struct mail_index_ext *ext;
+
if (MAIL_CACHE_IS_UNUSABLE(cache) && cache->need_compress) {
/* unusable, we're just waiting for compression */
return 0;
@@ -81,15 +84,19 @@
if (mail_cache_header_fields_read(cache) < 0)
return -1;
- if (cache->hdr->file_seq != cache->index->hdr->cache_file_seq) {
+ view = mail_index_view_open(cache->index);
+ ext = mail_index_view_get_ext(view, cache->ext_id);
+ if (ext == NULL || cache->hdr->file_seq != ext->reset_id) {
/* still different - maybe a race condition or maybe the
file_seq really is corrupted. either way, this shouldn't
happen often so we'll just mark cache to be compressed
later which fixes this. */
cache->need_compress = TRUE;
+ mail_index_view_close(view);
return 0;
}
+ mail_index_view_close(view);
return 1;
}
@@ -218,6 +225,13 @@
}
}
+ cache->ext_id =
+ mail_index_ext_register(index, "cache", 0,
+ sizeof(uint32_t), sizeof(uint32_t));
+ mail_index_register_expunge_handler(index, cache->ext_id,
+ mail_cache_expunge_handler);
+ mail_index_register_sync_handler(index, cache->ext_id,
+ mail_cache_sync_handler);
return cache;
}
@@ -236,7 +250,8 @@
int mail_cache_lock(struct mail_cache *cache)
{
- unsigned int lock_id;
+ struct mail_index_view *view;
+ const struct mail_index_ext *ext;
int i, ret;
i_assert(!cache->locked);
@@ -244,13 +259,20 @@
if (MAIL_CACHE_IS_UNUSABLE(cache))
return 0;
- if (mail_index_lock_shared(cache->index, TRUE, &lock_id) < 0)
+ if (mail_index_view_open_locked(cache->index, &view) < 0)
return -1;
- if (cache->hdr->file_seq != cache->index->hdr->cache_file_seq) {
+ ext = mail_index_view_get_ext(view, cache->ext_id);
+ if (ext == NULL) {
+ /* cache not used */
+ mail_index_view_close(view);
+ return 0;
+ }
+
+ if (cache->hdr->file_seq != ext->reset_id) {
/* we want the latest cache file */
if ((ret = mail_cache_reopen(cache)) <= 0) {
- mail_index_unlock(cache->index, lock_id);
+ mail_index_view_close(view);
return ret;
}
}
@@ -265,7 +287,7 @@
}
cache->locked = TRUE;
- if (cache->hdr->file_seq == cache->index->hdr->cache_file_seq) {
+ if (cache->hdr->file_seq == ext->reset_id) {
/* got it */
break;
}
@@ -280,7 +302,7 @@
if (ret > 0)
cache->hdr_copy = *cache->hdr;
- mail_index_unlock(cache->index, lock_id);
+ mail_index_view_close(view);
return ret;
}
@@ -349,6 +371,9 @@
if (view->cache->field_header_write_pending)
(void)mail_cache_header_fields_update(view->cache);
+ if (view->trans_view != NULL)
+ mail_index_view_close(view->trans_view);
+
buffer_free(view->offsets_buf);
buffer_free(view->cached_exists_buf);
i_free(view);
Index: mail-index-private.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-private.h,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -d -r1.33 -r1.34
--- mail-index-private.h 25 Oct 2004 17:42:51 -0000 1.33
+++ mail-index-private.h 6 Nov 2004 17:20:18 -0000 1.34
@@ -9,6 +9,7 @@
#include "mail-index.h"
struct mail_transaction_header;
+struct mail_index_sync_map_ctx;
/* How many seconds to wait a lock for index file. */
#define MAIL_INDEX_LOCK_SECS 120
@@ -27,11 +28,19 @@
((struct mail_index_record *) \
PTR_OFFSET((map)->records, (idx) * (map)->hdr->record_size))
+typedef int mail_index_expunge_handler_t(struct mail_index_sync_map_ctx *ctx,
+ uint32_t seq, const void *data,
+ void **context);
+typedef int mail_index_sync_handler_t(struct mail_index_sync_map_ctx *ctx,
+ uint32_t seq, void *old_data,
+ const void *new_data, void **context);
+
#define MAIL_INDEX_HEADER_SIZE_ALIGN(size) \
(((size) + 7) & ~7)
struct mail_index_ext {
const char *name;
+ uint32_t reset_id;
uint32_t hdr_offset;
uint32_t hdr_size;
uint16_t record_offset;
@@ -41,6 +50,7 @@
struct mail_index_ext_header {
uint32_t hdr_size;
+ uint32_t reset_id;
uint16_t record_offset;
uint16_t record_size;
uint16_t record_align;
@@ -87,6 +97,9 @@
pool_t extension_pool;
buffer_t *extensions; /* struct mail_index_ext[] */
+ buffer_t *expunge_handlers; /* mail_index_expunge_handler_t*[] */
+ buffer_t *sync_handlers; /* mail_index_sync_handler_t*[] */
+
char *filepath;
int fd;
@@ -114,6 +127,13 @@
unsigned int fsck:1;
};
+/* Add/replace sync handler for specified extra record. */
+void mail_index_register_expunge_handler(struct mail_index *index,
+ uint32_t ext_id,
+ mail_index_expunge_handler_t *cb);
+void mail_index_register_sync_handler(struct mail_index *index, uint32_t ext_id,
+ mail_index_sync_handler_t *cb);
+
int mail_index_write_base_header(struct mail_index *index,
const struct mail_index_header *hdr);
@@ -151,21 +171,11 @@
struct mail_index_map *map, const char *name,
uint32_t hdr_offset, uint32_t hdr_size,
uint32_t record_offset, uint32_t record_size,
- uint32_t record_align);
+ uint32_t record_align, uint32_t reset_id);
int mail_index_map_get_ext_idx(struct mail_index_map *map,
uint32_t ext_id, uint32_t *idx_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);
-
-void mail_index_reset_cache(struct mail_index_transaction *t,
- uint32_t new_file_seq);
-void mail_index_update_cache(struct mail_index_transaction *t, uint32_t seq,
- uint32_t file_seq, uint32_t offset,
- uint32_t *old_offset_r);
-int mail_index_update_cache_lookup(struct mail_index_transaction *t,
- uint32_t seq, uint32_t *offset_r);
+const struct mail_index_ext *
+mail_index_view_get_ext(struct mail_index_view *view, uint32_t ext_id);
int mail_index_fix_header(struct mail_index *index, struct mail_index_map *map,
struct mail_index_header *hdr, const char **error_r);
Index: mail-index-sync-private.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-sync-private.h,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- mail-index-sync-private.h 25 Oct 2004 17:42:51 -0000 1.14
+++ mail-index-sync-private.h 6 Nov 2004 17:20:18 -0000 1.15
@@ -25,16 +25,31 @@
unsigned int sync_dirty:1;
};
+struct mail_index_expunge_handler {
+ mail_index_expunge_handler_t *handler;
+ void **context;
+ uint32_t record_offset;
+};
+
struct mail_index_sync_map_ctx {
struct mail_index_view *view;
- uint32_t last_ext_id;
+ uint32_t cur_ext_id;
- unsigned int update_cache:1;
- unsigned int cache_locked:1;
+ buffer_t *expunge_handlers; /* struct mail_index_expunge_handler[] */
+
+ buffer_t *extra_context_buf;
+ void **extra_context;
+
+ unsigned int sync_handlers_initialized:1;
+ unsigned int expunge_handlers_set:1;
+ unsigned int expunge_handlers_used:1;
+ unsigned int cur_ext_ignore:1;
};
extern struct mail_transaction_map_functions mail_index_map_sync_funcs;
+void mail_index_sync_map_init(struct mail_index_sync_map_ctx *sync_map_ctx,
+ struct mail_index_view *view);
int mail_index_sync_update_index(struct mail_index_sync_ctx *sync_ctx,
int sync_only_external);
Index: mail-index-sync-update.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-sync-update.c,v
retrieving revision 1.52
retrieving revision 1.53
diff -u -d -r1.52 -r1.53
--- mail-index-sync-update.c 25 Oct 2004 17:42:51 -0000 1.52
+++ mail-index-sync-update.c 6 Nov 2004 17:20:18 -0000 1.53
@@ -9,7 +9,6 @@
#include "mail-index-sync-private.h"
#include "mail-transaction-log.h"
#include "mail-transaction-util.h"
-#include "mail-cache-private.h"
#include <stdlib.h>
@@ -26,6 +25,117 @@
}
static void
+mail_index_sync_init_expunge_handlers(struct mail_index_sync_map_ctx *ctx)
+{
+ const mail_index_expunge_handler_t *const *handlers;
+ const struct mail_index_ext *extensions;
+ const uint32_t *id_map;
+ struct mail_index_expunge_handler eh;
+ size_t handlers_count, id_map_size, size;
+ uint32_t ext_id;
+
+ handlers = buffer_get_data(ctx->view->index->expunge_handlers,
+ &handlers_count);
+ handlers_count /= sizeof(*handlers);
+
+ if (handlers_count == 0)
+ return;
+
+ /* set expunge handlers */
+ memset(&eh, 0, sizeof(eh));
+ if (ctx->expunge_handlers != NULL)
+ buffer_set_used_size(ctx->expunge_handlers, 0);
+ else {
+ ctx->expunge_handlers =
+ buffer_create_dynamic(default_pool, 256);
+ }
+
+ extensions = ctx->view->map->extensions->data;
+ id_map = buffer_get_data(ctx->view->map->ext_id_map, &id_map_size);
+ id_map_size /= sizeof(*id_map);
+
+ size = I_MIN(handlers_count, id_map_size);
+ for (ext_id = 0; ext_id < size; ext_id++) {
+ if (handlers[ext_id] == NULL || id_map[ext_id] == (uint32_t)-1)
+ continue;
+
+ eh.handler = handlers[ext_id];
+ eh.context = &ctx->extra_context[ext_id];
+ eh.record_offset = extensions[id_map[ext_id]].record_offset;
+ buffer_append(ctx->expunge_handlers, &eh, sizeof(eh));
+ }
+ ctx->expunge_handlers_set = TRUE;
+ ctx->expunge_handlers_used = TRUE;
+}
+
+static void
+mail_index_sync_deinit_expunge_handlers(struct mail_index_sync_map_ctx *ctx)
+{
+ const struct mail_index_expunge_handler *eh;
+ size_t i, size;
+
+ if (ctx->expunge_handlers == NULL)
+ return;
+
+ eh = buffer_get_data(ctx->expunge_handlers, &size);
+ size /= sizeof(*eh);
+
+ for (i = 0; i < size; i++) {
+ if (eh->context != NULL)
+ eh[i].handler(ctx, 0, NULL, eh->context);
+ }
+
+ buffer_free(ctx->expunge_handlers);
+}
+
+static void mail_index_sync_init_handlers(struct mail_index_sync_map_ctx *ctx)
+{
+ size_t size;
+
+ if (ctx->view->map->extensions == NULL)
+ return;
+
+ /* set space for extra contexts */
+ size = sizeof(void *) * (ctx->view->index->extensions->used /
+ sizeof(struct mail_index_ext));
+ if (ctx->extra_context_buf == NULL) {
+ ctx->extra_context_buf =
+ buffer_create_dynamic(default_pool, size);
+ } else {
+ buffer_set_used_size(ctx->extra_context_buf, 0);
+ }
+ buffer_append_zero(ctx->extra_context_buf, size);
+ ctx->extra_context =
+ buffer_get_modifyable_data(ctx->extra_context_buf, NULL);
+
+ ctx->expunge_handlers_set = FALSE;
+ ctx->sync_handlers_initialized = TRUE;
+}
+
+static void mail_index_sync_deinit_handlers(struct mail_index_sync_map_ctx *ctx)
+{
+ mail_index_sync_handler_t *const *sync_handlers;
+ size_t i, size;
+
+ if (ctx->extra_context == NULL)
+ return;
+
+ sync_handlers = buffer_get_data(ctx->view->index->sync_handlers, &size);
+ size /= sizeof(*sync_handlers);
+
+ i_assert(size <= ctx->extra_context_buf->used / sizeof(void *));
+
+ for (i = 0; i < size; i++) {
+ if (ctx->extra_context[i] != NULL) {
+ sync_handlers[i](ctx, 0, NULL, NULL,
+ &ctx->extra_context[i]);
+ }
+ }
+
+ buffer_free(ctx->extra_context_buf);
+}
+
+static void
mail_index_header_update_counts(struct mail_index_header *hdr,
uint8_t old_flags, uint8_t new_flags)
{
@@ -69,24 +179,6 @@
hdr->first_deleted_uid_lowwater = rec->uid;
}
-static void mail_index_sync_cache_expunge(struct mail_index_sync_map_ctx *ctx,
- uoff_t cache_offset)
-{
- if (!ctx->update_cache)
- return;
-
- if (!ctx->cache_locked) {
- if (mail_cache_lock(ctx->view->index->cache) <= 0)
- return;
- ctx->cache_locked = TRUE;
- }
-
- if (!MAIL_CACHE_IS_UNUSABLE(ctx->view->index->cache) &&
- ctx->view->map->hdr->cache_file_seq !=
- ctx->view->index->cache->hdr->file_seq)
- (void)mail_cache_delete(ctx->view->index->cache, cache_offset);
-}
-
static int sync_expunge(const struct mail_transaction_expunge *e, void *context)
{
struct mail_index_sync_map_ctx *ctx = context;
@@ -95,6 +187,8 @@
struct mail_index_header *hdr;
struct mail_index_record *rec;
uint32_t count, seq, seq1, seq2;
+ struct mail_index_expunge_handler *expunge_handlers, *eh;
+ size_t i, expunge_handlers_count;
if (!view->map->write_to_disk) {
/* expunges have to be atomic. so we'll have to copy
@@ -115,13 +209,35 @@
if (seq1 == 0)
return 1;
+ if (ctx->sync_handlers_initialized) {
+ if (!ctx->expunge_handlers_set)
+ mail_index_sync_init_expunge_handlers(ctx);
+
+ expunge_handlers =
+ buffer_get_modifyable_data(ctx->expunge_handlers,
+ &expunge_handlers_count);
+ expunge_handlers_count /= sizeof(*expunge_handlers);
+ } else {
+ /* syncing view - don't call expunge handlers */
+ expunge_handlers = NULL;
+ expunge_handlers_count = 0;
+ }
+
hdr = buffer_get_modifyable_data(map->hdr_copy_buf, NULL);
for (seq = seq1; seq <= seq2; seq++) {
rec = MAIL_INDEX_MAP_IDX(map, seq-1);
mail_index_header_update_counts(hdr, rec->flags, 0);
-
- if (rec->cache_offset != 0)
- mail_index_sync_cache_expunge(ctx, rec->cache_offset);
+ }
+
+ for (i = 0; i < expunge_handlers_count; i++) {
+ eh = &expunge_handlers[i];
+
+ for (seq = seq1; seq <= seq2; seq++) {
+ rec = MAIL_INDEX_MAP_IDX(map, seq-1);
+ eh->handler(ctx, seq,
+ PTR_OFFSET(rec, eh->record_offset),
+ eh->context);
+ }
}
/* @UNSAFE */
@@ -236,62 +352,6 @@
return 1;
}
-static int sync_cache_reset(const struct mail_transaction_cache_reset *u,
- void *context)
-{
- struct mail_index_sync_map_ctx *ctx = context;
- struct mail_index_view *view = ctx->view;
- struct mail_index_header *hdr;
- uint32_t i;
-
- hdr = buffer_get_modifyable_data(view->map->hdr_copy_buf, NULL);
- hdr->cache_file_seq = u->new_file_seq;
-
- for (i = 0; i < view->messages_count; i++)
- MAIL_INDEX_MAP_IDX(view->map, i)->cache_offset = 0;
- return 1;
-}
-
-static int sync_cache_update(const struct mail_transaction_cache_update *u,
- void *context)
-{
- struct mail_index_sync_map_ctx *ctx = context;
- struct mail_index_view *view = ctx->view;
- struct mail_index_record *rec;
- uint32_t seq;
- int ret;
-
- if (mail_index_lookup_uid_range(view, u->uid, u->uid, &seq, &seq) < 0)
- return -1;
-
- if (seq == 0) {
- /* already expunged */
- return 1;
- }
-
- rec = MAIL_INDEX_MAP_IDX(view->map, seq-1);
- if (rec->cache_offset != 0 && ctx->update_cache) {
- /* we'll need to link the old and new cache records */
- if (!ctx->cache_locked) {
- if ((ret = mail_cache_lock(view->index->cache)) <= 0)
- return ret < 0 ? -1 : 1;
- ctx->cache_locked = TRUE;
- }
-
- if (view->map->hdr->cache_file_seq !=
- view->index->cache->hdr->file_seq) {
- /* cache has been compressed, don't modify it */
- return 1;
- }
-
- if (mail_cache_link(view->index->cache,
- rec->cache_offset, u->cache_offset) < 0)
- return -1;
- }
- rec->cache_offset = u->cache_offset;
- return 1;
-}
-
static int sync_header_update(const struct mail_transaction_header_update *u,
void *context)
{
@@ -311,6 +371,25 @@
return 1;
}
+static struct mail_index_ext_header *
+get_ext_header(struct mail_index_map *map, const struct mail_index_ext *ext)
+{
+ struct mail_index_ext_header *ext_hdr;
+ uint32_t offset;
+ void *hdr;
+
+ /* do some kludgy jumping to get to it. */
+ offset = ext->hdr_offset -
+ MAIL_INDEX_HEADER_SIZE_ALIGN(sizeof(*ext_hdr) +
+ strlen(ext->name));
+
+ hdr = buffer_get_modifyable_data(map->hdr_copy_buf, NULL);
+ ext_hdr = PTR_OFFSET(hdr, offset);
+ i_assert(memcmp((char *)(ext_hdr + 1),
+ ext->name, strlen(ext->name)) == 0);
+ return ext_hdr;
+}
+
static int mail_index_ext_align_cmp(const void *p1, const void *p2)
{
const struct mail_index_ext *const *e1 = p1, *const *e2 = p2;
@@ -327,7 +406,6 @@
uint16_t *old_offsets, min_align;
uint32_t offset, old_records_count, rec_idx;
const void *src;
- void *hdr;
size_t i, size;
t_push();
@@ -407,15 +485,8 @@
new_map->records_count = old_records_count;
/* update record offsets in headers */
- hdr = buffer_get_modifyable_data(new_map->hdr_copy_buf, NULL);
for (i = 0; i < size; i++) {
- /* kludgy jumping to get to the beginning of header. */
- offset = ext[i].hdr_offset -
- MAIL_INDEX_HEADER_SIZE_ALIGN(sizeof(*ext_hdr) +
- strlen(ext[i].name));
- ext_hdr = PTR_OFFSET(hdr, offset);
- i_assert(memcmp((char *)(ext_hdr + 1),
- ext[i].name, strlen(ext->name)) == 0);
+ ext_hdr = get_ext_header(new_map, &ext[i]);
ext_hdr->record_offset = ext[i].record_offset;
}
@@ -431,7 +502,7 @@
struct mail_index_ext *ext;
struct mail_index_ext_header *ext_hdr;
struct mail_index_header *hdr;
- uint32_t offset, old_size, new_size, old_record_size;
+ uint32_t old_size, new_size, old_record_size;
int modified = FALSE;
ext = buffer_get_modifyable_data(map->extensions, NULL);
@@ -466,14 +537,8 @@
hdr->header_size = map->hdr_copy_buf->used;
map->hdr = hdr;
- /* we need to modify ext header. do some kludgy jumping to
- get to it. */
- offset = ext->hdr_offset -
- MAIL_INDEX_HEADER_SIZE_ALIGN(sizeof(*ext_hdr) +
- strlen(ext->name));
- ext_hdr = PTR_OFFSET(hdr, offset);
- i_assert(memcmp((char *)(ext_hdr + 1),
- ext->name, strlen(ext->name)) == 0);
+ ext_hdr = get_ext_header(map, ext);
+ ext_hdr->reset_id = ext->reset_id;
ext_hdr->hdr_size = ext->hdr_size;
ext_hdr->record_offset = ext->record_offset;
ext_hdr->record_size = ext->record_size;
@@ -483,7 +548,6 @@
if (old_record_size != u->record_size) {
map = sync_ext_reorder(map, ext_id, old_record_size);
mail_index_sync_replace_map(ctx->view, map);
- modified = TRUE;
}
}
@@ -523,11 +587,22 @@
}
if (ext_id != (uint32_t)-1) {
- /* exists already - are we resizing? */
- sync_ext_resize(u, ext_id, ctx);
+ /* exists already */
+ ext = map->extensions->data;
+ ext += ext_id;
+
+ if (u->reset_id == ext->reset_id) {
+ /* check if we need to resize anything */
+ sync_ext_resize(u, ext_id, ctx);
+ ctx->cur_ext_ignore = FALSE;
+ } else {
+ /* extension was reset and this transaction hadn't
+ yet seen it. ignore this update. */
+ ctx->cur_ext_ignore = TRUE;
+ }
t_pop();
- ctx->last_ext_id = ext_id;
+ ctx->cur_ext_id = ext_id;
return 1;
}
@@ -539,14 +614,14 @@
hdr_buf->used);
}
- /* register record offset initially using record size,
+ /* register record offset initially using zero,
sync_ext_reorder() will fix it. */
hdr_offset = map->hdr_copy_buf->used + sizeof(ext_hdr) + strlen(name);
hdr_offset = MAIL_INDEX_HEADER_SIZE_ALIGN(hdr_offset);
- ext_id = mail_index_map_register_ext(ctx->view->index, map,
- name, hdr_offset, u->hdr_size,
- map->hdr->record_size,
- u->record_size, u->record_align);
+ ext_id = mail_index_map_register_ext(ctx->view->index, map, name,
+ hdr_offset, u->hdr_size, 0,
+ u->record_size, u->record_align,
+ u->reset_id);
ext = map->extensions->data;
ext += ext_id;
@@ -554,6 +629,7 @@
/* <ext_hdr> <name> [padding] [header data] */
memset(&ext_hdr, 0, sizeof(ext_hdr));
ext_hdr.name_size = strlen(name);
+ ext_hdr.reset_id = ext->reset_id;
ext_hdr.hdr_size = ext->hdr_size;
ext_hdr.record_offset = ext->record_offset;
ext_hdr.record_size = ext->record_size;
@@ -573,30 +649,38 @@
t_pop();
+ mail_index_sync_init_handlers(ctx);
+
map = sync_ext_reorder(map, ext_id, 0);
mail_index_sync_replace_map(ctx->view, map);
- ctx->last_ext_id = ext_id;
+ ctx->cur_ext_ignore = FALSE;
+ ctx->cur_ext_id = ext_id;
return 1;
}
-static int sync_ext_reset(void *context)
+static int sync_ext_reset(const struct mail_transaction_ext_reset *u,
+ void *context)
{
struct mail_index_sync_map_ctx *ctx = context;
struct mail_index_view *view = ctx->view;
struct mail_index_map *map = view->map;
- const struct mail_index_ext *ext;
+ struct mail_index_ext_header *ext_hdr;
+ struct mail_index_ext *ext;
struct mail_index_record *rec;
uint32_t i;
- if (ctx->last_ext_id == (uint32_t)-1) {
+ if (ctx->cur_ext_id == (uint32_t)-1) {
mail_transaction_log_view_set_corrupted(view->log_view,
"Extension reset without intro prefix");
return -1;
}
+ if (ctx->cur_ext_ignore)
+ return 1;
- ext = map->extensions->data;
- ext += ctx->last_ext_id;
+ ext = buffer_get_modifyable_data(map->extensions, NULL);
+ ext += ctx->cur_ext_id;
+ ext->reset_id = u->new_reset_id;
memset(buffer_get_space_unsafe(map->hdr_copy_buf, ext->hdr_offset,
ext->hdr_size), 0, ext->hdr_size);
@@ -607,6 +691,10 @@
memset(PTR_OFFSET(rec, ext->record_offset), 0,
ext->record_size);
}
+
+ ext_hdr = get_ext_header(map, ext);
+ ext_hdr->reset_id = u->new_reset_id;
+
return 1;
}
@@ -617,14 +705,16 @@
struct mail_index_map *map = ctx->view->map;
const struct mail_index_ext *ext;
- if (ctx->last_ext_id == (uint32_t)-1) {
+ if (ctx->cur_ext_id == (uint32_t)-1) {
mail_transaction_log_view_set_corrupted(ctx->view->log_view,
"Extension header update without intro prefix");
return -1;
}
+ if (ctx->cur_ext_ignore)
+ return 1;
ext = map->extensions->data;
- ext += ctx->last_ext_id;
+ ext += ctx->cur_ext_id;
buffer_write(map->hdr_copy_buf, ext->hdr_offset + u->offset,
u + 1, u->size);
@@ -639,26 +729,40 @@
struct mail_index_sync_map_ctx *ctx = context;
struct mail_index_view *view = ctx->view;
struct mail_index_record *rec;
- const struct mail_index_ext *ext;
+ mail_index_sync_handler_t *const *sync_handlers;
+ const struct mail_index_ext *ext;
+ void *old_data;
uint32_t seq;
+ int ret;
- if (ctx->last_ext_id == (uint32_t)-1) {
- mail_transaction_log_view_set_corrupted(ctx->view->log_view,
- "Extension record update update without intro prefix");
- return -1;
- }
+ i_assert(ctx->cur_ext_id != (uint32_t)-1);
+ i_assert(!ctx->cur_ext_ignore);
if (mail_index_lookup_uid_range(view, u->uid, u->uid, &seq, &seq) < 0)
return -1;
- if (seq != 0) {
- ext = view->map->extensions->data;
- ext += ctx->last_ext_id;
+ if (seq == 0)
+ return 1;
- rec = MAIL_INDEX_MAP_IDX(view->map, seq-1);
- memcpy(PTR_OFFSET(rec, ext->record_offset),
- u + 1, ext->record_size);
+ ext = view->map->extensions->data;
+ ext += ctx->cur_ext_id;
+
+ rec = MAIL_INDEX_MAP_IDX(view->map, seq-1);
+ old_data = PTR_OFFSET(rec, ext->record_offset);
+
+ /* @UNSAFE */
+ sync_handlers = view->index->sync_handlers->data;
+ sync_handlers += ctx->cur_ext_id;
+
+ /* call sync handlers only when we're syncing index (not view) */
+ if (*sync_handlers != NULL && ctx->sync_handlers_initialized) {
+ ret = (*sync_handlers)(ctx, seq, old_data, u + 1,
+ &ctx->extra_context[ctx->cur_ext_id]);
+ if (ret <= 0)
+ return ret;
}
+
+ memcpy(old_data, u + 1, ext->record_size);
return 1;
}
@@ -792,23 +896,6 @@
}
break;
}
- case MAIL_TRANSACTION_CACHE_RESET: {
- const struct mail_transaction_cache_reset *rec = data;
-
- ret = sync_cache_reset(rec, ctx);
- break;
- }
- case MAIL_TRANSACTION_CACHE_UPDATE: {
- const struct mail_transaction_cache_update *rec, *end;
-
- end = CONST_PTR_OFFSET(data, hdr->size);
- for (rec = data; rec != end; rec++) {
- ret = sync_cache_update(rec, ctx);
- if (ret <= 0)
- break;
- }
- break;
- }
case MAIL_TRANSACTION_HEADER_UPDATE: {
const struct mail_transaction_header_update *rec;
unsigned int i;
@@ -846,9 +933,11 @@
}
break;
}
- case MAIL_TRANSACTION_EXT_RESET:
- ret = sync_ext_reset(ctx);
+ case MAIL_TRANSACTION_EXT_RESET: {
+ const struct mail_transaction_ext_reset *rec = data;
+ ret = sync_ext_reset(rec, ctx);
break;
+ }
case MAIL_TRANSACTION_EXT_HDR_UPDATE: {
const struct mail_transaction_ext_hdr_update *rec = data;
unsigned int i;
@@ -870,16 +959,24 @@
const struct mail_index_ext *ext;
unsigned int record_size;
- /* call the first one, it checks if last_ext_id isn't set */
- rec = data;
- ret = sync_ext_rec_update(rec, ctx);
- if (ret <= 0)
+ if (ctx->cur_ext_id == (uint32_t)-1) {
+ mail_transaction_log_view_set_corrupted(
+ ctx->view->log_view,
+ "Extension record update update "
+ "without intro prefix");
+ ret = -1;
+ break;
+ }
+
+ if (ctx->cur_ext_ignore) {
+ ret = 1;
break;
+ }
ext = ctx->view->map->extensions->data;
- record_size = sizeof(*rec) + ext[ctx->last_ext_id].record_size;
+ record_size = sizeof(*rec) + ext[ctx->cur_ext_id].record_size;
- rec = CONST_PTR_OFFSET(rec, record_size);
+ rec = data;
end = CONST_PTR_OFFSET(data, hdr->size);
while (rec < end) {
ret = sync_ext_rec_update(rec, ctx);
@@ -897,6 +994,14 @@
return ret;
}
+void mail_index_sync_map_init(struct mail_index_sync_map_ctx *sync_map_ctx,
+ struct mail_index_view *view)
+{
+ memset(sync_map_ctx, 0, sizeof(*sync_map_ctx));
+ sync_map_ctx->view = view;
+ sync_map_ctx->cur_ext_id = (uint32_t)-1;
+}
+
int mail_index_sync_update_index(struct mail_index_sync_ctx *sync_ctx,
int sync_only_external)
{
@@ -912,10 +1017,8 @@
uoff_t offset;
int ret, had_dirty, skipped, check_ext_offsets;
- memset(&sync_map_ctx, 0, sizeof(sync_map_ctx));
- sync_map_ctx.view = view;
- sync_map_ctx.update_cache = TRUE;
- sync_map_ctx.last_ext_id = (uint32_t)-1;
+ mail_index_sync_map_init(&sync_map_ctx, view);
+ mail_index_sync_init_handlers(&sync_map_ctx);
/* we'll have to update view->lock_id to avoid mail_index_view_lock()
trying to update the file later. */
@@ -997,10 +1100,9 @@
}
map = view->map;
- if (sync_map_ctx.cache_locked) {
- mail_cache_unlock(index->cache);
- sync_map_ctx.cache_locked = FALSE;
- }
+ if (sync_map_ctx.expunge_handlers_used)
+ mail_index_sync_deinit_expunge_handlers(&sync_map_ctx);
+ mail_index_sync_deinit_handlers(&sync_map_ctx);
if (ret < 0) {
mail_index_view_unlock(view);
Index: mail-index-transaction-private.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-transaction-private.h,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- mail-index-transaction-private.h 17 Oct 2004 18:24:21 -0000 1.15
+++ mail-index-transaction-private.h 6 Nov 2004 17:20:18 -0000 1.16
@@ -21,9 +21,8 @@
buffer_t *ext_rec_updates; /* buffer[] */
buffer_t *ext_resizes; /* struct mail_transaction_ext_intro[] */
+ buffer_t *ext_resets; /* uint32_t[] */
- uint32_t new_cache_file_seq, last_cache_file_seq;
- buffer_t *cache_updates;
struct mail_cache_transaction_ctx *cache_trans_ctx;
unsigned int hide_transaction:1;
Index: mail-index-transaction-view.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-transaction-view.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- mail-index-transaction-view.c 26 Sep 2004 14:15:54 -0000 1.6
+++ mail-index-transaction-view.c 6 Nov 2004 17:20:18 -0000 1.7
@@ -134,8 +134,10 @@
return 0;
}
-static int _tview_lookup_ext(struct mail_index_view *view, uint32_t seq,
- uint32_t ext_id, const void **data_r)
+static int
+_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)
{
struct mail_index_view_transaction *tview =
(struct mail_index_view_transaction *)view;
@@ -143,21 +145,29 @@
buffer_t *const *ext_bufs;
size_t size, pos;
- if (seq < tview->t->first_new_seq)
- return tview->parent->lookup_ext(view, seq, ext_id, data_r);
-
- i_assert(seq <= tview->t->last_new_seq);
i_assert(ext_id < view->index->extensions->used / sizeof(*ext));
ext = view->index->extensions->data;
ext += ext_id;
- ext_bufs = buffer_get_data(tview->t->ext_rec_updates, &size);
- size /= sizeof(*ext_bufs);
+ if (tview->t->ext_rec_updates == NULL) {
+ ext_bufs = NULL;
+ size = 0;
+ } else {
+ ext_bufs = buffer_get_data(tview->t->ext_rec_updates, &size);
+ size /= sizeof(*ext_bufs);
+ }
+ *map_r = view->index->map;
if (size <= ext_id || ext_bufs[ext_id] == NULL ||
!mail_index_seq_buffer_lookup(ext_bufs[ext_id], seq,
ext->record_size, &pos)) {
+ /* not updated, return the existing value */
+ if (seq < tview->t->first_new_seq) {
+ return tview->parent->lookup_ext_full(view, seq, ext_id,
+ map_r, data_r);
+ }
+
*data_r = NULL;
return 1;
}
@@ -166,6 +176,18 @@
return 1;
}
+static int _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 */
+ return tview->parent->get_header_ext(view, map, ext_id,
+ data_r, data_size_r);
+}
+
static struct mail_index_view_methods view_methods = {
_tview_close,
_tview_get_message_count,
@@ -174,7 +196,8 @@
_tview_lookup_uid,
_tview_lookup_uid_range,
_tview_lookup_first,
- _tview_lookup_ext
+ _tview_lookup_ext_full,
+ _tview_get_header_ext
};
struct mail_index_view *
Index: mail-index-transaction.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-transaction.c,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -d -r1.32 -r1.33
--- mail-index-transaction.c 17 Oct 2004 18:24:21 -0000 1.32
+++ mail-index-transaction.c 6 Nov 2004 17:20:18 -0000 1.33
@@ -55,8 +55,10 @@
buffer_free(t->expunges);
if (t->updates != NULL)
buffer_free(t->updates);
- if (t->cache_updates != NULL)
- buffer_free(t->cache_updates);
+ if (t->ext_resizes != NULL)
+ buffer_free(t->ext_resizes);
+ if (t->ext_resets != NULL)
+ buffer_free(t->ext_resets);
i_free(t);
}
@@ -134,8 +136,6 @@
sizeof(struct mail_transaction_expunge), TRUE);
mail_index_buffer_convert_to_uids(t, t->updates,
sizeof(struct mail_transaction_flag_update), TRUE);
- mail_index_buffer_convert_to_uids(t, t->cache_updates,
- sizeof(struct mail_transaction_cache_update), FALSE);
return 0;
}
@@ -560,96 +560,6 @@
}
}
-static void
-mail_index_transaction_reset_cache_updates(struct mail_index_transaction *t)
-{
- struct mail_index_record *rec;
- uint32_t seq;
-
- if (t->last_cache_file_seq == 0)
- return;
-
- buffer_set_used_size(t->cache_updates, 0);
-
- if (t->first_new_seq != 0) {
- for (seq = t->first_new_seq; seq <= t->last_new_seq; seq++) {
- rec = mail_index_transaction_lookup(t, seq);
- rec->cache_offset = 0;
- }
- }
-}
-
-void mail_index_reset_cache(struct mail_index_transaction *t,
- uint32_t new_file_seq)
-{
- t->log_updates = TRUE;
-
- mail_index_transaction_reset_cache_updates(t);
- t->new_cache_file_seq = new_file_seq;
- t->last_cache_file_seq = new_file_seq;
-}
-
-void mail_index_update_cache(struct mail_index_transaction *t, uint32_t seq,
- uint32_t file_seq, uint32_t offset,
- uint32_t *old_offset_r)
-{
- struct mail_index_record *rec;
-
- i_assert(seq > 0 &&
- (seq <= mail_index_view_get_message_count(t->view) ||
- seq <= t->last_new_seq));
-
- t->log_updates = TRUE;
-
- if (file_seq != t->last_cache_file_seq) {
- mail_index_transaction_reset_cache_updates(t);
- t->last_cache_file_seq = file_seq;
- }
-
- if (seq >= t->first_new_seq) {
- /* just appended message, modify it directly */
- rec = mail_index_transaction_lookup(t, seq);
- *old_offset_r = rec->cache_offset;
- rec->cache_offset = offset;
- } else {
- if (!mail_index_update_seq_buffer(&t->cache_updates, seq,
- &offset, sizeof(offset),
- old_offset_r))
- *old_offset_r = 0;
- }
-}
-
-int mail_index_update_cache_lookup(struct mail_index_transaction *t,
- uint32_t seq, uint32_t *offset_r)
-{
- const void *p;
- size_t pos;
-
- i_assert(seq > 0 &&
- (seq <= mail_index_view_get_message_count(t->view) ||
- seq <= t->last_new_seq));
-
- if (t->cache_updates == NULL)
- return FALSE;
-
- if (MAIL_CACHE_IS_UNUSABLE(t->view->index->cache) ||
- t->view->index->cache->hdr->file_seq != t->last_cache_file_seq) {
- /* cache file was recreated, our offsets don't work anymore */
- mail_index_transaction_reset_cache_updates(t);
- t->last_cache_file_seq = 0;
- return FALSE;
- }
-
- if (!mail_index_seq_buffer_lookup(t->cache_updates, seq,
- sizeof(*offset_r), &pos))
- return FALSE;
-
- p = buffer_get_data(t->cache_updates, NULL);
- memcpy(offset_r, CONST_PTR_OFFSET(p, pos + sizeof(*offset_r)),
- sizeof(*offset_r));
- return TRUE;
-}
-
void mail_index_update_header(struct mail_index_transaction *t,
size_t offset, const void *data, size_t size)
{
@@ -687,6 +597,8 @@
(ext->record_size == record_size &&
ext->record_align == record_align));
+ t->log_updates = TRUE;
+
if (t->ext_resizes == NULL)
t->ext_resizes = buffer_create_dynamic(default_pool, 128);
@@ -698,6 +610,32 @@
&intro, sizeof(intro));
}
+void mail_index_ext_reset(struct mail_index_transaction *t, uint32_t ext_id,
+ uint32_t reset_id)
+{
+ size_t pos;
+
+ i_assert(reset_id != 0);
+
+ t->log_updates = TRUE;
+
+ if (t->ext_rec_updates != NULL &&
+ ext_id < t->ext_rec_updates->used / sizeof(buffer_t *)) {
+ buffer_t *const *buf = t->ext_rec_updates->data;
+ buf += ext_id;
+
+ if (*buf != NULL)
+ buffer_set_used_size(*buf, 0);
+ }
+
+ pos = ext_id * sizeof(uint32_t);
+ if (t->ext_resets == NULL) {
+ t->ext_resets = buffer_create_dynamic(default_pool,
+ pos + sizeof(uint32_t));
+ }
+ buffer_write(t->ext_resets, pos, &reset_id, sizeof(reset_id));
+}
+
void mail_index_update_header_ext(struct mail_index_transaction *t,
uint32_t ext_id, size_t offset,
const void *data, size_t size)
@@ -706,7 +644,7 @@
}
void mail_index_update_ext(struct mail_index_transaction *t, uint32_t seq,
- uint32_t ext_id, const void *data)
+ uint32_t ext_id, const void *data, void *old_data_r)
{
struct mail_index *index = t->view->index;
const struct mail_index_ext *ext;
@@ -741,5 +679,11 @@
buf = buffer_get_space_unsafe(t->ext_rec_updates,
ext_id * sizeof(buffer_t *),
sizeof(buffer_t *));
- mail_index_update_seq_buffer(buf, seq, data, record_size, NULL);
+
+ /* @UNSAFE */
+ if (!mail_index_update_seq_buffer(buf, seq, data, record_size,
+ old_data_r)) {
+ if (old_data_r != NULL)
+ memset(old_data_r, 0, record_size);
+ }
}
Index: mail-index-view-private.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-view-private.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- mail-index-view-private.h 17 Oct 2004 16:42:20 -0000 1.11
+++ mail-index-view-private.h 6 Nov 2004 17:20:18 -0000 1.12
@@ -18,8 +18,12 @@
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);
- int (*lookup_ext)(struct mail_index_view *view, uint32_t seq,
- uint32_t ext_id, const void **data_r);
+ int (*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);
+ int (*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 {
Index: mail-index-view-sync.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-view-sync.c,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -d -r1.26 -r1.27
--- mail-index-view-sync.c 25 Oct 2004 17:42:51 -0000 1.26
+++ mail-index-view-sync.c 6 Nov 2004 17:20:18 -0000 1.27
@@ -122,9 +122,7 @@
ctx->view = view;
ctx->trans_sync_mask = want_mask;
ctx->expunges = expunges;
-
- ctx->sync_map_ctx.view = view;
- ctx->sync_map_ctx.last_ext_id = (uint32_t)-1;
+ mail_index_sync_map_init(&ctx->sync_map_ctx, view);
if ((sync_mask & MAIL_INDEX_SYNC_TYPE_EXPUNGE) != 0) {
view->new_map = view->index->map;
Index: mail-index-view.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-view.c,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -d -r1.26 -r1.27
--- mail-index-view.c 25 Oct 2004 17:42:51 -0000 1.26
+++ mail-index-view.c 6 Nov 2004 17:20:18 -0000 1.27
@@ -374,25 +374,24 @@
return 0;
}
-static int _view_lookup_ext(struct mail_index_view *view, uint32_t seq,
- uint32_t ext_id, const void **data_r)
+static int _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)
{
const struct mail_index_ext *ext;
const struct mail_index_record *rec;
- struct mail_index_map *map;
uint32_t idx, offset;
int ret;
- if ((ret = mail_index_lookup_full(view, seq, &map, &rec)) < 0)
+ if ((ret = mail_index_lookup_full(view, seq, map_r, &rec)) < 0)
return -1;
- if (rec == NULL ||
- !mail_index_map_get_ext_idx(view->map, ext_id, &idx)) {
+ if (rec == NULL || !mail_index_map_get_ext_idx(*map_r, ext_id, &idx)) {
*data_r = NULL;
return ret;
}
- ext = view->map->extensions->data;
+ ext = (*map_r)->extensions->data;
ext += idx;
offset = ext->record_offset;
@@ -400,6 +399,30 @@
return ret;
}
+static int _view_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)
+{
+ const struct mail_index_ext *ext;
+
+ if (map != NULL) {
+ if (mail_index_view_lock(view) < 0)
+ return -1;
+ } else {
+ if (mail_index_view_lock_head(view, FALSE) < 0)
+ return -1;
+
+ map = view->index->map;
+ }
+
+ ext = map->extensions->data;
+ ext += ext_id;
+
+ *data_r = CONST_PTR_OFFSET(map->hdr, ext->hdr_offset);
+ *data_size_r = ext->hdr_size;
+ return 0;
+}
+
void mail_index_view_close(struct mail_index_view *view)
{
view->methods.close(view);
@@ -454,7 +477,31 @@
int mail_index_lookup_ext(struct mail_index_view *view, uint32_t seq,
uint32_t ext_id, const void **data_r)
{
- return view->methods.lookup_ext(view, seq, ext_id, data_r);
+ struct mail_index_map *map;
+
+ return view->methods.lookup_ext_full(view, seq, ext_id, &map, data_r);
+}
+
+int mail_index_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)
+{
+ return view->methods.lookup_ext_full(view, seq, ext_id, map_r, data_r);
+}
+
+int mail_index_get_header_ext(struct mail_index_view *view, uint32_t ext_id,
+ const void **data_r, size_t *data_size_r)
+{
+ return view->methods.get_header_ext(view, NULL, ext_id,
+ data_r, data_size_r);
+}
+
+int mail_index_map_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)
+{
+ return view->methods.get_header_ext(view, map, ext_id,
+ data_r, data_size_r);
}
static struct mail_index_view_methods view_methods = {
@@ -465,7 +512,8 @@
_view_lookup_uid,
_view_lookup_uid_range,
_view_lookup_first,
- _view_lookup_ext
+ _view_lookup_ext_full,
+ _view_get_header_ext
};
struct mail_index_view *mail_index_view_open(struct mail_index *index)
@@ -488,3 +536,35 @@
view->map->log_file_ext_offset);
return view;
}
+
+int mail_index_view_open_locked(struct mail_index *index,
+ struct mail_index_view **view_r)
+{
+ unsigned int lock_id;
+
+ if (mail_index_lock_shared(index, TRUE, &lock_id) < 0)
+ return -1;
+
+ *view_r = mail_index_view_open(index);
+ if (mail_index_view_lock_head(*view_r, FALSE) < 0) {
+ mail_index_view_close(*view_r);
+ mail_index_unlock(index, lock_id);
+ return -1;
+ }
+
+ mail_index_unlock(index, lock_id);
+ return 0;
+}
+
+const struct mail_index_ext *
+mail_index_view_get_ext(struct mail_index_view *view, uint32_t ext_id)
+{
+ const struct mail_index_ext *ext;
+ uint32_t idx;
+
+ if (!mail_index_map_get_ext_idx(view->map, ext_id, &idx))
+ return 0;
+
+ ext = view->map->extensions->data;
+ return &ext[idx];
+}
Index: mail-index.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index.c,v
retrieving revision 1.160
retrieving revision 1.161
diff -u -d -r1.160 -r1.161
--- mail-index.c 25 Oct 2004 20:04:43 -0000 1.160
+++ mail-index.c 6 Nov 2004 17:20:19 -0000 1.161
@@ -27,6 +27,8 @@
index->extension_pool = pool_alloconly_create("extension", 256);
index->extensions = buffer_create_dynamic(index->extension_pool, 64);
+ index->sync_handlers = buffer_create_dynamic(default_pool, 32);
+ index->expunge_handlers = buffer_create_dynamic(default_pool, 32);
index->mode = 0600;
index->gid = (gid_t)-1;
@@ -38,6 +40,9 @@
mail_index_close(index);
pool_unref(index->extension_pool);
+ buffer_free(index->sync_handlers);
+ buffer_free(index->expunge_handlers);
+
i_free(index->error);
i_free(index->dir);
i_free(index->prefix);
@@ -64,6 +69,9 @@
extensions = buffer_get_data(index->extensions, &ext_count);
ext_count /= sizeof(*extensions);
+ i_assert(index->sync_handlers->used /
+ sizeof(mail_index_sync_handler_t *) == ext_count);
+
/* see if it's already there */
for (i = 0; i < ext_count; i++) {
if (strcmp(extensions[i].name, name) == 0)
@@ -77,9 +85,26 @@
ext.record_align = default_record_align;
buffer_append(index->extensions, &ext, sizeof(ext));
+ buffer_append_zero(index->sync_handlers,
+ sizeof(mail_index_sync_handler_t *));
return ext_count;
}
+void mail_index_register_expunge_handler(struct mail_index *index,
+ uint32_t ext_id,
+ mail_index_expunge_handler_t *cb)
+{
+ buffer_write(index->expunge_handlers, ext_id * sizeof(cb),
+ &cb, sizeof(cb));
+}
+
+void mail_index_register_sync_handler(struct mail_index *index, uint32_t ext_id,
+ mail_index_sync_handler_t *cb)
+{
+ buffer_write(index->sync_handlers, ext_id * sizeof(cb),
+ &cb, sizeof(cb));
+}
+
static void mail_index_map_init_extbufs(struct mail_index_map *map,
unsigned int initial_count)
{
@@ -125,7 +150,7 @@
struct mail_index_map *map, const char *name,
uint32_t hdr_offset, uint32_t hdr_size,
uint32_t record_offset, uint32_t record_size,
- uint32_t record_align)
+ uint32_t record_align, uint32_t reset_id)
{
struct mail_index_ext *ext;
uint32_t idx, ext_id;
@@ -146,6 +171,7 @@
ext->record_offset = record_offset;
ext->record_size = record_size;
ext->record_align = record_align;
+ ext->reset_id = reset_id;
ext_id = mail_index_ext_register(index, name, hdr_size,
record_size, record_align);
@@ -216,7 +242,8 @@
offset, ext_hdr->hdr_size,
ext_hdr->record_offset,
ext_hdr->record_size,
- ext_hdr->record_align);
+ ext_hdr->record_align,
+ ext_hdr->reset_id);
t_pop();
offset += MAIL_INDEX_HEADER_SIZE_ALIGN(ext_hdr->hdr_size);
@@ -577,8 +604,15 @@
ret = mail_index_map_try_existing(index->map);
if (ret != 0)
return ret;
+
+ if (index->lock_type == F_WRLCK) {
+ /* we're syncing, don't break the mapping */
+ return 1;
+ }
}
+ i_assert(index->lock_type != F_WRLCK);
+
if (index->map != NULL && index->map->refcount > 1) {
/* this map is already used by some views and they may have
pointers into it. leave them and create a new mapping. */
Index: mail-index.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index.h,v
retrieving revision 1.133
retrieving revision 1.134
diff -u -d -r1.133 -r1.134
--- mail-index.h 25 Oct 2004 17:42:51 -0000 1.133
+++ mail-index.h 6 Nov 2004 17:20:19 -0000 1.134
@@ -6,7 +6,7 @@
#define MAIL_INDEX_MAJOR_VERSION 6
#define MAIL_INDEX_MINOR_VERSION 0
-#define MAIL_INDEX_HEADER_MIN_SIZE 124
+#define MAIL_INDEX_HEADER_MIN_SIZE 120
/* Number of keywords in mail_index_record. */
#define INDEX_KEYWORDS_COUNT (3*8)
@@ -103,8 +103,6 @@
uint64_t sync_size;
uint32_t sync_stamp;
- uint32_t cache_file_seq;
-
/* daily first UIDs that have been added to index. */
uint32_t day_stamp;
uint32_t day_first_uid[8];
@@ -114,7 +112,6 @@
uint32_t uid;
uint8_t flags; /* mail_flags | mail_index_mail_flags */
keywords_mask_t keywords;
- uint32_t cache_offset;
};
enum mail_index_sync_type {
@@ -136,6 +133,7 @@
};
struct mail_index;
+struct mail_index_map;
struct mail_index_view;
struct mail_index_transaction;
struct mail_index_sync_ctx;
@@ -158,9 +156,11 @@
/* View can be used to look into index. Sequence numbers inside view change
only when you synchronize it. The view acquires required locks
- automatically, but you'll have to drop them manually. Opening view
- acquires a lock immediately. */
+ automatically, but you'll have to drop them manually. */
struct mail_index_view *mail_index_view_open(struct mail_index *index);
+/* Open view to latest index locked. */
+int mail_index_view_open_locked(struct mail_index *index,
+ struct mail_index_view **view_r);
void mail_index_view_close(struct mail_index_view *view);
/* Returns the index for given view. */
@@ -255,6 +255,9 @@
expunged but data was returned from some older index. */
int mail_index_lookup(struct mail_index_view *view, uint32_t seq,
const struct mail_index_record **rec_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);
/* Returns the UID for given message. May be slightly faster than
mail_index_lookup()->uid. */
int mail_index_lookup_uid(struct mail_index_view *view, uint32_t seq,
@@ -318,19 +321,33 @@
uint32_t hdr_size, uint16_t record_size,
uint16_t record_align);
+/* Reset extension records and header. Any updates for this extension which
+ were issued before the writer had seen this reset are discarded. reset_id is
+ used to figure this out, so it must be different every time. */
+void mail_index_ext_reset(struct mail_index_transaction *t, uint32_t ext_id,
+ uint32_t reset_id);
+
/* Returns extension header. */
int mail_index_get_header_ext(struct mail_index_view *view, uint32_t ext_id,
const void **data_r, size_t *data_size_r);
+int mail_index_map_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);
/* Returns the wanted extension record for given message. If it doesn't exist,
*data_r is set to NULL. Return values are same as for mail_index_lookup(). */
int mail_index_lookup_ext(struct mail_index_view *view, uint32_t seq,
uint32_t ext_id, const void **data_r);
+int mail_index_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);
/* Update extension header field. */
void mail_index_update_header_ext(struct mail_index_transaction *t,
uint32_t ext_id, size_t offset,
const void *data, size_t size);
-/* Update extension record. */
+/* Update extension record. If old_data_r is non-NULL and the record extension
+ was already updated in this transaction, it's set to contain the data it's
+ now overwriting. */
void mail_index_update_ext(struct mail_index_transaction *t, uint32_t seq,
- uint32_t ext_id, const void *data);
+ uint32_t ext_id, const void *data, void *old_data);
#endif
Index: mail-transaction-log.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-transaction-log.c,v
retrieving revision 1.69
retrieving revision 1.70
diff -u -d -r1.69 -r1.70
--- mail-transaction-log.c 25 Oct 2004 17:42:51 -0000 1.69
+++ mail-transaction-log.c 6 Nov 2004 17:20:19 -0000 1.70
@@ -25,14 +25,6 @@
#define LOG_NEW_DOTLOCK_SUFFIX ".newlock"
-struct mail_transaction_add_ctx {
- struct mail_transaction_log *log;
- struct mail_index_view *view;
-
- buffer_t *appends, *expunges;
- buffer_t *flag_updates, *cache_updates;
-};
-
static struct mail_transaction_log_file *
mail_transaction_log_file_open_or_create(struct mail_transaction_log *log,
const char *path);
@@ -921,55 +913,6 @@
return ret;
}
-static int mail_transaction_log_scan_pending(struct mail_transaction_log *log,
- struct mail_index_transaction *t)
-{
- struct mail_transaction_log_view *sync_view;
- const struct mail_transaction_header *hdr;
- const void *data;
- uint32_t max_cache_file_seq = 0;
- int ret;
-
- sync_view = mail_transaction_log_view_open(log);
- ret = mail_transaction_log_view_set(sync_view, t->view->log_file_seq,
- t->view->log_file_offset,
- log->head->hdr.file_seq, (uoff_t)-1,
- MAIL_TRANSACTION_TYPE_MASK);
- while ((ret = mail_transaction_log_view_next(sync_view,
- &hdr, &data, NULL)) == 1) {
- switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) {
- case MAIL_TRANSACTION_CACHE_RESET: {
- const struct mail_transaction_cache_reset *reset = data;
-
- max_cache_file_seq = reset->new_file_seq;
- break;
- }
- }
- }
-
- /* make sure we're not writing cache_offsets to old cache file */
- if (t->new_cache_file_seq == 0 && max_cache_file_seq != 0 &&
- max_cache_file_seq != t->last_cache_file_seq &&
- t->cache_updates != NULL) {
- buffer_free(t->cache_updates);
- t->cache_updates = NULL;
-
- if (t->appends != NULL) {
- struct mail_index_record *rec;
- size_t i, size;
-
- rec = buffer_get_modifyable_data(t->appends, &size);
- size /= sizeof(*rec);
-
- for (i = 0; i < size; i++)
- rec[i].cache_offset = 0;
- }
- }
-
- mail_transaction_log_view_close(sync_view);
- return ret;
-}
-
static int log_append_buffer(struct mail_transaction_log_file *file,
const buffer_t *buf, const buffer_t *hdr_buf,
enum mail_transaction_type type, int external)
@@ -1028,19 +971,6 @@
return 0;
}
-static const buffer_t *get_cache_reset_buf(struct mail_index_transaction *t)
-{
- struct mail_transaction_cache_reset u;
- buffer_t *buf;
-
- memset(&u, 0, sizeof(u));
- u.new_file_seq = t->new_cache_file_seq;
-
- buf = buffer_create_static_hard(pool_datastack_create(), sizeof(u));
- buffer_append(buf, &u, sizeof(u));
- return buf;
-}
-
static const buffer_t *
log_get_hdr_update_buffer(struct mail_index_transaction *t)
{
@@ -1071,10 +1001,9 @@
return buf;
}
-static int
-mail_transaction_log_append_ext_intro(struct mail_transaction_log_file *file,
- struct mail_index_transaction *t,
- uint32_t ext_id)
+static int log_append_ext_intro(struct mail_transaction_log_file *file,
+ struct mail_index_transaction *t,
+ uint32_t ext_id, uint32_t reset_id)
{
const struct mail_index_ext *ext;
struct mail_transaction_ext_intro *intro;
@@ -1117,6 +1046,19 @@
intro->name_size = idx != (uint32_t)-1 ? 0 :
strlen(ext->name);
}
+ if (reset_id != 0) {
+ /* we're going to reset this extension in this transaction */
+ intro->reset_id = reset_id;
+ } else if (idx != (uint32_t)-1) {
+ /* use the existing reset_id */
+ const struct mail_index_ext *map_ext =
+ t->view->map->extensions->data;
+ map_ext += idx;
+
+ intro->reset_id = map_ext->reset_id;
+ } else {
+ /* new extension, reset_id defaults to 0 */
+ }
buffer_append(buf, ext->name, intro->name_size);
if ((buf->used % 4) != 0)
@@ -1131,15 +1073,18 @@
struct mail_index_transaction *t)
{
const struct mail_transaction_ext_intro *resize;
- uint32_t ext_id, ext_count, update_count, resize_count;
- buffer_t **update;
+ struct mail_transaction_ext_reset ext_reset;
+ uint32_t ext_id, ext_count, update_count, resize_count, reset_count;
+ const uint32_t *reset;
+ const buffer_t *const *update;
+ buffer_t *buf;
size_t size;
if (t->ext_rec_updates == NULL) {
update = NULL;
update_count = 0;
} else {
- update = buffer_get_modifyable_data(t->ext_rec_updates, &size);
+ update = buffer_get_data(t->ext_rec_updates, &size);
update_count = size / sizeof(*update);
}
@@ -1147,17 +1092,39 @@
resize = NULL;
resize_count = 0;
} else {
- resize = buffer_get_modifyable_data(t->ext_resizes, &size);
+ resize = buffer_get_data(t->ext_resizes, &size);
resize_count = size / sizeof(*resize);
}
- ext_count = I_MAX(update_count, resize_count);
+ if (t->ext_resets == NULL) {
+ reset = NULL;
+ reset_count = 0;
+ } else {
+ reset = buffer_get_data(t->ext_resets, &size);
+ reset_count = size / sizeof(*reset);
+ }
+
+ memset(&ext_reset, 0, sizeof(ext_reset));
+
+ buf = buffer_create_data(pool_datastack_create(),
+ &ext_reset, sizeof(ext_reset));
+ buffer_set_used_size(buf, sizeof(ext_reset));
+ ext_count = I_MAX(I_MAX(update_count, resize_count), reset_count);
for (ext_id = 0; ext_id < ext_count; ext_id++) {
+ ext_reset.new_reset_id =
+ ext_id < reset_count && reset[ext_id] != 0 ?
+ reset[ext_id] : 0;
if ((ext_id < resize_count && resize[ext_id].name_size) ||
- (ext_id < update_count && update[ext_id] != NULL)) {
- if (mail_transaction_log_append_ext_intro(file, t,
- ext_id) < 0)
+ (ext_id < update_count && update[ext_id] != NULL) ||
+ ext_reset.new_reset_id != 0) {
+ if (log_append_ext_intro(file, t, ext_id, 0) < 0)
+ return -1;
+ }
+ if (ext_reset.new_reset_id != 0) {
+ if (log_append_buffer(file, buf, NULL,
+ MAIL_TRANSACTION_EXT_RESET,
+ t->view->external) < 0)
return -1;
}
}
@@ -1165,6 +1132,48 @@
return 0;
}
+static int log_append_ext_rec_updates(struct mail_transaction_log_file *file,
+ struct mail_index_transaction *t,
+ int external)
+{
+ buffer_t **updates;
+ const uint32_t *reset;
+ uint32_t ext_id, reset_id, reset_count;
+ size_t size;
+
+ if (t->ext_rec_updates == NULL) {
+ updates = NULL;
+ size = 0;
+ } else {
+ updates = buffer_get_modifyable_data(t->ext_rec_updates, &size);
+ size /= sizeof(*updates);
+ }
+
+ if (t->ext_resets == NULL) {
+ reset = NULL;
+ reset_count = 0;
+ } else {
+ reset = buffer_get_data(t->ext_resets, &size);
+ reset_count = size / sizeof(*reset);
+ }
+
+ for (ext_id = 0; ext_id < size; ext_id++) {
+ if (updates[ext_id] == NULL)
+ continue;
+
+ reset_id = ext_id < reset_count && reset[ext_id] != 0 ?
+ reset[ext_id] : 0;
+ if (log_append_ext_intro(file, t, ext_id, reset_id) < 0)
+ return -1;
+
+ if (log_append_buffer(file, updates[ext_id], NULL,
+ MAIL_TRANSACTION_EXT_REC_UPDATE,
+ external) < 0)
+ return -1;
+ }
+ return 0;
+}
+
int mail_transaction_log_append(struct mail_index_transaction *t,
uint32_t *log_file_seq_r,
uoff_t *log_file_offset_r)
@@ -1175,9 +1184,7 @@
struct mail_transaction_log_file *file;
struct mail_index_header idx_hdr;
uoff_t append_offset;
- buffer_t **updates;
- unsigned int i, lock_id;
- size_t size;
+ unsigned int lock_id;
int ret;
index = mail_index_view_get_index(view);
@@ -1232,23 +1239,6 @@
file->first_append_size = 0;
append_offset = file->sync_offset;
- if (t->cache_updates != NULL &&
- t->last_cache_file_seq < idx_hdr.cache_file_seq) {
- /* cache_offsets point to old file, don't allow */
- buffer_free(t->cache_updates);
- t->cache_updates = NULL;
- }
-
- if (t->appends != NULL ||
- (t->cache_updates != NULL && t->new_cache_file_seq == 0) ||
- (t->ext_rec_updates != NULL && t->ext_rec_updates->used > 0)) {
- if (mail_transaction_log_scan_pending(log, t) < 0) {
- if (!log->index->log_locked)
- mail_transaction_log_file_unlock(file);
- return -1;
- }
- }
-
ret = 0;
/* send all extension introductions and resizes before appends
@@ -1265,37 +1255,9 @@
MAIL_TRANSACTION_FLAG_UPDATE,
view->external);
}
- if (t->new_cache_file_seq != 0) {
- ret = log_append_buffer(file, get_cache_reset_buf(t), NULL,
- MAIL_TRANSACTION_CACHE_RESET,
- view->external);
- }
- if (t->cache_updates != NULL && ret == 0) {
- ret = log_append_buffer(file, t->cache_updates, NULL,
- MAIL_TRANSACTION_CACHE_UPDATE,
- view->external);
- }
-
- if (t->ext_rec_updates == NULL) {
- updates = NULL;
- size = 0;
- } else {
- updates = buffer_get_modifyable_data(t->ext_rec_updates, &size);
- size /= sizeof(*updates);
- }
- for (i = 0; i < size && ret == 0; i++) {
- if (updates[i] == NULL)
- continue;
-
- ret = mail_transaction_log_append_ext_intro(file, t, i);
- if (ret < 0)
- break;
-
- ret = log_append_buffer(file, updates[i], NULL,
- MAIL_TRANSACTION_EXT_REC_UPDATE,
- view->external);
- }
+ if (t->ext_rec_updates != NULL && ret == 0)
+ ret = log_append_ext_rec_updates(file, t, view->external);
if (t->expunges != NULL && ret == 0) {
ret = log_append_buffer(file, t->expunges, NULL,
Index: mail-transaction-log.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-transaction-log.h,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- mail-transaction-log.h 17 Oct 2004 18:24:21 -0000 1.20
+++ mail-transaction-log.h 6 Nov 2004 17:20:19 -0000 1.21
@@ -16,8 +16,6 @@
MAIL_TRANSACTION_EXPUNGE = 0x00000001,
MAIL_TRANSACTION_APPEND = 0x00000002,
MAIL_TRANSACTION_FLAG_UPDATE = 0x00000004,
- MAIL_TRANSACTION_CACHE_RESET = 0x00000008,
- MAIL_TRANSACTION_CACHE_UPDATE = 0x00000010,
MAIL_TRANSACTION_HEADER_UPDATE = 0x00000020,
MAIL_TRANSACTION_EXT_INTRO = 0x00000040,
MAIL_TRANSACTION_EXT_RESET = 0x00000080,
@@ -53,15 +51,6 @@
keywords_mask_t remove_keywords;
};
-struct mail_transaction_cache_reset {
- uint32_t new_file_seq;
-};
-
-struct mail_transaction_cache_update {
- uint32_t uid;
- uint32_t cache_offset;
-};
-
struct mail_transaction_header_update {
uint16_t offset;
uint16_t size;
@@ -72,6 +61,7 @@
/* old extension: set ext_id. don't set name.
new extension: ext_id = (uint32_t)-1. give name. */
uint32_t ext_id;
+ uint32_t reset_id;
uint32_t hdr_size;
uint16_t record_size;
uint16_t record_align;
@@ -80,6 +70,10 @@
/* unsigned char name[]; */
};
+struct mail_transaction_ext_reset {
+ uint32_t new_reset_id;
+};
+
/* these are set for the last ext_intro */
struct mail_transaction_ext_hdr_update {
uint16_t offset;
Index: mail-transaction-util.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-transaction-util.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- mail-transaction-util.c 17 Oct 2004 18:24:21 -0000 1.20
+++ mail-transaction-util.c 6 Nov 2004 17:20:19 -0000 1.21
@@ -13,13 +13,10 @@
sizeof(struct mail_transaction_expunge) },
{ MAIL_TRANSACTION_FLAG_UPDATE, MAIL_INDEX_SYNC_TYPE_FLAGS,
sizeof(struct mail_transaction_flag_update) },
- { MAIL_TRANSACTION_CACHE_RESET, 0,
- sizeof(struct mail_transaction_cache_reset) },
- { MAIL_TRANSACTION_CACHE_UPDATE, 0,
- sizeof(struct mail_transaction_cache_update) },
{ MAIL_TRANSACTION_HEADER_UPDATE, 0, 1 }, /* variable size, use 1 */
{ MAIL_TRANSACTION_EXT_INTRO, 0, 1 },
- { MAIL_TRANSACTION_EXT_RESET, 0, 0 },
+ { MAIL_TRANSACTION_EXT_RESET, 0,
+ sizeof(struct mail_transaction_ext_reset) },
{ MAIL_TRANSACTION_EXT_HDR_UPDATE, 0, 1 },
{ MAIL_TRANSACTION_EXT_REC_UPDATE, 0, 1 },
{ 0, 0, 0 }
More information about the dovecot-cvs
mailing list