[dovecot-cvs] dovecot: When compressing cache file, update the cache file offs...
dovecot at dovecot.org
dovecot at dovecot.org
Tue May 22 21:46:11 EEST 2007
details: http://hg.dovecot.org/dovecot/rev/9404d2c41cb2
changeset: 5652:9404d2c41cb2
user: Timo Sirainen <tss at iki.fi>
date: Tue May 22 21:46:07 2007 +0300
description:
When compressing cache file, update the cache file offsets using the
existing sync transaction.
diffstat:
3 files changed, 73 insertions(+), 46 deletions(-)
src/lib-index/mail-cache-compress.c | 95 +++++++++++++++++++++++------------
src/lib-index/mail-cache.h | 5 +
src/lib-index/mail-index-sync.c | 19 ++-----
diffs (264 lines):
diff -r aff5fb7bb580 -r 9404d2c41cb2 src/lib-index/mail-cache-compress.c
--- a/src/lib-index/mail-cache-compress.c Tue May 22 21:32:10 2007 +0300
+++ b/src/lib-index/mail-cache-compress.c Tue May 22 21:46:07 2007 +0300
@@ -1,7 +1,7 @@
/* Copyright (C) 2003-2004 Timo Sirainen */
#include "lib.h"
-#include "buffer.h"
+#include "array.h"
#include "ostream.h"
#include "nfs-workarounds.h"
#include "read-full.h"
@@ -13,6 +13,8 @@
#include <sys/stat.h>
+ARRAY_DEFINE_TYPE(ext_offset, uint32_t);
+
struct mail_cache_copy_context {
bool new_msg;
buffer_t *buffer, *field_seen;
@@ -113,18 +115,21 @@ get_next_file_seq(struct mail_cache *cac
}
static int
-mail_cache_copy(struct mail_cache *cache, struct mail_index_view *view, int fd)
+mail_cache_copy(struct mail_cache *cache, struct mail_index_transaction *trans,
+ int fd, uint32_t *file_seq_r,
+ ARRAY_TYPE(ext_offset) *ext_offsets)
{
struct mail_cache_copy_context ctx;
+ struct mail_index_view *view;
struct mail_cache_view *cache_view;
- struct mail_index_transaction *t;
const struct mail_index_header *idx_hdr;
struct mail_cache_header hdr;
struct mail_cache_record cache_rec;
struct ostream *output;
buffer_t *buffer;
- uint32_t i, message_count, seq, first_new_seq, old_offset;
- uoff_t offset;
+ uint32_t i, message_count, seq, first_new_seq, ext_offset;
+
+ view = mail_index_transaction_get_view(trans);
/* get sequence of first message which doesn't need its temp fields
removed. */
@@ -142,7 +147,6 @@ mail_cache_copy(struct mail_cache *cache
}
cache_view = mail_cache_view_open(cache, view);
- t = mail_index_transaction_begin(view, FALSE, TRUE);
output = o_stream_create_file(fd, default_pool, 0, FALSE);
memset(&hdr, 0, sizeof(hdr));
@@ -157,9 +161,13 @@ mail_cache_copy(struct mail_cache *cache
ctx.field_seen = buffer_create_dynamic(default_pool, 64);
ctx.field_seen_value = 0;
- mail_index_ext_reset(t, cache->ext_id, hdr.file_seq);
-
+ t_array_init(ext_offsets, message_count);
for (seq = 1; seq <= message_count; seq++) {
+ if (mail_index_transaction_is_expunged(trans, seq)) {
+ (void)array_append_space(ext_offsets);
+ continue;
+ }
+
ctx.new_msg = seq >= first_new_seq;
buffer_set_used_size(ctx.buffer, 0);
@@ -176,15 +184,19 @@ mail_cache_copy(struct mail_cache *cache
mail_cache_compress_callback, &ctx);
cache_rec.size = buffer_get_used_size(ctx.buffer);
- if (cache_rec.size == sizeof(cache_rec))
- continue;
-
- 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, ctx.buffer->data, cache_rec.size);
- }
+ if (cache_rec.size == sizeof(cache_rec)) {
+ /* nothing cached */
+ ext_offset = 0;
+ } else {
+ ext_offset = output->offset;
+ buffer_write(ctx.buffer, 0, &cache_rec,
+ sizeof(cache_rec));
+ o_stream_send(output, ctx.buffer->data, cache_rec.size);
+ }
+
+ array_append(ext_offsets, &ext_offset, 1);
+ }
+ i_assert(array_count(ext_offsets) == message_count);
if (cache->fields_count != 0) {
hdr.field_header_offset =
@@ -217,7 +229,6 @@ mail_cache_copy(struct mail_cache *cache
if (o_stream_flush(output) < 0) {
errno = output->stream_errno;
mail_cache_set_syscall_error(cache, "o_stream_flush()");
- (void)mail_index_transaction_rollback(&t);
o_stream_destroy(&output);
return -1;
}
@@ -232,12 +243,12 @@ mail_cache_copy(struct mail_cache *cache
if (!cache->index->fsync_disable) {
if (fdatasync(fd) < 0) {
mail_cache_set_syscall_error(cache, "fdatasync()");
- (void)mail_index_transaction_rollback(&t);
- return -1;
- }
- }
-
- return mail_index_transaction_commit(&t, &seq, &offset);
+ return -1;
+ }
+ }
+
+ *file_seq_r = hdr.file_seq;
+ return 0;
}
static int mail_cache_compress_has_file_changed(struct mail_cache *cache)
@@ -275,11 +286,15 @@ static int mail_cache_compress_has_file_
}
static int mail_cache_compress_locked(struct mail_cache *cache,
- struct mail_index_view *view,
+ struct mail_index_transaction *trans,
bool *unlock)
{
struct dotlock *dotlock;
mode_t old_mask;
+ uint32_t file_seq, old_offset;
+ ARRAY_TYPE(ext_offset) ext_offsets;
+ const uint32_t *offsets;
+ unsigned int i, count;
int fd, ret;
/* get the latest info on fields */
@@ -319,8 +334,10 @@ static int mail_cache_compress_locked(st
return -1;
}
- if (mail_cache_copy(cache, view, fd) < 0) {
+ t_push();
+ if (mail_cache_copy(cache, trans, fd, &file_seq, &ext_offsets) < 0) {
(void)file_dotlock_delete(&dotlock);
+ t_pop();
return -1;
}
@@ -329,8 +346,21 @@ static int mail_cache_compress_locked(st
mail_cache_set_syscall_error(cache,
"file_dotlock_replace()");
(void)close(fd);
- return -1;
- }
+ t_pop();
+ return -1;
+ }
+
+ /* once we're sure that the compression was successful,
+ update the offsets */
+ mail_index_ext_reset(trans, cache->ext_id, file_seq);
+ offsets = array_get(&ext_offsets, &count);
+ for (i = 0; i < count; i++) {
+ if (offsets[i] != 0) {
+ mail_index_update_ext(trans, i + 1, cache->ext_id,
+ &offsets[i], &old_offset);
+ }
+ }
+ t_pop();
if (*unlock) {
(void)mail_cache_unlock(cache);
@@ -352,7 +382,8 @@ static int mail_cache_compress_locked(st
return 0;
}
-int mail_cache_compress(struct mail_cache *cache, struct mail_index_view *view)
+int mail_cache_compress(struct mail_cache *cache,
+ struct mail_index_transaction *trans)
{
bool unlock = FALSE;
int ret;
@@ -363,7 +394,7 @@ int mail_cache_compress(struct mail_cach
if (cache->index->lock_method == FILE_LOCK_METHOD_DOTLOCK) {
/* we're using dotlocking, cache file creation itself creates
the dotlock file we need. */
- return mail_cache_compress_locked(cache, view, &unlock);
+ return mail_cache_compress_locked(cache, trans, &unlock);
}
switch (mail_cache_lock(cache)) {
@@ -372,11 +403,11 @@ int mail_cache_compress(struct mail_cach
case 0:
/* couldn't lock, either it's broken or doesn't exist.
just start creating it. */
- return mail_cache_compress_locked(cache, view, &unlock);
+ return mail_cache_compress_locked(cache, trans, &unlock);
default:
/* locking succeeded. */
unlock = TRUE;
- ret = mail_cache_compress_locked(cache, view, &unlock);
+ ret = mail_cache_compress_locked(cache, trans, &unlock);
if (unlock) {
if (mail_cache_unlock(cache) < 0)
ret = -1;
diff -r aff5fb7bb580 -r 9404d2c41cb2 src/lib-index/mail-cache.h
--- a/src/lib-index/mail-cache.h Tue May 22 21:32:10 2007 +0300
+++ b/src/lib-index/mail-cache.h Tue May 22 21:46:07 2007 +0300
@@ -58,8 +58,9 @@ mail_cache_register_get_list(struct mail
/* Returns TRUE if cache should be compressed. */
bool mail_cache_need_compress(struct mail_cache *cache);
-/* Compress cache file. */
-int mail_cache_compress(struct mail_cache *cache, struct mail_index_view *view);
+/* Compress cache file. Offsets are updated to given transaction. */
+int mail_cache_compress(struct mail_cache *cache,
+ struct mail_index_transaction *trans);
struct mail_cache_view *
mail_cache_view_open(struct mail_cache *cache, struct mail_index_view *iview);
diff -r aff5fb7bb580 -r 9404d2c41cb2 src/lib-index/mail-index-sync.c
--- a/src/lib-index/mail-index-sync.c Tue May 22 21:32:10 2007 +0300
+++ b/src/lib-index/mail-index-sync.c Tue May 22 21:46:07 2007 +0300
@@ -654,6 +654,13 @@ int mail_index_sync_commit(struct mail_i
uoff_t offset;
int ret = 0;
+ if (mail_cache_need_compress(index->cache)) {
+ /* if cache compression fails, we don't really care.
+ the cache offsets are updated only if the compression was
+ successful. */
+ (void)mail_cache_compress(index->cache, ctx->ext_trans);
+ }
+
if (mail_index_transaction_commit(&ctx->ext_trans, &seq, &offset) < 0)
ret = -1;
@@ -679,18 +686,6 @@ int mail_index_sync_commit(struct mail_i
ret = -1;
}
- if (ret == 0 && mail_cache_need_compress(index->cache)) {
- /* if cache compression fails, we don't really care */
- if (mail_cache_compress(index->cache, ctx->view) == 0) {
- /* cache_offsets have changed, sync them */
- if (mail_index_sync_set_log_view(ctx->view,
- seq, offset) < 0)
- ret = -1;
- else if (mail_index_sync_update_index(ctx, FALSE) < 0)
- ret = -1;
- }
- }
-
if (ret == 0) {
index->sync_log_file_seq = index->map->hdr.log_file_seq;
index->sync_log_file_offset =
More information about the dovecot-cvs
mailing list