dovecot-1.1: Added mail_index_ext_reset_inc() to atomically incr...
dovecot at dovecot.org
dovecot at dovecot.org
Thu May 29 06:37:15 EEST 2008
details: http://hg.dovecot.org/dovecot-1.1/rev/6de1aed24ce5
changeset: 7563:6de1aed24ce5
user: Timo Sirainen <tss at iki.fi>
date: Thu May 29 04:47:53 2008 +0300
description:
Added mail_index_ext_reset_inc() to atomically increase extension's
reset_id. Added clear_data parameter to mail_index_ext_reset*().
diffstat:
9 files changed, 157 insertions(+), 50 deletions(-)
src/lib-index/mail-cache-compress.c | 2
src/lib-index/mail-index-sync-ext.c | 55 +++++++++--------
src/lib-index/mail-index-sync-update.c | 13 ++--
src/lib-index/mail-index-transaction-private.h | 3
src/lib-index/mail-index-transaction.c | 34 ++++++++--
src/lib-index/mail-index.h | 21 ++++--
src/lib-index/mail-transaction-log-append.c | 75 ++++++++++++++++++++++--
src/lib-index/mail-transaction-log.h | 2
src/lib-storage/index/dbox/dbox-sync-rebuild.c | 2
diffs (truncated from 378 to 300 lines):
diff -r 4c702defc245 -r 6de1aed24ce5 src/lib-index/mail-cache-compress.c
--- a/src/lib-index/mail-cache-compress.c Wed May 28 19:03:42 2008 +0300
+++ b/src/lib-index/mail-cache-compress.c Thu May 29 04:47:53 2008 +0300
@@ -414,7 +414,7 @@ static int mail_cache_compress_locked(st
/* once we're sure that the compression was successful,
update the offsets */
- mail_index_ext_reset(trans, cache->ext_id, file_seq);
+ mail_index_ext_reset(trans, cache->ext_id, file_seq, TRUE);
offsets = array_get(&ext_offsets, &count);
for (i = 0; i < count; i++) {
if (offsets[i] != 0) {
diff -r 4c702defc245 -r 6de1aed24ce5 src/lib-index/mail-index-sync-ext.c
--- a/src/lib-index/mail-index-sync-ext.c Wed May 28 19:03:42 2008 +0300
+++ b/src/lib-index/mail-index-sync-ext.c Thu May 29 04:47:53 2008 +0300
@@ -424,7 +424,8 @@ int mail_index_sync_ext_intro(struct mai
ctx->cur_ext_ignore = FALSE;
} else {
/* extension was reset and this transaction hadn't
- yet seen it. ignore this update. */
+ yet seen it. ignore this update (except for
+ resets). */
ctx->cur_ext_ignore = TRUE;
}
@@ -476,30 +477,12 @@ int mail_index_sync_ext_intro(struct mai
return 1;
}
-int mail_index_sync_ext_reset(struct mail_index_sync_map_ctx *ctx,
- const struct mail_transaction_ext_reset *u)
-{
- struct mail_index_view *view = ctx->view;
- struct mail_index_map *map = view->map;
- struct mail_index_ext_header *ext_hdr;
- struct mail_index_ext *ext;
+static void mail_index_sync_ext_clear(struct mail_index_view *view,
+ struct mail_index_map *map,
+ struct mail_index_ext *ext)
+{
struct mail_index_record *rec;
uint32_t i;
-
- if (ctx->cur_ext_map_idx == (uint32_t)-1) {
- mail_index_sync_set_corrupted(ctx,
- "Extension reset without intro prefix");
- return -1;
- }
- if (ctx->cur_ext_ignore)
- return 1;
-
- /* a new index file will be created, so the old data won't be
- accidentally used by other processes. */
- map = mail_index_sync_get_atomic_map(ctx);
-
- ext = array_idx_modifiable(&map->extensions, ctx->cur_ext_map_idx);
- 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);
@@ -512,10 +495,34 @@ int mail_index_sync_ext_reset(struct mai
}
map->rec_map->write_seq_first = 1;
map->rec_map->write_seq_last = view->map->rec_map->records_count;
+}
+
+int mail_index_sync_ext_reset(struct mail_index_sync_map_ctx *ctx,
+ const struct mail_transaction_ext_reset *u)
+{
+ struct mail_index_map *map = ctx->view->map;
+ struct mail_index_ext_header *ext_hdr;
+ struct mail_index_ext *ext;
+
+ if (ctx->cur_ext_map_idx == (uint32_t)-1) {
+ mail_index_sync_set_corrupted(ctx,
+ "Extension reset without intro prefix");
+ return -1;
+ }
+ /* since we're resetting the extension, don't check cur_ext_ignore */
+
+ /* a new index file will be created, so the old data won't be
+ accidentally used by other processes. */
+ map = mail_index_sync_get_atomic_map(ctx);
+
+ ext = array_idx_modifiable(&map->extensions, ctx->cur_ext_map_idx);
+ ext->reset_id = u->new_reset_id;
+
+ if (!u->preserve_data)
+ mail_index_sync_ext_clear(ctx->view, map, ext);
ext_hdr = get_ext_header(map, ext);
ext_hdr->reset_id = u->new_reset_id;
-
return 1;
}
diff -r 4c702defc245 -r 6de1aed24ce5 src/lib-index/mail-index-sync-update.c
--- a/src/lib-index/mail-index-sync-update.c Wed May 28 19:03:42 2008 +0300
+++ b/src/lib-index/mail-index-sync-update.c Thu May 29 04:47:53 2008 +0300
@@ -532,15 +532,17 @@ int mail_index_sync_record(struct mail_i
break;
}
case MAIL_TRANSACTION_EXT_RESET: {
- const struct mail_transaction_ext_reset *rec = data;
-
- if (hdr->size != sizeof(*rec)) {
+ struct mail_transaction_ext_reset rec;
+
+ /* old versions have only new_reset_id */
+ if (hdr->size < sizeof(uint32_t)) {
mail_index_sync_set_corrupted(ctx,
"ext reset: invalid record size");
ret = -1;
break;
}
- ret = mail_index_sync_ext_reset(ctx, rec);
+ memcpy(&rec, data, I_MIN(hdr->size, sizeof(rec)));
+ ret = mail_index_sync_ext_reset(ctx, &rec);
break;
}
case MAIL_TRANSACTION_EXT_HDR_UPDATE: {
@@ -781,6 +783,9 @@ int mail_index_sync_map(struct mail_inde
map->hdr_base = map->hdr_copy_buf->data;
}
+ mail_transaction_log_view_get_prev_pos(view->log_view,
+ &prev_seq, &prev_offset);
+
mail_index_sync_map_init(&sync_map_ctx, view, type);
if (reset) {
/* Reset the entire index. Leave only indexid and
diff -r 4c702defc245 -r 6de1aed24ce5 src/lib-index/mail-index-transaction-private.h
--- a/src/lib-index/mail-index-transaction-private.h Wed May 28 19:03:42 2008 +0300
+++ b/src/lib-index/mail-index-transaction-private.h Thu May 29 04:47:53 2008 +0300
@@ -51,8 +51,9 @@ struct mail_index_transaction {
struct mail_index_transaction_ext_hdr_update *);
ARRAY_DEFINE(ext_rec_updates, ARRAY_TYPE(seq_array));
ARRAY_DEFINE(ext_resizes, struct mail_transaction_ext_intro);
- ARRAY_DEFINE(ext_resets, uint32_t);
+ ARRAY_DEFINE(ext_resets, struct mail_transaction_ext_reset);
ARRAY_DEFINE(ext_reset_ids, uint32_t);
+ ARRAY_DEFINE(ext_reset_atomic, uint32_t);
ARRAY_DEFINE(keyword_updates,
struct mail_index_transaction_keyword_update);
diff -r 4c702defc245 -r 6de1aed24ce5 src/lib-index/mail-index-transaction.c
--- a/src/lib-index/mail-index-transaction.c Wed May 28 19:03:42 2008 +0300
+++ b/src/lib-index/mail-index-transaction.c Thu May 29 04:47:53 2008 +0300
@@ -75,6 +75,8 @@ void mail_index_transaction_reset(struct
array_free(&t->ext_resets);
if (array_is_created(&t->ext_reset_ids))
array_free(&t->ext_reset_ids);
+ if (array_is_created(&t->ext_reset_atomic))
+ array_free(&t->ext_reset_atomic);
t->first_new_seq = mail_index_view_get_messages_count(t->view)+1;
t->last_new_seq = 0;
@@ -1087,16 +1089,34 @@ void mail_index_ext_resize(struct mail_i
}
void mail_index_ext_reset(struct mail_index_transaction *t, uint32_t ext_id,
- uint32_t reset_id)
-{
+ uint32_t reset_id, bool clear_data)
+{
+ struct mail_transaction_ext_reset reset;
+
i_assert(reset_id != 0);
+
+ memset(&reset, 0, sizeof(reset));
+ reset.new_reset_id = reset_id;
+ reset.preserve_data = !clear_data;
mail_index_ext_set_reset_id(t, ext_id, reset_id);
if (!array_is_created(&t->ext_resets))
i_array_init(&t->ext_resets, ext_id + 2);
- array_idx_set(&t->ext_resets, ext_id, &reset_id);
+ array_idx_set(&t->ext_resets, ext_id, &reset);
t->log_ext_updates = TRUE;
+}
+
+void mail_index_ext_reset_inc(struct mail_index_transaction *t, uint32_t ext_id,
+ uint32_t prev_reset_id, bool clear_data)
+{
+ uint32_t expected_reset_id = prev_reset_id + 1;
+
+ mail_index_ext_reset(t, ext_id, (uint32_t)-1, clear_data);
+
+ if (!array_is_created(&t->ext_reset_atomic))
+ i_array_init(&t->ext_reset_atomic, ext_id + 2);
+ array_idx_set(&t->ext_reset_atomic, ext_id, &expected_reset_id);
}
static bool
@@ -1123,11 +1143,11 @@ mail_index_transaction_has_ext_changes(s
}
}
if (array_is_created(&t->ext_resets)) {
- const uint32_t *ids;
-
- ids = array_get(&t->ext_resets, &count);
+ const struct mail_transaction_ext_reset *resets;
+
+ resets = array_get(&t->ext_resets, &count);
for (i = 0; i < count; i++) {
- if (ids[i] != 0)
+ if (resets[i].new_reset_id != 0)
return TRUE;
}
}
diff -r 4c702defc245 -r 6de1aed24ce5 src/lib-index/mail-index.h
--- a/src/lib-index/mail-index.h Wed May 28 19:03:42 2008 +0300
+++ b/src/lib-index/mail-index.h Thu May 29 04:47:53 2008 +0300
@@ -428,14 +428,21 @@ void mail_index_ext_resize(struct mail_i
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. */
+/* Reset extension. 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. If clear_data=TRUE, records and
+ header is zeroed. */
void mail_index_ext_reset(struct mail_index_transaction *t, uint32_t ext_id,
- uint32_t reset_id);
-/* Discard existing extension updates and write new updates using the given
- reset_id. The difference to mail_index_ext_reset() is that this doesn't
- clear any existing record or header data. */
+ uint32_t reset_id, bool clear_data);
+/* Like mail_index_ext_reset(), but increase extension's reset_id atomically
+ when the transaction is being committed. If prev_reset_id doesn't match the
+ latest reset_id, the reset_id isn't increased and all extension changes are
+ ignored. */
+void mail_index_ext_reset_inc(struct mail_index_transaction *t, uint32_t ext_id,
+ uint32_t prev_reset_id, bool clear_data);
+/* Discard existing extension updates in this transaction and write new updates
+ using the given reset_id. The difference to mail_index_ext_reset() is that
+ this doesn't clear any existing record or header data. */
void mail_index_ext_set_reset_id(struct mail_index_transaction *t,
uint32_t ext_id, uint32_t reset_id);
/* Get the current reset_id for given extension. Returns TRUE if it exists. */
diff -r 4c702defc245 -r 6de1aed24ce5 src/lib-index/mail-transaction-log-append.c
--- a/src/lib-index/mail-transaction-log-append.c Wed May 28 19:03:42 2008 +0300
+++ b/src/lib-index/mail-transaction-log-append.c Thu May 29 04:47:53 2008 +0300
@@ -166,6 +166,58 @@ log_get_hdr_update_buffer(struct mail_in
return buf;
}
+static void
+ext_reset_update_atomic(struct mail_index_transaction *t,
+ uint32_t ext_id, uint32_t expected_reset_id)
+{
+ const struct mail_index_ext *map_ext;
+ struct mail_transaction_ext_reset *reset;
+ uint32_t idx, reset_id;
+
+ if (!mail_index_map_get_ext_idx(t->view->index->map, ext_id, &idx)) {
+ /* new extension */
+ reset_id = 1;
+ } else {
+ map_ext = array_idx(&t->view->index->map->extensions, idx);
+ reset_id = map_ext->reset_id + 1;
+ }
+ if (reset_id != expected_reset_id) {
+ /* ignore this extension update */
+ mail_index_ext_set_reset_id(t, ext_id, 0);
+ return;
+ }
+
+ if (reset_id == 0)
+ reset_id++;
+
+ array_idx_set(&t->ext_reset_ids, ext_id, &reset_id);
+
+ /* reseting existing data is optional */
+ if (array_is_created(&t->ext_resets)) {
+ reset = array_idx_modifiable(&t->ext_resets, ext_id);
+ if (reset->new_reset_id == (uint32_t)-1)
+ reset->new_reset_id = reset_id;
+ }
+}
+
+static void
+transaction_update_atomic_reset_ids(struct mail_index_transaction *t)
+{
+ const uint32_t *expected_reset_ids;
+ unsigned int ext_id, count;
+
+ if (!array_is_created(&t->ext_reset_atomic))
+ return;
+
+ expected_reset_ids = array_get(&t->ext_reset_atomic, &count);
+ for (ext_id = 0; ext_id < count; ext_id++) {
+ if (expected_reset_ids[ext_id] != 0) {
+ ext_reset_update_atomic(t, ext_id,
+ expected_reset_ids[ext_id]);
+ }
+ }
More information about the dovecot-cvs
mailing list