dovecot: Prevent copying record data when appending new messages.
dovecot at dovecot.org
dovecot at dovecot.org
Mon Aug 6 15:43:53 EEST 2007
details: http://hg.dovecot.org/dovecot/rev/606f3d9f2769
changeset: 6167:606f3d9f2769
user: Timo Sirainen <tss at iki.fi>
date: Mon Aug 06 15:43:46 2007 +0300
description:
Prevent copying record data when appending new messages.
diffstat:
5 files changed, 70 insertions(+), 46 deletions(-)
src/lib-index/mail-index-map.c | 43 ++++++++++++++-----
src/lib-index/mail-index-private.h | 3 +
src/lib-index/mail-index-sync-private.h | 1
src/lib-index/mail-index-sync-update.c | 67 ++++++++++++++++---------------
src/lib-index/mail-index-view-sync.c | 2
diffs (271 lines):
diff -r 004534216202 -r 606f3d9f2769 src/lib-index/mail-index-map.c
--- a/src/lib-index/mail-index-map.c Fri Aug 03 03:25:13 2007 +0300
+++ b/src/lib-index/mail-index-map.c Mon Aug 06 15:43:46 2007 +0300
@@ -845,11 +845,6 @@ static void mail_index_map_copy_records(
{
size_t size;
- if (src == NULL) {
- dest->buffer = buffer_create_dynamic(default_pool, 1024);
- return;
- }
-
size = src->records_count * record_size;
dest->buffer = buffer_create_dynamic(default_pool, I_MIN(size, 1024));
buffer_append(dest->buffer, src->records, size);
@@ -878,9 +873,12 @@ static void mail_index_map_copy_header(s
}
buffer_append(dest->hdr_copy_buf, &dest->hdr,
I_MIN(sizeof(dest->hdr), src->hdr.base_header_size));
- buffer_write(dest->hdr_copy_buf, src->hdr.base_header_size,
- CONST_PTR_OFFSET(src->hdr_base, src->hdr.base_header_size),
- src->hdr.header_size - src->hdr.base_header_size);
+ if (src != dest) {
+ buffer_write(dest->hdr_copy_buf, src->hdr.base_header_size,
+ CONST_PTR_OFFSET(src->hdr_base,
+ src->hdr.base_header_size),
+ src->hdr.header_size - src->hdr.base_header_size);
+ }
dest->hdr_base = buffer_get_modifiable_data(dest->hdr_copy_buf, NULL);
}
@@ -904,10 +902,15 @@ struct mail_index_map *mail_index_map_cl
mem_map = i_new(struct mail_index_map, 1);
mem_map->index = map->index;
mem_map->refcount = 1;
- mem_map->rec_map = mail_index_record_map_alloc(mem_map);
-
- mail_index_map_copy_records(mem_map->rec_map, map->rec_map,
- map->hdr.record_size);
+ if (map->rec_map == NULL) {
+ mem_map->rec_map = mail_index_record_map_alloc(mem_map);
+ mem_map->rec_map->buffer =
+ buffer_create_dynamic(default_pool, 1024);
+ } else {
+ mem_map->rec_map = map->rec_map;
+ array_append(&mem_map->rec_map->maps, &mem_map, 1);
+ }
+
mail_index_map_copy_header(mem_map, map);
mem_map->write_atomic = map->write_atomic;
@@ -936,6 +939,22 @@ struct mail_index_map *mail_index_map_cl
return mem_map;
}
+void mail_index_record_map_move_to_private(struct mail_index_map *map)
+{
+ struct mail_index_record_map *new_map;
+
+ if (array_count(&map->rec_map->maps) == 1)
+ return;
+
+ new_map = mail_index_record_map_alloc(map);
+ mail_index_map_copy_records(new_map, map->rec_map,
+ map->hdr.record_size);
+
+ mail_index_map_unlock(map);
+ mail_index_record_map_unlink(map);
+ map->rec_map = new_map;
+}
+
void mail_index_map_move_to_memory(struct mail_index_map *map)
{
struct mail_index_record_map *new_map;
diff -r 004534216202 -r 606f3d9f2769 src/lib-index/mail-index-private.h
--- a/src/lib-index/mail-index-private.h Fri Aug 03 03:25:13 2007 +0300
+++ b/src/lib-index/mail-index-private.h Mon Aug 06 15:43:46 2007 +0300
@@ -115,6 +115,8 @@ struct mail_index_record_map {
void *records; /* struct mail_index_record[] */
unsigned int records_count;
+
+ uint32_t last_appended_uid;
/* If this mapping is written to disk and write_atomic=FALSE,
write_seq_* specify the message sequence range that needs to be
@@ -277,6 +279,7 @@ void mail_index_map_unlock(struct mail_i
/* Clone a map. The returned map is always in memory. */
struct mail_index_map *mail_index_map_clone(const struct mail_index_map *map);
+void mail_index_record_map_move_to_private(struct mail_index_map *map);
/* Move a mmaped map to memory. */
void mail_index_map_move_to_memory(struct mail_index_map *map);
diff -r 004534216202 -r 606f3d9f2769 src/lib-index/mail-index-sync-private.h
--- a/src/lib-index/mail-index-sync-private.h Fri Aug 03 03:25:13 2007 +0300
+++ b/src/lib-index/mail-index-sync-private.h Mon Aug 06 15:43:46 2007 +0300
@@ -54,7 +54,6 @@ int mail_index_sync_record(struct mail_i
const struct mail_transaction_header *hdr,
const void *data);
-void mail_index_sync_move_to_private(struct mail_index_sync_map_ctx *ctx);
struct mail_index_map *
mail_index_sync_get_atomic_map(struct mail_index_sync_map_ctx *ctx);
void mail_index_sync_write_seq_update(struct mail_index_sync_map_ctx *ctx,
diff -r 004534216202 -r 606f3d9f2769 src/lib-index/mail-index-sync-update.c
--- a/src/lib-index/mail-index-sync-update.c Fri Aug 03 03:25:13 2007 +0300
+++ b/src/lib-index/mail-index-sync-update.c Mon Aug 06 15:43:46 2007 +0300
@@ -59,7 +59,8 @@ static void mail_index_sync_replace_map(
view->index->map = map;
}
-void mail_index_sync_move_to_private(struct mail_index_sync_map_ctx *ctx)
+static void
+mail_index_sync_move_to_private_memory(struct mail_index_sync_map_ctx *ctx)
{
struct mail_index_map *map = ctx->view->map;
@@ -70,12 +71,6 @@ void mail_index_sync_move_to_private(str
map = mail_index_map_clone(map);
mail_index_sync_replace_map(ctx, map);
}
-}
-
-static void
-mail_index_sync_move_to_private_memory(struct mail_index_sync_map_ctx *ctx)
-{
- mail_index_sync_move_to_private(ctx);
if (!MAIL_INDEX_MAP_IS_IN_MEMORY(ctx->view->map))
mail_index_map_move_to_memory(ctx->view->map);
@@ -85,6 +80,7 @@ mail_index_sync_get_atomic_map(struct ma
mail_index_sync_get_atomic_map(struct mail_index_sync_map_ctx *ctx)
{
mail_index_sync_move_to_private_memory(ctx);
+ mail_index_record_map_move_to_private(ctx->view->map);
ctx->view->map->write_atomic = TRUE;
return ctx->view->map;
}
@@ -137,6 +133,7 @@ mail_index_header_update_counts(struct m
static void
mail_index_sync_header_update_counts_all(struct mail_index_sync_map_ctx *ctx,
+ uint32_t uid,
uint8_t old_flags, uint8_t new_flags)
{
struct mail_index_map *const *maps;
@@ -145,6 +142,9 @@ mail_index_sync_header_update_counts_all
maps = array_get(&ctx->view->map->rec_map->maps, &count);
for (i = 0; i < count; i++) {
+ if (uid >= maps[i]->hdr.next_uid)
+ continue;
+
if (mail_index_header_update_counts(&maps[i]->hdr,
old_flags, new_flags,
&error) < 0)
@@ -154,15 +154,16 @@ mail_index_sync_header_update_counts_all
static void
mail_index_sync_header_update_counts(struct mail_index_sync_map_ctx *ctx,
- uint8_t old_flags, uint8_t new_flags,
- bool all)
+ uint32_t uid, uint8_t old_flags,
+ uint8_t new_flags, bool all)
{
const char *error;
if (all) {
- mail_index_sync_header_update_counts_all(ctx, old_flags,
+ mail_index_sync_header_update_counts_all(ctx, uid, old_flags,
new_flags);
} else {
+ i_assert(uid < ctx->view->map->hdr.next_uid);
if (mail_index_header_update_counts(&ctx->view->map->hdr,
old_flags, new_flags,
&error) < 0)
@@ -240,7 +241,7 @@ sync_expunge(const struct mail_transacti
map = mail_index_sync_get_atomic_map(ctx);
for (seq = seq1; seq <= seq2; seq++) {
rec = MAIL_INDEX_MAP_IDX(map, seq-1);
- mail_index_sync_header_update_counts(ctx,
+ mail_index_sync_header_update_counts(ctx, rec->uid,
rec->flags, 0,
FALSE);
}
@@ -294,30 +295,36 @@ static int sync_append(const struct mail
mail_index_sync_move_to_private_memory(ctx);
map = view->map;
- /* don't rely on buffer->used being at the correct position.
- at least expunges can move it */
- append_pos = map->rec_map->records_count * map->hdr.record_size;
- dest = buffer_get_space_unsafe(map->rec_map->buffer, append_pos,
- map->hdr.record_size);
- map->rec_map->records =
- buffer_get_modifiable_data(map->rec_map->buffer, NULL);
-
- memcpy(dest, rec, sizeof(*rec));
- memset(PTR_OFFSET(dest, sizeof(*rec)), 0,
- map->hdr.record_size - sizeof(*rec));
+ if (rec->uid <= map->rec_map->last_appended_uid) {
+ i_assert(map->hdr.messages_count < map->rec_map->records_count);
+ } else {
+ /* don't rely on buffer->used being at the correct position.
+ at least expunges can move it */
+ append_pos = map->rec_map->records_count * map->hdr.record_size;
+ dest = buffer_get_space_unsafe(map->rec_map->buffer, append_pos,
+ map->hdr.record_size);
+ map->rec_map->records =
+ buffer_get_modifiable_data(map->rec_map->buffer, NULL);
+
+ memcpy(dest, rec, sizeof(*rec));
+ memset(PTR_OFFSET(dest, sizeof(*rec)), 0,
+ map->hdr.record_size - sizeof(*rec));
+ map->rec_map->records_count++;
+ map->rec_map->last_appended_uid = rec->uid;
+
+ mail_index_sync_write_seq_update(ctx, map->hdr.messages_count,
+ map->hdr.messages_count);
+ }
map->hdr.messages_count++;
map->hdr.next_uid = rec->uid+1;
- map->rec_map->records_count++;
-
- mail_index_sync_write_seq_update(ctx, map->hdr.messages_count,
- map->hdr.messages_count);
if ((rec->flags & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0)
map->hdr.flags |= MAIL_INDEX_HDR_FLAG_HAVE_DIRTY;
mail_index_header_update_lowwaters(ctx, rec);
- mail_index_sync_header_update_counts(ctx, 0, rec->flags, FALSE);
+ mail_index_sync_header_update_counts(ctx, rec->uid,
+ 0, rec->flags, FALSE);
return 1;
}
@@ -358,7 +365,8 @@ static int sync_flag_update(const struct
rec->flags = (rec->flags & flag_mask) | u->add_flags;
mail_index_header_update_lowwaters(ctx, rec);
- mail_index_sync_header_update_counts(ctx, old_flags,
+ mail_index_sync_header_update_counts(ctx, rec->uid,
+ old_flags,
rec->flags, TRUE);
}
}
@@ -585,9 +593,6 @@ int mail_index_sync_record(struct mail_i
i_unreached();
}
t_pop();
-
- i_assert(ctx->view->map->rec_map->records_count ==
- ctx->view->map->hdr.messages_count);
return ret;
}
diff -r 004534216202 -r 606f3d9f2769 src/lib-index/mail-index-view-sync.c
--- a/src/lib-index/mail-index-view-sync.c Fri Aug 03 03:25:13 2007 +0300
+++ b/src/lib-index/mail-index-view-sync.c Mon Aug 06 15:43:46 2007 +0300
@@ -324,8 +324,6 @@ int mail_index_view_sync_begin(struct ma
} else {
map = view->map;
}
- i_assert(map->rec_map->records_count ==
- map->hdr.messages_count);
}
#ifdef DEBUG
More information about the dovecot-cvs
mailing list