commit 68a412115a75223fb9561f0a467970d2a4af65bf
Author: Oswald Buddenhagen <o...@users.sf.net>
Date:   Mon Nov 25 20:55:41 2019 +0100

    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.

 src/run-tests.pl |  5 ++--
 src/sync.c       | 71 ++++++++++++++++++++++++++++++++++--------------
 2 files changed, 53 insertions(+), 23 deletions(-)

diff --git a/src/run-tests.pl b/src/run-tests.pl
index 1033407..4b936d9 100755
--- a/src/run-tests.pl
+++ b/src/run-tests.pl
@@ -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";
diff --git a/src/sync.c b/src/sync.c
index 8dbdc62..f191e68 100644
--- a/src/sync.c
+++ b/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 );
 


_______________________________________________
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel

Reply via email to