Mercurial > dovecot > core-2.2
changeset 15496:5d90e2aa1ba8
dsync: Use private modseqs to support syncing private flags in shared mailboxes.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Fri, 04 Jan 2013 01:13:05 +0200 |
parents | 69371578720f |
children | 5bb879b6e3f3 |
files | src/doveadm/dsync/dsync-brain-mailbox.c src/doveadm/dsync/dsync-brain-mails.c src/doveadm/dsync/dsync-ibc-stream.c src/doveadm/dsync/dsync-mail.c src/doveadm/dsync/dsync-mail.h src/doveadm/dsync/dsync-mailbox-export.c src/doveadm/dsync/dsync-mailbox-export.h src/doveadm/dsync/dsync-mailbox-import.c src/doveadm/dsync/dsync-mailbox-import.h src/doveadm/dsync/dsync-mailbox-state.c src/doveadm/dsync/dsync-mailbox-state.h src/doveadm/dsync/dsync-mailbox.h src/doveadm/dsync/dsync-transaction-log-scan.c src/doveadm/dsync/dsync-transaction-log-scan.h |
diffstat | 14 files changed, 176 insertions(+), 60 deletions(-) [+] |
line wrap: on
line diff
--- a/src/doveadm/dsync/dsync-brain-mailbox.c Fri Jan 04 01:12:24 2013 +0200 +++ b/src/doveadm/dsync/dsync-brain-mailbox.c Fri Jan 04 01:13:05 2013 +0200 @@ -140,17 +140,20 @@ { enum dsync_mailbox_exporter_flags exporter_flags = 0; uint32_t last_common_uid, highest_wanted_uid; - uint64_t last_common_modseq; + uint64_t last_common_modseq, last_common_pvt_modseq; i_assert(brain->log_scan == NULL); last_common_uid = brain->mailbox_state.last_common_uid; last_common_modseq = brain->mailbox_state.last_common_modseq; + last_common_pvt_modseq = brain->mailbox_state.last_common_pvt_modseq; highest_wanted_uid = last_common_uid == 0 ? (uint32_t)-1 : last_common_uid; if (dsync_transaction_log_scan_init(brain->box->view, + brain->box->view_pvt, highest_wanted_uid, last_common_modseq, + last_common_pvt_modseq, &brain->log_scan) < 0) { i_error("Failed to read transaction log for mailbox %s", mailbox_get_vname(brain->box)); @@ -165,7 +168,7 @@ brain->box_exporter = brain->backup_recv ? NULL : dsync_mailbox_export_init(brain->box, brain->log_scan, - last_common_uid, last_common_modseq, + last_common_uid, exporter_flags); return 0; } @@ -176,7 +179,7 @@ enum dsync_mailbox_import_flags import_flags = 0; const struct dsync_mailbox_state *state; uint32_t last_common_uid; - uint64_t last_common_modseq; + uint64_t last_common_modseq, last_common_pvt_modseq; i_assert(brain->box_importer == NULL); i_assert(brain->log_scan != NULL); @@ -191,9 +194,11 @@ if (state != NULL) { last_common_uid = state->last_common_uid; last_common_modseq = state->last_common_modseq; + last_common_pvt_modseq = state->last_common_pvt_modseq; } else { last_common_uid = 0; last_common_modseq = 0; + last_common_pvt_modseq = 0; } if (brain->guid_requests) @@ -208,9 +213,11 @@ brain->box_importer = brain->backup_send ? NULL : dsync_mailbox_import_init(brain->box, brain->log_scan, last_common_uid, last_common_modseq, + last_common_pvt_modseq, remote_dsync_box->uid_next, remote_dsync_box->first_recent_uid, remote_dsync_box->highest_modseq, + remote_dsync_box->highest_pvt_modseq, import_flags); } @@ -228,13 +235,14 @@ } if (brain->box_importer != NULL) { uint32_t last_common_uid; - uint64_t last_common_modseq; + uint64_t last_common_modseq, last_common_pvt_modseq; bool changes_during_sync; i_assert(brain->failed); (void)dsync_mailbox_import_deinit(&brain->box_importer, &last_common_uid, &last_common_modseq, + &last_common_pvt_modseq, &changes_during_sync); } if (brain->log_scan != NULL) @@ -248,7 +256,8 @@ { const enum mailbox_status_items status_items = STATUS_UIDVALIDITY | STATUS_UIDNEXT | STATUS_MESSAGES | - STATUS_FIRST_RECENT_UID | STATUS_HIGHESTMODSEQ; + STATUS_FIRST_RECENT_UID | STATUS_HIGHESTMODSEQ | + STATUS_HIGHESTPVTMODSEQ; const enum mailbox_metadata_items metadata_items = MAILBOX_METADATA_CACHE_FIELDS | MAILBOX_METADATA_GUID; struct mailbox_status status; @@ -283,6 +292,7 @@ dsync_box_r->messages_count = status.messages; dsync_box_r->first_recent_uid = status.first_recent_uid; dsync_box_r->highest_modseq = status.highest_modseq; + dsync_box_r->highest_pvt_modseq = status.highest_pvt_modseq; dsync_box_r->cache_fields = *metadata.cache_fields; return 1; } @@ -300,7 +310,8 @@ return state == NULL || state->last_uidvalidity != dsync_box->uid_validity || state->last_common_uid+1 != dsync_box->uid_next || - state->last_common_modseq != dsync_box->highest_modseq; + state->last_common_modseq != dsync_box->highest_modseq || + state->last_common_pvt_modseq != dsync_box->highest_pvt_modseq; } static int @@ -406,6 +417,7 @@ const struct dsync_mailbox *box2) { return box1->highest_modseq != box2->highest_modseq || + box1->highest_pvt_modseq != box2->highest_pvt_modseq || box1->messages_count != box2->messages_count || box1->uid_next != box2->uid_next || box1->uid_validity != box2->uid_validity ||
--- a/src/doveadm/dsync/dsync-brain-mails.c Fri Jan 04 01:12:24 2013 +0200 +++ b/src/doveadm/dsync/dsync-brain-mails.c Fri Jan 04 01:13:05 2013 +0200 @@ -165,10 +165,13 @@ state.last_common_uid = brain->local_dsync_box.uid_next-1; state.last_common_modseq = brain->local_dsync_box.highest_modseq; + state.last_common_pvt_modseq = + brain->local_dsync_box.highest_pvt_modseq; } else { if (dsync_mailbox_import_deinit(&brain->box_importer, &state.last_common_uid, &state.last_common_modseq, + &state.last_common_pvt_modseq, &changes_during_sync) < 0) { i_error("Importing mailbox %s failed", mailbox_get_vname(brain->box));
--- a/src/doveadm/dsync/dsync-ibc-stream.c Fri Jan 04 01:12:24 2013 +0200 +++ b/src/doveadm/dsync/dsync-ibc-stream.c Fri Jan 04 01:13:05 2013 +0200 @@ -66,7 +66,7 @@ { .name = "mailbox_state", .chr = 'S', .required_keys = "mailbox_guid last_uidvalidity last_common_uid " - "last_common_modseq" + "last_common_modseq last_common_pvt_modseq" }, { .name = "mailbox_tree_node", .chr = 'N', @@ -81,14 +81,14 @@ }, { .name = "mailbox", .chr = 'B', - .required_keys = "mailbox_guid uid_validity uid_next " - "messages_count first_recent_uid highest_modseq", + .required_keys = "mailbox_guid uid_validity uid_next messages_count " + "first_recent_uid highest_modseq highest_pvt_modseq", .optional_keys = "mailbox_lost cache_fields" }, { .name = "mail_change", .chr = 'C', .required_keys = "type uid", - .optional_keys = "guid hdr_hash modseq save_timestamp " + .optional_keys = "guid hdr_hash modseq pvt_modseq save_timestamp " "add_flags remove_flags final_flags " "keywords_reset keyword_changes" }, @@ -642,6 +642,8 @@ dec2str(state->last_common_uid)); dsync_serializer_encode_add(encoder, "last_common_modseq", dec2str(state->last_common_modseq)); + dsync_serializer_encode_add(encoder, "last_common_pvt_modseq", + dec2str(state->last_common_pvt_modseq)); dsync_serializer_encode_finish(&encoder, str); dsync_ibc_stream_send_string(ibc, str); @@ -682,6 +684,11 @@ dsync_ibc_input_error(ibc, decoder, "Invalid last_common_modseq"); return DSYNC_IBC_RECV_RET_TRYAGAIN; } + value = dsync_deserializer_decode_get(decoder, "last_common_pvt_modseq"); + if (str_to_uint64(value, &state_r->last_common_pvt_modseq) < 0) { + dsync_ibc_input_error(ibc, decoder, "Invalid last_common_pvt_modseq"); + return DSYNC_IBC_RECV_RET_TRYAGAIN; + } return DSYNC_IBC_RECV_RET_OK; } @@ -1002,6 +1009,8 @@ dec2str(dsync_box->first_recent_uid)); dsync_serializer_encode_add(encoder, "highest_modseq", dec2str(dsync_box->highest_modseq)); + dsync_serializer_encode_add(encoder, "highest_pvt_modseq", + dec2str(dsync_box->highest_pvt_modseq)); value = get_cache_fields(ibc, dsync_box); if (value != NULL) @@ -1113,6 +1122,11 @@ dsync_ibc_input_error(ibc, decoder, "Invalid highest_modseq"); return DSYNC_IBC_RECV_RET_TRYAGAIN; } + value = dsync_deserializer_decode_get(decoder, "highest_pvt_modseq"); + if (str_to_uint64(value, &box->highest_pvt_modseq) < 0) { + dsync_ibc_input_error(ibc, decoder, "Invalid highest_pvt_modseq"); + return DSYNC_IBC_RECV_RET_TRYAGAIN; + } p_array_init(&box->cache_fields, pool, 32); if (dsync_deserializer_decode_try(decoder, "cache_fields", &value)) { @@ -1164,6 +1178,10 @@ dsync_serializer_encode_add(encoder, "modseq", dec2str(change->modseq)); } + if (change->pvt_modseq != 0) { + dsync_serializer_encode_add(encoder, "pvt_modseq", + dec2str(change->pvt_modseq)); + } if (change->save_timestamp != 0) { dsync_serializer_encode_add(encoder, "save_timestamp", dec2str(change->save_timestamp)); @@ -1252,6 +1270,11 @@ dsync_ibc_input_error(ibc, decoder, "Invalid modseq"); return DSYNC_IBC_RECV_RET_TRYAGAIN; } + if (dsync_deserializer_decode_try(decoder, "pvt_modseq", &value) && + str_to_uint64(value, &change->pvt_modseq) < 0) { + dsync_ibc_input_error(ibc, decoder, "Invalid pvt_modseq"); + return DSYNC_IBC_RECV_RET_TRYAGAIN; + } if (dsync_deserializer_decode_try(decoder, "save_timestamp", &value) && str_to_time(value, &change->save_timestamp) < 0) { dsync_ibc_input_error(ibc, decoder, "Invalid save_timestamp");
--- a/src/doveadm/dsync/dsync-mail.c Fri Jan 04 01:12:24 2013 +0200 +++ b/src/doveadm/dsync/dsync-mail.c Fri Jan 04 01:13:05 2013 +0200 @@ -73,6 +73,7 @@ } dest_r->hdr_hash = p_strdup(pool, src->hdr_hash); dest_r->modseq = src->modseq; + dest_r->pvt_modseq = src->pvt_modseq; dest_r->save_timestamp = src->save_timestamp; dest_r->add_flags = src->add_flags;
--- a/src/doveadm/dsync/dsync-mail.h Fri Jan 04 01:12:24 2013 +0200 +++ b/src/doveadm/dsync/dsync-mail.h Fri Jan 04 01:13:05 2013 +0200 @@ -49,6 +49,9 @@ /* Message's current modseq (saves, flag changes) */ uint64_t modseq; + /* Message's current private modseq (for private flags in + shared mailboxes, otherwise 0) */ + uint64_t pvt_modseq; /* Message's save timestamp (saves) */ time_t save_timestamp; @@ -57,6 +60,7 @@ /* Flags added/removed since last sync, and final flags containing flags that exist now but haven't changed */ uint8_t add_flags, remove_flags, final_flags; + uint8_t add_pvt_flags, remove_pvt_flags; /* Remove all keywords before applying changes. This is used only with old transaction logs, new ones never reset keywords (just explicitly remove unwanted keywords) */
--- a/src/doveadm/dsync/dsync-mailbox-export.c Fri Jan 04 01:12:24 2013 +0200 +++ b/src/doveadm/dsync/dsync-mailbox-export.c Fri Jan 04 01:13:05 2013 +0200 @@ -21,7 +21,6 @@ struct mailbox *box; struct dsync_transaction_log_scan *log_scan; uint32_t last_common_uid; - uint64_t last_common_modseq; struct mailbox_transaction_context *trans; struct mail_search_context *search_ctx; @@ -99,6 +98,7 @@ i_assert((change->add_flags & change->remove_flags) == 0); change->modseq = mail_get_modseq(mail); + change->pvt_modseq = mail_get_pvt_modseq(mail); change->final_flags = mail_get_flags(mail) & MAIL_FLAGS_NONRECENT; keywords = mail_get_keywords(mail); @@ -416,7 +416,6 @@ dsync_mailbox_export_init(struct mailbox *box, struct dsync_transaction_log_scan *log_scan, uint32_t last_common_uid, - uint64_t last_common_modseq, enum dsync_mailbox_exporter_flags flags) { struct dsync_mailbox_exporter *exporter; @@ -429,7 +428,6 @@ exporter->box = box; exporter->log_scan = log_scan; exporter->last_common_uid = last_common_uid; - exporter->last_common_modseq = last_common_modseq; exporter->auto_export_mails = (flags & DSYNC_MAILBOX_EXPORTER_FLAG_AUTO_EXPORT_MAILS) != 0; exporter->mails_have_guids =
--- a/src/doveadm/dsync/dsync-mailbox-export.h Fri Jan 04 01:12:24 2013 +0200 +++ b/src/doveadm/dsync/dsync-mailbox-export.h Fri Jan 04 01:13:05 2013 +0200 @@ -10,7 +10,6 @@ dsync_mailbox_export_init(struct mailbox *box, struct dsync_transaction_log_scan *log_scan, uint32_t last_common_uid, - uint64_t last_common_modseq, enum dsync_mailbox_exporter_flags flags); const struct dsync_mail_change * dsync_mailbox_export_next(struct dsync_mailbox_exporter *exporter);
--- a/src/doveadm/dsync/dsync-mailbox-import.c Fri Jan 04 01:12:24 2013 +0200 +++ b/src/doveadm/dsync/dsync-mailbox-import.c Fri Jan 04 01:13:05 2013 +0200 @@ -40,10 +40,10 @@ pool_t pool; struct mailbox *box; uint32_t last_common_uid; - uint64_t last_common_modseq; + uint64_t last_common_modseq, last_common_pvt_modseq; uint32_t remote_uid_next; uint32_t remote_first_recent_uid; - uint64_t remote_highest_modseq; + uint64_t remote_highest_modseq, remote_highest_pvt_modseq; struct mailbox_transaction_context *trans, *ext_trans; struct mail_search_context *search_ctx; @@ -70,7 +70,7 @@ unsigned int mail_request_idx; uint32_t prev_uid, next_local_seq, local_uid_next; - uint64_t local_initial_highestmodseq; + uint64_t local_initial_highestmodseq, local_initial_highestpvtmodseq; unsigned int failed:1; unsigned int last_common_uid_found:1; @@ -112,9 +112,11 @@ struct dsync_transaction_log_scan *log_scan, uint32_t last_common_uid, uint64_t last_common_modseq, + uint64_t last_common_pvt_modseq, uint32_t remote_uid_next, uint32_t remote_first_recent_uid, uint64_t remote_highest_modseq, + uint64_t remote_highest_pvt_modseq, enum dsync_mailbox_import_flags flags) { const enum mailbox_transaction_flags ext_trans_flags = @@ -132,11 +134,13 @@ importer->box = box; importer->last_common_uid = last_common_uid; importer->last_common_modseq = last_common_modseq; + importer->last_common_pvt_modseq = last_common_pvt_modseq; importer->last_common_uid_found = last_common_uid != 0 || last_common_modseq != 0; importer->remote_uid_next = remote_uid_next; importer->remote_first_recent_uid = remote_first_recent_uid; importer->remote_highest_modseq = remote_highest_modseq; + importer->remote_highest_pvt_modseq = remote_highest_pvt_modseq; hash_table_create(&importer->import_guids, pool, 0, str_hash, strcmp); hash_table_create_direct(&importer->import_uids, pool, 0); @@ -162,11 +166,12 @@ importer->revert_local_changes = (flags & DSYNC_MAILBOX_IMPORT_FLAG_REVERT_LOCAL_CHANGES) != 0; - mailbox_get_open_status(importer->box, - STATUS_UIDNEXT | STATUS_HIGHESTMODSEQ, + mailbox_get_open_status(importer->box, STATUS_UIDNEXT | + STATUS_HIGHESTMODSEQ | STATUS_HIGHESTPVTMODSEQ, &status); importer->local_uid_next = status.uidnext; importer->local_initial_highestmodseq = status.highest_modseq; + importer->local_initial_highestpvtmodseq = status.highest_pvt_modseq; dsync_mailbox_import_search_init(importer); importer->local_changes = dsync_transaction_log_scan_get_hash(log_scan); @@ -428,27 +433,40 @@ static void merge_flags(uint32_t local_final, uint32_t local_add, uint32_t local_remove, uint32_t remote_final, uint32_t remote_add, uint32_t remote_remove, - bool prefer_remote, + uint32_t pvt_mask, bool prefer_remote, bool prefer_pvt_remote, uint32_t *change_add_r, uint32_t *change_remove_r) { uint32_t combined_add, combined_remove, conflict_flags; - uint32_t local_wanted, remote_wanted; + uint32_t local_wanted, remote_wanted, conflict_pvt_flags; /* resolve conflicts */ conflict_flags = local_add & remote_remove; if (conflict_flags != 0) { + conflict_pvt_flags = conflict_flags & pvt_mask; + conflict_flags &= ~pvt_mask; if (prefer_remote) local_add &= ~conflict_flags; else remote_remove &= ~conflict_flags; + if (prefer_pvt_remote) + local_add &= ~conflict_pvt_flags; + else + remote_remove &= ~conflict_pvt_flags; } - conflict_flags = local_remove & remote_add; + conflict_flags = (local_remove & remote_add) & ~pvt_mask; if (conflict_flags != 0) { + conflict_pvt_flags = conflict_flags & pvt_mask; + conflict_flags &= ~pvt_mask; if (prefer_remote) local_remove &= ~conflict_flags; else remote_add &= ~conflict_flags; + if (prefer_pvt_remote) + local_remove &= ~conflict_pvt_flags; + else + remote_add &= ~conflict_pvt_flags; } + combined_add = local_add|remote_add; combined_remove = local_remove|remote_remove; i_assert((combined_add & combined_remove) == 0); @@ -459,10 +477,15 @@ conflict_flags = local_wanted ^ remote_wanted; if (conflict_flags != 0) { - if (prefer_remote) + if (prefer_remote && prefer_pvt_remote) local_wanted = remote_wanted; - /*else - remote_wanted = local_wanted;*/ + else if (prefer_remote && !prefer_pvt_remote) { + local_wanted = (local_wanted & pvt_mask) | + (remote_wanted & ~pvt_mask); + } else if (!prefer_remote && prefer_pvt_remote) { + local_wanted = (local_wanted & ~pvt_mask) | + (remote_wanted & pvt_mask); + } } *change_add_r = local_wanted & ~local_final; @@ -609,7 +632,8 @@ for (i = 0; i < array_size; i++) { merge_flags(local_final[i], local_add[i], local_remove[i], remote_final[i], remote_add[i], remote_remove[i], - prefer_remote, &change_add[i], &change_remove[i]); + 0, prefer_remote, prefer_remote, + &change_add[i], &change_remove[i]); if (change_add[i] != 0) { keywords_append(&add_keywords, &all_keywords, change_add[i], i*32); @@ -673,6 +697,7 @@ mail_update_flags(mail, MODIFY_REPLACE, change->add_flags | change->final_flags); mail_update_modseq(mail, change->modseq); + mail_update_pvt_modseq(mail, change->pvt_modseq); } static void @@ -684,7 +709,7 @@ uint32_t change_add, change_remove; ARRAY_TYPE(const_string) local_keyword_changes = ARRAY_INIT; struct mail *mail; - bool prefer_remote; + bool prefer_remote, prefer_pvt_remote; i_assert((change->add_flags & change->remove_flags) == 0); @@ -723,11 +748,19 @@ they become unsynced. */ prefer_remote = !importer->master_brain; } + if (mail_get_pvt_modseq(mail) < change->pvt_modseq) + prefer_pvt_remote = TRUE; + else if (mail_get_pvt_modseq(mail) > change->pvt_modseq) + prefer_pvt_remote = FALSE; + else + prefer_pvt_remote = !importer->master_brain; /* merge flags */ merge_flags(mail_get_flags(mail), local_add, local_remove, change->final_flags, change->add_flags, change->remove_flags, - prefer_remote, &change_add, &change_remove); + mailbox_get_private_flags_mask(mail->box), + prefer_remote, prefer_pvt_remote, + &change_add, &change_remove); if (change_add != 0) mail_update_flags(mail, MODIFY_ADD, change_add); @@ -738,6 +771,7 @@ merge_keywords(mail, &local_keyword_changes, &change->keyword_changes, prefer_remote); mail_update_modseq(mail, change->modseq); + mail_update_pvt_modseq(mail, change->pvt_modseq); } static void @@ -1138,6 +1172,9 @@ (void)mailbox_enable(importer->box, MAILBOX_FEATURE_CONDSTORE); mailbox_save_set_min_modseq(save_ctx, change->modseq); } + /* FIXME: if there already are private flags, they get lost because + saving can't handle updating private index. they get added on the + next sync though. if this is fixed here, set min_pvt_modseq also. */ } static int @@ -1409,6 +1446,7 @@ I_MIN(importer->last_common_uid+1, importer->remote_first_recent_uid); update.min_highest_modseq = importer->remote_highest_modseq; + update.min_highest_pvt_modseq = importer->remote_highest_pvt_modseq; if (mailbox_update(importer->box, &update) < 0) { i_error("Mailbox update failed to mailbox %s: %s", @@ -1477,6 +1515,7 @@ int dsync_mailbox_import_deinit(struct dsync_mailbox_importer **_importer, uint32_t *last_common_uid_r, uint64_t *last_common_modseq_r, + uint64_t *last_common_pvt_modseq_r, bool *changes_during_sync_r) { struct dsync_mailbox_importer *importer = *_importer; @@ -1517,14 +1556,16 @@ array_free(&importer->mail_requests); *last_common_uid_r = importer->last_common_uid; - if (!*changes_during_sync_r) + if (!*changes_during_sync_r) { *last_common_modseq_r = importer->remote_highest_modseq; - else { + *last_common_pvt_modseq_r = importer->remote_highest_pvt_modseq; + } else { /* local changes occurred during dsync. we exported changes up to local_initial_highestmodseq, so all of the changes have happened after it. we want the next run to see those changes, so return it as the last common modseq */ *last_common_modseq_r = importer->local_initial_highestmodseq; + *last_common_pvt_modseq_r = importer->local_initial_highestpvtmodseq; } ret = importer->failed ? -1 : 0;
--- a/src/doveadm/dsync/dsync-mailbox-import.h Fri Jan 04 01:12:24 2013 +0200 +++ b/src/doveadm/dsync/dsync-mailbox-import.h Fri Jan 04 01:13:05 2013 +0200 @@ -18,9 +18,11 @@ struct dsync_transaction_log_scan *log_scan, uint32_t last_common_uid, uint64_t last_common_modseq, + uint64_t last_common_pvt_modseq, uint32_t remote_uid_next, uint32_t remote_first_recent_uid, uint64_t remote_highest_modseq, + uint64_t remote_highest_pvt_modseq, enum dsync_mailbox_import_flags flags); void dsync_mailbox_import_change(struct dsync_mailbox_importer *importer, const struct dsync_mail_change *change); @@ -32,6 +34,7 @@ int dsync_mailbox_import_deinit(struct dsync_mailbox_importer **importer, uint32_t *last_common_uid_r, uint64_t *last_common_modseq_r, + uint64_t *last_common_pvt_modseq_r, bool *changes_during_sync_r); #endif
--- a/src/doveadm/dsync/dsync-mailbox-state.c Fri Jan 04 01:12:24 2013 +0200 +++ b/src/doveadm/dsync/dsync-mailbox-state.c Fri Jan 04 01:13:05 2013 +0200 @@ -40,6 +40,8 @@ put_uint32(buf, state->last_common_uid); put_uint32(buf, state->last_common_modseq & 0xffffffffU); put_uint32(buf, state->last_common_modseq >> 32); + put_uint32(buf, state->last_common_pvt_modseq & 0xffffffffU); + put_uint32(buf, state->last_common_pvt_modseq >> 32); if (buf->used % 3 == 0) { crc = crc32_data_more(crc, buf->data, buf->used); base64_encode(buf->data, buf->used, output); @@ -93,6 +95,9 @@ state->last_common_modseq = get_uint32(data + GUID_128_SIZE + 8) | (uint64_t)get_uint32(data + GUID_128_SIZE + 12) << 32; + state->last_common_pvt_modseq = + get_uint32(data + GUID_128_SIZE + 16) | + (uint64_t)get_uint32(data + GUID_128_SIZE + 20) << 32; guid_p = state->mailbox_guid; hash_table_insert(states, guid_p, state); }
--- a/src/doveadm/dsync/dsync-mailbox-state.h Fri Jan 04 01:12:24 2013 +0200 +++ b/src/doveadm/dsync/dsync-mailbox-state.h Fri Jan 04 01:13:05 2013 +0200 @@ -8,6 +8,7 @@ uint32_t last_uidvalidity; uint32_t last_common_uid; uint64_t last_common_modseq; + uint64_t last_common_pvt_modseq; }; ARRAY_DEFINE_TYPE(dsync_mailbox_state, struct dsync_mailbox_state); HASH_TABLE_DEFINE_TYPE(dsync_mailbox_state, uint8_t *, struct dsync_mailbox_state *);
--- a/src/doveadm/dsync/dsync-mailbox.h Fri Jan 04 01:12:24 2013 +0200 +++ b/src/doveadm/dsync/dsync-mailbox.h Fri Jan 04 01:13:05 2013 +0200 @@ -10,7 +10,7 @@ bool mailbox_lost; uint32_t uid_validity, uid_next, messages_count, first_recent_uid; - uint64_t highest_modseq; + uint64_t highest_modseq, highest_pvt_modseq; ARRAY_TYPE(mailbox_cache_field) cache_fields; };
--- a/src/doveadm/dsync/dsync-transaction-log-scan.c Fri Jan 04 01:12:24 2013 +0200 +++ b/src/doveadm/dsync/dsync-transaction-log-scan.c Fri Jan 04 01:13:05 2013 +0200 @@ -105,11 +105,11 @@ } static void -log_add_expunge_guid(struct dsync_transaction_log_scan *ctx, const void *data, +log_add_expunge_guid(struct dsync_transaction_log_scan *ctx, + struct mail_index_view *view, const void *data, const struct mail_transaction_header *hdr) { const struct mail_transaction_expunge_guid *rec = data, *end; - struct mail_index_view *view = ctx->view; struct dsync_mail_change *change; uint32_t seq; bool external; @@ -271,7 +271,7 @@ static void log_add_modseq_update(struct dsync_transaction_log_scan *ctx, const void *data, - const struct mail_transaction_header *hdr) + const struct mail_transaction_header *hdr, bool pvt_scan) { const struct mail_transaction_modseq_update *rec = data, *end; struct dsync_mail_change *change; @@ -292,16 +292,21 @@ modseq = rec->modseq_low32 | ((uint64_t)rec->modseq_high32 << 32); - if (change->modseq < modseq) - change->modseq = modseq; + if (!pvt_scan) { + if (change->modseq < modseq) + change->modseq = modseq; + } else { + if (change->pvt_modseq < modseq) + change->pvt_modseq = modseq; + } } } static int dsync_log_set(struct dsync_transaction_log_scan *ctx, + struct mail_index_view *view, bool pvt_scan, struct mail_transaction_log_view *log_view, uint64_t modseq) { - struct mail_index_view *view = ctx->view; uint32_t log_seq; uoff_t log_offset; bool reset; @@ -320,35 +325,25 @@ } if (ret == 0) { /* return everything we've got */ - ctx->returned_all_changes = TRUE; + if (!pvt_scan) + ctx->returned_all_changes = TRUE; return mail_transaction_log_view_set_all(log_view); } return ret < 0 ? -1 : 0; } -int dsync_transaction_log_scan_init(struct mail_index_view *view, - uint32_t highest_wanted_uid, - uint64_t modseq, - struct dsync_transaction_log_scan **scan_r) +static int +dsync_log_scan(struct dsync_transaction_log_scan *ctx, + struct mail_index_view *view, uint64_t modseq, bool pvt_scan) { - struct dsync_transaction_log_scan *ctx; struct mail_transaction_log_view *log_view; const struct mail_transaction_header *hdr; const void *data; uint32_t file_seq, max_seq; uoff_t file_offset, max_offset; - pool_t pool; - - pool = pool_alloconly_create(MEMPOOL_GROWING"dsync transaction log scan", - 10240); - ctx = p_new(pool, struct dsync_transaction_log_scan, 1); - ctx->pool = pool; - hash_table_create_direct(&ctx->changes, pool, 0); - ctx->view = view; - ctx->highest_wanted_uid = highest_wanted_uid; log_view = mail_transaction_log_view_open(view->index->log); - if (dsync_log_set(ctx, log_view, modseq) < 0) { + if (dsync_log_set(ctx, view, pvt_scan, log_view, modseq) < 0) { mail_transaction_log_view_close(&log_view); return -1; } @@ -376,10 +371,12 @@ switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) { case MAIL_TRANSACTION_EXPUNGE: - log_add_expunge(ctx, data, hdr); + if (!pvt_scan) + log_add_expunge(ctx, data, hdr); break; case MAIL_TRANSACTION_EXPUNGE_GUID: - log_add_expunge_guid(ctx, data, hdr); + if (!pvt_scan) + log_add_expunge_guid(ctx, view, data, hdr); break; case MAIL_TRANSACTION_FLAG_UPDATE: log_add_flag_update(ctx, data, hdr); @@ -393,15 +390,43 @@ } T_END; break; case MAIL_TRANSACTION_MODSEQ_UPDATE: - log_add_modseq_update(ctx, data, hdr); + log_add_modseq_update(ctx, data, hdr, pvt_scan); break; } } - ctx->last_log_seq = file_seq; - ctx->last_log_offset = file_offset; + if (!pvt_scan) { + ctx->last_log_seq = file_seq; + ctx->last_log_offset = file_offset; + } + mail_transaction_log_view_close(&log_view); + return 0; +} - mail_transaction_log_view_close(&log_view); +int dsync_transaction_log_scan_init(struct mail_index_view *view, + struct mail_index_view *pvt_view, + uint32_t highest_wanted_uid, + uint64_t modseq, uint64_t pvt_modseq, + struct dsync_transaction_log_scan **scan_r) +{ + struct dsync_transaction_log_scan *ctx; + pool_t pool; + + pool = pool_alloconly_create(MEMPOOL_GROWING"dsync transaction log scan", + 10240); + ctx = p_new(pool, struct dsync_transaction_log_scan, 1); + ctx->pool = pool; + hash_table_create_direct(&ctx->changes, pool, 0); + ctx->view = view; + ctx->highest_wanted_uid = highest_wanted_uid; + + if (dsync_log_scan(ctx, view, modseq, FALSE) < 0) + return -1; + if (pvt_view != NULL) { + if (dsync_log_scan(ctx, pvt_view, pvt_modseq, TRUE) < 0) + return -1; + } + *scan_r = ctx; return 0; }
--- a/src/doveadm/dsync/dsync-transaction-log-scan.h Fri Jan 04 01:12:24 2013 +0200 +++ b/src/doveadm/dsync/dsync-transaction-log-scan.h Fri Jan 04 01:13:05 2013 +0200 @@ -8,8 +8,9 @@ struct dsync_transaction_log_scan; int dsync_transaction_log_scan_init(struct mail_index_view *view, + struct mail_index_view *pvt_view, uint32_t highest_wanted_uid, - uint64_t modseq, + uint64_t modseq, uint64_t pvt_modseq, struct dsync_transaction_log_scan **scan_r); HASH_TABLE_TYPE(dsync_uid_mail_change) dsync_transaction_log_scan_get_hash(struct dsync_transaction_log_scan *scan);