Mercurial > dovecot > core-2.2
changeset 11524:c955d4789553 HEAD
dsync: Fixed syncing \noselect mailboxes.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Fri, 11 Jun 2010 22:36:38 +0100 |
parents | b135e13f42b2 |
children | 93c3d6a46446 |
files | src/dsync/dsync-brain.c src/dsync/dsync-data.c src/dsync/dsync-data.h src/dsync/dsync-proxy-client.c src/dsync/dsync-proxy-server-cmd.c src/dsync/dsync-worker-local.c src/dsync/dsync-worker-private.h src/dsync/dsync-worker.c src/dsync/dsync-worker.h src/dsync/test-dsync-worker.c src/dsync/test-dsync-worker.h |
diffstat | 11 files changed, 185 insertions(+), 16 deletions(-) [+] |
line wrap: on
line diff
--- a/src/dsync/dsync-brain.c Fri Jun 11 21:45:51 2010 +0100 +++ b/src/dsync/dsync-brain.c Fri Jun 11 22:36:38 2010 +0100 @@ -102,7 +102,7 @@ if (dsync_worker_mailbox_iter_deinit(&list->iter) < 0) dsync_brain_fail(list->brain); array_sort(&list->mailboxes, dsync_mailbox_p_guid_cmp); - array_sort(&list->dirs, dsync_mailbox_p_name_cmp); + array_sort(&list->dirs, dsync_mailbox_p_name_sha1_cmp); dsync_brain_mailbox_list_finished(list->brain); } } @@ -313,6 +313,76 @@ } } +static void dsync_brain_sync_dirs(struct dsync_brain *brain) +{ + struct dsync_mailbox *const *src_boxes, *const *dest_boxes, new_box; + unsigned int src, dest, src_count, dest_count; + bool src_deleted, dest_deleted; + int ret; + + memset(&new_box, 0, sizeof(new_box)); + + /* create/delete missing directories. */ + src_boxes = array_get(&brain->src_mailbox_list->dirs, &src_count); + dest_boxes = array_get(&brain->dest_mailbox_list->dirs, &dest_count); + for (src = dest = 0; src < src_count && dest < dest_count; ) { + src_deleted = (src_boxes[src]->flags & + DSYNC_MAILBOX_FLAG_DELETED_DIR) != 0; + dest_deleted = (dest_boxes[dest]->flags & + DSYNC_MAILBOX_FLAG_DELETED_DIR) != 0; + ret = memcmp(src_boxes[src]->name_sha1.guid, + dest_boxes[dest]->name_sha1.guid, + sizeof(src_boxes[src]->name_sha1.guid)); + if (ret < 0) { + /* exists only in source */ + if (!src_deleted) { + new_box = *src_boxes[src]; + dsync_worker_create_mailbox(brain->dest_worker, + &new_box); + } + src++; + } else if (ret > 0) { + /* exists only in dest */ + if (!dest_deleted) { + new_box = *dest_boxes[dest]; + dsync_worker_create_mailbox(brain->src_worker, + &new_box); + } + dest++; + } else if (src_deleted) { + /* delete from dest too */ + if (!dest_deleted) { + dsync_worker_delete_dir(brain->dest_worker, + dest_boxes[dest]); + } + src++; dest++; + } else if (dest_deleted) { + /* delete from src too */ + dsync_worker_delete_dir(brain->src_worker, + src_boxes[src]); + src++; dest++; + } else { + src++; dest++; + } + } + for (; src < src_count; src++) { + if ((src_boxes[src]->flags & + DSYNC_MAILBOX_FLAG_DELETED_DIR) != 0) + continue; + + new_box = *src_boxes[src]; + dsync_worker_create_mailbox(brain->dest_worker, &new_box); + } + for (; dest < dest_count; dest++) { + if ((dest_boxes[dest]->flags & + DSYNC_MAILBOX_FLAG_DELETED_DIR) != 0) + continue; + + new_box = *dest_boxes[dest]; + dsync_worker_create_mailbox(brain->src_worker, &new_box); + } +} + static bool dsync_brain_is_unsubscribed(struct dsync_brain_subs_list *list, const struct dsync_worker_subscription *subs, @@ -612,6 +682,7 @@ break; case DSYNC_STATE_SYNC_MAILBOXES: dsync_brain_sync_mailboxes(brain); + dsync_brain_sync_dirs(brain); brain->state++; /* fall through */ case DSYNC_STATE_SYNC_SUBSCRIPTIONS:
--- a/src/dsync/dsync-data.c Fri Jun 11 21:45:51 2010 +0100 +++ b/src/dsync/dsync-data.c Fri Jun 11 22:36:38 2010 +0100 @@ -62,16 +62,23 @@ return dsync_mailbox_guid_cmp(*box1, *box2); } -int dsync_mailbox_name_cmp(const struct dsync_mailbox *box1, - const struct dsync_mailbox *box2) +int dsync_mailbox_name_sha1_cmp(const struct dsync_mailbox *box1, + const struct dsync_mailbox *box2) { + int ret; + + ret = memcmp(box1->name_sha1.guid, box2->name_sha1.guid, + sizeof(box1->name_sha1.guid)); + if (ret != 0) + return ret; + return strcmp(box1->name, box2->name); } -int dsync_mailbox_p_name_cmp(struct dsync_mailbox *const *box1, - struct dsync_mailbox *const *box2) +int dsync_mailbox_p_name_sha1_cmp(struct dsync_mailbox *const *box1, + struct dsync_mailbox *const *box2) { - return dsync_mailbox_name_cmp(*box1, *box2); + return dsync_mailbox_name_sha1_cmp(*box1, *box2); } bool dsync_keyword_list_equals(const char *const *k1, const char *const *k2)
--- a/src/dsync/dsync-data.h Fri Jun 11 21:45:51 2010 +0100 +++ b/src/dsync/dsync-data.h Fri Jun 11 22:36:38 2010 +0100 @@ -66,10 +66,10 @@ int dsync_mailbox_p_guid_cmp(struct dsync_mailbox *const *box1, struct dsync_mailbox *const *box2); -int dsync_mailbox_name_cmp(const struct dsync_mailbox *box1, - const struct dsync_mailbox *box2); -int dsync_mailbox_p_name_cmp(struct dsync_mailbox *const *box1, - struct dsync_mailbox *const *box2); +int dsync_mailbox_name_sha1_cmp(const struct dsync_mailbox *box1, + const struct dsync_mailbox *box2); +int dsync_mailbox_p_name_sha1_cmp(struct dsync_mailbox *const *box1, + struct dsync_mailbox *const *box2); bool dsync_keyword_list_equals(const char *const *k1, const char *const *k2);
--- a/src/dsync/dsync-proxy-client.c Fri Jun 11 21:45:51 2010 +0100 +++ b/src/dsync/dsync-proxy-client.c Fri Jun 11 22:36:38 2010 +0100 @@ -727,6 +727,25 @@ } static void +proxy_client_worker_delete_dir(struct dsync_worker *_worker, + const struct dsync_mailbox *dsync_box) +{ + struct proxy_client_dsync_worker *worker = + (struct proxy_client_dsync_worker *)_worker; + + i_assert(worker->save_input == NULL); + + T_BEGIN { + string_t *str = t_str_new(128); + + str_append(str, "DIR-DELETE\t"); + str_tabescape_write(str, dsync_box->name); + str_printfa(str, "\t%s\n", dec2str(dsync_box->last_change)); + o_stream_send(worker->output, str_data(str), str_len(str)); + } T_END; +} + +static void proxy_client_worker_rename_mailbox(struct dsync_worker *_worker, const mailbox_guid_t *mailbox, const struct dsync_mailbox *dsync_box) @@ -1037,6 +1056,7 @@ proxy_client_worker_create_mailbox, proxy_client_worker_delete_mailbox, + proxy_client_worker_delete_dir, proxy_client_worker_rename_mailbox, proxy_client_worker_update_mailbox,
--- a/src/dsync/dsync-proxy-server-cmd.c Fri Jun 11 21:45:51 2010 +0100 +++ b/src/dsync/dsync-proxy-server-cmd.c Fri Jun 11 22:36:38 2010 +0100 @@ -262,6 +262,21 @@ } static int +cmd_dir_delete(struct dsync_proxy_server *server, const char *const *args) +{ + struct dsync_mailbox dsync_box; + + if (str_array_length(args) < 2) + return -1; + + memset(&dsync_box, 0, sizeof(dsync_box)); + dsync_box.name = str_tabunescape(t_strdup_noconst(args[0])); + dsync_box.last_change = strtoul(args[1], NULL, 10); + dsync_worker_delete_dir(server->worker, &dsync_box); + return 1; +} + +static int cmd_box_rename(struct dsync_proxy_server *server, const char *const *args) { mailbox_guid_t guid; @@ -552,6 +567,7 @@ { "MSG-LIST", cmd_msg_list }, { "BOX-CREATE", cmd_box_create }, { "BOX-DELETE", cmd_box_delete }, + { "DIR-DELETE", cmd_dir_delete }, { "BOX-RENAME", cmd_box_rename }, { "BOX-UPDATE", cmd_box_update }, { "BOX-SELECT", cmd_box_select },
--- a/src/dsync/dsync-worker-local.c Fri Jun 11 21:45:51 2010 +0100 +++ b/src/dsync/dsync-worker-local.c Fri Jun 11 22:36:38 2010 +0100 @@ -454,7 +454,8 @@ dsync_box_r->name = ""; dsync_box_r->name_sha1 = change->name_sha1; dsync_box_r->last_change = change->last_delete; - dsync_box_r->flags |= DSYNC_MAILBOX_FLAG_DELETED_DIR; + dsync_box_r->flags |= DSYNC_MAILBOX_FLAG_NOSELECT | + DSYNC_MAILBOX_FLAG_DELETED_DIR; return 1; } } @@ -478,7 +479,7 @@ struct mailbox_status status; uint8_t mailbox_guid[MAIL_GUID_128_SIZE]; struct local_dsync_mailbox_change *change; - struct local_dsync_dir_change *dir_change; + struct local_dsync_dir_change *dir_change, change_lookup; const char *const *fields; unsigned int i, field_count; @@ -491,17 +492,20 @@ dsync_box_r->name = info->name; dsync_box_r->name_sep = info->ns->sep; + storage_name = mail_namespace_get_storage_name(info->ns, info->name); + dsync_str_sha_to_guid(storage_name, &dsync_box_r->name_sha1); + /* get last change timestamp */ - dsync_str_sha_to_guid(info->name, &dsync_box_r->name_sha1); - dir_change = hash_table_lookup(worker->mailbox_changes_hash, - dsync_box_r->name_sha1.guid); + change_lookup.list = info->ns->list; + change_lookup.name_sha1 = dsync_box_r->name_sha1; + dir_change = hash_table_lookup(worker->dir_changes_hash, + &change_lookup); if (dir_change != NULL) { /* it shouldn't be marked as deleted, but drop it to be sure */ dir_change->deleted_dir = FALSE; dsync_box_r->last_change = dir_change->last_rename; } - storage_name = mail_namespace_get_storage_name(info->ns, info->name); if ((info->flags & MAILBOX_NOSELECT) != 0) { dsync_box_r->flags |= DSYNC_MAILBOX_FLAG_NOSELECT; local_dsync_worker_add_mailbox(worker, info->ns, storage_name, @@ -1136,6 +1140,27 @@ } static void +local_worker_delete_dir(struct dsync_worker *_worker, + const struct dsync_mailbox *dsync_box) +{ + struct local_dsync_worker *worker = + (struct local_dsync_worker *)_worker; + struct mail_namespace *ns; + const char *storage_name; + + storage_name = dsync_box->name; + ns = mail_namespace_find(worker->user->namespaces, &storage_name); + + mailbox_list_set_changelog_timestamp(ns->list, dsync_box->last_change); + if (mailbox_list_delete_dir(ns->list, storage_name) < 0) { + i_error("Can't delete mailbox directory %s: %s", + dsync_box->name, + mailbox_list_get_last_error(ns->list, NULL)); + } + mailbox_list_set_changelog_timestamp(ns->list, (time_t)-1); +} + +static void local_worker_rename_mailbox(struct dsync_worker *_worker, const mailbox_guid_t *mailbox, const struct dsync_mailbox *dsync_box) @@ -1632,6 +1657,7 @@ local_worker_create_mailbox, local_worker_delete_mailbox, + local_worker_delete_dir, local_worker_rename_mailbox, local_worker_update_mailbox,
--- a/src/dsync/dsync-worker-private.h Fri Jun 11 21:45:51 2010 +0100 +++ b/src/dsync/dsync-worker-private.h Fri Jun 11 22:36:38 2010 +0100 @@ -40,6 +40,8 @@ const struct dsync_mailbox *dsync_box); void (*delete_mailbox)(struct dsync_worker *worker, const struct dsync_mailbox *dsync_box); + void (*delete_dir)(struct dsync_worker *worker, + const struct dsync_mailbox *dsync_box); void (*rename_mailbox)(struct dsync_worker *worker, const mailbox_guid_t *mailbox, const struct dsync_mailbox *dsync_box);
--- a/src/dsync/dsync-worker.c Fri Jun 11 21:45:51 2010 +0100 +++ b/src/dsync/dsync-worker.c Fri Jun 11 22:36:38 2010 +0100 @@ -145,6 +145,14 @@ } T_END; } +void dsync_worker_delete_dir(struct dsync_worker *worker, + const struct dsync_mailbox *dsync_box) +{ + if (!worker->readonly) T_BEGIN { + worker->v.delete_dir(worker, dsync_box); + } T_END; +} + void dsync_worker_rename_mailbox(struct dsync_worker *worker, const mailbox_guid_t *mailbox, const struct dsync_mailbox *dsync_box)
--- a/src/dsync/dsync-worker.h Fri Jun 11 21:45:51 2010 +0100 +++ b/src/dsync/dsync-worker.h Fri Jun 11 22:36:38 2010 +0100 @@ -101,6 +101,9 @@ /* Delete mailbox/dir with given GUID. */ void dsync_worker_delete_mailbox(struct dsync_worker *worker, const struct dsync_mailbox *dsync_box); +/* Delete mailbox's directory. Fail if it would also delete mailbox. */ +void dsync_worker_delete_dir(struct dsync_worker *worker, + const struct dsync_mailbox *dsync_box); /* Change a mailbox and its childrens' name. The name is taken from the given dsync_box (applying name_sep if necessary). */ void dsync_worker_rename_mailbox(struct dsync_worker *worker,
--- a/src/dsync/test-dsync-worker.c Fri Jun 11 21:45:51 2010 +0100 +++ b/src/dsync/test-dsync-worker.c Fri Jun 11 22:36:38 2010 +0100 @@ -246,6 +246,20 @@ } static void +test_worker_delete_dir(struct dsync_worker *_worker, + const struct dsync_mailbox *dsync_box) +{ + struct test_dsync_worker *worker = (struct test_dsync_worker *)_worker; + struct test_dsync_box_event event; + + memset(&event, 0, sizeof(event)); + event.type = LAST_BOX_TYPE_DELETE_DIR; + + event.box = *dsync_box; + array_append(&worker->box_events, &event, 1); +} + +static void test_worker_rename_mailbox(struct dsync_worker *_worker, const mailbox_guid_t *mailbox, const struct dsync_mailbox *dsync_box) @@ -447,6 +461,7 @@ test_worker_create_mailbox, test_worker_delete_mailbox, + test_worker_delete_dir, test_worker_rename_mailbox, test_worker_update_mailbox,
--- a/src/dsync/test-dsync-worker.h Fri Jun 11 21:45:51 2010 +0100 +++ b/src/dsync/test-dsync-worker.h Fri Jun 11 22:36:38 2010 +0100 @@ -6,6 +6,7 @@ enum test_dsync_last_box_type { LAST_BOX_TYPE_CREATE, LAST_BOX_TYPE_DELETE, + LAST_BOX_TYPE_DELETE_DIR, LAST_BOX_TYPE_RENAME, LAST_BOX_TYPE_UPDATE, LAST_BOX_TYPE_SUBSCRIBE,