don't rewrite state gratuitously
delay the creation of the new state and journal until there is actually something interesting to write. this saves some cpu cycles and prolongs ssd life a whee bit.
This commit is contained in:
parent
0e5046e14a
commit
68a412115a
|
@ -702,7 +702,7 @@ sub test($$$@)
|
|||
rmtree "far";
|
||||
|
||||
my $njl = (@nj - 1) * 2;
|
||||
for (my $l = 2; $l < $njl; $l++) {
|
||||
for (my $l = 1; $l <= $njl; $l++) {
|
||||
mkchan($$sx[0], $$sx[1], @{ $$sx[2] });
|
||||
|
||||
my ($nxc, @nret) = runsync("-J$l", "4-interrupt.log");
|
||||
|
@ -721,7 +721,8 @@ sub test($$$@)
|
|||
print "Options:\n";
|
||||
print " [ ".join(", ", map('"'.qm($_).'"', @sfx))." ]\n";
|
||||
my @nnj = readfile("near/.mbsyncstate.journal");
|
||||
print "Journal:\n".join("", @nnj[0..($l / 2 - 1)])."-------\n".join("", @nnj[($l / 2)..$#nnj])."\n";
|
||||
my $ln = int($l / 2);
|
||||
print "Journal:\n".join("", @nnj[0..$ln])."-------\n".join("", @nnj[($ln + 1)..$#nnj])."\n";
|
||||
print "Full journal:\n".join("", @nj)."\n";
|
||||
if (!$nxc) {
|
||||
print "Expected result:\n";
|
||||
|
|
71
src/sync.c
71
src/sync.c
|
@ -39,6 +39,8 @@
|
|||
# define fdatasync fsync
|
||||
#endif
|
||||
|
||||
#define JOURNAL_VERSION "4"
|
||||
|
||||
channel_conf_t global_conf;
|
||||
channel_conf_t *channels;
|
||||
group_conf_t *groups;
|
||||
|
@ -167,10 +169,12 @@ typedef struct {
|
|||
uint ref_count, nsrecs, opts[2];
|
||||
uint new_pending[2], flags_pending[2], trash_pending[2];
|
||||
uint maxuid[2]; // highest UID that was already propagated
|
||||
uint oldmaxuid[2]; // highest UID that was already propagated before this run
|
||||
uint uidval[2]; // UID validity value
|
||||
uint newuidval[2]; // UID validity obtained from driver
|
||||
uint finduid[2]; // TUID lookup makes sense only for UIDs >= this
|
||||
uint maxxfuid; // highest expired UID on far side
|
||||
uint oldmaxxfuid; // highest expired UID on far side before this run
|
||||
uchar good_flags[2], bad_flags[2];
|
||||
} sync_vars_t;
|
||||
|
||||
|
@ -218,6 +222,15 @@ static int check_cancel( sync_vars_t *svars );
|
|||
#define ST_SENDING_NEW (1<<15)
|
||||
|
||||
|
||||
static void
|
||||
create_state( sync_vars_t *svars )
|
||||
{
|
||||
if (!(svars->nfp = fopen( svars->nname, "w" ))) {
|
||||
sys_error( "Error: cannot create new sync state %s", svars->nname );
|
||||
exit( 1 );
|
||||
}
|
||||
}
|
||||
|
||||
static void ATTR_PRINTFLIKE(2, 3)
|
||||
jFprintf( sync_vars_t *svars, const char *msg, ... )
|
||||
{
|
||||
|
@ -225,6 +238,16 @@ jFprintf( sync_vars_t *svars, const char *msg, ... )
|
|||
|
||||
if (JLimit && !--JLimit)
|
||||
exit( 101 );
|
||||
if (!svars->jfp) {
|
||||
create_state( svars );
|
||||
if (!(svars->jfp = fopen( svars->jname, svars->replayed ? "a" : "w" ))) {
|
||||
sys_error( "Error: cannot create journal %s", svars->jname );
|
||||
exit( 1 );
|
||||
}
|
||||
setlinebuf( svars->jfp );
|
||||
if (!svars->replayed)
|
||||
Fprintf( svars->jfp, JOURNAL_VERSION "\n" );
|
||||
}
|
||||
va_start( va, msg );
|
||||
vFprintf( svars->jfp, msg, va );
|
||||
va_end( va );
|
||||
|
@ -625,8 +648,6 @@ clean_strdup( const char *s )
|
|||
}
|
||||
|
||||
|
||||
#define JOURNAL_VERSION "4"
|
||||
|
||||
static int
|
||||
prepare_state( sync_vars_t *svars )
|
||||
{
|
||||
|
@ -704,6 +725,12 @@ save_state( sync_vars_t *svars )
|
|||
sync_rec_t *srec;
|
||||
char fbuf[16]; /* enlarge when support for keywords is added */
|
||||
|
||||
// If no change was made, the state is also unmodified.
|
||||
if (!svars->jfp && !svars->replayed)
|
||||
return;
|
||||
|
||||
if (!svars->nfp)
|
||||
create_state( svars );
|
||||
Fprintf( svars->nfp,
|
||||
"FarUidValidity %u\nNearUidValidity %u\nMaxPulledUid %u\nMaxPushedUid %u\n",
|
||||
svars->uidval[F], svars->uidval[N], svars->maxuid[F], svars->maxuid[N] );
|
||||
|
@ -719,7 +746,8 @@ save_state( sync_vars_t *svars )
|
|||
}
|
||||
|
||||
Fclose( svars->nfp, 1 );
|
||||
Fclose( svars->jfp, 0 );
|
||||
if (svars->jfp)
|
||||
Fclose( svars->jfp, 0 );
|
||||
if (!(DFlags & KEEPJOURNAL)) {
|
||||
/* order is important! */
|
||||
if (rename( svars->nname, svars->dname ))
|
||||
|
@ -1234,18 +1262,6 @@ box_opened2( sync_vars_t *svars, int t )
|
|||
|
||||
if (!lock_state( svars ))
|
||||
goto bail;
|
||||
if (!(svars->nfp = fopen( svars->nname, "w" ))) {
|
||||
sys_error( "Error: cannot create new sync state %s", svars->nname );
|
||||
goto bail;
|
||||
}
|
||||
if (!(svars->jfp = fopen( svars->jname, "a" ))) {
|
||||
sys_error( "Error: cannot create journal %s", svars->jname );
|
||||
fclose( svars->nfp );
|
||||
goto bail;
|
||||
}
|
||||
setlinebuf( svars->jfp );
|
||||
if (!svars->replayed)
|
||||
jFprintf( svars, JOURNAL_VERSION "\n" );
|
||||
|
||||
opts[F] = opts[N] = 0;
|
||||
if (fails)
|
||||
|
@ -1495,10 +1511,16 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux
|
|||
JLOG( "| %u %u", (svars->uidval[F], svars->uidval[N]), "new UIDVALIDITYs" );
|
||||
}
|
||||
|
||||
svars->oldmaxuid[F] = svars->maxuid[F];
|
||||
svars->oldmaxuid[N] = svars->maxuid[N];
|
||||
svars->oldmaxxfuid = svars->maxxfuid;
|
||||
|
||||
info( "Synchronizing...\n" );
|
||||
for (t = 0; t < 2; t++)
|
||||
svars->good_flags[t] = (uchar)svars->drv[t]->get_supported_flags( svars->ctx[t] );
|
||||
|
||||
int any_new[2] = { 0, 0 };
|
||||
|
||||
debug( "synchronizing old entries\n" );
|
||||
for (srec = svars->srecs; srec; srec = srec->next) {
|
||||
if (srec->status & S_DEAD)
|
||||
|
@ -1643,6 +1665,7 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux
|
|||
srec->status = S_PENDING;
|
||||
JLOG( "~ %u %u %u", (srec->uid[F], srec->uid[N], srec->status), "was too big" );
|
||||
}
|
||||
any_new[t] = 1;
|
||||
} else {
|
||||
if (srec->status == S_SKIPPED) {
|
||||
debug( "-> still too big\n" );
|
||||
|
@ -1825,12 +1848,16 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux
|
|||
}
|
||||
|
||||
debug( "propagating new messages\n" );
|
||||
if (UseFSync)
|
||||
if (UseFSync && svars->jfp)
|
||||
fdatasync( fileno( svars->jfp ) );
|
||||
for (t = 0; t < 2; t++) {
|
||||
svars->finduid[t] = svars->drv[t]->get_uidnext( svars->ctx[t] );
|
||||
JLOG( "F %d %u", (t, svars->finduid[t]), "save UIDNEXT of %s", str_fn[t] );
|
||||
svars->new_msgs[t] = svars->msgs[1-t];
|
||||
if (any_new[t]) {
|
||||
svars->finduid[t] = svars->drv[t]->get_uidnext( svars->ctx[t] );
|
||||
JLOG( "F %d %u", (t, svars->finduid[t]), "save UIDNEXT of %s", str_fn[t] );
|
||||
svars->new_msgs[t] = svars->msgs[1-t];
|
||||
} else {
|
||||
svars->state[t] |= ST_SENT_NEW;
|
||||
}
|
||||
msgs_copied( svars, t );
|
||||
if (check_cancel( svars ))
|
||||
goto out;
|
||||
|
@ -2164,7 +2191,8 @@ box_closed_p2( sync_vars_t *svars, int t )
|
|||
// ensure that all pending messages are still loaded next time in case
|
||||
// of interruption - in particular skipping big messages would otherwise
|
||||
// up the limit too early.
|
||||
JLOG( "N %d %u", (t, svars->maxuid[t]), "up maxuid of %s", str_fn[t] );
|
||||
if (svars->maxuid[t] != svars->oldmaxuid[t])
|
||||
JLOG( "N %d %u", (t, svars->maxuid[t]), "up maxuid of %s", str_fn[t] );
|
||||
}
|
||||
|
||||
if (((svars->state[F] | svars->state[N]) & ST_DID_EXPUNGE) || svars->chan->max_messages) {
|
||||
|
@ -2191,7 +2219,8 @@ 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->maxxfuid, "max expired UID on far side" );
|
||||
if (svars->maxxfuid != svars->oldmaxxfuid)
|
||||
JLOG( "! %u", svars->maxxfuid, "max expired UID on far side" );
|
||||
|
||||
save_state( svars );
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user