dovecot-2.0: dsync: Fixed uid conflict handling.
dovecot at dovecot.org
dovecot at dovecot.org
Thu Jul 9 00:23:05 EEST 2009
details: http://hg.dovecot.org/dovecot-2.0/rev/7b0bcf423fca
changeset: 9592:7b0bcf423fca
user: Timo Sirainen <tss at iki.fi>
date: Wed Jul 08 17:22:59 2009 -0400
description:
dsync: Fixed uid conflict handling.
diffstat:
2 files changed, 113 insertions(+), 33 deletions(-)
src/dsync/dsync-brain.c | 9 ++
src/dsync/test-dsync-brain.c | 137 ++++++++++++++++++++++++++++++++----------
diffs (256 lines):
diff -r 2cd15c71923d -r 7b0bcf423fca src/dsync/dsync-brain.c
--- a/src/dsync/dsync-brain.c Wed Jul 08 16:59:12 2009 -0400
+++ b/src/dsync/dsync-brain.c Wed Jul 08 17:22:59 2009 -0400
@@ -220,6 +220,7 @@ static int dsync_brain_msg_sync_pair(str
{
struct dsync_message *src_msg = &sync->src_msg_iter->msg;
struct dsync_message *dest_msg = &sync->dest_msg_iter->msg;
+ struct dsync_mailbox *const *boxp;
struct dsync_brain_uid_conflict *conflict;
if (src_msg->uid < dest_msg->uid) {
@@ -242,11 +243,17 @@ static int dsync_brain_msg_sync_pair(str
src_msg->guid = NULL;
dest_msg->guid = NULL;
} else {
- /* UID conflict */
+ /* UID conflict. change UID in destination */
sync->uid_conflict = TRUE;
conflict = array_append_space(&sync->uid_conflicts);
conflict->mailbox_idx = sync->src_msg_iter->mailbox_idx;
conflict->uid = dest_msg->uid;
+
+ /* give new UID for the source message message too. */
+ boxp = array_idx(&sync->brain->src_mailbox_list->mailboxes,
+ conflict->mailbox_idx);
+ src_msg->uid = (*boxp)->uid_next++;
+
dsync_brain_msg_sync_save_source(sync);
src_msg->guid = NULL;
dest_msg->guid = NULL;
diff -r 2cd15c71923d -r 7b0bcf423fca src/dsync/test-dsync-brain.c
--- a/src/dsync/test-dsync-brain.c Wed Jul 08 16:59:12 2009 -0400
+++ b/src/dsync/test-dsync-brain.c Wed Jul 08 17:22:59 2009 -0400
@@ -54,7 +54,7 @@ static struct dsync_message box3_dest_ms
{ NULL, 0, 0, NULL, 0, 0 }
};
-static struct test_dsync_mailbox mailboxes[] = {
+static struct test_dsync_mailbox basic_mailboxes[] = {
{ { "box1", { { 0x12, 0x34, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
0x21, 0x43, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe } },
1234567890, 4321, 605040302010ULL },
@@ -68,9 +68,11 @@ static struct test_dsync_mailbox mailbox
4545454, 656, 2366 }, box3_src_msgs,
box3_dest_msgs, FLAG_EXISTS },
{ { "dir1", { { 0, } }, 0, 0, 0 }, NULL, NULL, FLAG_EXISTS },
- { { "dir2", { { 0, } }, 0, 0, 0 }, NULL, NULL, 0 }
-};
-
+ { { "dir2", { { 0, } }, 0, 0, 0 }, NULL, NULL, 0 },
+ { { NULL, { { 0, } }, 0, 0, 0 }, NULL, NULL, 0 }
+};
+
+static struct test_dsync_mailbox *mailboxes;
struct master_service *master_service;
void master_service_stop(struct master_service *master_service ATTR_UNUSED)
@@ -81,7 +83,7 @@ static bool mailbox_find(const char *nam
{
unsigned int i;
- for (i = 0; i < N_ELEMENTS(mailboxes); i++) {
+ for (i = 0; mailboxes[i].box.name != NULL; i++) {
if (strcmp(mailboxes[i].box.name, name) == 0) {
*idx_r = i;
return TRUE;
@@ -103,7 +105,7 @@ static void test_dsync_sync_msgs(struct
struct dsync_message *msgs;
unsigned int i, j;
- for (i = 0; i < N_ELEMENTS(mailboxes); i++) {
+ for (i = 0; mailboxes[i].box.name != NULL; i++) {
msgs = dest ? mailboxes[i].dest_msgs : mailboxes[i].src_msgs;
if (msgs == NULL)
continue;
@@ -140,7 +142,7 @@ static bool test_dsync_msg_find_guid(con
{
unsigned int i, j;
- for (i = 0; i < N_ELEMENTS(mailboxes); i++) {
+ for (i = 0; mailboxes[i].box.name != NULL; i++) {
if (mailboxes[i].src_msgs == NULL)
continue;
@@ -275,25 +277,43 @@ test_dsync_brain_verify_mailbox(const st
}
static void
-test_dsync_brain_verify_msg_events(const struct test_dsync_msg_event *events)
-{
- unsigned int i;
-
- for (i = 0; i < N_ELEMENTS(mailboxes); i++)
+test_dsync_brain_verify_msg_events(struct test_dsync_worker *dest_test_worker)
+{
+ ARRAY_DEFINE(msg_events, struct test_dsync_msg_event);
+ const struct test_dsync_msg_event *events, *events_end;
+ struct test_dsync_msg_event msg_event;
+ unsigned int i, event_count;
+
+ /* get events and sort them so we can easily check if they're correct */
+ t_array_init(&msg_events, 64);
+ while (test_dsync_worker_next_msg_event(dest_test_worker, &msg_event))
+ array_append(&msg_events, &msg_event, 1);
+ array_sort(&msg_events, test_dsync_msg_event_cmp);
+
+ events = array_get(&msg_events, &event_count);
+ events_end = events + event_count;
+ for (i = 0; mailboxes[i].box.name != NULL; i++)
test_dsync_brain_verify_mailbox(&mailboxes[i], &events);
- test_assert(events->msg.guid == NULL);
-}
-
-static void test_dsync_brain_run(void)
+ test_assert(events == events_end);
+}
+
+static void
+test_dsync_brain_run(const struct test_dsync_mailbox *test_mailboxes,
+ void (*verify_func)(struct test_dsync_worker *))
{
struct dsync_brain *brain;
struct dsync_worker *src_worker, *dest_worker;
struct test_dsync_worker *src_test_worker, *dest_test_worker;
struct dsync_mailbox new_box;
- ARRAY_DEFINE(msg_events, struct test_dsync_msg_event);
struct test_dsync_box_event box_event;
- struct test_dsync_msg_event msg_event;
- unsigned int i;
+ unsigned int i, box_count;
+
+ box_count = 0;
+ while (test_mailboxes[box_count].box.name != NULL)
+ box_count++;
+
+ mailboxes = t_new(struct test_dsync_mailbox, box_count + 1);
+ memcpy(mailboxes, test_mailboxes, sizeof(*mailboxes) * box_count);
src_worker = dsync_worker_init_test();
dest_worker = dsync_worker_init_test();
@@ -304,7 +324,7 @@ static void test_dsync_brain_run(void)
dsync_brain_sync(brain);
/* have brain read the mailboxes */
- for (i = 0; i < N_ELEMENTS(mailboxes); i++) {
+ for (i = 0; mailboxes[i].box.name != NULL; i++) {
src_test_worker->box_iter.next_box = &mailboxes[i].box;
src_worker->input_callback(src_worker->input_context);
@@ -333,26 +353,19 @@ static void test_dsync_brain_run(void)
/* brain wants mailboxes in guid order. make things easier for us
by sorting them now. */
- qsort(mailboxes, N_ELEMENTS(mailboxes), sizeof(*mailboxes),
+ qsort(mailboxes, box_count, sizeof(*mailboxes),
test_dsync_mailbox_cmp);
/* start syncing messages */
- test_assert(dest_test_worker->msg_iter_mailbox_count == N_ELEMENTS(mailboxes));
- for (i = 0; i < N_ELEMENTS(mailboxes); i++) {
+ test_assert(dest_test_worker->msg_iter_mailbox_count == box_count);
+ for (i = 0; mailboxes[i].box.name != NULL; i++) {
test_assert(memcmp(&dest_test_worker->msg_iter_mailboxes[i],
mailboxes[i].box.guid.guid, MAILBOX_GUID_SIZE) == 0);
}
test_dsync_sync_msgs(src_test_worker, FALSE);
test_dsync_sync_msgs(dest_test_worker, TRUE);
- /* get events and sort them so we can easily check if they're correct */
- t_array_init(&msg_events, 64);
- while (test_dsync_worker_next_msg_event(dest_test_worker, &msg_event))
- array_append(&msg_events, &msg_event, 1);
- array_sort(&msg_events, test_dsync_msg_event_cmp);
- (void)array_append_space(&msg_events);
-
- test_dsync_brain_verify_msg_events(array_idx(&msg_events, 0));
+ verify_func(dest_test_worker);
dsync_worker_deinit(&src_worker);
dsync_worker_deinit(&dest_worker);
@@ -362,7 +375,66 @@ static void test_dsync_brain(void)
static void test_dsync_brain(void)
{
test_begin("dsync brain basics");
- test_dsync_brain_run();
+ test_dsync_brain_run(basic_mailboxes,
+ test_dsync_brain_verify_msg_events);
+ test_end();
+}
+
+static struct dsync_message conflict_src_msgs[] = {
+ { "guid1", 1, 0, NULL, 1, 1 },
+ { "guid3", 3, 0, NULL, 1, 1 },
+ { "guid5", 5, 0, NULL, 1, 1 },
+ { "guidy", 6, 0, NULL, 1, 1 },
+ { NULL, 0, 0, NULL, 0, 0 }
+};
+static struct dsync_message conflict_dest_msgs[] = {
+ { "guid1", 1, 0, NULL, 1, 1 },
+ { "guid2", 2, 0, NULL, 1, 1 },
+ { "guidx", 3, 0, NULL, 1, 1 },
+ { "guid4", 4, 0, NULL, 1, 1 },
+ { "guid5", 5, 0, NULL, 1, 1 },
+ { NULL, 0, 0, NULL, 0, 0 }
+};
+
+static struct test_dsync_mailbox conflict_mailboxes[] = {
+ { { "box1", { { 0x12, 0x34, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0x21, 0x43, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe } },
+ 1234567890, 4321, 605040302010ULL },
+ conflict_src_msgs, conflict_dest_msgs, FLAG_EXISTS },
+ { { NULL, { { 0, } }, 0, 0, 0 }, NULL, NULL, 0 }
+};
+
+static void
+test_dsync_brain_verify_uid_conflict(struct test_dsync_worker *dest_test_worker)
+{
+ struct test_dsync_msg_event event;
+
+ test_assert(test_dsync_worker_next_msg_event(dest_test_worker, &event));
+ test_assert(event.type == LAST_MSG_TYPE_EXPUNGE);
+ test_assert(event.msg.uid == 2);
+
+ test_assert(test_dsync_worker_next_msg_event(dest_test_worker, &event));
+ test_assert(event.type == LAST_MSG_TYPE_SAVE);
+ test_assert(event.msg.uid == 4321);
+ test_assert(strcmp(event.msg.guid, "guid3") == 0);
+
+ test_assert(test_dsync_worker_next_msg_event(dest_test_worker, &event));
+ test_assert(event.type == LAST_MSG_TYPE_SAVE);
+ test_assert(event.msg.uid == 6);
+ test_assert(strcmp(event.msg.guid, "guidy") == 0);
+
+ test_assert(test_dsync_worker_next_msg_event(dest_test_worker, &event));
+ test_assert(event.type == LAST_MSG_TYPE_UPDATE_UID);
+ test_assert(event.msg.uid == 3);
+
+ test_assert(!test_dsync_worker_next_msg_event(dest_test_worker, &event));
+}
+
+static void test_dsync_brain_uid_conflict(void)
+{
+ test_begin("dsync brain uid conflict");
+ test_dsync_brain_run(conflict_mailboxes,
+ test_dsync_brain_verify_uid_conflict);
test_end();
}
@@ -370,6 +442,7 @@ int main(void)
{
static void (*test_functions[])(void) = {
test_dsync_brain,
+ test_dsync_brain_uid_conflict,
NULL
};
return test_run(test_functions);
More information about the dovecot-cvs
mailing list