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";
|
rmtree "far";
|
||||||
|
|
||||||
my $njl = (@nj - 1) * 2;
|
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] });
|
mkchan($$sx[0], $$sx[1], @{ $$sx[2] });
|
||||||
|
|
||||||
my ($nxc, @nret) = runsync("-J$l", "4-interrupt.log");
|
my ($nxc, @nret) = runsync("-J$l", "4-interrupt.log");
|
||||||
|
@ -721,7 +721,8 @@ sub test($$$@)
|
||||||
print "Options:\n";
|
print "Options:\n";
|
||||||
print " [ ".join(", ", map('"'.qm($_).'"', @sfx))." ]\n";
|
print " [ ".join(", ", map('"'.qm($_).'"', @sfx))." ]\n";
|
||||||
my @nnj = readfile("near/.mbsyncstate.journal");
|
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";
|
print "Full journal:\n".join("", @nj)."\n";
|
||||||
if (!$nxc) {
|
if (!$nxc) {
|
||||||
print "Expected result:\n";
|
print "Expected result:\n";
|
||||||
|
|
59
src/sync.c
59
src/sync.c
|
@ -39,6 +39,8 @@
|
||||||
# define fdatasync fsync
|
# define fdatasync fsync
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define JOURNAL_VERSION "4"
|
||||||
|
|
||||||
channel_conf_t global_conf;
|
channel_conf_t global_conf;
|
||||||
channel_conf_t *channels;
|
channel_conf_t *channels;
|
||||||
group_conf_t *groups;
|
group_conf_t *groups;
|
||||||
|
@ -167,10 +169,12 @@ typedef struct {
|
||||||
uint ref_count, nsrecs, opts[2];
|
uint ref_count, nsrecs, opts[2];
|
||||||
uint new_pending[2], flags_pending[2], trash_pending[2];
|
uint new_pending[2], flags_pending[2], trash_pending[2];
|
||||||
uint maxuid[2]; // highest UID that was already propagated
|
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 uidval[2]; // UID validity value
|
||||||
uint newuidval[2]; // UID validity obtained from driver
|
uint newuidval[2]; // UID validity obtained from driver
|
||||||
uint finduid[2]; // TUID lookup makes sense only for UIDs >= this
|
uint finduid[2]; // TUID lookup makes sense only for UIDs >= this
|
||||||
uint maxxfuid; // highest expired UID on far side
|
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];
|
uchar good_flags[2], bad_flags[2];
|
||||||
} sync_vars_t;
|
} sync_vars_t;
|
||||||
|
|
||||||
|
@ -218,6 +222,15 @@ static int check_cancel( sync_vars_t *svars );
|
||||||
#define ST_SENDING_NEW (1<<15)
|
#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)
|
static void ATTR_PRINTFLIKE(2, 3)
|
||||||
jFprintf( sync_vars_t *svars, const char *msg, ... )
|
jFprintf( sync_vars_t *svars, const char *msg, ... )
|
||||||
{
|
{
|
||||||
|
@ -225,6 +238,16 @@ jFprintf( sync_vars_t *svars, const char *msg, ... )
|
||||||
|
|
||||||
if (JLimit && !--JLimit)
|
if (JLimit && !--JLimit)
|
||||||
exit( 101 );
|
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 );
|
va_start( va, msg );
|
||||||
vFprintf( svars->jfp, msg, va );
|
vFprintf( svars->jfp, msg, va );
|
||||||
va_end( va );
|
va_end( va );
|
||||||
|
@ -625,8 +648,6 @@ clean_strdup( const char *s )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define JOURNAL_VERSION "4"
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
prepare_state( sync_vars_t *svars )
|
prepare_state( sync_vars_t *svars )
|
||||||
{
|
{
|
||||||
|
@ -704,6 +725,12 @@ save_state( sync_vars_t *svars )
|
||||||
sync_rec_t *srec;
|
sync_rec_t *srec;
|
||||||
char fbuf[16]; /* enlarge when support for keywords is added */
|
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,
|
Fprintf( svars->nfp,
|
||||||
"FarUidValidity %u\nNearUidValidity %u\nMaxPulledUid %u\nMaxPushedUid %u\n",
|
"FarUidValidity %u\nNearUidValidity %u\nMaxPulledUid %u\nMaxPushedUid %u\n",
|
||||||
svars->uidval[F], svars->uidval[N], svars->maxuid[F], svars->maxuid[N] );
|
svars->uidval[F], svars->uidval[N], svars->maxuid[F], svars->maxuid[N] );
|
||||||
|
@ -719,6 +746,7 @@ save_state( sync_vars_t *svars )
|
||||||
}
|
}
|
||||||
|
|
||||||
Fclose( svars->nfp, 1 );
|
Fclose( svars->nfp, 1 );
|
||||||
|
if (svars->jfp)
|
||||||
Fclose( svars->jfp, 0 );
|
Fclose( svars->jfp, 0 );
|
||||||
if (!(DFlags & KEEPJOURNAL)) {
|
if (!(DFlags & KEEPJOURNAL)) {
|
||||||
/* order is important! */
|
/* order is important! */
|
||||||
|
@ -1234,18 +1262,6 @@ box_opened2( sync_vars_t *svars, int t )
|
||||||
|
|
||||||
if (!lock_state( svars ))
|
if (!lock_state( svars ))
|
||||||
goto bail;
|
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;
|
opts[F] = opts[N] = 0;
|
||||||
if (fails)
|
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" );
|
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" );
|
info( "Synchronizing...\n" );
|
||||||
for (t = 0; t < 2; t++)
|
for (t = 0; t < 2; t++)
|
||||||
svars->good_flags[t] = (uchar)svars->drv[t]->get_supported_flags( svars->ctx[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" );
|
debug( "synchronizing old entries\n" );
|
||||||
for (srec = svars->srecs; srec; srec = srec->next) {
|
for (srec = svars->srecs; srec; srec = srec->next) {
|
||||||
if (srec->status & S_DEAD)
|
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;
|
srec->status = S_PENDING;
|
||||||
JLOG( "~ %u %u %u", (srec->uid[F], srec->uid[N], srec->status), "was too big" );
|
JLOG( "~ %u %u %u", (srec->uid[F], srec->uid[N], srec->status), "was too big" );
|
||||||
}
|
}
|
||||||
|
any_new[t] = 1;
|
||||||
} else {
|
} else {
|
||||||
if (srec->status == S_SKIPPED) {
|
if (srec->status == S_SKIPPED) {
|
||||||
debug( "-> still too big\n" );
|
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" );
|
debug( "propagating new messages\n" );
|
||||||
if (UseFSync)
|
if (UseFSync && svars->jfp)
|
||||||
fdatasync( fileno( svars->jfp ) );
|
fdatasync( fileno( svars->jfp ) );
|
||||||
for (t = 0; t < 2; t++) {
|
for (t = 0; t < 2; t++) {
|
||||||
|
if (any_new[t]) {
|
||||||
svars->finduid[t] = svars->drv[t]->get_uidnext( svars->ctx[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] );
|
JLOG( "F %d %u", (t, svars->finduid[t]), "save UIDNEXT of %s", str_fn[t] );
|
||||||
svars->new_msgs[t] = svars->msgs[1-t];
|
svars->new_msgs[t] = svars->msgs[1-t];
|
||||||
|
} else {
|
||||||
|
svars->state[t] |= ST_SENT_NEW;
|
||||||
|
}
|
||||||
msgs_copied( svars, t );
|
msgs_copied( svars, t );
|
||||||
if (check_cancel( svars ))
|
if (check_cancel( svars ))
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -2164,6 +2191,7 @@ box_closed_p2( sync_vars_t *svars, int t )
|
||||||
// ensure that all pending messages are still loaded next time in case
|
// ensure that all pending messages are still loaded next time in case
|
||||||
// of interruption - in particular skipping big messages would otherwise
|
// of interruption - in particular skipping big messages would otherwise
|
||||||
// up the limit too early.
|
// up the limit too early.
|
||||||
|
if (svars->maxuid[t] != svars->oldmaxuid[t])
|
||||||
JLOG( "N %d %u", (t, svars->maxuid[t]), "up maxuid of %s", str_fn[t] );
|
JLOG( "N %d %u", (t, svars->maxuid[t]), "up maxuid of %s", str_fn[t] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2191,6 +2219,7 @@ box_closed_p2( sync_vars_t *svars, int t )
|
||||||
// This is just an optimization, so it needs no journaling of intermediate states.
|
// 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
|
// However, doing it before the entry purge would require ensuring that the
|
||||||
// exception list includes all relevant messages.
|
// exception list includes all relevant messages.
|
||||||
|
if (svars->maxxfuid != svars->oldmaxxfuid)
|
||||||
JLOG( "! %u", svars->maxxfuid, "max expired UID on far side" );
|
JLOG( "! %u", svars->maxxfuid, "max expired UID on far side" );
|
||||||
|
|
||||||
save_state( svars );
|
save_state( svars );
|
||||||
|
|
Loading…
Reference in New Issue
Block a user