Browse Source

make progress counters global

which means they are now cumulative, and include channels and boxes.
wip/server-refactor
Oswald Buddenhagen 10 years ago
parent
commit
8aa22a62e7
  1. 6
      src/common.h
  2. 2
      src/drv_imap.c
  3. 61
      src/main.c
  4. 15
      src/mbsync.1
  5. 77
      src/sync.c

6
src/common.h

@ -78,6 +78,12 @@ extern const char *Home;
extern int BufferLimit; extern int BufferLimit;
extern int new_total[2], new_done[2];
extern int flags_total[2], flags_done[2];
extern int trash_total[2], trash_done[2];
void stats( void );
/* util.c */ /* util.c */
void ATTR_PRINTFLIKE(1, 2) debug( const char *, ... ); void ATTR_PRINTFLIKE(1, 2) debug( const char *, ... );

2
src/drv_imap.c

@ -1728,6 +1728,7 @@ ensure_password( imap_server_conf_t *srvc )
int ret; int ret;
char buffer[80]; char buffer[80];
flushn();
if (!(fp = popen( srvc->pass_cmd, "r" ))) { if (!(fp = popen( srvc->pass_cmd, "r" ))) {
pipeerr: pipeerr:
sys_error( "Skipping account %s, password command failed", srvc->name ); sys_error( "Skipping account %s, password command failed", srvc->name );
@ -1754,6 +1755,7 @@ ensure_password( imap_server_conf_t *srvc )
} else if (!srvc->pass) { } else if (!srvc->pass) {
char *pass, prompt[80]; char *pass, prompt[80];
flushn();
sprintf( prompt, "Password (%s): ", srvc->name ); sprintf( prompt, "Password (%s): ", srvc->name );
pass = getpass( prompt ); pass = getpass( prompt );
if (!pass) { if (!pass) {

61
src/main.c

@ -45,6 +45,12 @@ const char *Home; /* for config */
int BufferLimit = 10 * 1024 * 1024; int BufferLimit = 10 * 1024 * 1024;
int chans_total, chans_done;
int boxes_total, boxes_done;
int new_total[2], new_done[2];
int flags_total[2], flags_done[2];
int trash_total[2], trash_done[2];
static void static void
version( void ) version( void )
{ {
@ -123,6 +129,32 @@ crashHandler( int n )
} }
#endif #endif
void
stats( void )
{
char buf[3][64];
char *cs;
int t, l, ll, cls;
static int cols = -1;
if (DFlags & QUIET)
return;
if (cols < 0 && (!(cs = getenv( "COLUMNS" )) || !(cols = atoi( cs ))))
cols = 80;
ll = sprintf( buf[2], "C: %d/%d B: %d/%d", chans_done, chans_total, boxes_done, boxes_total );
cls = (cols - ll - 10) / 2;
for (t = 0; t < 2; t++) {
l = sprintf( buf[t], "+%d/%d *%d/%d #%d/%d",
new_done[t], new_total[t],
flags_done[t], flags_total[t],
trash_done[t], trash_total[t] );
if (l > cls)
buf[t][cls - 1] = '~';
}
infon( "\v\r%s M: %.*s S: %.*s", buf[2], cls, buf[0], cls, buf[1] );
}
static int static int
matches( const char *t, const char *p ) matches( const char *t, const char *p )
{ {
@ -254,6 +286,7 @@ add_channel( chan_ent_t ***chanapp, channel_conf_t *chan, int ops[] )
**chanapp = ce; **chanapp = ce;
*chanapp = &ce->next; *chanapp = &ce->next;
chans_total++;
return ce; return ce;
} }
@ -297,8 +330,12 @@ add_named_channel( chan_ent_t ***chanapp, char *channame, int ops[] )
mbox->next = 0; mbox->next = 0;
*mboxapp = mbox; *mboxapp = mbox;
mboxapp = &mbox->next; mboxapp = &mbox->next;
boxes_total++;
boxp = nboxp; boxp = nboxp;
} while (boxp); } while (boxp);
} else {
if (!chan->patterns)
boxes_total++;
} }
ce = add_channel( chanapp, chan, ops ); ce = add_channel( chanapp, chan, ops );
@ -315,7 +352,7 @@ typedef struct {
chan_ent_t *chanptr; chan_ent_t *chanptr;
box_ent_t *boxptr; box_ent_t *boxptr;
char *names[2]; char *names[2];
int ret, multiple, all, list, state[2]; int ret, all, list, state[2];
char done, skip, cben; char done, skip, cben;
} main_vars_t; } main_vars_t;
@ -605,8 +642,11 @@ main( int argc, char **argv )
} }
if (mvars->all) { if (mvars->all) {
for (chan = channels; chan; chan = chan->next) for (chan = channels; chan; chan = chan->next) {
add_channel( &chanapp, chan, ops ); add_channel( &chanapp, chan, ops );
if (!chan->patterns)
boxes_total++;
}
} else { } else {
for (; argv[oind]; oind++) { for (; argv[oind]; oind++) {
for (group = groups; group; group = group->next) { for (group = groups; group; group = group->next) {
@ -627,11 +667,14 @@ main( int argc, char **argv )
return 1; return 1;
} }
mvars->chanptr = chans; mvars->chanptr = chans;
mvars->multiple = !!chans->next;
if (!mvars->list)
stats();
mvars->cben = 1; mvars->cben = 1;
sync_chans( mvars, E_START ); sync_chans( mvars, E_START );
main_loop(); main_loop();
if (!mvars->list)
flushn();
return mvars->ret; return mvars->ret;
} }
@ -723,13 +766,16 @@ sync_chans( main_vars_t *mvars, int ent )
mbox->next = 0; mbox->next = 0;
*mboxapp = mbox; *mboxapp = mbox;
mboxapp = &mbox->next; mboxapp = &mbox->next;
boxes_total++;
} }
free( boxes[M] ); free( boxes[M] );
free( boxes[S] ); free( boxes[S] );
if (!mvars->list)
stats();
} }
mvars->boxptr = mvars->chanptr->boxes; mvars->boxptr = mvars->chanptr->boxes;
if (mvars->list && mvars->multiple) if (mvars->list && chans_total > 1)
printf( "%s:\n", mvars->chan->name ); printf( "%s:\n", mvars->chan->name );
syncml: syncml:
mvars->done = mvars->cben = 0; mvars->done = mvars->cben = 0;
@ -775,7 +821,10 @@ sync_chans( main_vars_t *mvars, int ent )
mvars->chanptr->boxlist = 0; mvars->chanptr->boxlist = 0;
} }
next2: next2:
; if (!mvars->list) {
chans_done++;
stats();
}
} while ((mvars->chanptr = mvars->chanptr->next)); } while ((mvars->chanptr = mvars->chanptr->next));
for (t = 0; t < N_DRIVERS; t++) for (t = 0; t < N_DRIVERS; t++)
drivers[t]->cleanup(); drivers[t]->cleanup();
@ -921,6 +970,8 @@ done_sync( int sts, void *aux )
main_vars_t *mvars = (main_vars_t *)aux; main_vars_t *mvars = (main_vars_t *)aux;
mvars->done = 1; mvars->done = 1;
boxes_done++;
stats();
if (sts) { if (sts) {
mvars->ret = 1; mvars->ret = 1;
if (sts & (SYNC_BAD(M) | SYNC_BAD(S))) { if (sts & (SYNC_BAD(M) | SYNC_BAD(S))) {

15
src/mbsync.1

@ -591,6 +591,21 @@ absolute limit, as even a single message can consume more memory than
this. this.
(Default: \fI10M\fR) (Default: \fI10M\fR)
.. ..
.SH CONSOLE OUTPUT
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
.in -4
.P
This represents the cumulative progress over channels, boxes, and messages
affected on master and slave, 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
time as more information is gathered.
..
.SH RECOMMENDATIONS .SH RECOMMENDATIONS
Make sure your IMAP server does not auto-expunge deleted messages - it is Make sure your IMAP server does not auto-expunge deleted messages - it is
slow, and semantically somewhat questionable. Specifically, Gmail needs to slow, and semantically somewhat questionable. Specifically, Gmail needs to

77
src/sync.c

@ -156,9 +156,7 @@ typedef struct {
const char *orig_name[2]; const char *orig_name[2];
message_t *new_msgs[2]; message_t *new_msgs[2];
int state[2], ref_count, nsrecs, ret, lfd, existing, replayed; int state[2], ref_count, nsrecs, ret, lfd, existing, replayed;
int new_total[2], new_done[2]; int new_pending[2], flags_pending[2], trash_pending[2];
int flags_total[2], flags_done[2];
int trash_total[2], trash_done[2];
int maxuid[2]; /* highest UID that was already propagated */ int maxuid[2]; /* highest UID that was already propagated */
int newmaxuid[2]; /* highest UID that is currently being propagated */ int newmaxuid[2]; /* highest UID that is currently being propagated */
int uidval[2]; /* UID validity value */ int uidval[2]; /* UID validity value */
@ -446,30 +444,6 @@ msg_stored( int sts, int uid, void *aux )
} }
static void
stats( sync_vars_t *svars )
{
char buf[2][64];
char *cs;
int t, l;
static int cols = -1;
if (cols < 0 && (!(cs = getenv( "COLUMNS" )) || !(cols = atoi( cs ) / 2)))
cols = 36;
if (!(DFlags & QUIET)) {
for (t = 0; t < 2; t++) {
l = sprintf( buf[t], "+%d/%d *%d/%d #%d/%d",
svars->new_done[t], svars->new_total[t],
svars->flags_done[t], svars->flags_total[t],
svars->trash_done[t], svars->trash_total[t] );
if (l > cols)
buf[t][cols - 1] = '~';
}
infon( "\v\rM: %.*s S: %.*s", cols, buf[0], cols, buf[1] );
}
}
static void sync_bail( sync_vars_t *svars ); static void sync_bail( sync_vars_t *svars );
static void sync_bail2( sync_vars_t *svars ); static void sync_bail2( sync_vars_t *svars );
static void sync_bail3( sync_vars_t *svars ); static void sync_bail3( sync_vars_t *svars );
@ -1697,8 +1671,9 @@ box_loaded( int sts, void *aux )
dflags &= srec->msg[t]->flags; dflags &= srec->msg[t]->flags;
} }
if (aflags | dflags) { if (aflags | dflags) {
svars->flags_total[t]++; flags_total[t]++;
stats( svars ); stats();
svars->flags_pending[t]++;
fv = nfmalloc( sizeof(*fv) ); fv = nfmalloc( sizeof(*fv) );
fv->aux = AUX; fv->aux = AUX;
fv->srec = srec; fv->srec = srec;
@ -1756,8 +1731,9 @@ msg_copied( int sts, int uid, copy_vars_t *vars )
return; return;
} }
free( vars ); free( vars );
svars->new_done[t]++; new_done[t]++;
stats( svars ); stats();
svars->new_pending[t]--;
msgs_copied( svars, t ); msgs_copied( svars, t );
} }
@ -1812,8 +1788,9 @@ msgs_copied( sync_vars_t *svars, int t )
svars->new_msgs[t] = tmsg; svars->new_msgs[t] = tmsg;
goto out; goto out;
} }
svars->new_total[t]++; new_total[t]++;
stats( svars ); stats();
svars->new_pending[t]++;
svars->state[t] |= ST_SENDING_NEW; svars->state[t] |= ST_SENDING_NEW;
cv = nfmalloc( sizeof(*cv) ); cv = nfmalloc( sizeof(*cv) );
cv->cb = msg_copied; cv->cb = msg_copied;
@ -1829,7 +1806,7 @@ msgs_copied( sync_vars_t *svars, int t )
svars->state[t] |= ST_SENT_NEW; svars->state[t] |= ST_SENT_NEW;
} }
if (svars->new_done[t] < svars->new_total[t]) if (svars->new_pending[t])
goto out; goto out;
Fprintf( svars->jfp, "%c %d\n", ")("[t], svars->maxuid[1-t] ); Fprintf( svars->jfp, "%c %d\n", ")("[t], svars->maxuid[1-t] );
@ -1885,8 +1862,9 @@ flags_set( int sts, void *aux )
break; break;
} }
free( vars ); free( vars );
svars->flags_done[t]++; flags_done[t]++;
stats( svars ); stats();
svars->flags_pending[t]--;
msgs_flags_set( svars, t ); msgs_flags_set( svars, t );
} }
@ -1930,7 +1908,7 @@ msgs_flags_set( sync_vars_t *svars, int t )
message_t *tmsg; message_t *tmsg;
copy_vars_t *cv; copy_vars_t *cv;
if (!(svars->state[t] & ST_SENT_FLAGS) || svars->flags_done[t] < svars->flags_total[t]) if (!(svars->state[t] & ST_SENT_FLAGS) || svars->flags_pending[t])
return; return;
sync_ref( svars ); sync_ref( svars );
@ -1943,8 +1921,9 @@ msgs_flags_set( sync_vars_t *svars, int t )
if (svars->ctx[t]->conf->trash) { if (svars->ctx[t]->conf->trash) {
if (!svars->ctx[t]->conf->trash_only_new || !tmsg->srec || tmsg->srec->uid[1-t] < 0) { if (!svars->ctx[t]->conf->trash_only_new || !tmsg->srec || tmsg->srec->uid[1-t] < 0) {
debug( "%s: trashing message %d\n", str_ms[t], tmsg->uid ); debug( "%s: trashing message %d\n", str_ms[t], tmsg->uid );
svars->trash_total[t]++; trash_total[t]++;
stats( svars ); stats();
svars->trash_pending[t]++;
svars->drv[t]->trash_msg( svars->ctx[t], tmsg, msg_trashed, AUX ); svars->drv[t]->trash_msg( svars->ctx[t], tmsg, msg_trashed, AUX );
if (check_cancel( svars )) if (check_cancel( svars ))
goto out; goto out;
@ -1954,8 +1933,9 @@ msgs_flags_set( sync_vars_t *svars, int t )
if (!tmsg->srec || tmsg->srec->uid[1-t] < 0) { if (!tmsg->srec || tmsg->srec->uid[1-t] < 0) {
if (tmsg->size <= svars->ctx[1-t]->conf->max_size) { if (tmsg->size <= svars->ctx[1-t]->conf->max_size) {
debug( "%s: remote trashing message %d\n", str_ms[t], tmsg->uid ); debug( "%s: remote trashing message %d\n", str_ms[t], tmsg->uid );
svars->trash_total[t]++; trash_total[t]++;
stats( svars ); stats();
svars->trash_pending[t]++;
cv = nfmalloc( sizeof(*cv) ); cv = nfmalloc( sizeof(*cv) );
cv->cb = msg_rtrashed; cv->cb = msg_rtrashed;
cv->aux = INV_AUX; cv->aux = INV_AUX;
@ -1988,8 +1968,9 @@ msg_trashed( int sts, void *aux )
if (check_ret( sts, aux )) if (check_ret( sts, aux ))
return; return;
INIT_SVARS(aux); INIT_SVARS(aux);
svars->trash_done[t]++; trash_done[t]++;
stats( svars ); stats();
svars->trash_pending[t]--;
sync_close( svars, t ); sync_close( svars, t );
} }
@ -2008,8 +1989,9 @@ msg_rtrashed( int sts, int uid ATTR_UNUSED, copy_vars_t *vars )
} }
free( vars ); free( vars );
t ^= 1; t ^= 1;
svars->trash_done[t]++; trash_done[t]++;
stats( svars ); stats();
svars->trash_pending[t]--;
sync_close( svars, t ); sync_close( svars, t );
} }
@ -2019,8 +2001,8 @@ static void box_closed_p2( sync_vars_t *svars, int t );
static void static void
sync_close( sync_vars_t *svars, int t ) sync_close( sync_vars_t *svars, int t )
{ {
if ((~svars->state[t] & (ST_FOUND_NEW|ST_SENT_TRASH)) || svars->trash_done[t] < svars->trash_total[t] || if ((~svars->state[t] & (ST_FOUND_NEW|ST_SENT_TRASH)) || svars->trash_pending[t] ||
!(svars->state[1-t] & ST_SENT_NEW) || svars->new_done[1-t] < svars->new_total[1-t]) !(svars->state[1-t] & ST_SENT_NEW) || svars->new_pending[1-t])
return; return;
if (svars->state[t] & ST_CLOSING) if (svars->state[t] & ST_CLOSING)
@ -2120,7 +2102,6 @@ sync_bail2( sync_vars_t *svars )
free( svars->nname ); free( svars->nname );
free( svars->jname ); free( svars->jname );
free( svars->dname ); free( svars->dname );
flushn();
sync_bail3( svars ); sync_bail3( svars );
} }

Loading…
Cancel
Save