dovecot-2.2: dsync: Fixed unsubscribing from an already deleted ...
dovecot at dovecot.org
dovecot at dovecot.org
Mon May 20 17:30:38 EEST 2013
details: http://hg.dovecot.org/dovecot-2.2/rev/9878986a028d
changeset: 16380:9878986a028d
user: Timo Sirainen <tss at iki.fi>
date: Mon May 20 17:30:23 2013 +0300
description:
dsync: Fixed unsubscribing from an already deleted mailbox.
diffstat:
src/doveadm/dsync/dsync-brain-mailbox-tree.c | 34 +++++++++---
src/doveadm/dsync/dsync-ibc-stream.c | 73 ++++++++++++++++-----------
src/doveadm/dsync/dsync-mailbox-tree-fill.c | 17 +++++-
src/doveadm/dsync/dsync-mailbox-tree.c | 2 +-
src/doveadm/dsync/dsync-mailbox-tree.h | 13 +++-
5 files changed, 96 insertions(+), 43 deletions(-)
diffs (271 lines):
diff -r 4f76d60ba7dd -r 9878986a028d src/doveadm/dsync/dsync-brain-mailbox-tree.c
--- a/src/doveadm/dsync/dsync-brain-mailbox-tree.c Mon May 20 02:25:26 2013 +0300
+++ b/src/doveadm/dsync/dsync-brain-mailbox-tree.c Mon May 20 17:30:23 2013 +0300
@@ -371,11 +371,24 @@
if (node == NULL)
return;
- if (!other_del->delete_mailbox &&
- other_del->timestamp <= node->last_renamed_or_created) {
- /* we don't want to delete this directory, we already have a
- newer timestamp for it */
- return;
+ switch (other_del->type) {
+ case DSYNC_MAILBOX_DELETE_TYPE_MAILBOX:
+ /* mailbox is always deleted */
+ break;
+ case DSYNC_MAILBOX_DELETE_TYPE_DIR:
+ if (other_del->timestamp <= node->last_renamed_or_created) {
+ /* we don't want to delete this directory, we already
+ have a newer timestamp for it */
+ return;
+ }
+ break;
+ case DSYNC_MAILBOX_DELETE_TYPE_UNSUBSCRIBE:
+ if (other_del->timestamp <= node->last_subscription_change) {
+ /* we don't want to unsubscribe, since we already have
+ a newer subscription timestamp */
+ return;
+ }
+ break;
}
/* make a node for it in the other mailbox tree */
@@ -384,20 +397,25 @@
if (!guid_128_is_empty(other_node->mailbox_guid) ||
(other_node->existence == DSYNC_MAILBOX_NODE_EXISTS &&
- !other_del->delete_mailbox)) {
+ other_del->type != DSYNC_MAILBOX_DELETE_TYPE_MAILBOX)) {
/* other side has already created a new mailbox or
directory with this name, we can't delete it */
return;
}
/* ok, mark the other node deleted */
- if (other_del->delete_mailbox) {
+ if (other_del->type == DSYNC_MAILBOX_DELETE_TYPE_MAILBOX) {
memcpy(other_node->mailbox_guid, node->mailbox_guid,
sizeof(other_node->mailbox_guid));
}
i_assert(other_node->ns == NULL || other_node->ns == node->ns);
other_node->ns = node->ns;
- other_node->existence = DSYNC_MAILBOX_NODE_DELETED;
+ if (other_del->type != DSYNC_MAILBOX_DELETE_TYPE_UNSUBSCRIBE)
+ other_node->existence = DSYNC_MAILBOX_NODE_DELETED;
+ else {
+ other_node->last_subscription_change = other_del->timestamp;
+ other_node->subscribed = FALSE;
+ }
if (dsync_mailbox_tree_guid_hash_add(other_tree, other_node,
&old_node) < 0)
diff -r 4f76d60ba7dd -r 9878986a028d src/doveadm/dsync/dsync-ibc-stream.c
--- a/src/doveadm/dsync/dsync-ibc-stream.c Mon May 20 02:25:26 2013 +0300
+++ b/src/doveadm/dsync/dsync-ibc-stream.c Mon May 20 17:30:23 2013 +0300
@@ -90,7 +90,7 @@
{ .name = "mailbox_delete",
.chr = 'D',
.required_keys = "hierarchy_sep",
- .optional_keys = "mailboxes dirs"
+ .optional_keys = "mailboxes dirs unsubscribes"
},
{ .name = "mailbox",
.chr = 'B',
@@ -936,6 +936,28 @@
}
static void
+dsync_ibc_stream_encode_delete(string_t *str,
+ struct dsync_serializer_encoder *encoder,
+ const struct dsync_mailbox_delete *deletes,
+ unsigned int count, const char *key,
+ enum dsync_mailbox_delete_type type)
+{
+ unsigned int i;
+
+ str_truncate(str, 0);
+ for (i = 0; i < count; i++) {
+ if (deletes[i].type == type) {
+ str_append(str, guid_128_to_string(deletes[i].guid));
+ str_printfa(str, " %ld ", (long)deletes[i].timestamp);
+ }
+ }
+ if (str_len(str) > 0) {
+ str_truncate(str, str_len(str)-1);
+ dsync_serializer_encode_add(encoder, key, str_c(str));
+ }
+}
+
+static void
dsync_ibc_stream_send_mailbox_deletes(struct dsync_ibc *_ibc,
const struct dsync_mailbox_delete *deletes,
unsigned int count, char hierarchy_sep)
@@ -944,7 +966,6 @@
struct dsync_serializer_encoder *encoder;
string_t *str, *substr;
char sep[2];
- unsigned int i;
str = t_str_new(128);
str_append_c(str, items[ITEM_MAILBOX_DELETE].chr);
@@ -954,29 +975,15 @@
dsync_serializer_encode_add(encoder, "hierarchy_sep", sep);
substr = t_str_new(128);
- for (i = 0; i < count; i++) {
- if (deletes[i].delete_mailbox) {
- str_append(substr, guid_128_to_string(deletes[i].guid));
- str_printfa(substr, " %ld ", (long)deletes[i].timestamp);
- }
- }
- if (str_len(substr) > 0) {
- str_truncate(substr, str_len(substr)-1);
- dsync_serializer_encode_add(encoder, "mailboxes",
- str_c(substr));
- }
-
- str_truncate(substr, 0);
- for (i = 0; i < count; i++) {
- if (!deletes[i].delete_mailbox) {
- str_append(substr, guid_128_to_string(deletes[i].guid));
- str_printfa(substr, " %ld ", (long)deletes[i].timestamp);
- }
- }
- if (str_len(substr) > 0) {
- str_truncate(substr, str_len(substr)-1);
- dsync_serializer_encode_add(encoder, "dirs", str_c(substr));
- }
+ dsync_ibc_stream_encode_delete(substr, encoder, deletes, count,
+ "mailboxes",
+ DSYNC_MAILBOX_DELETE_TYPE_MAILBOX);
+ dsync_ibc_stream_encode_delete(substr, encoder, deletes, count,
+ "dirs",
+ DSYNC_MAILBOX_DELETE_TYPE_DIR);
+ dsync_ibc_stream_encode_delete(substr, encoder, deletes, count,
+ "unsubscribes",
+ DSYNC_MAILBOX_DELETE_TYPE_UNSUBSCRIBE);
dsync_serializer_encode_finish(&encoder, str);
dsync_ibc_stream_send_string(ibc, str);
}
@@ -984,7 +991,7 @@
ARRAY_DEFINE_TYPE(dsync_mailbox_delete, struct dsync_mailbox_delete);
static int
decode_mailbox_deletes(ARRAY_TYPE(dsync_mailbox_delete) *deletes,
- const char *value, bool delete_mailbox)
+ const char *value, enum dsync_mailbox_delete_type type)
{
struct dsync_mailbox_delete *del;
const char *const *tmp;
@@ -993,7 +1000,7 @@
tmp = t_strsplit(value, " ");
for (i = 0; tmp[i] != NULL; i += 2) {
del = array_append_space(deletes);
- del->delete_mailbox = delete_mailbox;
+ del->type = type;
if (guid_128_from_string(tmp[i], del->guid) < 0)
return -1;
if (tmp[i+1] == NULL ||
@@ -1029,12 +1036,20 @@
*hierarchy_sep_r = value[0];
if (dsync_deserializer_decode_try(decoder, "mailboxes", &value) &&
- decode_mailbox_deletes(&deletes, value, TRUE) < 0) {
+ decode_mailbox_deletes(&deletes, value,
+ DSYNC_MAILBOX_DELETE_TYPE_MAILBOX) < 0) {
dsync_ibc_input_error(ibc, decoder, "Invalid mailboxes");
return DSYNC_IBC_RECV_RET_TRYAGAIN;
}
if (dsync_deserializer_decode_try(decoder, "dirs", &value) &&
- decode_mailbox_deletes(&deletes, value, FALSE) < 0) {
+ decode_mailbox_deletes(&deletes, value,
+ DSYNC_MAILBOX_DELETE_TYPE_DIR) < 0) {
+ dsync_ibc_input_error(ibc, decoder, "Invalid dirs");
+ return DSYNC_IBC_RECV_RET_TRYAGAIN;
+ }
+ if (dsync_deserializer_decode_try(decoder, "unsubscribes", &value) &&
+ decode_mailbox_deletes(&deletes, value,
+ DSYNC_MAILBOX_DELETE_TYPE_UNSUBSCRIBE) < 0) {
dsync_ibc_input_error(ibc, decoder, "Invalid dirs");
return DSYNC_IBC_RECV_RET_TRYAGAIN;
}
diff -r 4f76d60ba7dd -r 9878986a028d src/doveadm/dsync/dsync-mailbox-tree-fill.c
--- a/src/doveadm/dsync/dsync-mailbox-tree-fill.c Mon May 20 02:25:26 2013 +0300
+++ b/src/doveadm/dsync/dsync-mailbox-tree-fill.c Mon May 20 17:30:23 2013 +0300
@@ -163,7 +163,7 @@
break;
}
del = array_append_space(&tree->deletes);
- del->delete_mailbox = TRUE;
+ del->type = DSYNC_MAILBOX_DELETE_TYPE_MAILBOX;
del->timestamp = timestamp;
memcpy(del->guid, rec->mailbox_guid, sizeof(del->guid));
break;
@@ -177,6 +177,7 @@
dsync side, it can match this deletion to the
name. */
del = array_append_space(&tree->deletes);
+ del->type = DSYNC_MAILBOX_DELETE_TYPE_DIR;
del->timestamp = timestamp;
memcpy(del->guid, rec->mailbox_guid, sizeof(del->guid));
break;
@@ -195,10 +196,22 @@
node->last_renamed_or_created = timestamp;
break;
case MAILBOX_LOG_RECORD_SUBSCRIBE:
- case MAILBOX_LOG_RECORD_UNSUBSCRIBE:
if (node != NULL)
node->last_subscription_change = timestamp;
break;
+ case MAILBOX_LOG_RECORD_UNSUBSCRIBE:
+ if (node != NULL) {
+ node->last_subscription_change = timestamp;
+ break;
+ }
+ /* The mailbox is already deleted, but it may still
+ exist on the other side (even the subscription
+ alone). */
+ del = array_append_space(&tree->deletes);
+ del->type = DSYNC_MAILBOX_DELETE_TYPE_UNSUBSCRIBE;
+ del->timestamp = timestamp;
+ memcpy(del->guid, rec->mailbox_guid, sizeof(del->guid));
+ break;
}
}
if (mailbox_log_iter_deinit(&iter) < 0) {
diff -r 4f76d60ba7dd -r 9878986a028d src/doveadm/dsync/dsync-mailbox-tree.c
--- a/src/doveadm/dsync/dsync-mailbox-tree.c Mon May 20 02:25:26 2013 +0300
+++ b/src/doveadm/dsync/dsync-mailbox-tree.c Mon May 20 17:30:23 2013 +0300
@@ -359,7 +359,7 @@
i_assert(hash_table_is_created(tree->guid_hash));
i_assert(tree->remote_sep != '\0');
- if (del->delete_mailbox) {
+ if (del->type == DSYNC_MAILBOX_DELETE_TYPE_MAILBOX) {
/* find node by GUID */
return hash_table_lookup(tree->guid_hash, guid_p);
}
diff -r 4f76d60ba7dd -r 9878986a028d src/doveadm/dsync/dsync-mailbox-tree.h
--- a/src/doveadm/dsync/dsync-mailbox-tree.h Mon May 20 02:25:26 2013 +0300
+++ b/src/doveadm/dsync/dsync-mailbox-tree.h Mon May 20 17:30:23 2013 +0300
@@ -63,10 +63,17 @@
#define dsync_mailbox_node_is_dir(node) \
guid_128_is_empty((node)->mailbox_guid)
+enum dsync_mailbox_delete_type {
+ /* Delete mailbox by given GUID */
+ DSYNC_MAILBOX_DELETE_TYPE_MAILBOX = 1,
+ /* Delete mailbox directory by given SHA1 name */
+ DSYNC_MAILBOX_DELETE_TYPE_DIR,
+ /* Unsubscribe mailbox by given SHA1 name */
+ DSYNC_MAILBOX_DELETE_TYPE_UNSUBSCRIBE,
+};
+
struct dsync_mailbox_delete {
- /* true: guid = mailbox GUID
- false: guid = sha1 of directory name */
- bool delete_mailbox;
+ enum dsync_mailbox_delete_type type;
guid_128_t guid;
time_t timestamp;
};
More information about the dovecot-cvs
mailing list