dovecot-2.0-sslstream: dsync: If some uid/modseq changes couldn'...
dovecot at dovecot.org
dovecot at dovecot.org
Sat Feb 13 02:56:35 EET 2010
details: http://hg.dovecot.org/dovecot-2.0-sslstream/rev/9f2e8d230bd5
changeset: 10369:9f2e8d230bd5
user: Timo Sirainen <tss at iki.fi>
date: Wed Nov 18 19:58:37 2009 -0500
description:
dsync: If some uid/modseq changes couldn't be done, exit with different value.
diffstat:
9 files changed, 111 insertions(+), 27 deletions(-)
src/dsync/dsync-brain.c | 6 ++
src/dsync/dsync-brain.h | 2
src/dsync/dsync-proxy-client.c | 14 +++++-
src/dsync/dsync-proxy-server-cmd.c | 10 ++++
src/dsync/dsync-worker-local.c | 76 +++++++++++++++++++++++++++---------
src/dsync/dsync-worker-private.h | 1
src/dsync/dsync-worker.c | 5 ++
src/dsync/dsync-worker.h | 3 +
src/dsync/dsync.c | 21 +++++++--
diffs (truncated from 305 to 300 lines):
diff -r 75d3d4374dda -r 9f2e8d230bd5 src/dsync/dsync-brain.c
--- a/src/dsync/dsync-brain.c Wed Nov 18 19:58:07 2009 -0500
+++ b/src/dsync/dsync-brain.c Wed Nov 18 19:58:37 2009 -0500
@@ -614,3 +614,9 @@ void dsync_brain_sync_all(struct dsync_b
i_assert(brain->state != old_state);
}
}
+
+bool dsync_brain_has_unexpected_changes(struct dsync_brain *brain)
+{
+ return dsync_worker_has_unexpected_changes(brain->src_worker) ||
+ dsync_worker_has_unexpected_changes(brain->dest_worker);
+}
diff -r 75d3d4374dda -r 9f2e8d230bd5 src/dsync/dsync-brain.h
--- a/src/dsync/dsync-brain.h Wed Nov 18 19:58:07 2009 -0500
+++ b/src/dsync/dsync-brain.h Wed Nov 18 19:58:37 2009 -0500
@@ -17,4 +17,6 @@ void dsync_brain_sync(struct dsync_brain
void dsync_brain_sync(struct dsync_brain *brain);
void dsync_brain_sync_all(struct dsync_brain *brain);
+bool dsync_brain_has_unexpected_changes(struct dsync_brain *brain);
+
#endif
diff -r 75d3d4374dda -r 9f2e8d230bd5 src/dsync/dsync-proxy-client.c
--- a/src/dsync/dsync-proxy-client.c Wed Nov 18 19:58:07 2009 -0500
+++ b/src/dsync/dsync-proxy-client.c Wed Nov 18 19:58:37 2009 -0500
@@ -196,10 +196,18 @@ proxy_client_worker_next_msg_get(struct
}
static void
-proxy_client_worker_next_finish(const struct proxy_client_request *request,
+proxy_client_worker_next_finish(struct proxy_client_dsync_worker *worker,
+ const struct proxy_client_request *request,
const char *line)
{
- request->callback.finish(line[0] == '1', request->context);
+ bool success = TRUE;
+
+ if (strcmp(line, "changes") == 0)
+ worker->worker.unexpected_changes = TRUE;
+ else if (strcmp(line, "ok") != 0)
+ success = FALSE;
+
+ request->callback.finish(success, request->context);
}
static bool
@@ -229,7 +237,7 @@ proxy_client_worker_next_reply(struct pr
break;
case PROXY_CLIENT_REQUEST_TYPE_FINISH:
worker->finished = TRUE;
- proxy_client_worker_next_finish(&request, line);
+ proxy_client_worker_next_finish(worker, &request, line);
break;
}
return ret;
diff -r 75d3d4374dda -r 9f2e8d230bd5 src/dsync/dsync-proxy-server-cmd.c
--- a/src/dsync/dsync-proxy-server-cmd.c Wed Nov 18 19:58:07 2009 -0500
+++ b/src/dsync/dsync-proxy-server-cmd.c Wed Nov 18 19:58:37 2009 -0500
@@ -503,9 +503,17 @@ static void cmd_finish_callback(bool suc
static void cmd_finish_callback(bool success, void *context)
{
struct dsync_proxy_server *server = context;
+ const char *reply;
+
+ if (!success)
+ reply = "fail\n";
+ else if (dsync_worker_has_unexpected_changes(server->worker))
+ reply = "changes\n";
+ else
+ reply = "ok\n";
server->finished = TRUE;
- o_stream_send_str(server->output, success ? "1\n" : "0\n");
+ o_stream_send_str(server->output, reply);
}
static int
diff -r 75d3d4374dda -r 9f2e8d230bd5 src/dsync/dsync-worker-local.c
--- a/src/dsync/dsync-worker-local.c Wed Nov 18 19:58:07 2009 -0500
+++ b/src/dsync/dsync-worker-local.c Wed Nov 18 19:58:37 2009 -0500
@@ -77,6 +77,8 @@ struct local_dsync_worker {
struct mailbox *selected_box;
struct mail *mail, *ext_mail;
+ ARRAY_TYPE(uint32_t) saved_uids;
+
mailbox_guid_t get_mailbox;
struct mail *get_mail;
@@ -133,6 +135,7 @@ dsync_worker_init_local(struct mail_user
worker->mailbox_hash =
hash_table_create(default_pool, pool, 0,
mailbox_guid_hash, mailbox_guid_cmp);
+ i_array_init(&worker->saved_uids, 128);
return &worker->worker;
}
@@ -150,6 +153,7 @@ static void local_worker_deinit(struct d
hash_table_destroy(&worker->mailbox_changes_hash);
if (worker->subscription_changes_hash != NULL)
hash_table_destroy(&worker->subscription_changes_hash);
+ array_free(&worker->saved_uids);
pool_unref(&worker->pool);
}
@@ -1013,28 +1017,60 @@ local_worker_rename_mailbox(struct dsync
}
}
+static bool
+has_expected_save_uids(struct local_dsync_worker *worker,
+ const struct mail_transaction_commit_changes *changes)
+{
+ struct seq_range_iter iter;
+ const uint32_t *expected_uids;
+ uint32_t uid;
+ unsigned int i, n, expected_count;
+
+ expected_uids = array_get(&worker->saved_uids, &expected_count);
+ seq_range_array_iter_init(&iter, &changes->saved_uids); i = n = 0;
+ while (seq_range_array_iter_nth(&iter, n++, &uid)) {
+ if (i == expected_count || uid != expected_uids[i++])
+ return FALSE;
+ }
+ return i == expected_count;
+}
+
static void local_worker_mailbox_close(struct local_dsync_worker *worker)
{
struct mailbox_transaction_context *trans, *ext_trans;
+ struct mail_transaction_commit_changes changes;
i_assert(worker->save_input == NULL);
- if (worker->selected_box != NULL) {
- trans = worker->mail->transaction;
- ext_trans = worker->ext_mail->transaction;
- mail_free(&worker->mail);
- mail_free(&worker->ext_mail);
- if (mailbox_transaction_commit(&ext_trans) < 0)
- dsync_worker_set_failure(&worker->worker);
- if (mailbox_transaction_commit(&trans) < 0 ||
- mailbox_sync(worker->selected_box,
- MAILBOX_SYNC_FLAG_FULL_WRITE, 0, NULL) < 0)
- dsync_worker_set_failure(&worker->worker);
-
- mailbox_close(&worker->selected_box);
- }
memset(&worker->selected_box_guid, 0,
sizeof(worker->selected_box_guid));
+
+ if (worker->selected_box == NULL)
+ return;
+
+ trans = worker->mail->transaction;
+ ext_trans = worker->ext_mail->transaction;
+ mail_free(&worker->mail);
+ mail_free(&worker->ext_mail);
+
+ /* all saves and copies go to ext_trans */
+ if (mailbox_transaction_commit_get_changes(&ext_trans, &changes) < 0)
+ dsync_worker_set_failure(&worker->worker);
+ else {
+ if (changes.ignored_uid_changes != 0 ||
+ changes.ignored_modseq_changes != 0 ||
+ !has_expected_save_uids(worker, &changes))
+ worker->worker.unexpected_changes = TRUE;
+ pool_unref(&changes.pool);
+ }
+ array_clear(&worker->saved_uids);
+
+ if (mailbox_transaction_commit(&trans) < 0 ||
+ mailbox_sync(worker->selected_box,
+ MAILBOX_SYNC_FLAG_FULL_WRITE, 0, NULL) < 0)
+ dsync_worker_set_failure(&worker->worker);
+
+ mailbox_close(&worker->selected_box);
}
static void
@@ -1173,11 +1209,14 @@ static void local_worker_msg_expunge(str
}
static void
-local_worker_msg_save_set_metadata(struct mailbox *box,
+local_worker_msg_save_set_metadata(struct local_dsync_worker *worker,
+ struct mailbox *box,
struct mail_save_context *save_ctx,
const struct dsync_message *msg)
{
struct mail_keywords *keywords;
+
+ i_assert(msg->uid != 0);
if (msg->modseq > 1)
(void)mailbox_enable(box, MAILBOX_FEATURE_CONDSTORE);
@@ -1190,6 +1229,8 @@ local_worker_msg_save_set_metadata(struc
mailbox_save_set_uid(save_ctx, msg->uid);
mailbox_save_set_save_date(save_ctx, msg->save_date);
mailbox_save_set_min_modseq(save_ctx, msg->modseq);
+
+ array_append(&worker->saved_uids, &msg->uid, 1);
}
static void
@@ -1217,7 +1258,7 @@ local_worker_msg_copy(struct dsync_worke
ret = -1;
else {
save_ctx = mailbox_save_alloc(worker->ext_mail->transaction);
- local_worker_msg_save_set_metadata(worker->mail->box,
+ local_worker_msg_save_set_metadata(worker, worker->mail->box,
save_ctx, dest_msg);
ret = mailbox_copy(&save_ctx, src_mail);
}
@@ -1290,7 +1331,8 @@ local_worker_msg_save(struct dsync_worke
save_ctx = mailbox_save_alloc(worker->ext_mail->transaction);
mailbox_save_set_guid(save_ctx, msg->guid);
- local_worker_msg_save_set_metadata(worker->mail->box, save_ctx, msg);
+ local_worker_msg_save_set_metadata(worker, worker->mail->box,
+ save_ctx, msg);
mailbox_save_set_pop3_uidl(save_ctx, data->pop3_uidl);
mailbox_save_set_received_date(save_ctx, data->received_date, 0);
diff -r 75d3d4374dda -r 9f2e8d230bd5 src/dsync/dsync-worker-private.h
--- a/src/dsync/dsync-worker-private.h Wed Nov 18 19:58:07 2009 -0500
+++ b/src/dsync/dsync-worker-private.h Wed Nov 18 19:58:37 2009 -0500
@@ -76,6 +76,7 @@ struct dsync_worker {
unsigned int readonly:1;
unsigned int failed:1;
+ unsigned int unexpected_changes:1;
};
struct dsync_worker_mailbox_iter {
diff -r 75d3d4374dda -r 9f2e8d230bd5 src/dsync/dsync-worker.c
--- a/src/dsync/dsync-worker.c Wed Nov 18 19:58:07 2009 -0500
+++ b/src/dsync/dsync-worker.c Wed Nov 18 19:58:37 2009 -0500
@@ -242,3 +242,8 @@ bool dsync_worker_has_failed(struct dsyn
{
return worker->failed;
}
+
+bool dsync_worker_has_unexpected_changes(struct dsync_worker *worker)
+{
+ return worker->unexpected_changes;
+}
diff -r 75d3d4374dda -r 9f2e8d230bd5 src/dsync/dsync-worker.h
--- a/src/dsync/dsync-worker.h Wed Nov 18 19:58:07 2009 -0500
+++ b/src/dsync/dsync-worker.h Wed Nov 18 19:58:37 2009 -0500
@@ -147,5 +147,8 @@ void dsync_worker_finish(struct dsync_wo
/* Returns TRUE if some commands have failed. */
bool dsync_worker_has_failed(struct dsync_worker *worker);
+/* Returns TRUE if some UID or modseq changes didn't get assigned as
+ requested. */
+bool dsync_worker_has_unexpected_changes(struct dsync_worker *worker);
#endif
diff -r 75d3d4374dda -r 9f2e8d230bd5 src/dsync/dsync.c
--- a/src/dsync/dsync.c Wed Nov 18 19:58:07 2009 -0500
+++ b/src/dsync/dsync.c Wed Nov 18 19:58:37 2009 -0500
@@ -84,7 +84,7 @@ int main(int argc, char *argv[])
struct dsync_worker *worker1, *worker2;
const char *error, *username, *mailbox = NULL, *mirror_cmd = NULL;
const char *convert_location = NULL;
- bool dsync_server = FALSE, readonly = FALSE;
+ bool dsync_server = FALSE, readonly = FALSE, unexpected_changes = FALSE;
char alt_hierarchy_char = '_';
int c, ret, fd_in = STDIN_FILENO, fd_out = STDOUT_FILENO;
@@ -207,10 +207,13 @@ int main(int argc, char *argv[])
master_service_run(master_service, dsync_connected);
}
- if (brain != NULL)
+ if (brain == NULL)
+ ret = 0;
+ else {
+ if (dsync_brain_has_unexpected_changes(brain))
+ unexpected_changes = TRUE;
ret = dsync_brain_deinit(&brain);
- else
- ret = 0;
+ }
if (server != NULL)
dsync_proxy_server_deinit(&server);
@@ -223,7 +226,13 @@ int main(int argc, char *argv[])
mail_user_unref(&mail_user2);
mail_storage_service_user_free(&service_user);
+ if (unexpected_changes &&
+ (brain_flags & DSYNC_BRAIN_FLAG_VERBOSE) != 0) {
+ i_info("Mailbox changes caused a desync. "
+ "You might want to run dsync again.");
+ }
+
mail_storage_service_deinit(&storage_service);
More information about the dovecot-cvs
mailing list