commit 4ddacef2c1469299a9c85310d402fec56fa668d9
Author: Oswald Buddenhagen <o...@users.sf.net>
Date:   Fri Dec 10 18:37:28 2021 +0100

    fix expiration completion during --noop run
    
    make sure that an expiration calculation run is performed if ongoing
    expiration transactions have been loaded from the journal. this has the
    nice side effect of centralizing the regular trigger condition as well.
    
    flags_set_p2() is also adjusted to query S_NEXPIRE only if an expiration
    is actually ongoing, like the flag propagation submission loop already
    did.
    
    this went unnoticed, because expiration upon arrival of new messages
    wasn't autotested at all - despite being the common case.

 src/run-tests.pl | 25 +++++++++++++++++++++++++
 src/sync.c       | 33 +++++++++++++++++++++------------
 src/sync_p.h     |  2 +-
 3 files changed, 47 insertions(+), 13 deletions(-)

diff --git a/src/run-tests.pl b/src/run-tests.pl
index 64c926ad..796ad55f 100755
--- a/src/run-tests.pl
+++ b/src/run-tests.pl
@@ -1210,6 +1210,31 @@ my @X32 = (
 );
 test("max messages vs. unread", \@x30, \@X32, \@O32);
 
+my @x33 = (
+  G, D, G,
+  A, "*F", "*F", "*F",
+  B, "*", "*", "*S",
+  C, "*S", "*", "*",
+  D, "*S", "", "",
+  E, "*", "*", "*S",
+  F, "*S", "*S", "*S",
+  G, "*", "*", "*S",
+  H, "*", "", "",
+  I, "*", "", "",
+);
+
+my @X33 = (
+  I, F, I,
+  B, "+S", "+~S", "+T",
+  C, "", "+~S", "+ST",
+  E, "+S", "+~S", "+T",
+  F, "", "+~", "+T",
+  G, "+S", "+S", "",
+  H, "", "*", "*",
+  I, "", "*", "*",
+);
+test("max messages + expire - full", \@x33, \@X33, \@O31);
+
 my @x38 = (
   F, C, 0,
   A, "*FS", "*FS", "*S",
diff --git a/src/sync.c b/src/sync.c
index 6048d22e..05a6f142 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -714,6 +714,8 @@ box_opened2( sync_vars_t *svars, int t )
                                any_dummies[!srec->uid[F] ? F : N]++;
                        if (!svars->replayed)
                                continue;
+                       if ((shifted_bit(srec->status, S_EXPIRE, S_EXPIRED) ^ 
srec->status) & S_EXPIRED)
+                               svars->any_expiring = 1;
                        if (srec->status & S_PURGE) {
                                any_purges[srec->uid[F] ? F : N]++;
                        } else if (srec->status & S_PENDING) {
@@ -787,7 +789,10 @@ box_opened2( sync_vars_t *svars, int t )
        // but it's more natural to treat it as read-only in that case.
        // OP_RENEW makes sense only for legacy S_SKIPPED entries.
        if ((chan->ops[N] & (OP_NEW|OP_RENEW|OP_FLAGS)) && chan->max_messages)
+               svars->any_expiring = 1;
+       if (svars->any_expiring) {
                opts[N] |= OPEN_OLD | OPEN_FLAGS;
+       }
        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] );
 
@@ -1228,7 +1233,7 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int 
recent_msgs, void *aux
                }
        }
 
-       if ((svars->chan->ops[N] & (OP_NEW|OP_RENEW|OP_FLAGS)) && 
svars->chan->max_messages) {
+       if (svars->any_expiring) {
                // 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. */
@@ -1585,17 +1590,21 @@ flags_set_p2( sync_vars_t *svars, sync_rec_t *srec, int 
t )
                        srec->flags = nflags;
                }
                if (t == N) {
-                       uchar nex = (srec->status / S_NEXPIRE) & 1;
-                       if (nex != ((srec->status / S_EXPIRED) & 1)) {
-                               if (nex && svars->maxxfuid < srec->uid[F])
-                                       svars->maxxfuid = srec->uid[F];
-                               srec->status = (srec->status & ~S_EXPIRED) | 
(nex * S_EXPIRED);
-                               JLOG( "~ %u %u %d", (srec->uid[F], 
srec->uid[N], srec->status & S_LOGGED),
-                                     "expired %d - commit", nex );
-                       } else if (nex != ((srec->status / S_EXPIRE) & 1)) {
-                               srec->status = (srec->status & ~S_EXPIRE) | 
(nex * S_EXPIRE);
-                               JLOG( "~ %u %u %d", (srec->uid[F], 
srec->uid[N], srec->status & S_LOGGED),
-                                     "expire %d - cancel", nex );
+                       uchar ex = (srec->status / S_EXPIRE) & 1;
+                       uchar exd = (srec->status / S_EXPIRED) & 1;
+                       if (ex != exd) {
+                               uchar nex = (srec->status / S_NEXPIRE) & 1;
+                               if (nex == ex) {
+                                       if (nex && svars->maxxfuid < 
srec->uid[F])
+                                               svars->maxxfuid = srec->uid[F];
+                                       srec->status = (srec->status & 
~S_EXPIRED) | (nex * S_EXPIRED);
+                                       JLOG( "~ %u %u %d", (srec->uid[F], 
srec->uid[N], srec->status & S_LOGGED),
+                                             "expired %d - commit", nex );
+                               } else {
+                                       srec->status = (srec->status & 
~S_EXPIRE) | (nex * S_EXPIRE);
+                                       JLOG( "~ %u %u %d", (srec->uid[F], 
srec->uid[N], srec->status & S_LOGGED),
+                                             "expire %d - cancel", nex );
+                               }
                        }
                }
        }
diff --git a/src/sync_p.h b/src/sync_p.h
index 45fcd3c6..80dea84e 100644
--- a/src/sync_p.h
+++ b/src/sync_p.h
@@ -53,7 +53,7 @@ typedef struct {
        const char *orig_name[2];
        message_t *msgs[2], *new_msgs[2];
        uint_array_alloc_t trashed_msgs[2];
-       int state[2], lfd, ret, existing, replayed;
+       int state[2], lfd, ret, existing, replayed, any_expiring;
        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


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

Reply via email to