From c8f402e43f9c6a3c685fe0f716ffda741beeac13 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 22 Jul 2020 19:44:26 +0200 Subject: [PATCH] deprecate master/slave terminology the underlying metaphor refers to an inhumane practice, so using it casually is rightfully offensive to many people. it isn't even a particularly apt metaphor, as it suggests a strict hierarchy that is counter to mbsync's highly symmetrical mode of operation. the far/near terminology has been chosen as the replacement, as it is a natural fit for the push/pull terminology. on the downside, due to these not being nouns, a few uses are a bit awkward, and several others had to be amended to include 'side'. also, it's conceptually quite close to remote/local, which matches the typical use case, but is maybe a bit too suggestive of actually non-existing limitations. the new f/n suffixes of the -C/-R/-X options clash with pre-existing options, so direct concatenation of short options is even less practical than before (some suffixes of -D already clashed), but doing that leads to unreadable command lines anyway. as with previous deprecations, all pre-existing command line and config options keep working, but yield a warning. the state files are silently upgraded. --- NEWS | 2 + TODO | 8 +- src/config.c | 95 +++++----- src/config.h | 1 + src/main.c | 160 +++++++++-------- src/mbsync.1 | 54 +++--- src/mbsyncrc.sample | 26 +-- src/run-tests.pl | 104 +++++------ src/sync.c | 410 ++++++++++++++++++++++---------------------- src/sync.h | 10 +- 10 files changed, 450 insertions(+), 420 deletions(-) diff --git a/NEWS b/NEWS index 4133a50..8b6aae1 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,8 @@ The IMAP user query can be scripted now. Added built-in support for macOS Keychain. +The use of Master/Slave terminology has been deprecated. + [1.3.0] Network timeout handling has been added. diff --git a/TODO b/TODO index 66c9489..7a6c98d 100644 --- a/TODO +++ b/TODO @@ -15,7 +15,7 @@ should complain when multiple Channels match the same folders. propagate folder deletions even when the folders are non-empty. - verify that "most" of the folders in the Channel are still there. - refuse to delete unpropagated messages when trashing on the remote side. -- refuse to delete master if it has unpropagated messages. symmetry? +- refuse to delete far side if it has unpropagated messages. symmetry? add message expiration based on arrival date (message date would be too unreliable). MaxAge; probably mutually exclusive to MaxMessages. @@ -28,9 +28,9 @@ add support for event notification callbacks. it would be also possible to report more differentiated exit codes, but that seems too limiting in the general case. -make it possible to have different mailbox names for Master and Slave in +make it possible to have different mailbox names for far and near side in Patterns. -- use master:slave for the pattern +- use far:near for the pattern - for quoting, use more colons: the longest sequence of colons is the separator - this makes Groups mostly useless, as they are mostly a workaround for this @@ -63,7 +63,7 @@ use MULTIAPPEND and FETCH with multiple messages. create dummies describing MIME structure of messages bigger than MaxSize. flagging the dummy would fetch the real message. possibly remove --renew. -note that all interaction needs to happen on the slave side probably. +note that all interaction needs to happen on the near side probably. don't SELECT boxes unless really needed; in particular not for appending, and in write-only mode not before changes are made. diff --git a/src/config.c b/src/config.c index 5ba3724..e6d0ff4 100644 --- a/src/config.c +++ b/src/config.c @@ -174,21 +174,21 @@ getopt_helper( conffile_t *cfile, int *cops, channel_conf_t *conf ) else if (!strcasecmp( "Flags", arg )) *cops |= OP_FLAGS; else if (!strcasecmp( "PullReNew", arg )) - conf->ops[S] |= OP_RENEW; + conf->ops[N] |= OP_RENEW; else if (!strcasecmp( "PullNew", arg )) - conf->ops[S] |= OP_NEW; + conf->ops[N] |= OP_NEW; else if (!strcasecmp( "PullDelete", arg )) - conf->ops[S] |= OP_DELETE; + conf->ops[N] |= OP_DELETE; else if (!strcasecmp( "PullFlags", arg )) - conf->ops[S] |= OP_FLAGS; + conf->ops[N] |= OP_FLAGS; else if (!strcasecmp( "PushReNew", arg )) - conf->ops[M] |= OP_RENEW; + conf->ops[F] |= OP_RENEW; else if (!strcasecmp( "PushNew", arg )) - conf->ops[M] |= OP_NEW; + conf->ops[F] |= OP_NEW; else if (!strcasecmp( "PushDelete", arg )) - conf->ops[M] |= OP_DELETE; + conf->ops[F] |= OP_DELETE; else if (!strcasecmp( "PushFlags", arg )) - conf->ops[M] |= OP_FLAGS; + conf->ops[F] |= OP_FLAGS; else if (!strcasecmp( "All", arg ) || !strcasecmp( "Full", arg )) *cops |= XOP_PULL|XOP_PUSH; else if (strcasecmp( "None", arg ) && strcasecmp( "Noop", arg )) { @@ -197,7 +197,7 @@ getopt_helper( conffile_t *cfile, int *cops, channel_conf_t *conf ) cfile->err = 1; } while ((arg = get_arg( cfile, ARG_OPTIONAL, NULL ))); - conf->ops[M] |= XOP_HAVE_TYPE; + conf->ops[F] |= XOP_HAVE_TYPE; } else if (!strcasecmp( "SyncState", cfile->cmd )) conf->sync_state = expand_strdup( cfile->val ); else if (!strcasecmp( "CopyArrivalDate", cfile->cmd )) @@ -214,17 +214,23 @@ getopt_helper( conffile_t *cfile, int *cops, channel_conf_t *conf ) do { if (!strcasecmp( "Both", arg )) { *cops |= op; - } else if (!strcasecmp( "Master", arg )) { - conf->ops[M] |= op; - } else if (!strcasecmp( "Slave", arg )) { - conf->ops[S] |= op; + } else if (!strcasecmp( "Far", arg )) { + conf->ops[F] |= op; + } else if (!strcasecmp( "Master", arg )) { // Pre-1.4 legacy + conf->ops[F] |= op; + cfile->ms_warn = 1; + } else if (!strcasecmp( "Near", arg )) { + conf->ops[N] |= op; + } else if (!strcasecmp( "Slave", arg )) { // Pre-1.4 legacy + conf->ops[N] |= op; + cfile->ms_warn = 1; } else if (strcasecmp( "None", arg )) { error( "%s:%d: invalid %s arg '%s'\n", cfile->file, cfile->line, boxOps[i].name, arg ); cfile->err = 1; } } while ((arg = get_arg( cfile, ARG_OPTIONAL, NULL ))); - conf->ops[M] |= op * (XOP_HAVE_EXPUNGE / OP_EXPUNGE); + conf->ops[F] |= op * (XOP_HAVE_EXPUNGE / OP_EXPUNGE); return 1; } } @@ -265,25 +271,25 @@ merge_ops( int cops, int ops[] ) int aops, op; uint i; - aops = ops[M] | ops[S]; - if (ops[M] & XOP_HAVE_TYPE) { + aops = ops[F] | ops[N]; + if (ops[F] & XOP_HAVE_TYPE) { if (aops & OP_MASK_TYPE) { if (aops & cops & OP_MASK_TYPE) { cfl: error( "Conflicting Sync args specified.\n" ); return 1; } - ops[M] |= cops & OP_MASK_TYPE; - ops[S] |= cops & OP_MASK_TYPE; + ops[F] |= cops & OP_MASK_TYPE; + ops[N] |= cops & OP_MASK_TYPE; if (cops & XOP_PULL) { - if (ops[S] & OP_MASK_TYPE) + if (ops[N] & OP_MASK_TYPE) goto cfl; - ops[S] |= OP_MASK_TYPE; + ops[N] |= OP_MASK_TYPE; } if (cops & XOP_PUSH) { - if (ops[M] & OP_MASK_TYPE) + if (ops[F] & OP_MASK_TYPE) goto cfl; - ops[M] |= OP_MASK_TYPE; + ops[F] |= OP_MASK_TYPE; } } else if (cops & (OP_MASK_TYPE|XOP_MASK_DIR)) { if (!(cops & OP_MASK_TYPE)) @@ -291,20 +297,20 @@ merge_ops( int cops, int ops[] ) else if (!(cops & XOP_MASK_DIR)) cops |= XOP_PULL|XOP_PUSH; if (cops & XOP_PULL) - ops[S] |= cops & OP_MASK_TYPE; + ops[N] |= cops & OP_MASK_TYPE; if (cops & XOP_PUSH) - ops[M] |= cops & OP_MASK_TYPE; + ops[F] |= cops & OP_MASK_TYPE; } } for (i = 0; i < as(boxOps); i++) { op = boxOps[i].op; - if (ops[M] & (op * (XOP_HAVE_EXPUNGE / OP_EXPUNGE))) { + if (ops[F] & (op * (XOP_HAVE_EXPUNGE / OP_EXPUNGE))) { if (aops & cops & op) { error( "Conflicting %s args specified.\n", boxOps[i].name ); return 1; } - ops[M] |= cops & op; - ops[S] |= cops & op; + ops[F] |= cops & op; + ops[N] |= cops & op; } } return 0; @@ -320,7 +326,7 @@ load_config( const char *where, int pseudo ) string_list_t *chanlist, **chanlistapp; char *arg, *p; uint len, max_size; - int cops, gcops, ms, i; + int cops, gcops, fn, i; char path[_POSIX_PATH_MAX]; char buf[1024]; @@ -343,6 +349,7 @@ load_config( const char *where, int pseudo ) cfile.bufl = sizeof(buf) - 1; cfile.line = 0; cfile.err = 0; + cfile.ms_warn = 0; cfile.rest = NULL; gcops = 0; @@ -384,11 +391,19 @@ load_config( const char *where, int pseudo ) add_string_list( &channel->patterns, arg ); while ((arg = get_arg( &cfile, ARG_OPTIONAL, NULL ))); } - else if (!strcasecmp( "Master", cfile.cmd )) { - ms = M; + else if (!strcasecmp( "Far", cfile.cmd )) { + fn = F; goto linkst; - } else if (!strcasecmp( "Slave", cfile.cmd )) { - ms = S; + } else if (!strcasecmp( "Master", cfile.cmd )) { // Pre-1.4 legacy + fn = F; + goto olinkst; + } else if (!strcasecmp( "Near", cfile.cmd )) { + fn = N; + goto linkst; + } else if (!strcasecmp( "Slave", cfile.cmd )) { // Pre-1.4 legacy + fn = N; + olinkst: + cfile.ms_warn = 1; linkst: if (*cfile.val != ':' || !(p = strchr( cfile.val + 1, ':' ))) { error( "%s:%d: malformed mailbox spec\n", @@ -399,7 +414,7 @@ load_config( const char *where, int pseudo ) *p = 0; for (store = stores; store; store = store->next) if (!strcmp( store->name, cfile.val + 1 )) { - channel->stores[ms] = store; + channel->stores[fn] = store; goto stpcom; } error( "%s:%d: unknown store '%s'\n", @@ -408,17 +423,17 @@ load_config( const char *where, int pseudo ) continue; stpcom: if (*++p) - channel->boxes[ms] = nfstrdup( p ); + channel->boxes[fn] = nfstrdup( p ); } else if (!getopt_helper( &cfile, &cops, channel )) { error( "%s:%d: unknown keyword '%s'\n", cfile.file, cfile.line, cfile.cmd ); cfile.err = 1; } } - if (!channel->stores[M]) { - error( "channel '%s' refers to no master store\n", channel->name ); + if (!channel->stores[F]) { + error( "channel '%s' refers to no far side store\n", channel->name ); cfile.err = 1; - } else if (!channel->stores[S]) { - error( "channel '%s' refers to no slave store\n", channel->name ); + } else if (!channel->stores[N]) { + error( "channel '%s' refers to no near side store\n", channel->name ); cfile.err = 1; } else if (merge_ops( cops, channel->ops )) cfile.err = 1; @@ -426,7 +441,7 @@ load_config( const char *where, int pseudo ) if (max_size != UINT_MAX) { if (!max_size) max_size = UINT_MAX; - channel->stores[M]->max_size = channel->stores[S]->max_size = max_size; + channel->stores[F]->max_size = channel->stores[N]->max_size = max_size; } *channelapp = channel; channelapp = &channel->next; @@ -505,6 +520,8 @@ load_config( const char *where, int pseudo ) } } fclose (cfile.fp); + if (cfile.ms_warn) + warn( "Notice: Master/Slave are deprecated; use Far/Near instead.\n" ); cfile.err |= merge_ops( gcops, global_conf.ops ); if (!global_conf.sync_state) global_conf.sync_state = expand_strdup( "~/." EXE "/" ); diff --git a/src/config.h b/src/config.h index a8d6089..c54c8fc 100644 --- a/src/config.h +++ b/src/config.h @@ -32,6 +32,7 @@ typedef struct { int bufl; int line; int err; + int ms_warn; char *cmd, *val, *rest; } conffile_t; diff --git a/src/main.c b/src/main.c index b35de25..6bf1e87 100644 --- a/src/main.c +++ b/src/main.c @@ -78,8 +78,8 @@ PACKAGE " " VERSION " - mailbox synchronizer\n" " -d, --delete propagate message deletions\n" " -f, --flags propagate message flag changes\n" " -N, --renew propagate previously not propagated new messages\n" -" -L, --pull propagate from master to slave\n" -" -H, --push propagate from slave to master\n" +" -L, --pull propagate from far to near side\n" +" -H, --push propagate from near to far side\n" " -C, --create propagate creations of mailboxes\n" " -R, --remove propagate deletions of mailboxes\n" " -X, --expunge expunge deleted messages\n" @@ -92,7 +92,7 @@ PACKAGE " " VERSION " - mailbox synchronizer\n" "\nIf neither --pull nor --push are specified, both are active.\n" "If neither --new, --delete, --flags nor --renew are specified, all are active.\n" "Direction and operation can be concatenated like --pull-new, etc.\n" -"--create, --remove, and --expunge can be suffixed with -master/-slave.\n" +"--create, --remove, and --expunge can be suffixed with -far/-near.\n" "See the man page for details.\n" "\nSupported mailbox formats are: IMAP4rev1, Maildir\n" "\nCompile time options:\n" @@ -205,7 +205,7 @@ stats( void ) if (l > cls) buf[t][cls - 1] = '~'; } - progress( "\r%s M: %.*s S: %.*s", buf[2], cls, buf[0], cls, buf[1] ); + progress( "\r%s F: %.*s N: %.*s", buf[2], cls, buf[0], cls, buf[1] ); } static int @@ -297,18 +297,18 @@ filter_boxes( string_list_t *boxes, const char *prefix, string_list_t *patterns static void merge_actions( channel_conf_t *chan, int ops[], int have, int mask, int def ) { - if (ops[M] & have) { - chan->ops[M] &= ~mask; - chan->ops[M] |= ops[M] & mask; - chan->ops[S] &= ~mask; - chan->ops[S] |= ops[S] & mask; - } else if (!(chan->ops[M] & have)) { - if (global_conf.ops[M] & have) { - chan->ops[M] |= global_conf.ops[M] & mask; - chan->ops[S] |= global_conf.ops[S] & mask; + if (ops[F] & have) { + chan->ops[F] &= ~mask; + chan->ops[F] |= ops[F] & mask; + chan->ops[N] &= ~mask; + chan->ops[N] |= ops[N] & mask; + } else if (!(chan->ops[F] & have)) { + if (global_conf.ops[F] & have) { + chan->ops[F] |= global_conf.ops[F] & mask; + chan->ops[N] |= global_conf.ops[N] & mask; } else { - chan->ops[M] |= def; - chan->ops[S] |= def; + chan->ops[F] |= def; + chan->ops[N] |= def; } } } @@ -380,7 +380,7 @@ add_named_channel( chan_ent_t ***chanapp, char *channame, int ops[] ) mbox->name = nfstrndup( boxp, boxl ); else mbox->name = nfstrndup( "INBOX", 5 ); - mbox->present[M] = mbox->present[S] = BOX_POSSIBLE; + mbox->present[F] = mbox->present[N] = BOX_POSSIBLE; mbox->next = NULL; *mboxapp = mbox; mboxapp = &mbox->next; @@ -431,7 +431,7 @@ main( int argc, char **argv ) channel_conf_t *chan; string_list_t *channame; char *config = NULL, *opt, *ochar; - int oind, cops = 0, op, ops[2] = { 0, 0 }, pseudo = 0; + int oind, cops = 0, op, ops[2] = { 0, 0 }, pseudo = 0, ms_warn = 0; tzset(); gethostname( Hostname, sizeof(Hostname) ); @@ -504,22 +504,26 @@ main( int argc, char **argv ) goto badopt; DFlags |= op; } else if (!strcmp( opt, "pull" )) - cops |= XOP_PULL, ops[M] |= XOP_HAVE_TYPE; + cops |= XOP_PULL, ops[F] |= XOP_HAVE_TYPE; else if (!strcmp( opt, "push" )) - cops |= XOP_PUSH, ops[M] |= XOP_HAVE_TYPE; + cops |= XOP_PUSH, ops[F] |= XOP_HAVE_TYPE; else if (starts_with( opt, -1, "create", 6 )) { opt += 6; op = OP_CREATE|XOP_HAVE_CREATE; lcop: if (!*opt) cops |= op; - else if (!strcmp( opt, "-master" )) - ops[M] |= op; - else if (!strcmp( opt, "-slave" )) - ops[S] |= op; + else if (!strcmp( opt, "-far" )) + ops[F] |= op; + else if (!strcmp( opt, "-master" )) // Pre-1.4 legacy + ops[F] |= op, ms_warn = 1; + else if (!strcmp( opt, "-near" )) + ops[N] |= op; + else if (!strcmp( opt, "-slave" )) // Pre-1.4 legacy + ops[N] |= op, ms_warn = 1; else goto badopt; - ops[M] |= op & (XOP_HAVE_CREATE|XOP_HAVE_REMOVE|XOP_HAVE_EXPUNGE); + ops[F] |= op & (XOP_HAVE_CREATE|XOP_HAVE_REMOVE|XOP_HAVE_EXPUNGE); } else if (starts_with( opt, -1, "remove", 6 )) { opt += 6; op = OP_REMOVE|XOP_HAVE_REMOVE; @@ -529,15 +533,15 @@ main( int argc, char **argv ) op = OP_EXPUNGE|XOP_HAVE_EXPUNGE; goto lcop; } else if (!strcmp( opt, "no-expunge" )) - ops[M] |= XOP_HAVE_EXPUNGE; + ops[F] |= XOP_HAVE_EXPUNGE; else if (!strcmp( opt, "no-create" )) - ops[M] |= XOP_HAVE_CREATE; + ops[F] |= XOP_HAVE_CREATE; else if (!strcmp( opt, "no-remove" )) - ops[M] |= XOP_HAVE_REMOVE; + ops[F] |= XOP_HAVE_REMOVE; else if (!strcmp( opt, "full" )) - ops[M] |= XOP_HAVE_TYPE|XOP_PULL|XOP_PUSH; + ops[F] |= XOP_HAVE_TYPE|XOP_PULL|XOP_PUSH; else if (!strcmp( opt, "noop" )) - ops[M] |= XOP_HAVE_TYPE; + ops[F] |= XOP_HAVE_TYPE; else if (starts_with( opt, -1, "pull", 4 )) { op = XOP_PULL; lcac: @@ -569,11 +573,11 @@ main( int argc, char **argv ) return 1; } switch (op & XOP_MASK_DIR) { - case XOP_PULL: ops[S] |= op & OP_MASK_TYPE; break; - case XOP_PUSH: ops[M] |= op & OP_MASK_TYPE; break; + case XOP_PULL: ops[N] |= op & OP_MASK_TYPE; break; + case XOP_PUSH: ops[F] |= op & OP_MASK_TYPE; break; default: cops |= op; break; } - ops[M] |= XOP_HAVE_TYPE; + ops[F] |= XOP_HAVE_TYPE; } continue; } @@ -604,15 +608,19 @@ main( int argc, char **argv ) case 'C': op = OP_CREATE|XOP_HAVE_CREATE; cop: - if (*ochar == 'm') - ops[M] |= op, ochar++; - else if (*ochar == 's') - ops[S] |= op, ochar++; + if (*ochar == 'f') + ops[F] |= op, ochar++; + else if (*ochar == 'm') // Pre-1.4 legacy + ops[F] |= op, ms_warn = 1, ochar++; + else if (*ochar == 'n') + ops[N] |= op, ochar++; + else if (*ochar == 's') // Pre-1.4 legacy + ops[N] |= op, ms_warn = 1, ochar++; else if (*ochar == '-') ochar++; else cops |= op; - ops[M] |= op & (XOP_HAVE_CREATE|XOP_HAVE_REMOVE|XOP_HAVE_EXPUNGE); + ops[F] |= op & (XOP_HAVE_CREATE|XOP_HAVE_REMOVE|XOP_HAVE_EXPUNGE); break; case 'R': op = OP_REMOVE|XOP_HAVE_REMOVE; @@ -624,7 +632,7 @@ main( int argc, char **argv ) cops |= XOP_PULL|XOP_PUSH; FALLTHROUGH case '0': - ops[M] |= XOP_HAVE_TYPE; + ops[F] |= XOP_HAVE_TYPE; break; case 'n': case 'd': @@ -647,13 +655,13 @@ main( int argc, char **argv ) } if (op & OP_MASK_TYPE) switch (op & XOP_MASK_DIR) { - case XOP_PULL: ops[S] |= op & OP_MASK_TYPE; break; - case XOP_PUSH: ops[M] |= op & OP_MASK_TYPE; break; + case XOP_PULL: ops[N] |= op & OP_MASK_TYPE; break; + case XOP_PUSH: ops[F] |= op & OP_MASK_TYPE; break; default: cops |= op; break; } else cops |= op; - ops[M] |= XOP_HAVE_TYPE; + ops[F] |= XOP_HAVE_TYPE; break; case 'L': op = XOP_PULL; @@ -722,6 +730,8 @@ main( int argc, char **argv ) return 1; } } + if (ms_warn) + warn( "Notice: -master/-slave/m/s suffixes are deprecated; use -far/-near/f/n instead.\n" ); if (!(DFlags & (QUIET | DEBUG_ALL)) && isatty( 1 )) DFlags |= PROGRESS; @@ -839,17 +849,17 @@ sync_chans( main_vars_t *mvars, int ent ) int st = mvars->chan->stores[t]->driver->get_fail_state( mvars->chan->stores[t] ); if (st != FAIL_TEMP) { info( "Skipping due to %sfailed %s store %s.\n", - (st == FAIL_WAIT) ? "temporarily " : "", str_ms[t], mvars->chan->stores[t]->name ); + (st == FAIL_WAIT) ? "temporarily " : "", str_fn[t], mvars->chan->stores[t]->name ); mvars->skip = 1; } } if (mvars->skip) goto next2; - mvars->state[M] = mvars->state[S] = ST_FRESH; - if ((DFlags & DEBUG_DRV) || (mvars->chan->stores[M]->driver->get_caps( NULL ) & mvars->chan->stores[S]->driver->get_caps( NULL ) & DRV_VERBOSE)) - labels[M] = "M: ", labels[S] = "S: "; + mvars->state[F] = mvars->state[N] = ST_FRESH; + if ((DFlags & DEBUG_DRV) || (mvars->chan->stores[F]->driver->get_caps( NULL ) & mvars->chan->stores[N]->driver->get_caps( NULL ) & DRV_VERBOSE)) + labels[F] = "F: ", labels[N] = "N: "; else - labels[M] = labels[S] = ""; + labels[F] = labels[N] = ""; for (t = 0; t < 2; t++) { driver_t *drv = mvars->chan->stores[t]->driver; store_t *ctx = drv->alloc_store( mvars->chan->stores[t], labels[t] ); @@ -862,7 +872,7 @@ sync_chans( main_vars_t *mvars, int ent ) drv->set_bad_callback( ctx, store_bad, AUX ); } for (t = 0; ; t++) { - info( "Opening %s store %s...\n", str_ms[t], mvars->chan->stores[t]->name ); + info( "Opening %s store %s...\n", str_fn[t], mvars->chan->stores[t]->name ); mvars->drv[t]->connect_store( mvars->ctx[t], store_connected, AUX ); if (t || mvars->skip) break; @@ -872,35 +882,35 @@ sync_chans( main_vars_t *mvars, int ent ) opened: if (mvars->skip) goto next; - if (mvars->state[M] != ST_OPEN || mvars->state[S] != ST_OPEN) + if (mvars->state[F] != ST_OPEN || mvars->state[N] != ST_OPEN) return; if (!mvars->chanptr->boxlist && mvars->chan->patterns) { mvars->chanptr->boxlist = 2; - boxes[M] = filter_boxes( mvars->boxes[M], mvars->chan->boxes[M], mvars->chan->patterns ); - boxes[S] = filter_boxes( mvars->boxes[S], mvars->chan->boxes[S], mvars->chan->patterns ); + boxes[F] = filter_boxes( mvars->boxes[F], mvars->chan->boxes[F], mvars->chan->patterns ); + boxes[N] = filter_boxes( mvars->boxes[N], mvars->chan->boxes[N], mvars->chan->patterns ); mboxapp = &mvars->chanptr->boxes; for (mb = sb = 0; ; ) { - char *mname = boxes[M] ? boxes[M][mb] : NULL; - char *sname = boxes[S] ? boxes[S][sb] : NULL; + char *mname = boxes[F] ? boxes[F][mb] : NULL; + char *sname = boxes[N] ? boxes[N][sb] : NULL; if (!mname && !sname) break; mbox = nfmalloc( sizeof(*mbox) ); if (!(cmp = !mname - !sname) && !(cmp = cmp_box_names( &mname, &sname ))) { mbox->name = mname; free( sname ); - mbox->present[M] = mbox->present[S] = BOX_PRESENT; + mbox->present[F] = mbox->present[N] = BOX_PRESENT; mb++; sb++; } else if (cmp < 0) { mbox->name = mname; - mbox->present[M] = BOX_PRESENT; - mbox->present[S] = (!mb && !strcmp( mbox->name, "INBOX" )) ? BOX_PRESENT : BOX_ABSENT; + mbox->present[F] = BOX_PRESENT; + mbox->present[N] = (!mb && !strcmp( mbox->name, "INBOX" )) ? BOX_PRESENT : BOX_ABSENT; mb++; } else { mbox->name = sname; - mbox->present[M] = (!sb && !strcmp( mbox->name, "INBOX" )) ? BOX_PRESENT : BOX_ABSENT; - mbox->present[S] = BOX_PRESENT; + mbox->present[F] = (!sb && !strcmp( mbox->name, "INBOX" )) ? BOX_PRESENT : BOX_ABSENT; + mbox->present[N] = BOX_PRESENT; sb++; } mbox->next = NULL; @@ -908,8 +918,8 @@ sync_chans( main_vars_t *mvars, int ent ) mboxapp = &mbox->next; boxes_total++; } - free( boxes[M] ); - free( boxes[S] ); + free( boxes[F] ); + free( boxes[N] ); if (!mvars->list) stats(); } @@ -938,7 +948,7 @@ sync_chans( main_vars_t *mvars, int ent ) if (!mvars->skip) goto syncml; } else - printf( "%s <=> %s\n", nz( mvars->chan->boxes[M], "INBOX" ), nz( mvars->chan->boxes[S], "INBOX" ) ); + printf( "%s <=> %s\n", nz( mvars->chan->boxes[F], "INBOX" ), nz( mvars->chan->boxes[N], "INBOX" ) ); } next: @@ -956,7 +966,7 @@ sync_chans( main_vars_t *mvars, int ent ) } } mvars->cben = 1; - if (mvars->state[M] != ST_CLOSED || mvars->state[S] != ST_CLOSED) { + if (mvars->state[F] != ST_CLOSED || mvars->state[N] != ST_CLOSED) { mvars->skip = 1; return; } @@ -1067,7 +1077,7 @@ store_listed( int sts, string_list_t *boxes, void *aux ) } } if (mvars->ctx[t]->conf->map_inbox) { - debug( "adding mapped inbox to %s: %s\n", str_ms[t], mvars->ctx[t]->conf->map_inbox ); + debug( "adding mapped inbox to %s store: %s\n", str_fn[t], mvars->ctx[t]->conf->map_inbox ); add_string_list( &mvars->boxes[t], mvars->ctx[t]->conf->map_inbox ); } break; @@ -1082,19 +1092,19 @@ store_listed( int sts, string_list_t *boxes, void *aux ) static int sync_listed_boxes( main_vars_t *mvars, box_ent_t *mbox ) { - if (mvars->chan->boxes[M] || mvars->chan->boxes[S]) { - const char *mpfx = nz( mvars->chan->boxes[M], "" ); - const char *spfx = nz( mvars->chan->boxes[S], "" ); + if (mvars->chan->boxes[F] || mvars->chan->boxes[N]) { + const char *mpfx = nz( mvars->chan->boxes[F], "" ); + const char *spfx = nz( mvars->chan->boxes[N], "" ); if (!mvars->list) { - nfasprintf( &mvars->names[M], "%s%s", mpfx, mbox->name ); - nfasprintf( &mvars->names[S], "%s%s", spfx, mbox->name ); + nfasprintf( &mvars->names[F], "%s%s", mpfx, mbox->name ); + nfasprintf( &mvars->names[N], "%s%s", spfx, mbox->name ); sync_boxes( mvars->ctx, (const char * const *)mvars->names, mbox->present, mvars->chan, done_sync_2_dyn, mvars ); return 1; } printf( "%s%s <=> %s%s\n", mpfx, mbox->name, spfx, mbox->name ); } else { if (!mvars->list) { - mvars->names[M] = mvars->names[S] = mbox->name; + mvars->names[F] = mvars->names[N] = mbox->name; sync_boxes( mvars->ctx, (const char * const *)mvars->names, mbox->present, mvars->chan, done_sync, mvars ); return 1; } @@ -1108,8 +1118,8 @@ done_sync_2_dyn( int sts, void *aux ) { main_vars_t *mvars = (main_vars_t *)aux; - free( mvars->names[M] ); - free( mvars->names[S] ); + free( mvars->names[F] ); + free( mvars->names[N] ); done_sync( sts, aux ); } @@ -1123,11 +1133,11 @@ done_sync( int sts, void *aux ) stats(); if (sts) { mvars->ret = 1; - if (sts & (SYNC_BAD(M) | SYNC_BAD(S))) { - if (sts & SYNC_BAD(M)) - mvars->state[M] = ST_CLOSED; - if (sts & SYNC_BAD(S)) - mvars->state[S] = ST_CLOSED; + if (sts & (SYNC_BAD(F) | SYNC_BAD(N))) { + if (sts & SYNC_BAD(F)) + mvars->state[F] = ST_CLOSED; + if (sts & SYNC_BAD(N)) + mvars->state[N] = ST_CLOSED; mvars->skip = 1; } } diff --git a/src/mbsync.1 b/src/mbsync.1 index 16572ba..1c8eeeb 100644 --- a/src/mbsync.1 +++ b/src/mbsync.1 @@ -57,13 +57,13 @@ line are ignored. Don't synchronize anything, but list all mailboxes in the selected channels and exit. .TP -\fB-C\fR[\fBm\fR][\fBs\fR], \fB--create\fR[\fB-master\fR|\fB-slave\fR] +\fB-C\fR[\fBf\fR][\fBn\fR], \fB--create\fR[\fB-far\fR|\fB-near\fR] Override any \fBCreate\fR options from the config file. See below. .TP -\fB-R\fR[\fBm\fR][\fBs\fR], \fB--remove\fR[\fB-master\fR|\fB-slave\fR] +\fB-R\fR[\fBf\fR][\fBn\fR], \fB--remove\fR[\fB-far\fR|\fB-near\fR] Override any \fBRemove\fR options from the config file. See below. .TP -\fB-X\fR[\fBm\fR][\fBs\fR], \fB--expunge\fR[\fB-master\fR|\fB-slave\fR] +\fB-X\fR[\fBf\fR][\fBn\fR], \fB--expunge\fR[\fB-far\fR|\fB-near\fR] Override any \fBExpunge\fR options from the config file. See below. .TP {\fB-n\fR|\fB-N\fR|\fB-d\fR|\fB-f\fR|\fB-0\fR|\fB-F\fR},\ @@ -174,7 +174,7 @@ If \fIsize\fR is 0, the maximum message size is \fBunlimited\fR. \fBMapInbox\fR \fImailbox\fR Create a virtual mailbox (relative to \fBPath\fR) which aliases the \fBINBOX\fR. Makes sense in conjunction with \fBPatterns\fR in the -Channels section, though with a Maildir slave, you probably want to +Channels section, though with a Maildir near side, you probably want to place \fBInbox\fR under \fBPath\fR instead. This virtual mailbox does not support subfolders. . @@ -511,8 +511,8 @@ This option make sense only in conjunction with \fBPatterns\fR. Define the Channel \fIname\fR, opening a section for its parameters. . .TP -{\fBMaster\fR|\fBSlave\fR} \fB:\fIstore\fB:\fR[\fImailbox\fR] -Specify the Master resp. Slave Store to be connected by this Channel. +{\fBFar\fR|\fBNear\fR} \fB:\fIstore\fB:\fR[\fImailbox\fR] +Specify the far resp. near side Store to be connected by this Channel. If \fBPatterns\fR are specified, \fImailbox\fR is interpreted as a prefix which is not matched against the patterns, and which is not affected by mailbox list overrides. @@ -521,8 +521,8 @@ Otherwise, if \fImailbox\fR is omitted, \fBINBOX\fR is assumed. .TP \fBPattern\fR[\fBs\fR] [\fB!\fR]\fIpattern\fR ... Instead of synchronizing only one mailbox pair, synchronize all mailboxes -that match the \fIpattern\fR(s). The mailbox names are the same on both -Master and Slave. Patterns are IMAP4 patterns, i.e., \fB*\fR matches anything +that match the \fIpattern\fR(s). The mailbox names are the same on the far +and near side. Patterns are IMAP4 patterns, i.e., \fB*\fR matches anything and \fB%\fR matches anything up to the next hierarchy delimiter. Prepending \fB!\fR to a pattern makes it an exclusion. Multiple patterns can be specified (either by supplying multiple arguments or by using \fBPattern\fR multiple @@ -539,12 +539,12 @@ Example: "\fBPatterns\fR\ \fI%\ !Trash\fR" .TP \fBMaxSize\fR \fIsize\fR[\fBk\fR|\fBm\fR][\fBb\fR] Analogous to the homonymous option in the Stores section, but applies equally -to Master and Slave. Note that this actually modifies the Stores, so take care +to Far and Near. Note that this actually modifies the Stores, so take care not to provide conflicting settings if you use the Stores in multiple Channels. . .TP \fBMaxMessages\fR \fIcount\fR -Sets the maximum number of messages to keep in each Slave mailbox. +Sets the maximum number of messages to keep in each near side mailbox. This is useful for mailboxes where you keep a complete archive on the server, but want to mirror only the last messages (for instance, for mailing lists). The messages that were the first to arrive in the mailbox (independently of @@ -568,9 +568,9 @@ case you need to enable this option. \fBSync\fR {\fBNone\fR|[\fBPull\fR] [\fBPush\fR] [\fBNew\fR] [\fBReNew\fR] [\fBDelete\fR] [\fBFlags\fR]|\fBAll\fR} Select the synchronization operation(s) to perform: .br -\fBPull\fR - propagate changes from Master to Slave. +\fBPull\fR - propagate changes from far to near side. .br -\fBPush\fR - propagate changes from Slave to Master. +\fBPush\fR - propagate changes from near to far side. .br \fBNew\fR - propagate newly appeared messages. .br @@ -602,10 +602,10 @@ In the first style, the flags select entire rows/colums in the matrix. Only the cells which are selected both horizontally and vertically are asserted. Specifying no flags from a class is like specifying all flags from this class. For example, "\fBSync\fR\ \fBPull\fR\ \fBNew\fR\ \fBFlags\fR" will propagate -new messages and flag changes from the Master to the Slave, +new messages and flag changes from the far side to the near side, "\fBSync\fR\ \fBNew\fR\ \fBDelete\fR" will propagate message arrivals and deletions both ways, and "\fBSync\fR\ \fBPush\fR" will propagate all changes -from the Slave to the Master. +from the near side to the far side. .br In the second style, direction flags are concatenated with type flags; every compound flag immediately asserts a cell in the matrix. In addition to at least @@ -613,22 +613,22 @@ one compound flag, the individual flags can be used as well, but as opposed to the first style, they immediately assert all cells in their respective row/column. For example, "\fBSync\fR\ \fBPullNew\fR\ \fBPullDelete\fR\ \fBPush\fR" will propagate -message arrivals and deletions from the Master to the Slave and any changes -from the Slave to the Master. +message arrivals and deletions from the far side to the near side and any +changes from the near side to the far side. Note that it is not allowed to assert a cell in two ways, e.g. "\fBSync\fR\ \fBPullNew\fR\ \fBPull\fR" and "\fBSync\fR\ \fBPullNew\fR\ \fBDelete\fR\ \fBPush\fR" induce error messages. . .TP -\fBCreate\fR {\fBNone\fR|\fBMaster\fR|\fBSlave\fR|\fBBoth\fR} -Automatically create missing mailboxes [on the Master/Slave]. +\fBCreate\fR {\fBNone\fR|\fBFar\fR|\fBNear\fR|\fBBoth\fR} +Automatically create missing mailboxes [on the far/near side]. Otherwise print an error message and skip that mailbox pair if a mailbox and the corresponding sync state does not exist. (Global default: \fBNone\fR) . .TP -\fBRemove\fR {\fBNone\fR|\fBMaster\fR|\fBSlave\fR|\fBBoth\fR} -Propagate mailbox deletions [to the Master/Slave]. +\fBRemove\fR {\fBNone\fR|\fBFar\fR|\fBNear\fR|\fBBoth\fR} +Propagate mailbox deletions [to the far/near side]. Otherwise print an error message and skip that mailbox pair if a mailbox does not exist but the corresponding sync state does. .br @@ -640,8 +640,8 @@ Note that for safety, non-empty mailboxes are never deleted. (Global default: \fBNone\fR) . .TP -\fBExpunge\fR {\fBNone\fR|\fBMaster\fR|\fBSlave\fR|\fBBoth\fR} -Permanently remove all messages [on the Master/Slave] marked for deletion. +\fBExpunge\fR {\fBNone\fR|\fBFar\fR|\fBNear\fR|\fBBoth\fR} +Permanently remove all messages [on the far/near side] marked for deletion. See \fBRECOMMENDATIONS\fR below. (Global default: \fBNone\fR) . @@ -666,15 +666,15 @@ which in turn are overridden by command line switches. \fBSyncState\fR {\fB*\fR|\fIpath\fR} Set the location of this Channel's synchronization state files. \fB*\fR means that the state should be saved in a file named .mbsyncstate -in the Slave mailbox itself; this has the advantage that you do not need +in the near side mailbox itself; this has the advantage that you do not need to handle the state file separately if you delete the mailbox, but it works only with Maildir mailboxes, obviously. -Otherwise this is interpreted as a string to prepend to the Slave mailbox +Otherwise this is interpreted as a string to prepend to the near side mailbox name to make up a complete path. .br This option can be used outside any section for a global effect. In this case the appended string is made up according to the pattern -\fB:\fImaster\fB:\fImaster-box\fB_:\fIslave\fB:\fIslave-box\fR +\fB:\fIfar-store\fB:\fIfar-box\fB_:\fInear-store\fB:\fInear-box\fR (see also \fBFieldDelimiter\fR below). .br (Global default: \fI~/.mbsync/\fR). @@ -734,11 +734,11 @@ If \fBmbsync\fR's output is connected to a console, it will print progress counters by default. The output will look like this: .P .in +4 -C: 1/2 B: 3/4 M: +13/13 *23/42 #0/0 S: +0/7 *0/0 #0/0 +C: 1/2 B: 3/4 F: +13/13 *23/42 #0/0 N: +0/7 *0/0 #0/0 .in -4 .P This represents the cumulative progress over channels, boxes, and messages -affected on master and slave, respectively. +affected on the far and near side, respectively. The message counts represent added messages, messages with updated flags, and trashed messages, respectively. No attempt is made to calculate the totals in advance, so they grow over diff --git a/src/mbsyncrc.sample b/src/mbsyncrc.sample index a9d9b13..afc274f 100644 --- a/src/mbsyncrc.sample +++ b/src/mbsyncrc.sample @@ -23,9 +23,9 @@ Pass xxxxxxxx #PassCmd "echo -ne 'GET myIsp\\tpassword' | pwmc datafile" Channel work -Master :work: -Slave :local:work -Expunge Slave +Far :work: +Near :local:work +Expunge Near Sync PullNew Push @@ -35,8 +35,8 @@ Port 6789 RequireSSL no Channel personal -Master :personal: -Slave :local:personal +Far :personal: +Near :local:personal Expunge Both MaxMessages 150 MaxSize 200k @@ -45,8 +45,8 @@ IMAPStore remote Tunnel "ssh -q host.remote.com /usr/sbin/imapd" Channel remote -Master :remote: -Slave :local:remote +Far :remote: +Near :local:remote Group boxes @@ -65,8 +65,8 @@ RequireSSL no UseTLSv1 no Channel rst -Master :st1:somebox -Slave :st2: +Far :st1:somebox +Near :st2: IMAPAccount server @@ -84,14 +84,14 @@ Path ~/Maildir/ SubFolders Verbatim Channel o2o -Master :server: -Slave :mirror: +Far :server: +Near :mirror: Patterns % Group partial o2o:inbox,sent-mail,foobar # INBOX => server, INBOX.foo => server.foo, etc. Channel inbox -Master :server:INBOX -Slave :mirror:server +Far :server:INBOX +Near :mirror:server Patterns * diff --git a/src/run-tests.pl b/src/run-tests.pl index 3fd15b4..77e0abc 100755 --- a/src/run-tests.pl +++ b/src/run-tests.pl @@ -37,9 +37,9 @@ sub test($$$@); ################################################################################ -# Format of the test defs: [ master, slave, state ] -# master/slave: [ maxuid, { seq, uid, flags }... ] -# state: [ MaxPulledUid, MaxExpiredMasterUid, MaxPushedUid, { muid, suid, flags }... ] +# Format of the test defs: [ far, near, state ] +# far/near: [ maxuid, { seq, uid, flags }... ] +# state: [ MaxPulledUid, MaxExpiredFarUid, MaxPushedUid, { muid, suid, flags }... ] use enum qw(:=1 A..Z); sub mn($) { chr(64 + shift) } @@ -78,7 +78,7 @@ my @X02 = ( ); test("full + expunge both", \@x01, \@X02, @O02); -my @O03 = ("", "", "Expunge Slave\n"); +my @O03 = ("", "", "Expunge Near\n"); #show("01", "03", "03"); my @X03 = ( [ 10, @@ -88,7 +88,7 @@ my @X03 = ( [ 9, 0, 9, 1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 0, "T", 6, 0, "", 7, 0, "T", 10, 9, "", 9, 10, "" ], ); -test("full + expunge slave", \@x01, \@X03, @O03); +test("full + expunge near side", \@x01, \@X03, @O03); my @O04 = ("", "", "Sync Pull\n"); #show("01", "04", "04"); @@ -183,7 +183,7 @@ my @X22 = ( [ 2, 0, 1, 3, 1, "", 1, 2, "", 2, 0, "^" ], ); -test("slave max size", \@X11, \@X22, @O22); +test("near side max size", \@X11, \@X22, @O22); # expiration tests @@ -258,7 +258,7 @@ sub qm($) return $_; } -# $master, $slave, $channel +# $far, $near, $channel sub writecfg($$$) { open(FILE, ">", ".mbsyncrc") or @@ -266,17 +266,17 @@ sub writecfg($$$) print FILE "FSync no -MaildirStore master +MaildirStore far Path ./ -Inbox ./master +Inbox ./far ".shift()." -MaildirStore slave +MaildirStore near Path ./ -Inbox ./slave +Inbox ./near ".shift()." Channel test -Master :master: -Slave :slave: +Far :far: +Near :near: SyncState * ".shift(); close FILE; @@ -371,8 +371,8 @@ sub showbox($) # $filename # Output: -# [ maxuid[M], mmaxxuid, maxuid[S], -# uid[M], uid[S], "flags", ... ], +# [ maxuid[F], maxxfuid, maxuid[N], +# uid[F], uid[N], "flags", ... ], sub showstate($) { my ($fn) = @_; @@ -400,7 +400,7 @@ sub showstate($) return; } my @T = ($hdr{'MaxPulledUid'} // "missing", - $hdr{'MaxExpiredMasterUid'} // "0", + $hdr{'MaxExpiredFarUid'} // "0", $hdr{'MaxPushedUid'} // "missing"); for (@ls) { /^(\d+) (\d+) (.*)$/; @@ -414,8 +414,8 @@ sub showchan($) { my ($fn) = @_; - showbox("master"); - showbox("slave"); + showbox("far"); + showbox("near"); showstate($fn); } @@ -428,17 +428,17 @@ sub show($$$) eval "\@sfx = \@O$sfxn"; mkchan($sp[0], $sp[1], @{ $sp[2] }); print "my \@x$sx = (\n"; - showchan("slave/.mbsyncstate"); + showchan("near/.mbsyncstate"); print ");\n"; &writecfg(@sfx); runsync("", ""); killcfg(); print "my \@X$tx = (\n"; - showchan("slave/.mbsyncstate"); + showchan("near/.mbsyncstate"); print ");\n"; print "test(\"\", \\\@x$sx, \\\@X$tx, \@O$sfxn);\n\n"; - rmtree "slave"; - rmtree "master"; + rmtree "near"; + rmtree "far"; } # $boxname, $maxuid, @msgs @@ -462,16 +462,16 @@ sub mkbox($$@) } } -# \@master, \@slave, @syncstate +# \@far, \@near, @syncstate sub mkchan($$@) { my ($m, $s, @t) = @_; - &mkbox("master", @{ $m }); - &mkbox("slave", @{ $s }); - open(FILE, ">", "slave/.mbsyncstate") or + &mkbox("far", @{ $m }); + &mkbox("near", @{ $s }); + open(FILE, ">", "near/.mbsyncstate") or die "Cannot create sync state.\n"; - print FILE "MasterUidValidity 1\nMaxPulledUid ".shift(@t)."\n". - "SlaveUidValidity 1\nMaxExpiredMasterUid ".shift(@t)."\nMaxPushedUid ".shift(@t)."\n\n"; + print FILE "FarUidValidity 1\nMaxPulledUid ".shift(@t)."\n". + "NearUidValidity 1\nMaxExpiredFarUid ".shift(@t)."\nMaxPushedUid ".shift(@t)."\n\n"; while (@t) { print FILE shift(@t)." ".shift(@t)." ".shift(@t)."\n"; } @@ -514,13 +514,13 @@ sub ckbox($$@) # $filename, @syncstate sub ckstate($@) { - my ($fn, $mmaxuid, $mmaxxuid, $smaxuid, @T) = @_; + my ($fn, $fmaxuid, $maxxfuid, $nmaxuid, @T) = @_; my %hdr; - $hdr{'MasterUidValidity'} = "1"; - $hdr{'SlaveUidValidity'} = "1"; - $hdr{'MaxPulledUid'} = $mmaxuid; - $hdr{'MaxPushedUid'} = $smaxuid; - $hdr{'MaxExpiredMasterUid'} = $mmaxxuid if ($mmaxxuid ne 0); + $hdr{'FarUidValidity'} = "1"; + $hdr{'NearUidValidity'} = "1"; + $hdr{'MaxPulledUid'} = $fmaxuid; + $hdr{'MaxPushedUid'} = $nmaxuid; + $hdr{'MaxExpiredFarUid'} = $maxxfuid if ($maxxfuid ne 0); open(FILE, "<", $fn) or die "Cannot read sync state $fn.\n"; chomp(my @ls = ); close FILE; @@ -573,8 +573,8 @@ sub ckchan($$) { my ($F, $cs) = @_; my $rslt = ckstate($F, @{ $$cs[2] }); - $rslt |= &ckbox("master", @{ $$cs[0] }); - $rslt |= &ckbox("slave", @{ $$cs[1] }); + $rslt |= &ckbox("far", @{ $$cs[0] }); + $rslt |= &ckbox("near", @{ $$cs[1] }); return $rslt; } @@ -618,8 +618,8 @@ sub printchan($) { my ($cs) = @_; - &printbox("master", @{ $$cs[0] }); - &printbox("slave", @{ $$cs[1] }); + &printbox("far", @{ $$cs[0] }); + &printbox("near", @{ $$cs[1] }); printstate(@{ $$cs[2] }); } @@ -645,7 +645,7 @@ sub test($$$@) mkchan($$sx[0], $$sx[1], @{ $$sx[2] }); my ($xc, @ret) = runsync("-J", "1-initial.log"); - if ($xc || ckchan("slave/.mbsyncstate.new", $tx)) { + if ($xc || ckchan("near/.mbsyncstate.new", $tx)) { print "Input:\n"; printchan($sx); print "Options:\n"; @@ -654,16 +654,16 @@ sub test($$$@) print "Expected result:\n"; printchan($tx); print "Actual result:\n"; - showchan("slave/.mbsyncstate.new"); + showchan("near/.mbsyncstate.new"); } print "Debug output:\n"; print @ret; exit 1; } - my @nj = readfile("slave/.mbsyncstate.journal"); + my @nj = readfile("near/.mbsyncstate.journal"); my ($jxc, @jret) = runsync("-0 --no-expunge", "2-replay.log"); - if ($jxc || ckstate("slave/.mbsyncstate", @{ $$tx[2] })) { + if ($jxc || ckstate("near/.mbsyncstate", @{ $$tx[2] })) { print "Journal replay failed.\n"; print "Options:\n"; print " [ ".join(", ", map('"'.qm($_).'"', @sfx))." ], [ \"-0\", \"--no-expunge\" ]\n"; @@ -674,7 +674,7 @@ sub test($$$@) print "Expected New State:\n"; printstate(@{ $$tx[2] }); print "New State:\n"; - showstate("slave/.mbsyncstate"); + showstate("near/.mbsyncstate"); } print "Debug output:\n"; print @jret; @@ -682,7 +682,7 @@ sub test($$$@) } my ($ixc, @iret) = runsync("", "3-verify.log"); - if ($ixc || ckchan("slave/.mbsyncstate", $tx)) { + if ($ixc || ckchan("near/.mbsyncstate", $tx)) { print "Idempotence verification run failed.\n"; print "Input == Expected result:\n"; printchan($tx); @@ -690,15 +690,15 @@ sub test($$$@) print " [ ".join(", ", map('"'.qm($_).'"', @sfx))." ]\n"; if (!$ixc) { print "Actual result:\n"; - showchan("slave/.mbsyncstate"); + showchan("near/.mbsyncstate"); } print "Debug output:\n"; print @iret; exit 1; } - rmtree "slave"; - rmtree "master"; + rmtree "near"; + rmtree "far"; my $njl = (@nj - 1) * 2; for (my $l = 2; $l < $njl; $l++) { @@ -713,28 +713,28 @@ sub test($$$@) } ($nxc, @nret) = runsync("-J", "5-resume.log"); - if ($nxc || ckchan("slave/.mbsyncstate.new", $tx)) { + if ($nxc || ckchan("near/.mbsyncstate.new", $tx)) { print "Resuming from step $l/$njl failed.\n"; print "Input:\n"; printchan($sx); print "Options:\n"; print " [ ".join(", ", map('"'.qm($_).'"', @sfx))." ]\n"; - my @nnj = readfile("slave/.mbsyncstate.journal"); + my @nnj = readfile("near/.mbsyncstate.journal"); print "Journal:\n".join("", @nnj[0..($l / 2 - 1)])."-------\n".join("", @nnj[($l / 2)..$#nnj])."\n"; print "Full journal:\n".join("", @nj)."\n"; if (!$nxc) { print "Expected result:\n"; printchan($tx); print "Actual result:\n"; - showchan("slave/.mbsyncstate.new"); + showchan("near/.mbsyncstate.new"); } print "Debug output:\n"; print @nret; exit 1; } - rmtree "slave"; - rmtree "master"; + rmtree "near"; + rmtree "far"; } killcfg(); diff --git a/src/sync.c b/src/sync.c index f35b3f7..0defc11 100644 --- a/src/sync.c +++ b/src/sync.c @@ -43,7 +43,7 @@ channel_conf_t global_conf; channel_conf_t *channels; group_conf_t *groups; -const char *str_ms[] = { "master", "slave" }, *str_hl[] = { "push", "pull" }; +const char *str_fn[] = { "far side", "near side" }, *str_hl[] = { "push", "pull" }; static void ATTR_PRINTFLIKE(1, 2) debug( const char *msg, ... ) @@ -131,8 +131,8 @@ make_flags( uchar flags, char *buf ) // These is the (mostly) persistent status of the sync record. // Most of these bits are actually mutually exclusive. It is a // bitfield to allow for easy testing for multiple states. -#define S_EXPIRE (1<<0) // the entry is being expired (slave message removal scheduled) -#define S_EXPIRED (1<<1) // the entry is expired (slave message removal confirmed) +#define S_EXPIRE (1<<0) // the entry is being expired (near side message removal scheduled) +#define S_EXPIRED (1<<1) // the entry is expired (near side message removal confirmed) #define S_PENDING (1<<2) // the entry is new and awaits propagation (possibly a retry) #define S_SKIPPED (1<<3) // the entry was not propagated (message is too big) #define S_DEAD (1<<7) // ephemeral: the entry was killed and should be ignored @@ -140,7 +140,7 @@ make_flags( uchar flags, char *buf ) // Ephemeral working set. #define W_NEXPIRE (1<<0) // temporary: new expiration state #define W_DELETE (1<<1) // ephemeral: flags propagation is a deletion -#define W_DEL(ms) (1<<(2+(ms))) // ephemeral: m/s message would be subject to expunge +#define W_DEL(fn) (1<<(2+(fn))) // ephemeral: f/n message would be subject to expunge typedef struct sync_rec { struct sync_rec *next; @@ -171,7 +171,7 @@ typedef struct { uint uidval[2]; // UID validity value uint newuidval[2]; // UID validity obtained from driver uint newuid[2]; // TUID lookup makes sense only for UIDs >= this - uint mmaxxuid; // highest expired UID on master + uint maxxfuid; // highest expired UID on far side uchar good_flags[2], bad_flags[2]; } sync_vars_t; @@ -194,11 +194,11 @@ static int check_cancel( sync_vars_t *svars ); /* operation dependencies: select(x): - load(x): select(x) - new(M), new(S), flags(M), flags(S): load(M) & load(S) + new(F), new(N), flags(F), flags(N): load(F) & load(N) find_new(x): new(x) trash(x): flags(x) close(x): trash(x) & find_new(x) & new(!x) // with expunge - cleanup: close(M) & close(S) + cleanup: close(F) & close(N) */ #define ST_LOADED (1<<0) @@ -257,7 +257,7 @@ match_tuids( sync_vars_t *svars, int t, message_t *msgs ) if (srec->status & S_DEAD) continue; if (!srec->uid[t] && srec->tuid[0]) { - debug( "pair(%u,%u) TUID %." stringify(TUIDL) "s\n", srec->uid[M], srec->uid[S], srec->tuid ); + debug( "pair(%u,%u) TUID %." stringify(TUIDL) "s\n", srec->uid[F], srec->uid[N], srec->tuid ); for (tmsg = ntmsg; tmsg; tmsg = tmsg->next) { if (tmsg->status & M_DEAD) continue; @@ -274,13 +274,13 @@ match_tuids( sync_vars_t *svars, int t, message_t *msgs ) goto mfound; } } - JLOG( "& %u %u", (srec->uid[M], srec->uid[S]), "TUID lost" ); + JLOG( "& %u %u", (srec->uid[F], srec->uid[N]), "TUID lost" ); // Note: status remains S_PENDING. srec->tuid[0] = 0; num_lost++; continue; mfound: - JLOG( "%c %u %u %u", ("<>"[t], srec->uid[M], srec->uid[S], tmsg->uid), "TUID matched %s", diag ); + JLOG( "%c %u %u %u", ("<>"[t], srec->uid[F], srec->uid[N], tmsg->uid), "TUID matched %s", diag ); tmsg->srec = srec; srec->msg[t] = tmsg; ntmsg = tmsg->next; @@ -304,7 +304,7 @@ sanitize_flags( uchar tflags, sync_vars_t *svars, int t ) if (bflags) { char bfbuf[16]; make_flags( bflags, bfbuf ); - notice( "Notice: %s does not support flag(s) '%s'; not propagating.\n", str_ms[t], bfbuf ); + notice( "Notice: %s store does not support flag(s) '%s'; not propagating.\n", str_fn[t], bfbuf ); svars->bad_flags[t] |= bflags; } } @@ -458,7 +458,7 @@ msg_fetched( int sts, void *aux ) if (vars->srec || scr != tcr) { if (!copy_msg_convert( scr, tcr, vars )) { warn( "Warning: message %u from %s has incomplete header.\n", - vars->msg->uid, str_ms[1-t] ); + vars->msg->uid, str_fn[1-t] ); vars->cb( SYNC_NOGOOD, 0, vars ); return; } @@ -495,7 +495,7 @@ msg_stored( int sts, uint uid, void *aux ) INIT_SVARS(vars->aux); (void)svars; warn( "Warning: %s refuses to store message %u from %s.\n", - str_ms[t], vars->msg->uid, str_ms[1-t] ); + str_fn[t], vars->msg->uid, str_fn[1-t] ); vars->cb( SYNC_NOGOOD, 0, vars ); break; default: @@ -557,7 +557,7 @@ store_bad( void *aux ) static int check_cancel( sync_vars_t *svars ) { - return (svars->state[M] | svars->state[S]) & (ST_SENT_CANCEL | ST_CANCELED); + return (svars->state[F] | svars->state[N]) & (ST_SENT_CANCEL | ST_CANCELED); } static int @@ -623,21 +623,21 @@ prepare_state( sync_vars_t *svars ) chan = svars->chan; if (!strcmp( chan->sync_state ? chan->sync_state : global_conf.sync_state, "*" )) { - const char *path = svars->drv[S]->get_box_path( svars->ctx[S] ); + const char *path = svars->drv[N]->get_box_path( svars->ctx[N] ); if (!path) { - error( "Error: store '%s' does not support in-box sync state\n", chan->stores[S]->name ); + error( "Error: store '%s' does not support in-box sync state\n", chan->stores[N]->name ); return 0; } nfasprintf( &svars->dname, "%s/." EXE "state", path ); } else { - csname = clean_strdup( svars->box_name[S] ); + csname = clean_strdup( svars->box_name[N] ); if (chan->sync_state) nfasprintf( &svars->dname, "%s%s", chan->sync_state, csname ); else { char c = FieldDelimiter; - cmname = clean_strdup( svars->box_name[M] ); + cmname = clean_strdup( svars->box_name[F] ); nfasprintf( &svars->dname, "%s%c%s%c%s_%c%s%c%s", global_conf.sync_state, - c, chan->stores[M]->name, c, cmname, c, chan->stores[S]->name, c, csname ); + c, chan->stores[F]->name, c, cmname, c, chan->stores[N]->name, c, csname ); free( cmname ); } free( csname ); @@ -678,7 +678,7 @@ lock_state( sync_vars_t *svars ) } if (fcntl( svars->lfd, F_SETLK, &lck )) { error( "Error: channel :%s:%s-:%s:%s is locked\n", - svars->chan->stores[M]->name, svars->orig_name[M], svars->chan->stores[S]->name, svars->orig_name[S] ); + svars->chan->stores[F]->name, svars->orig_name[F], svars->chan->stores[N]->name, svars->orig_name[N] ); close( svars->lfd ); svars->lfd = -1; return 0; @@ -693,16 +693,16 @@ save_state( sync_vars_t *svars ) char fbuf[16]; /* enlarge when support for keywords is added */ Fprintf( svars->nfp, - "MasterUidValidity %u\nSlaveUidValidity %u\nMaxPulledUid %u\nMaxPushedUid %u\n", - svars->uidval[M], svars->uidval[S], svars->maxuid[M], svars->maxuid[S] ); - if (svars->mmaxxuid) - Fprintf( svars->nfp, "MaxExpiredMasterUid %u\n", svars->mmaxxuid ); + "FarUidValidity %u\nNearUidValidity %u\nMaxPulledUid %u\nMaxPushedUid %u\n", + svars->uidval[F], svars->uidval[N], svars->maxuid[F], svars->maxuid[N] ); + if (svars->maxxfuid) + Fprintf( svars->nfp, "MaxExpiredFarUid %u\n", svars->maxxfuid ); Fprintf( svars->nfp, "\n" ); for (srec = svars->srecs; srec; srec = srec->next) { if (srec->status & S_DEAD) continue; make_flags( srec->flags, fbuf ); - Fprintf( svars->nfp, "%u %u %s%s\n", srec->uid[M], srec->uid[S], + Fprintf( svars->nfp, "%u %u %s%s\n", srec->uid[F], srec->uid[N], (srec->status & S_SKIPPED) ? "^" : (srec->status & S_EXPIRED) ? "~" : "", fbuf ); } @@ -724,7 +724,7 @@ load_state( sync_vars_t *svars ) char *s; FILE *jfp; uint ll; - uint smaxxuid = 0; + uint maxxnuid = 0; char c; struct stat st; char fbuf[16]; /* enlarge when support for keywords is added */ @@ -747,8 +747,8 @@ load_state( sync_vars_t *svars ) goto gothdr; if (line == 1 && isdigit( buf[0] )) { if (sscanf( buf, "%63s %63s", buf1, buf2 ) != 2 || - sscanf( buf1, "%u:%u", &svars->uidval[M], &svars->maxuid[M] ) < 2 || - sscanf( buf2, "%u:%u:%u", &svars->uidval[S], &smaxxuid, &svars->maxuid[S] ) < 3) { + sscanf( buf1, "%u:%u", &svars->uidval[F], &svars->maxuid[F] ) < 2 || + sscanf( buf2, "%u:%u:%u", &svars->uidval[N], &maxxnuid, &svars->maxuid[N] ) < 3) { error( "Error: invalid sync state header in %s\n", svars->dname ); goto jbail; } @@ -759,18 +759,18 @@ load_state( sync_vars_t *svars ) error( "Error: malformed sync state header entry at %s:%d\n", svars->dname, line ); goto jbail; } - if (!strcmp( buf1, "MasterUidValidity" )) - svars->uidval[M] = uid; - else if (!strcmp( buf1, "SlaveUidValidity" )) - svars->uidval[S] = uid; + if (!strcmp( buf1, "FarUidValidity" ) || !strcmp( buf1, "MasterUidValidity" ) /* Pre-1.4 legacy */) + svars->uidval[F] = uid; + else if (!strcmp( buf1, "NearUidValidity" ) || !strcmp( buf1, "SlaveUidValidity" ) /* Pre-1.4 legacy */) + svars->uidval[N] = uid; else if (!strcmp( buf1, "MaxPulledUid" )) - svars->maxuid[M] = uid; + svars->maxuid[F] = uid; else if (!strcmp( buf1, "MaxPushedUid" )) - svars->maxuid[S] = uid; - else if (!strcmp( buf1, "MaxExpiredMasterUid" )) - svars->mmaxxuid = uid; + svars->maxuid[N] = uid; + else if (!strcmp( buf1, "MaxExpiredFarUid" ) || !strcmp( buf1, "MaxExpiredMasterUid" ) /* Pre-1.4 legacy */) + svars->maxxfuid = uid; else if (!strcmp( buf1, "MaxExpiredSlaveUid" )) // Legacy - smaxxuid = uid; + maxxnuid = uid; else { error( "Error: unrecognized sync state header entry at %s:%d\n", svars->dname, line ); goto jbail; @@ -793,8 +793,8 @@ load_state( sync_vars_t *svars ) goto jbail; } srec = nfcalloc( sizeof(*srec) ); - srec->uid[M] = t1; - srec->uid[S] = t2; + srec->uid[F] = t1; + srec->uid[N] = t2; s = fbuf; if (*s == '^') { s++; @@ -802,15 +802,15 @@ load_state( sync_vars_t *svars ) } else if (*s == '~' || *s == 'X' /* Pre-1.3 legacy */) { s++; srec->status = S_EXPIRE | S_EXPIRED; - } else if (srec->uid[M] == (uint)-1) { // Pre-1.3 legacy - srec->uid[M] = 0; + } else if (srec->uid[F] == (uint)-1) { // Pre-1.3 legacy + srec->uid[F] = 0; srec->status = S_SKIPPED; - } else if (srec->uid[S] == (uint)-1) { - srec->uid[S] = 0; + } else if (srec->uid[N] == (uint)-1) { + srec->uid[N] = 0; srec->status = S_SKIPPED; } srec->flags = parse_flags( s ); - debug( " entry (%u,%u,%u,%s)\n", srec->uid[M], srec->uid[S], srec->flags, + debug( " entry (%u,%u,%u,%s)\n", srec->uid[F], srec->uid[N], srec->flags, (srec->status & S_SKIPPED) ? "SKIP" : (srec->status & S_EXPIRED) ? "XPIRE" : "" ); *svars->srecadd = srec; svars->srecadd = &srec->next; @@ -827,34 +827,34 @@ load_state( sync_vars_t *svars ) } // This is legacy support for pre-1.3 sync states. - if (smaxxuid) { + if (maxxnuid) { uint minwuid = UINT_MAX; for (srec = svars->srecs; srec; srec = srec->next) { - if ((srec->status & (S_DEAD | S_SKIPPED | S_PENDING)) || !srec->uid[M]) + if ((srec->status & (S_DEAD | S_SKIPPED | S_PENDING)) || !srec->uid[F]) continue; if (srec->status & S_EXPIRED) { - if (!srec->uid[S]) { + if (!srec->uid[N]) { // The expired message was already gone. continue; } // The expired message was not expunged yet, so re-examine it. // This will happen en masse, so just extend the bulk fetch. } else { - if (srec->uid[S] && smaxxuid >= srec->uid[S]) { + if (srec->uid[N] && maxxnuid >= srec->uid[N]) { // The non-expired message is in the generally expired range, // so don't make it contribute to the bulk fetch. continue; } // Usual non-expired message. } - if (minwuid > srec->uid[M]) - minwuid = srec->uid[M]; + if (minwuid > srec->uid[F]) + minwuid = srec->uid[F]; } - svars->mmaxxuid = minwuid - 1; + svars->maxxfuid = minwuid - 1; } - svars->newmaxuid[M] = svars->maxuid[M]; - svars->newmaxuid[S] = svars->maxuid[S]; + svars->newmaxuid[F] = svars->maxuid[F]; + svars->newmaxuid[N] = svars->maxuid[N]; int line = 0; if ((jfp = fopen( svars->jname, "r" ))) { if (!lock_state( svars )) @@ -900,18 +900,18 @@ load_state( sync_vars_t *svars ) else if (c == 'T') *uint_array_append( &svars->trashed_msgs[t1] ) = t2; else if (c == '!') - svars->mmaxxuid = t1; + svars->maxxfuid = t1; else if (c == '|') { - svars->uidval[M] = t1; - svars->uidval[S] = t2; + svars->uidval[F] = t1; + svars->uidval[N] = t2; } else if (c == '+') { srec = nfcalloc( sizeof(*srec) ); - srec->uid[M] = t1; - srec->uid[S] = t2; - if (svars->newmaxuid[M] < t1) - svars->newmaxuid[M] = t1; - if (svars->newmaxuid[S] < t2) - svars->newmaxuid[S] = t2; + srec->uid[F] = t1; + srec->uid[N] = t2; + if (svars->newmaxuid[F] < t1) + svars->newmaxuid[F] = t1; + if (svars->newmaxuid[N] < t2) + svars->newmaxuid[N] = t2; debug( " new entry(%u,%u)\n", t1, t2 ); srec->status = S_PENDING; *svars->srecadd = srec; @@ -919,15 +919,15 @@ load_state( sync_vars_t *svars ) svars->nsrecs++; } else { for (nsrec = srec; srec; srec = srec->next) - if (srec->uid[M] == t1 && srec->uid[S] == t2) + if (srec->uid[F] == t1 && srec->uid[N] == t2) goto syncfnd; for (srec = svars->srecs; srec != nsrec; srec = srec->next) - if (srec->uid[M] == t1 && srec->uid[S] == t2) + if (srec->uid[F] == t1 && srec->uid[N] == t2) goto syncfnd; error( "Error: journal entry at %s:%d refers to non-existing sync state entry\n", svars->jname, line ); goto jbail; syncfnd: - debugn( " entry(%u,%u,%u) ", srec->uid[M], srec->uid[S], srec->flags ); + debugn( " entry(%u,%u,%u) ", srec->uid[F], srec->uid[N], srec->flags ); switch (c) { case '-': debug( "killed\n" ); @@ -935,7 +935,7 @@ load_state( sync_vars_t *svars ) break; case '=': debug( "aborted\n" ); - svars->mmaxxuid = srec->uid[M]; + svars->maxxfuid = srec->uid[F]; srec->status = S_DEAD; break; case '#': @@ -947,14 +947,14 @@ load_state( sync_vars_t *svars ) srec->tuid[0] = 0; break; case '<': - debug( "master now %u\n", t3 ); - srec->uid[M] = t3; + debug( "far side now %u\n", t3 ); + srec->uid[F] = t3; srec->status &= ~S_PENDING; srec->tuid[0] = 0; break; case '>': - debug( "slave now %u\n", t3 ); - srec->uid[S] = t3; + debug( "near side now %u\n", t3 ); + srec->uid[N] = t3; srec->status &= ~S_PENDING; srec->tuid[0] = 0; break; @@ -1064,7 +1064,7 @@ sync_boxes( store_t *ctx[], const char * const names[], int present[], channel_c sync_ref( svars ); for (t = 0; ; t++) { - info( "Opening %s box %s...\n", str_ms[t], svars->orig_name[t] ); + info( "Opening %s box %s...\n", str_fn[t], svars->orig_name[t] ); if (present[t] == BOX_ABSENT) box_confirmed2( svars, t ); else @@ -1105,8 +1105,8 @@ box_confirmed2( sync_vars_t *svars, int t ) if (!(svars->state[t] & ST_PRESENT)) { if (!(svars->state[1-t] & ST_PRESENT)) { if (!svars->existing) { - error( "Error: channel %s: both master %s and slave %s cannot be opened.\n", - svars->chan->name, svars->orig_name[M], svars->orig_name[S] ); + error( "Error: channel %s: both far side %s and near side %s cannot be opened.\n", + svars->chan->name, svars->orig_name[F], svars->orig_name[N] ); bail: svars->ret = SYNC_FAIL; } else { @@ -1122,22 +1122,22 @@ box_confirmed2( sync_vars_t *svars, int t ) } if (svars->existing) { if (!(svars->chan->ops[1-t] & OP_REMOVE)) { - error( "Error: channel %s: %s %s cannot be opened.\n", - svars->chan->name, str_ms[t], svars->orig_name[t] ); + error( "Error: channel %s: %s box %s cannot be opened.\n", + svars->chan->name, str_fn[t], svars->orig_name[t] ); goto bail; } if (svars->drv[1-t]->confirm_box_empty( svars->ctx[1-t] ) != DRV_OK) { - warn( "Warning: channel %s: %s %s cannot be opened and %s %s not empty.\n", - svars->chan->name, str_ms[t], svars->orig_name[t], str_ms[1-t], svars->orig_name[1-t] ); + warn( "Warning: channel %s: %s box %s cannot be opened and %s box %s is not empty.\n", + svars->chan->name, str_fn[t], svars->orig_name[t], str_fn[1-t], svars->orig_name[1-t] ); goto done; } - info( "Deleting %s %s...\n", str_ms[1-t], svars->orig_name[1-t] ); + info( "Deleting %s box %s...\n", str_fn[1-t], svars->orig_name[1-t] ); svars->drv[1-t]->delete_box( svars->ctx[1-t], box_deleted, INV_AUX ); } else { if (!(svars->chan->ops[t] & OP_CREATE)) { box_opened( DRV_BOX_BAD, UIDVAL_BAD, AUX ); } else { - info( "Creating %s %s...\n", str_ms[t], svars->orig_name[t] ); + info( "Creating %s box %s...\n", str_fn[t], svars->orig_name[t] ); svars->drv[t]->create_box( svars->ctx[t], box_created, AUX ); } } @@ -1188,8 +1188,8 @@ box_opened( int sts, uint uidvalidity, void *aux ) return; if (sts == DRV_BOX_BAD) { - error( "Error: channel %s: %s %s cannot be opened.\n", - svars->chan->name, str_ms[t], svars->orig_name[t] ); + error( "Error: channel %s: %s box %s cannot be opened.\n", + svars->chan->name, str_fn[t], svars->orig_name[t] ); svars->ret = SYNC_FAIL; sync_bail( svars ); } else { @@ -1219,10 +1219,10 @@ box_opened2( sync_vars_t *svars, int t ) if (svars->uidval[t] != UIDVAL_BAD && svars->uidval[t] != svars->newuidval[t]) fails++; if (fails == 2) { - error( "Error: channel %s: UIDVALIDITY of both master and slave changed\n" - "(master got %u, expected %u; slave got %u, expected %u).\n", + error( "Error: channel %s: UIDVALIDITY of both far and near side changed\n" + "(far side got %u, expected %u; near side got %u, expected %u).\n", svars->chan->name, - svars->newuidval[M], svars->uidval[M], svars->newuidval[S], svars->uidval[S] ); + svars->newuidval[F], svars->uidval[F], svars->newuidval[N], svars->uidval[N] ); bail: svars->ret = SYNC_FAIL; sync_bail( svars ); @@ -1244,9 +1244,9 @@ box_opened2( sync_vars_t *svars, int t ) if (!svars->replayed) jFprintf( svars, JOURNAL_VERSION "\n" ); - opts[M] = opts[S] = 0; + opts[F] = opts[N] = 0; if (fails) - opts[M] = opts[S] = OPEN_OLD|OPEN_OLD_IDS; + opts[F] = opts[N] = OPEN_OLD|OPEN_OLD_IDS; for (t = 0; t < 2; t++) { if (chan->ops[t] & (OP_DELETE|OP_FLAGS)) { opts[t] |= OPEN_SETFLAGS; @@ -1279,47 +1279,47 @@ box_opened2( sync_vars_t *svars, int t ) opts[t] |= OPEN_NEW|OPEN_FLAGS; } } - if ((chan->ops[S] & (OP_NEW|OP_RENEW|OP_FLAGS)) && chan->max_messages) - opts[S] |= OPEN_OLD|OPEN_NEW|OPEN_FLAGS; + if ((chan->ops[N] & (OP_NEW|OP_RENEW|OP_FLAGS)) && chan->max_messages) + opts[N] |= OPEN_OLD|OPEN_NEW|OPEN_FLAGS; if (svars->replayed) for (srec = svars->srecs; srec; srec = srec->next) { if (srec->status & S_DEAD) continue; if (srec->tuid[0]) { - if (!srec->uid[M]) - opts[M] |= OPEN_NEW|OPEN_FIND, svars->state[M] |= ST_FIND_OLD; - else if (!srec->uid[S]) - opts[S] |= OPEN_NEW|OPEN_FIND, svars->state[S] |= ST_FIND_OLD; + if (!srec->uid[F]) + opts[F] |= OPEN_NEW|OPEN_FIND, svars->state[F] |= ST_FIND_OLD; + else if (!srec->uid[N]) + opts[N] |= OPEN_NEW|OPEN_FIND, svars->state[N] |= ST_FIND_OLD; else - warn( "Warning: sync record (%u,%u) has stray TUID. Ignoring.\n", srec->uid[M], srec->uid[S] ); + warn( "Warning: sync record (%u,%u) has stray TUID. Ignoring.\n", srec->uid[F], srec->uid[N] ); } } - svars->opts[M] = svars->drv[M]->prepare_load_box( ctx[M], opts[M] ); - svars->opts[S] = svars->drv[S]->prepare_load_box( ctx[S], opts[S] ); + svars->opts[F] = svars->drv[F]->prepare_load_box( ctx[F], opts[F] ); + svars->opts[N] = svars->drv[N]->prepare_load_box( ctx[N], opts[N] ); ARRAY_INIT( &mexcs ); - if (svars->opts[M] & OPEN_OLD) { + if (svars->opts[F] & OPEN_OLD) { if (chan->max_messages) { - /* When messages have been expired on the slave, the master fetch is split into + /* When messages have been expired on the near side, the far side fetch is split into * two ranges: The bulk fetch which corresponds with the most recent messages, and an * exception list of messages which would have been expired if they weren't important. */ - debug( "preparing master selection - max expired master uid is %u\n", svars->mmaxxuid ); + debug( "preparing far side selection - max expired far uid is %u\n", svars->maxxfuid ); /* First, find out the lower bound for the bulk fetch. */ - minwuid = svars->mmaxxuid + 1; + minwuid = svars->maxxfuid + 1; /* Next, calculate the exception fetch. */ for (srec = svars->srecs; srec; srec = srec->next) { if (srec->status & S_DEAD) continue; - if (!srec->uid[M]) + if (!srec->uid[F]) continue; // No message; other state is irrelevant - if (srec->uid[M] >= minwuid) + if (srec->uid[F] >= minwuid) continue; // Message is in non-expired range - if ((svars->opts[M] & OPEN_NEW) && srec->uid[M] >= svars->maxuid[M]) + if ((svars->opts[F] & OPEN_NEW) && srec->uid[F] >= svars->maxuid[F]) continue; // Message is in expired range, but new range overlaps that - if (!srec->uid[S] && !(srec->status & S_PENDING)) + if (!srec->uid[N] && !(srec->status & S_PENDING)) continue; // Only actually paired up messages matter // The pair is alive, but outside the bulk range - *uint_array_append( &mexcs ) = srec->uid[M]; + *uint_array_append( &mexcs ) = srec->uid[F]; } sort_uint_array( mexcs.array ); } else { @@ -1329,9 +1329,9 @@ box_opened2( sync_vars_t *svars, int t ) minwuid = UINT_MAX; } sync_ref( svars ); - load_box( svars, M, minwuid, mexcs.array ); + load_box( svars, F, minwuid, mexcs.array ); if (!check_cancel( svars )) - load_box( svars, S, (svars->opts[S] & OPEN_OLD) ? 1 : UINT_MAX, (uint_array_t){ NULL, 0 } ); + load_box( svars, N, (svars->opts[N] & OPEN_OLD) ? 1 : UINT_MAX, (uint_array_t){ NULL, 0 } ); sync_deref( svars ); } @@ -1369,7 +1369,7 @@ load_box( sync_vars_t *svars, int t, uint minwuid, uint_array_t mexcs ) * But if it is there, use it to avoid a possible gap in the fetched range. */ seenuid = svars->maxuid[t]; } - info( "Loading %s...\n", str_ms[t] ); + info( "Loading %s box...\n", str_fn[t] ); svars->drv[t]->load_box( svars->ctx[t], minwuid, maxwuid, svars->newuid[t], seenuid, mexcs, box_loaded, AUX ); } @@ -1407,14 +1407,14 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux INIT_SVARS(aux); svars->state[t] |= ST_LOADED; svars->msgs[t] = msgs; - info( "%s: %d messages, %d recent\n", str_ms[t], total_msgs, recent_msgs ); + info( "%s: %d messages, %d recent\n", str_fn[t], total_msgs, recent_msgs ); if (svars->state[t] & ST_FIND_OLD) { - debug( "matching previously copied messages on %s\n", str_ms[t] ); + debug( "matching previously copied messages on %s\n", str_fn[t] ); match_tuids( svars, t, msgs ); } - debug( "matching messages on %s against sync records\n", str_ms[t] ); + debug( "matching messages on %s against sync records\n", str_fn[t] ); hashsz = bucketsForSize( svars->nsrecs * 3 ); srecmap = nfcalloc( hashsz * sizeof(*srecmap) ); for (srec = svars->srecs; srec; srec = srec->next) { @@ -1456,7 +1456,7 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux for (t = 0; t < 2; t++) { if (svars->uidval[t] != UIDVAL_BAD && svars->uidval[t] != svars->newuidval[t]) { unsigned need = 0, got = 0; - debug( "trying to re-approve uid validity of %s\n", str_ms[t] ); + debug( "trying to re-approve uid validity of %s\n", str_fn[t] ); for (srec = svars->srecs; srec; srec = srec->next) { if (srec->status & S_DEAD) continue; @@ -1467,9 +1467,9 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux continue; // Messages without ID are useless for re-validation. if (!srec->msg[1-t]) continue; // Partner disappeared. - if (!srec->msg[1-t]->msgid || strcmp( srec->msg[M]->msgid, srec->msg[S]->msgid )) { - error( "Error: channel %s, %s %s: UIDVALIDITY genuinely changed (at UID %u).\n", - svars->chan->name, str_ms[t], svars->orig_name[t], srec->uid[t] ); + if (!srec->msg[1-t]->msgid || strcmp( srec->msg[F]->msgid, srec->msg[N]->msgid )) { + error( "Error: channel %s, %s box %s: UIDVALIDITY genuinely changed (at UID %u).\n", + svars->chan->name, str_fn[t], svars->orig_name[t], srec->uid[t] ); uvchg: svars->ret |= SYNC_FAIL; cancel_sync( svars ); @@ -1482,22 +1482,22 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux // A proper fallback would be fetching more headers (which potentially need // normalization) or the message body (which should be truncated for sanity) // and comparing. - error( "Error: channel %s, %s %s: Unable to recover from UIDVALIDITY change\n" + error( "Error: channel %s, %s box %s: Unable to recover from UIDVALIDITY change\n" "(got %u, expected %u).\n", - svars->chan->name, str_ms[t], svars->orig_name[t], + svars->chan->name, str_fn[t], svars->orig_name[t], svars->newuidval[t], svars->uidval[t] ); goto uvchg; } - notice( "Notice: channel %s, %s %s: Recovered from change of UIDVALIDITY.\n", - svars->chan->name, str_ms[t], svars->orig_name[t] ); + notice( "Notice: channel %s, %s box %s: Recovered from change of UIDVALIDITY.\n", + svars->chan->name, str_fn[t], svars->orig_name[t] ); svars->uidval[t] = UIDVAL_BAD; } } - if (svars->uidval[M] == UIDVAL_BAD || svars->uidval[S] == UIDVAL_BAD) { - svars->uidval[M] = svars->newuidval[M]; - svars->uidval[S] = svars->newuidval[S]; - JLOG( "| %u %u", (svars->uidval[M], svars->uidval[S]), "new UIDVALIDITYs" ); + if (svars->uidval[F] == UIDVAL_BAD || svars->uidval[N] == UIDVAL_BAD) { + svars->uidval[F] = svars->newuidval[F]; + svars->uidval[N] = svars->newuidval[N]; + JLOG( "| %u %u", (svars->uidval[F], svars->uidval[N]), "new UIDVALIDITYs" ); } info( "Synchronizing...\n" ); @@ -1508,21 +1508,21 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux for (srec = svars->srecs; srec; srec = srec->next) { if (srec->status & S_DEAD) continue; - debug( "pair (%u,%u)\n", srec->uid[M], srec->uid[S] ); + debug( "pair (%u,%u)\n", srec->uid[F], srec->uid[N] ); assert( !srec->tuid[0] ); // no[] means that a message is known to be not there. - no[M] = !srec->msg[M] && (svars->opts[M] & OPEN_OLD); - no[S] = !srec->msg[S] && (svars->opts[S] & OPEN_OLD); - if (no[M] && no[S]) { + no[F] = !srec->msg[F] && (svars->opts[F] & OPEN_OLD); + no[N] = !srec->msg[N] && (svars->opts[N] & OPEN_OLD); + if (no[F] && no[N]) { // It does not matter whether one side was already known to be missing // (never stored [skipped or failed] or expunged [possibly expired]) - // now both are missing, so the entry is superfluous. srec->status = S_DEAD; - JLOG( "- %u %u", (srec->uid[M], srec->uid[S]), "both missing" ); + JLOG( "- %u %u", (srec->uid[F], srec->uid[N]), "both missing" ); } else { // del[] means that a message becomes known to have been expunged. - del[M] = no[M] && srec->uid[M]; - del[S] = no[S] && srec->uid[S]; + del[F] = no[F] && srec->uid[F]; + del[N] = no[N] && srec->uid[N]; for (t = 0; t < 2; t++) { if (srec->msg[t] && (srec->msg[t]->flags & F_DELETED)) @@ -1538,13 +1538,13 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux } else if (del[1-t]) { // The source was newly expunged, so possibly propagate the deletion. // The target may be in an unknown state (not fetched). - if ((t == M) && (srec->status & (S_EXPIRE|S_EXPIRED))) { + if ((t == F) && (srec->status & (S_EXPIRE|S_EXPIRED))) { /* Don't propagate deletion resulting from expiration. */ - JLOG( "> %u %u 0", (srec->uid[M], srec->uid[S]), "slave expired, orphaning master" ); - srec->uid[S] = 0; + JLOG( "> %u %u 0", (srec->uid[F], srec->uid[N]), "near side expired, orphaning far side" ); + srec->uid[N] = 0; } else { if (srec->msg[t] && (srec->msg[t]->status & M_FLAGS) && srec->msg[t]->flags != srec->flags) - notice( "Notice: conflicting changes in (%u,%u)\n", srec->uid[M], srec->uid[S] ); + notice( "Notice: conflicting changes in (%u,%u)\n", srec->uid[F], srec->uid[N] ); if (svars->chan->ops[t] & OP_DELETE) { debug( " %sing delete\n", str_hl[t] ); srec->aflags[t] = F_DELETED; @@ -1556,14 +1556,14 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux } else if (!srec->msg[1-t]) { // We have no source to work with, because it was never stored, // it was previously expunged, or we did not fetch it. - debug( " no %s\n", str_ms[1-t] ); + debug( " no %s\n", str_fn[1-t] ); } else { // We have a source. The target may be in an unknown state. if (svars->chan->ops[t] & OP_FLAGS) { sflags = sanitize_flags( srec->msg[1-t]->flags, svars, t ); - if ((t == M) && (srec->status & (S_EXPIRE|S_EXPIRED))) { + if ((t == F) && (srec->status & (S_EXPIRE|S_EXPIRED))) { /* Don't propagate deletion resulting from expiration. */ - debug( " slave expiring\n" ); + debug( " near side expiring\n" ); sflags &= ~F_DELETED; } srec->aflags[t] = sflags & ~srec->flags; @@ -1600,12 +1600,12 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux (((srec->status & S_PENDING) && (svars->chan->ops[t] & OP_NEW)) || ((srec->status & S_SKIPPED) && (svars->chan->ops[t] & OP_RENEW))) : svars->newmaxuid[1-t] < tmsg->uid && (svars->chan->ops[t] & OP_NEW)) { - debug( "new message %u on %s\n", tmsg->uid, str_ms[1-t] ); + debug( "new message %u on %s\n", tmsg->uid, str_fn[1-t] ); if ((svars->chan->ops[t] & OP_EXPUNGE) && (tmsg->flags & F_DELETED)) { debug( "-> ignoring - would be expunged anyway\n" ); } else { if (srec) { - debug( "-> pair(%u,%u) exists\n", srec->uid[M], srec->uid[S] ); + debug( "-> pair(%u,%u) exists\n", srec->uid[F], srec->uid[N] ); } else { srec = nfcalloc( sizeof(*srec) ); *svars->srecadd = srec; @@ -1617,19 +1617,19 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux tmsg->srec = srec; if (svars->newmaxuid[1-t] < tmsg->uid) svars->newmaxuid[1-t] = tmsg->uid; - JLOG( "+ %u %u", (srec->uid[M], srec->uid[S]), "fresh" ); + JLOG( "+ %u %u", (srec->uid[F], srec->uid[N]), "fresh" ); } if ((tmsg->flags & F_FLAGGED) || tmsg->size <= svars->chan->stores[t]->max_size) { if (srec->status != S_PENDING) { srec->status = S_PENDING; - JLOG( "~ %u %u %u", (srec->uid[M], srec->uid[S], srec->status), "was too big" ); + JLOG( "~ %u %u %u", (srec->uid[F], srec->uid[N], srec->status), "was too big" ); } } else { if (srec->status == S_SKIPPED) { debug( "-> still too big\n" ); } else { srec->status = S_SKIPPED; - JLOG( "~ %u %u %u", (srec->uid[M], srec->uid[S], srec->status), "skipping - too big" ); + JLOG( "~ %u %u %u", (srec->uid[F], srec->uid[N], srec->status), "skipping - too big" ); } } } @@ -1637,65 +1637,65 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux } } - if ((svars->chan->ops[S] & (OP_NEW|OP_RENEW|OP_FLAGS)) && svars->chan->max_messages) { - /* Note: When this branch is entered, we have loaded all slave messages. */ + if ((svars->chan->ops[N] & (OP_NEW|OP_RENEW|OP_FLAGS)) && svars->chan->max_messages) { + // Note: When this branch is entered, we have loaded all near side messages. /* Expire excess messages. Important (flagged, unread, or unpropagated) messages * older than the first not expired message are not counted towards the total. */ debug( "preparing message expiration\n" ); alive = 0; - for (tmsg = svars->msgs[S]; tmsg; tmsg = tmsg->next) { + for (tmsg = svars->msgs[N]; tmsg; tmsg = tmsg->next) { if (tmsg->status & M_DEAD) continue; - if ((srec = tmsg->srec) && srec->uid[M] && - ((tmsg->flags | srec->aflags[S]) & ~srec->dflags[S] & F_DELETED) && + if ((srec = tmsg->srec) && srec->uid[F] && + ((tmsg->flags | srec->aflags[N]) & ~srec->dflags[N] & F_DELETED) && !(srec->status & (S_EXPIRE|S_EXPIRED))) { /* Message was not propagated yet, or is deleted. */ } else { alive++; } } - for (tmsg = svars->msgs[M]; tmsg; tmsg = tmsg->next) { + for (tmsg = svars->msgs[F]; tmsg; tmsg = tmsg->next) { if ((srec = tmsg->srec) && (srec->status & S_PENDING) && !(tmsg->flags & F_DELETED)) alive++; } todel = alive - svars->chan->max_messages; debug( "%d alive messages, %d excess - expiring\n", alive, todel ); alive = 0; - for (tmsg = svars->msgs[S]; tmsg; tmsg = tmsg->next) { + for (tmsg = svars->msgs[N]; tmsg; tmsg = tmsg->next) { if (tmsg->status & M_DEAD) continue; - if (!(srec = tmsg->srec) || !srec->uid[M]) { + if (!(srec = tmsg->srec) || !srec->uid[F]) { /* We did not push the message, so it must be kept. */ debug( " message %u unpropagated\n", tmsg->uid ); todel--; } else { - nflags = (tmsg->flags | srec->aflags[S]) & ~srec->dflags[S]; + nflags = (tmsg->flags | srec->aflags[N]) & ~srec->dflags[N]; if (!(nflags & F_DELETED) || (srec->status & (S_EXPIRE|S_EXPIRED))) { /* The message is not deleted, or is already (being) expired. */ if ((nflags & F_FLAGGED) || !((nflags & F_SEEN) || ((void)(todel > 0 && alive++), svars->chan->expire_unread > 0))) { /* Important messages are always kept. */ - debug( " old pair(%u,%u) important\n", srec->uid[M], srec->uid[S] ); + debug( " old pair(%u,%u) important\n", srec->uid[F], srec->uid[N] ); todel--; } else if (todel > 0 || ((srec->status & (S_EXPIRE|S_EXPIRED)) == (S_EXPIRE|S_EXPIRED)) || ((srec->status & (S_EXPIRE|S_EXPIRED)) && (tmsg->flags & F_DELETED))) { /* The message is excess or was already (being) expired. */ srec->wstate |= W_NEXPIRE; - debug( " old pair(%u,%u) expired\n", srec->uid[M], srec->uid[S] ); - if (svars->mmaxxuid < srec->uid[M]) - svars->mmaxxuid = srec->uid[M]; + debug( " old pair(%u,%u) expired\n", srec->uid[F], srec->uid[N] ); + if (svars->maxxfuid < srec->uid[F]) + svars->maxxfuid = srec->uid[F]; todel--; } } } } - for (tmsg = svars->msgs[M]; tmsg; tmsg = tmsg->next) { + for (tmsg = svars->msgs[F]; tmsg; tmsg = tmsg->next) { if ((srec = tmsg->srec) && (srec->status & S_PENDING)) { nflags = tmsg->flags; if (!(nflags & F_DELETED)) { if ((nflags & F_FLAGGED) || !((nflags & F_SEEN) || ((void)(todel > 0 && alive++), svars->chan->expire_unread > 0))) { /* Important messages are always fetched. */ - debug( " new pair(%u,%u) important\n", srec->uid[M], srec->uid[S] ); + debug( " new pair(%u,%u) important\n", srec->uid[F], srec->uid[N] ); todel--; } else if (todel > 0) { /* The message is excess. */ @@ -1709,7 +1709,7 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux if (svars->chan->expire_unread < 0 && alive * 2 > svars->chan->max_messages) { error( "%s: %d unread messages in excess of MaxMessages (%d).\n" "Please set ExpireUnread to decide outcome. Skipping mailbox.\n", - svars->orig_name[S], alive, svars->chan->max_messages ); + svars->orig_name[N], alive, svars->chan->max_messages ); svars->ret |= SYNC_FAIL; cancel_sync( svars ); return; @@ -1718,7 +1718,7 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux if (srec->status & S_DEAD) continue; if (!(srec->status & S_PENDING)) { - if (!srec->msg[S]) + if (!srec->msg[N]) continue; uchar nex = (srec->wstate / W_NEXPIRE) & 1; if (nex != ((srec->status / S_EXPIRED) & 1)) { @@ -1726,10 +1726,10 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux if (nex != ((srec->status / S_EXPIRE) & 1)) { /* ... and we need to start a transaction. */ srec->status = (srec->status & ~S_EXPIRE) | (nex * S_EXPIRE); - JLOG( "~ %u %u %u", (srec->uid[M], srec->uid[S], srec->status), "expire %u - begin", nex ); + JLOG( "~ %u %u %u", (srec->uid[F], srec->uid[N], srec->status), "expire %u - begin", nex ); } else { /* ... but the "right" transaction is already pending. */ - debug( "-> pair(%u,%u): expire %u (pending)\n", srec->uid[M], srec->uid[S], nex ); + debug( "-> pair(%u,%u): expire %u (pending)\n", srec->uid[F], srec->uid[N], nex ); } } else { /* Note: the "wrong" transaction may be pending here, @@ -1737,12 +1737,12 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux } } else { if (srec->wstate & W_NEXPIRE) { - JLOG( "= %u %u", (srec->uid[M], srec->uid[S]), "expire unborn" ); + JLOG( "= %u %u", (srec->uid[F], srec->uid[N]), "expire unborn" ); // If we have so many new messages that some of them are instantly expired, // but some are still propagated because they are important, we need to // ensure explicitly that the bulk fetch limit is upped. - svars->mmaxxuid = srec->uid[M]; - srec->msg[M]->srec = NULL; + svars->maxxfuid = srec->uid[F]; + srec->msg[F]->srec = NULL; srec->status = S_DEAD; } } @@ -1753,7 +1753,7 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux debug( "synchronizing flags\n" ); for (srec = svars->srecs; srec; srec = srec->next) { - if ((srec->status & S_DEAD) || !srec->uid[M] || !srec->uid[S]) + if ((srec->status & S_DEAD) || !srec->uid[F] || !srec->uid[N]) continue; for (t = 0; t < 2; t++) { aflags = srec->aflags[t]; @@ -1765,7 +1765,7 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux } } else { /* The trigger is an expiration transaction being ongoing ... */ - if ((t == S) && ((shifted_bit(srec->status, S_EXPIRE, S_EXPIRED) ^ srec->status) & S_EXPIRED)) { + if ((t == N) && ((shifted_bit(srec->status, S_EXPIRE, S_EXPIRED) ^ srec->status) & S_EXPIRED)) { /* ... but the actual action derives from the wanted state. */ if (srec->wstate & W_NEXPIRE) aflags |= F_DELETED; @@ -1815,7 +1815,7 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux fdatasync( fileno( svars->jfp ) ); for (t = 0; t < 2; t++) { svars->newuid[t] = svars->drv[t]->get_uidnext( svars->ctx[t] ); - JLOG( "F %d %u", (t, svars->newuid[t]), "save UIDNEXT of %s", str_ms[t] ); + JLOG( "F %d %u", (t, svars->newuid[t]), "save UIDNEXT of %s", str_fn[t] ); svars->new_msgs[t] = svars->msgs[1-t]; msgs_copied( svars, t ); if (check_cancel( svars )) @@ -1835,12 +1835,12 @@ msg_copied( int sts, uint uid, copy_vars_t *vars ) case SYNC_OK: if (vars->msg->flags != srec->flags) { srec->flags = vars->msg->flags; - JLOG( "* %u %u %u", (srec->uid[M], srec->uid[S], srec->flags), "%sed with flags", str_hl[t] ); + JLOG( "* %u %u %u", (srec->uid[F], srec->uid[N], srec->flags), "%sed with flags", str_hl[t] ); } if (!uid) { // Stored to a non-UIDPLUS mailbox svars->state[t] |= ST_FIND_NEW; } else { - JLOG( "%c %u %u %u", ("<>"[t], srec->uid[M], srec->uid[S], uid), "%sed message", str_hl[t] ); + JLOG( "%c %u %u %u", ("<>"[t], srec->uid[F], srec->uid[N], uid), "%sed message", str_hl[t] ); vars->srec->uid[t] = uid; vars->srec->status &= ~S_PENDING; vars->srec->tuid[0] = 0; @@ -1848,7 +1848,7 @@ msg_copied( int sts, uint uid, copy_vars_t *vars ) break; case SYNC_NOGOOD: srec->status = S_DEAD; - JLOG( "- %u %u", (srec->uid[M], srec->uid[S]), "%s failed", str_hl[t] ); + JLOG( "- %u %u", (srec->uid[F], srec->uid[N]), "%s failed", str_hl[t] ); break; default: cancel_sync( svars ); @@ -1889,7 +1889,7 @@ msgs_copied( sync_vars_t *svars, int t ) uchar c = arc4_getbyte() & 0x3f; srec->tuid[i] = (char)(c < 26 ? c + 'A' : c < 52 ? c + 'a' - 26 : c < 62 ? c + '0' - 52 : c == 62 ? '+' : '/'); } - JLOG( "# %u %u %." stringify(TUIDL) "s", (srec->uid[M], srec->uid[S], srec->tuid), "%sing message", str_hl[t] ); + JLOG( "# %u %u %." stringify(TUIDL) "s", (srec->uid[F], srec->uid[N], srec->tuid), "%sing message", str_hl[t] ); new_total[t]++; stats(); svars->new_pending[t]++; @@ -1913,14 +1913,14 @@ msgs_copied( sync_vars_t *svars, int t ) if (svars->maxuid[1-t] != svars->newmaxuid[1-t]) { svars->maxuid[1-t] = svars->newmaxuid[1-t]; - JLOG( "S %d", 1-t, "commit maxuid of %s", str_ms[1-t] ); + JLOG( "S %d", 1-t, "commit maxuid of %s", str_fn[1-t] ); } sync_close( svars, 1-t ); if (check_cancel( svars )) goto out; if (svars->state[t] & ST_FIND_NEW) { - debug( "finding just copied messages on %s\n", str_ms[t] ); + debug( "finding just copied messages on %s\n", str_fn[t] ); svars->drv[t]->find_new_msgs( svars->ctx[t], svars->newuid[t], msgs_found_new, AUX ); } else { msgs_new_done( svars, t ); @@ -1936,10 +1936,10 @@ msgs_found_new( int sts, message_t *msgs, void *aux ) SVARS_CHECK_RET; switch (sts) { case DRV_OK: - debug( "matching just copied messages on %s\n", str_ms[t] ); + debug( "matching just copied messages on %s\n", str_fn[t] ); break; default: - warn( "Warning: cannot find newly stored messages on %s.\n", str_ms[t] ); + warn( "Warning: cannot find newly stored messages on %s.\n", str_fn[t] ); break; } match_tuids( svars, t, msgs ); @@ -1978,22 +1978,22 @@ static void flags_set_p2( sync_vars_t *svars, sync_rec_t *srec, int t ) { if (srec->wstate & W_DELETE) { - JLOG( "%c %u %u 0", ("><"[t], srec->uid[M], srec->uid[S]), "%sed deletion", str_hl[t] ); + JLOG( "%c %u %u 0", ("><"[t], srec->uid[F], srec->uid[N]), "%sed deletion", str_hl[t] ); srec->uid[1-t] = 0; } else { uchar nflags = (srec->flags | srec->aflags[t]) & ~srec->dflags[t]; if (srec->flags != nflags) { - JLOG( "* %u %u %u", (srec->uid[M], srec->uid[S], nflags), "%sed flags; were %u", (str_hl[t], srec->flags) ); + JLOG( "* %u %u %u", (srec->uid[F], srec->uid[N], nflags), "%sed flags; were %u", (str_hl[t], srec->flags) ); srec->flags = nflags; } - if (t == S) { + if (t == N) { uchar nex = (srec->wstate / W_NEXPIRE) & 1; if (nex != ((srec->status / S_EXPIRED) & 1)) { srec->status = (srec->status & ~S_EXPIRED) | (nex * S_EXPIRED); - JLOG( "~ %u %u %u", (srec->uid[M], srec->uid[S], srec->status), "expired %d - commit", nex ); + JLOG( "~ %u %u %u", (srec->uid[F], srec->uid[N], srec->status), "expired %d - commit", nex ); } else if (nex != ((srec->status / S_EXPIRE) & 1)) { srec->status = (srec->status & ~S_EXPIRE) | (nex * S_EXPIRE); - JLOG( "~ %u %u %u", (srec->uid[M], srec->uid[S], srec->status), "expire %d - cancel", nex ); + JLOG( "~ %u %u %u", (srec->uid[F], srec->uid[N], srec->status), "expire %d - cancel", nex ); } } } @@ -2021,13 +2021,13 @@ msgs_flags_set( sync_vars_t *svars, int t ) if ((svars->chan->ops[t] & OP_EXPUNGE) && (svars->ctx[t]->conf->trash || (svars->ctx[1-t]->conf->trash && svars->ctx[1-t]->conf->trash_remote_new))) { - debug( "trashing in %s\n", str_ms[t] ); + debug( "trashing on %s\n", str_fn[t] ); for (tmsg = svars->msgs[t]; tmsg; tmsg = tmsg->next) if ((tmsg->flags & F_DELETED) && !find_uint_array( svars->trashed_msgs[t].array, tmsg->uid ) && - (t == M || !tmsg->srec || !(tmsg->srec->status & (S_EXPIRE|S_EXPIRED)))) { + (t == F || !tmsg->srec || !(tmsg->srec->status & (S_EXPIRE|S_EXPIRED)))) { if (svars->ctx[t]->conf->trash) { if (!svars->ctx[t]->conf->trash_only_new || !tmsg->srec || (tmsg->srec->status & (S_PENDING | S_SKIPPED))) { - debug( "%s: trashing message %u\n", str_ms[t], tmsg->uid ); + debug( "%s: trashing message %u\n", str_fn[t], tmsg->uid ); trash_total[t]++; stats(); svars->trash_pending[t]++; @@ -2038,11 +2038,11 @@ msgs_flags_set( sync_vars_t *svars, int t ) if (check_cancel( svars )) goto out; } else - debug( "%s: not trashing message %u - not new\n", str_ms[t], tmsg->uid ); + debug( "%s: not trashing message %u - not new\n", str_fn[t], tmsg->uid ); } else { if (!tmsg->srec || (tmsg->srec->status & (S_PENDING | S_SKIPPED))) { if (tmsg->size <= svars->ctx[1-t]->conf->max_size) { - debug( "%s: remote trashing message %u\n", str_ms[t], tmsg->uid ); + debug( "%s: remote trashing message %u\n", str_fn[t], tmsg->uid ); trash_total[t]++; stats(); svars->trash_pending[t]++; @@ -2055,9 +2055,9 @@ msgs_flags_set( sync_vars_t *svars, int t ) if (check_cancel( svars )) goto out; } else - debug( "%s: not remote trashing message %u - too big\n", str_ms[t], tmsg->uid ); + debug( "%s: not remote trashing message %u - too big\n", str_fn[t], tmsg->uid ); } else - debug( "%s: not remote trashing message %u - not new\n", str_ms[t], tmsg->uid ); + debug( "%s: not remote trashing message %u - not new\n", str_fn[t], tmsg->uid ); } } } @@ -2079,7 +2079,7 @@ msg_trashed( int sts, void *aux ) if (check_ret( sts, vars->aux )) return; INIT_SVARS(vars->aux); - JLOG( "T %d %u", (t, vars->msg->uid), "trashed on %s", str_ms[t] ); + JLOG( "T %d %u", (t, vars->msg->uid), "trashed on %s", str_fn[t] ); free( vars ); trash_done[t]++; stats(); @@ -2101,7 +2101,7 @@ msg_rtrashed( int sts, uint uid ATTR_UNUSED, copy_vars_t *vars ) return; } t ^= 1; - JLOG( "T %d %u", (t, vars->msg->uid), "trashed remotely on %s", str_ms[1-t] ); + JLOG( "T %d %u", (t, vars->msg->uid), "trashed remotely on %s", str_fn[1-t] ); free( vars ); trash_done[t]++; stats(); @@ -2124,7 +2124,7 @@ sync_close( sync_vars_t *svars, int t ) svars->state[t] |= ST_CLOSING; if ((svars->chan->ops[t] & OP_EXPUNGE) /*&& !(svars->state[t] & ST_TRASH_BAD)*/) { - debug( "expunging %s\n", str_ms[t] ); + debug( "expunging %s\n", str_fn[t] ); svars->drv[t]->close_box( svars->ctx[t], box_closed, AUX ); } else { box_closed_p2( svars, t ); @@ -2152,23 +2152,23 @@ box_closed_p2( sync_vars_t *svars, int t ) // the operations are idempotent, and we're about to commit the new state // right afterwards anyway. - if (((svars->state[M] | svars->state[S]) & ST_DID_EXPUNGE) || svars->chan->max_messages) { + if (((svars->state[F] | svars->state[N]) & ST_DID_EXPUNGE) || svars->chan->max_messages) { debug( "purging obsolete entries\n" ); for (srec = svars->srecs; srec; srec = srec->next) { if (srec->status & S_DEAD) continue; - if (!srec->uid[S] || ((srec->wstate & W_DEL(S)) && (svars->state[S] & ST_DID_EXPUNGE))) { - if (!srec->uid[M] || ((srec->wstate & W_DEL(M)) && (svars->state[M] & ST_DID_EXPUNGE)) || - ((srec->status & S_EXPIRED) && svars->maxuid[M] >= srec->uid[M] && svars->mmaxxuid >= srec->uid[M])) { - JLOG( "- %u %u", (srec->uid[M], srec->uid[S]), "killing" ); + if (!srec->uid[N] || ((srec->wstate & W_DEL(N)) && (svars->state[N] & ST_DID_EXPUNGE))) { + if (!srec->uid[F] || ((srec->wstate & W_DEL(F)) && (svars->state[F] & ST_DID_EXPUNGE)) || + ((srec->status & S_EXPIRED) && svars->maxuid[F] >= srec->uid[F] && svars->maxxfuid >= srec->uid[F])) { + JLOG( "- %u %u", (srec->uid[F], srec->uid[N]), "killing" ); srec->status = S_DEAD; - } else if (srec->uid[S]) { - JLOG( "> %u %u 0", (srec->uid[M], srec->uid[S]), "orphaning" ); - srec->uid[S] = 0; + } else if (srec->uid[N]) { + JLOG( "> %u %u 0", (srec->uid[F], srec->uid[N]), "orphaning" ); + srec->uid[N] = 0; } - } else if (srec->uid[M] && ((srec->wstate & W_DEL(M)) && (svars->state[M] & ST_DID_EXPUNGE))) { - JLOG( "< %u %u 0", (srec->uid[M], srec->uid[S]), "orphaning" ); - srec->uid[M] = 0; + } else if (srec->uid[F] && ((srec->wstate & W_DEL(F)) && (svars->state[F] & ST_DID_EXPUNGE))) { + JLOG( "< %u %u 0", (srec->uid[F], srec->uid[N]), "orphaning" ); + srec->uid[F] = 0; } } } @@ -2176,7 +2176,7 @@ box_closed_p2( sync_vars_t *svars, int t ) // This is just an optimization, so it needs no journaling of intermediate states. // However, doing it before the entry purge would require ensuring that the // exception list includes all relevant messages. - JLOG( "! %u", svars->mmaxxuid, "max expired UID on master" ); + JLOG( "! %u", svars->maxxfuid, "max expired UID on far side" ); save_state( svars ); @@ -2188,8 +2188,8 @@ sync_bail( sync_vars_t *svars ) { sync_rec_t *srec, *nsrec; - free( svars->trashed_msgs[M].array.data ); - free( svars->trashed_msgs[S].array.data ); + free( svars->trashed_msgs[F].array.data ); + free( svars->trashed_msgs[N].array.data ); for (srec = svars->srecs; srec; srec = nsrec) { nsrec = srec->next; free( srec ); @@ -2214,8 +2214,8 @@ sync_bail2( sync_vars_t *svars ) static void sync_bail3( sync_vars_t *svars ) { - free( svars->box_name[M] ); - free( svars->box_name[S] ); + free( svars->box_name[F] ); + free( svars->box_name[N] ); sync_deref( svars ); } diff --git a/src/sync.h b/src/sync.h index b98d186..5b0a36c 100644 --- a/src/sync.h +++ b/src/sync.h @@ -25,8 +25,8 @@ #include "driver.h" -#define M 0 /* master */ -#define S 1 /* slave */ +#define F 0 // far side +#define N 1 // near side #define OP_NEW (1<<0) #define OP_RENEW (1<<1) @@ -52,7 +52,7 @@ typedef struct channel_conf { char *sync_state; string_list_t *patterns; int ops[2]; - int max_messages; /* for slave only */ + int max_messages; // For near side only. signed char expire_unread; char use_internal_date; } channel_conf_t; @@ -67,11 +67,11 @@ extern channel_conf_t global_conf; extern channel_conf_t *channels; extern group_conf_t *groups; -extern const char *str_ms[2], *str_hl[2]; +extern const char *str_fn[2], *str_hl[2]; #define SYNC_OK 0 /* assumed to be 0 */ #define SYNC_FAIL 1 -#define SYNC_BAD(ms) (4<<(ms)) +#define SYNC_BAD(fn) (4<<(fn)) #define SYNC_NOGOOD 16 /* internal */ #define SYNC_CANCELED 32 /* internal */