]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
dsync: Skip syncing mailboxes whose uidvalidity/uidnext/highest-modseq hasn't changed.
authorTimo Sirainen <tss@iki.fi>
Thu, 16 Jul 2009 22:12:30 +0000 (18:12 -0400)
committerTimo Sirainen <tss@iki.fi>
Thu, 16 Jul 2009 22:12:30 +0000 (18:12 -0400)
--HG--
branch : HEAD

src/dsync/dsync-brain.c
src/dsync/dsync-data.h
src/dsync/test-dsync-brain.c

index 8df3d12e5172edeab01ee4d375949a999f56ea5e..688b949f18b7a1cacc10579c27696a635f78bc1f 100644 (file)
@@ -409,20 +409,55 @@ dsync_brain_msg_iter_init(struct dsync_brain_mailbox_sync *sync,
        return iter;
 }
 
+static bool dsync_mailbox_has_changed_msgs(const struct dsync_mailbox *box1,
+                                          const struct dsync_mailbox *box2)
+{
+       return box1->uid_validity != box2->uid_validity ||
+               box1->uid_next != box2->uid_next ||
+               box1->highest_modseq != box2->highest_modseq;
+}
+
+static void
+dsync_brain_get_changed_mailboxes(struct dsync_brain *brain,
+                                 ARRAY_TYPE(mailbox_guid) *guids)
+{
+       struct dsync_mailbox *const *src_boxes, *const *dest_boxes;
+       unsigned int src, dest, src_count, dest_count;
+       int ret;
+
+       src_boxes = array_get(&brain->src_mailbox_list->mailboxes, &src_count);
+       dest_boxes = array_get(&brain->dest_mailbox_list->mailboxes, &dest_count);
+
+       for (src = dest = 0; src < src_count && dest < dest_count; ) {
+               ret = dsync_mailbox_guid_cmp(src_boxes[src], dest_boxes[dest]);
+               if (ret == 0) {
+                       if (dsync_mailbox_has_changed_msgs(src_boxes[src],
+                                                          dest_boxes[dest]))
+                               array_append(guids, &src_boxes[src]->guid, 1);
+                       src++; dest++;
+               } else if (ret < 0) {
+                       /* exists only in source */
+                       array_append(guids, &src_boxes[src]->guid, 1);
+                       src++;
+               } else {
+                       /* exists only in dest */
+                       dest++;
+               }
+       }
+       for (; src < src_count; src++)
+               array_append(guids, &src_boxes[src]->guid, 1);
+}
+
 static struct dsync_brain_mailbox_sync *
 dsync_brain_msg_sync_init(struct dsync_brain *brain)
 {
        struct dsync_brain_mailbox_sync *sync;
-       ARRAY_DEFINE(guids, mailbox_guid_t);
-       struct dsync_mailbox *const *mailboxes;
-       unsigned int i, count;
+       ARRAY_TYPE(mailbox_guid) guids;
+       unsigned int count;
        pool_t pool;
 
-       /* initialize message iteration on both workers */
-       mailboxes = array_get(&brain->src_mailbox_list->mailboxes, &count);
-       t_array_init(&guids, count);
-       for (i = 0; i < count; i++)
-               array_append(&guids, &mailboxes[i]->guid, 1);
+       t_array_init(&guids, array_count(&brain->src_mailbox_list->mailboxes));
+       dsync_brain_get_changed_mailboxes(brain, &guids);
 
        pool = pool_alloconly_create("dsync brain mailbox sync", 1024*256);
        sync = p_new(pool, struct dsync_brain_mailbox_sync, 1);
@@ -432,6 +467,9 @@ dsync_brain_msg_sync_init(struct dsync_brain *brain)
        i_array_init(&sync->uid_conflicts, 128);
        i_array_init(&sync->new_msgs, 128);
        i_array_init(&sync->copy_retry_indexes, 32);
+
+       /* initialize message iteration on both workers */
+       count = array_count(&guids);
        sync->src_msg_iter =
                dsync_brain_msg_iter_init(sync, brain->src_worker,
                                          array_idx(&guids, 0), count);
index 2e6f90361da2f72b02622e8ae4c047eb5e348de3..9bc75442fc8a5cc7de7e97d6fc309a111b5af6d2 100644 (file)
@@ -6,6 +6,7 @@
 typedef struct {
        uint8_t guid[MAILBOX_GUID_SIZE];
 } mailbox_guid_t;
+ARRAY_DEFINE_TYPE(mailbox_guid, mailbox_guid_t);
 
 struct dsync_mailbox {
        const char *name;
index 01d7e2909550705f59500e65803c761891a388f1..7a3bfe3226ef53b3b8e2e4b7e3d7914a710fc32c 100644 (file)
@@ -14,6 +14,7 @@
 enum {
        FLAG_EXISTS     = 0x01,
        FLAG_CREATED    = 0x02,
+       FLAG_UNCHANGED  = 0x04
 };
 
 struct test_dsync_mailbox {
@@ -72,6 +73,10 @@ static struct test_dsync_mailbox basic_mailboxes[] = {
          box3_dest_msgs, FLAG_EXISTS },
        { { "dir1", { { 0, } }, 0, 0, 0 }, NULL, NULL, FLAG_EXISTS },
        { { "dir2", { { 0, } }, 0, 0, 0 }, NULL, NULL, 0 },
+       { { "box4", { { 0x46, 0x2d, 0xa3, 0x24, 0x2e, 0x5e, 0x28, 0x67,
+                       0xa6, 0xc7, 0xca, 0x8a, 0xe7, 0x36, 0xd4, 0xa4 } },
+           2142, 445, 53535 }, box3_src_msgs,
+         box3_dest_msgs, FLAG_EXISTS | FLAG_UNCHANGED },
        { { NULL, { { 0, } }, 0, 0, 0 }, NULL, NULL, 0 }
 };
 
@@ -121,6 +126,8 @@ static void test_dsync_sync_msgs(struct test_dsync_worker *worker, bool dest)
                msgs = dest ? mailboxes[i].dest_msgs : mailboxes[i].src_msgs;
                if (msgs == NULL)
                        continue;
+               if ((mailboxes[i].dest_flags & FLAG_UNCHANGED) != 0)
+                       continue;
 
                for (j = 0; msgs[j].guid != NULL; j++) {
                        test_msg.msg = msgs[j];
@@ -309,8 +316,10 @@ test_dsync_brain_verify_msg_events(struct test_dsync_worker *dest_test_worker)
 
        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);
+       for (i = 0; mailboxes[i].box.name != NULL; i++) {
+               if ((mailboxes[i].dest_flags & FLAG_UNCHANGED) == 0)
+                       test_dsync_brain_verify_mailbox(&mailboxes[i], &events);
+       }
        test_assert(events == events_end);
 }
 
@@ -323,7 +332,7 @@ test_dsync_brain_run(const struct test_dsync_mailbox *test_mailboxes,
        struct test_dsync_worker *src_test_worker, *dest_test_worker;
        struct dsync_mailbox new_box;
        struct test_dsync_box_event box_event;
-       unsigned int i, box_count;
+       unsigned int i, j, box_count;
 
        box_count = 0;
        while (test_mailboxes[box_count].box.name != NULL)
@@ -345,7 +354,9 @@ test_dsync_brain_run(const struct test_dsync_mailbox *test_mailboxes,
                src_test_worker->box_iter.next_box = &mailboxes[i].box;
                src_worker->input_callback(src_worker->input_context);
 
-               if (mailboxes[i].dest_flags & FLAG_EXISTS) {
+               if ((mailboxes[i].dest_flags & FLAG_EXISTS) != 0) {
+                       if ((mailboxes[i].dest_flags & FLAG_UNCHANGED) == 0)
+                               mailboxes[i].box.highest_modseq++;
                        dest_test_worker->box_iter.next_box = &mailboxes[i].box;
                        dest_worker->input_callback(dest_worker->input_context);
                }
@@ -374,11 +385,14 @@ test_dsync_brain_run(const struct test_dsync_mailbox *test_mailboxes,
              test_dsync_mailbox_cmp);
 
        /* start syncing messages */
-       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],
+       for (i = j = 0; mailboxes[i].box.name != NULL; i++) {
+               if ((mailboxes[i].dest_flags & FLAG_UNCHANGED) != 0)
+                       continue;
+               test_assert(memcmp(&dest_test_worker->msg_iter_mailboxes[j],
                                   mailboxes[i].box.guid.guid, MAILBOX_GUID_SIZE) == 0);
+               j++;
        }
+       test_assert(dest_test_worker->msg_iter_mailbox_count == j);
        test_dsync_sync_msgs(src_test_worker, FALSE);
        test_dsync_sync_msgs(dest_test_worker, TRUE);