Mercurial > dovecot > core-2.2
changeset 18181:35e4a6ae8d85
dsync: Added -F parameter to sync only mails with[out] specific flag.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Tue, 20 Jan 2015 04:07:09 +0200 |
parents | 39d00448490f |
children | c18b2ffeb882 |
files | src/doveadm/doveadm-dsync.c src/doveadm/dsync/dsync-brain-mailbox.c src/doveadm/dsync/dsync-brain-private.h src/doveadm/dsync/dsync-brain.c src/doveadm/dsync/dsync-brain.h src/doveadm/dsync/dsync-ibc-pipe.c src/doveadm/dsync/dsync-ibc-stream.c src/doveadm/dsync/dsync-ibc.h src/doveadm/dsync/dsync-mailbox-import.c src/doveadm/dsync/dsync-mailbox-import.h |
diffstat | 10 files changed, 118 insertions(+), 19 deletions(-) [+] |
line wrap: on
line diff
--- a/src/doveadm/doveadm-dsync.c Tue Jan 20 03:23:29 2015 +0200 +++ b/src/doveadm/doveadm-dsync.c Tue Jan 20 04:07:09 2015 +0200 @@ -14,6 +14,7 @@ #include "strescape.h" #include "var-expand.h" #include "settings-parser.h" +#include "imap-util.h" #include "master-service.h" #include "master-service-ssl-settings.h" #include "mail-storage.h" @@ -37,7 +38,7 @@ #include <ctype.h> #include <sys/wait.h> -#define DSYNC_COMMON_GETOPT_ARGS "+1a:dEfg:l:m:n:NPr:Rs:t:Ux:" +#define DSYNC_COMMON_GETOPT_ARGS "+1a:dEfF:g:l:m:n:NPr:Rs:t:Ux:" #define DSYNC_REMOTE_CMD_EXIT_WAIT_SECS 30 /* The broken_char is mainly set to get a proper error message when trying to convert a mailbox with a name that can't be used properly translated between @@ -56,6 +57,7 @@ struct doveadm_mail_cmd_context ctx; enum dsync_brain_sync_type sync_type; const char *mailbox; + const char *sync_flags; const char *virtual_all_box; guid_128_t mailbox_guid; const char *state_input, *rawlog_path; @@ -544,6 +546,7 @@ } set.sync_since_timestamp = ctx->sync_since_timestamp; set.sync_box = ctx->mailbox; + set.sync_flag = ctx->sync_flags; set.virtual_all_box = ctx->virtual_all_box; memcpy(set.sync_box_guid, ctx->mailbox_guid, sizeof(set.sync_box_guid)); set.lock_timeout_secs = ctx->lock_timeout; @@ -924,6 +927,18 @@ case 'f': ctx->sync_type = DSYNC_BRAIN_SYNC_TYPE_FULL; break; + case 'F': { + const char *str = optarg; + + if (strchr(str, ' ') != NULL) + i_fatal("-F parameter doesn't support multiple flags currently"); + if (str[0] == '-') + str++; + if (str[0] == '\\' && imap_parse_system_flag(str) == 0) + i_fatal("Invalid system flag given for -F parameter: '%s'", str); + ctx->sync_flags = optarg; + break; + } case 'g': if (optarg[0] == '\0') ctx->no_mail_sync = TRUE;
--- a/src/doveadm/dsync/dsync-brain-mailbox.c Tue Jan 20 03:23:29 2015 +0200 +++ b/src/doveadm/dsync/dsync-brain-mailbox.c Tue Jan 20 04:07:09 2015 +0200 @@ -222,6 +222,7 @@ remote_dsync_box->highest_modseq, remote_dsync_box->highest_pvt_modseq, brain->sync_since_timestamp, + brain->sync_flag, import_flags); }
--- a/src/doveadm/dsync/dsync-brain-private.h Tue Jan 20 03:23:29 2015 +0200 +++ b/src/doveadm/dsync/dsync-brain-private.h Tue Jan 20 04:07:09 2015 +0200 @@ -57,6 +57,7 @@ const char *const *exclude_mailboxes; enum dsync_brain_sync_type sync_type; time_t sync_since_timestamp; + const char *sync_flag; char alt_char; unsigned int lock_timeout;
--- a/src/doveadm/dsync/dsync-brain.c Tue Jan 20 03:23:29 2015 +0200 +++ b/src/doveadm/dsync/dsync-brain.c Tue Jan 20 04:07:09 2015 +0200 @@ -186,6 +186,7 @@ brain->alt_char = set->mailbox_alt_char == '\0' ? '_' : set->mailbox_alt_char; brain->sync_since_timestamp = set->sync_since_timestamp; + brain->sync_flag = p_strdup(brain->pool, set->sync_flag); brain->sync_box = p_strdup(brain->pool, set->sync_box); brain->exclude_mailboxes = set->exclude_mailboxes == NULL ? NULL : p_strarray_dup(brain->pool, set->exclude_mailboxes); @@ -223,6 +224,7 @@ ibc_set.virtual_all_box = set->virtual_all_box; ibc_set.exclude_mailboxes = set->exclude_mailboxes; ibc_set.sync_since_timestamp = set->sync_since_timestamp; + ibc_set.sync_flags = set->sync_flag; memcpy(ibc_set.sync_box_guid, set->sync_box_guid, sizeof(ibc_set.sync_box_guid)); ibc_set.sync_type = sync_type; @@ -471,6 +473,7 @@ brain->exclude_mailboxes = ibc_set->exclude_mailboxes == NULL ? NULL : p_strarray_dup(brain->pool, ibc_set->exclude_mailboxes); brain->sync_since_timestamp = ibc_set->sync_since_timestamp; + brain->sync_flag = p_strdup(brain->pool, ibc_set->sync_flags); memcpy(brain->sync_box_guid, ibc_set->sync_box_guid, sizeof(brain->sync_box_guid)); i_assert(brain->sync_type == DSYNC_BRAIN_SYNC_TYPE_UNKNOWN);
--- a/src/doveadm/dsync/dsync-brain.h Tue Jan 20 03:23:29 2015 +0200 +++ b/src/doveadm/dsync/dsync-brain.h Tue Jan 20 04:07:09 2015 +0200 @@ -61,6 +61,9 @@ char mailbox_alt_char; /* Sync only mails with received timestamp at least this high. */ time_t sync_since_timestamp; + /* Sync only mails which contains / doesn't contain this flag. + '-' at the beginning means this flag must not exist. */ + const char *sync_flag; /* If non-zero, use dsync lock file for this user */ unsigned int lock_timeout_secs;
--- a/src/doveadm/dsync/dsync-ibc-pipe.c Tue Jan 20 03:23:29 2015 +0200 +++ b/src/doveadm/dsync/dsync-ibc-pipe.c Tue Jan 20 04:07:09 2015 +0200 @@ -172,6 +172,8 @@ p_strarray_dup(item->pool, set->exclude_mailboxes); memcpy(item->u.set.sync_box_guid, set->sync_box_guid, sizeof(item->u.set.sync_box_guid)); + item->u.set.sync_since_timestamp = set->sync_since_timestamp; + item->u.set.sync_flags = p_strdup(item->pool, set->sync_flags); } static enum dsync_ibc_recv_ret
--- a/src/doveadm/dsync/dsync-ibc-stream.c Tue Jan 20 03:23:29 2015 +0200 +++ b/src/doveadm/dsync/dsync-ibc-stream.c Tue Jan 20 04:07:09 2015 +0200 @@ -76,7 +76,7 @@ "debug sync_visible_namespaces exclude_mailboxes " "send_mail_requests backup_send backup_recv lock_timeout " "no_mail_sync no_backup_overwrite purge_remote " - "sync_since_timestamp virtual_all_box" + "sync_since_timestamp sync_flags virtual_all_box" }, { .name = "mailbox_state", .chr = 'S', @@ -658,6 +658,10 @@ dsync_serializer_encode_add(encoder, "sync_since_timestamp", t_strdup_printf("%ld", (long)set->sync_since_timestamp)); } + if (set->sync_flags != NULL) { + dsync_serializer_encode_add(encoder, "sync_flags", + set->sync_flags); + } if ((set->brain_flags & DSYNC_BRAIN_FLAG_SEND_MAIL_REQUESTS) != 0) dsync_serializer_encode_add(encoder, "send_mail_requests", ""); if ((set->brain_flags & DSYNC_BRAIN_FLAG_BACKUP_SEND) != 0) @@ -760,6 +764,8 @@ return DSYNC_IBC_RECV_RET_TRYAGAIN; } } + if (dsync_deserializer_decode_try(decoder, "sync_flags", &value)) + set->sync_flags = p_strdup(pool, value); if (dsync_deserializer_decode_try(decoder, "send_mail_requests", &value)) set->brain_flags |= DSYNC_BRAIN_FLAG_SEND_MAIL_REQUESTS; if (dsync_deserializer_decode_try(decoder, "backup_send", &value))
--- a/src/doveadm/dsync/dsync-ibc.h Tue Jan 20 03:23:29 2015 +0200 +++ b/src/doveadm/dsync/dsync-ibc.h Tue Jan 20 04:07:09 2015 +0200 @@ -57,6 +57,8 @@ const char *const *exclude_mailboxes; /* Sync only mails with received timestamp at least this high. */ time_t sync_since_timestamp; + /* Sync only mails with specified flags. */ + const char *sync_flags; enum dsync_brain_sync_type sync_type; enum dsync_brain_flags brain_flags;
--- a/src/doveadm/dsync/dsync-mailbox-import.c Tue Jan 20 03:23:29 2015 +0200 +++ b/src/doveadm/dsync/dsync-mailbox-import.c Tue Jan 20 04:07:09 2015 +0200 @@ -63,6 +63,10 @@ uint64_t remote_highest_modseq, remote_highest_pvt_modseq; time_t sync_since_timestamp; + enum mail_flags sync_flag; + const char *sync_keyword; + bool sync_flag_dontwant; + struct mailbox_transaction_context *trans, *ext_trans; struct mail_search_context *search_ctx; struct mail *mail, *ext_mail; @@ -187,7 +191,7 @@ uint32_t remote_first_recent_uid, uint64_t remote_highest_modseq, uint64_t remote_highest_pvt_modseq, - time_t sync_since_timestamp, + time_t sync_since_timestamp, const char *sync_flag, enum dsync_mailbox_import_flags flags) { struct dsync_mailbox_importer *importer; @@ -211,6 +215,16 @@ importer->remote_highest_pvt_modseq = remote_highest_pvt_modseq; importer->sync_since_timestamp = sync_since_timestamp; importer->stateful_import = importer->last_common_uid_found; + if (sync_flag != NULL) { + if (sync_flag[0] == '-') { + importer->sync_flag_dontwant = TRUE; + sync_flag++; + } + if (sync_flag[0] == '\\') + importer->sync_flag = imap_parse_system_flag(sync_flag); + else + importer->sync_keyword = p_strdup(pool, sync_flag); + } hash_table_create(&importer->import_guids, pool, 0, str_hash, strcmp); hash_table_create_direct(&importer->import_uids, pool, 0); @@ -1226,11 +1240,72 @@ mail_update_pvt_modseq(mail, new_modseq); } +static bool +dsync_mail_change_have_keyword(const struct dsync_mail_change *change, + const char *keyword) +{ + const char *const *strp; + + array_foreach(&change->keyword_changes, strp) { + switch ((*strp)[0]) { + case KEYWORD_CHANGE_FINAL: + case KEYWORD_CHANGE_ADD_AND_FINAL: + if (strcasecmp((*strp)+1, keyword) == 0) + return TRUE; + break; + default: + break; + } + } + return FALSE; +} + +static bool +dsync_mailbox_import_want_change(struct dsync_mailbox_importer *importer, + const struct dsync_mail_change *change, + const char **result_r) +{ + if (importer->sync_since_timestamp > 0) { + i_assert(change->received_timestamp > 0); + if (change->received_timestamp < importer->sync_since_timestamp) { + /* mail has too old timestamp - skip it */ + *result_r = "Ignoring missing local mail with too old timestamp"; + return FALSE; + } + } + if (importer->sync_flag != 0) { + bool have_flag = (change->final_flags & importer->sync_flag) != 0; + + if (have_flag && importer->sync_flag_dontwant) { + *result_r = "Ignoring missing local mail that doesn't have wanted flags"; + return FALSE; + } + if (!have_flag && !importer->sync_flag_dontwant) { + *result_r = "Ignoring missing local mail that has unwanted flags"; + return FALSE; + } + } + if (importer->sync_keyword != NULL) { + bool have_kw = dsync_mail_change_have_keyword(change, importer->sync_keyword); + + if (have_kw && importer->sync_flag_dontwant) { + *result_r = "Ignoring missing local mail that doesn't have wanted keywords"; + return FALSE; + } + if (!have_kw && !importer->sync_flag_dontwant) { + *result_r = "Ignoring missing local mail that has unwanted keywords"; + return FALSE; + } + } + return TRUE; +} + static void dsync_mailbox_import_save(struct dsync_mailbox_importer *importer, const struct dsync_mail_change *change) { struct dsync_mail_change *save; + const char *result; i_assert(change->guid != NULL); @@ -1241,13 +1316,8 @@ dsync_mailbox_import_flag_change(importer, change); return; } - if (importer->sync_since_timestamp > 0) { - i_assert(change->received_timestamp > 0); - if (change->received_timestamp < importer->sync_since_timestamp) { - /* mail has too old timestamp - skip it */ - return; - } - } + if (!dsync_mailbox_import_want_change(importer, change, &result)) + return; save = p_new(importer->pool, struct dsync_mail_change, 1); dsync_mail_change_dup(importer->pool, change, save); @@ -1495,10 +1565,9 @@ return; } i_assert(change->guid != NULL); - if (importer->sync_since_timestamp > 0 && - change->received_timestamp < importer->sync_since_timestamp) { - *result_r = "Ignoring missing local mail with too old timestamp"; - } else if (importer->local_uid_next <= change->uid) { + if (!dsync_mailbox_import_want_change(importer, change, result_r)) + ; + else if (importer->local_uid_next <= change->uid) { dsync_mailbox_common_uid_found(importer); *result_r = "Mail's UID is above local UIDNEXT"; } else if (importer->revert_local_changes) { @@ -1538,11 +1607,8 @@ return; } /* mail exists remotely, but doesn't exist locally. */ - if (importer->sync_since_timestamp > 0 && - change->received_timestamp < importer->sync_since_timestamp) { - *result_r = "Ignoring missing local mail with too old timestamp"; + if (!dsync_mailbox_import_want_change(importer, change, result_r)) return; - } if (importer->revert_local_changes && change->type != DSYNC_MAIL_CHANGE_TYPE_EXPUNGE) { dsync_mailbox_revert_missing(importer, change);
--- a/src/doveadm/dsync/dsync-mailbox-import.h Tue Jan 20 03:23:29 2015 +0200 +++ b/src/doveadm/dsync/dsync-mailbox-import.h Tue Jan 20 04:07:09 2015 +0200 @@ -27,7 +27,7 @@ uint32_t remote_first_recent_uid, uint64_t remote_highest_modseq, uint64_t remote_highest_pvt_modseq, - time_t sync_since_timestamp, + time_t sync_since_timestamp, const char *sync_flag, enum dsync_mailbox_import_flags flags); int dsync_mailbox_import_attribute(struct dsync_mailbox_importer *importer, const struct dsync_mailbox_attribute *attr);