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.
This commit is contained in:
parent
ef43021f26
commit
4ddacef2c1
|
@ -1210,6 +1210,31 @@ my @X32 = (
|
||||||
);
|
);
|
||||||
test("max messages vs. unread", \@x30, \@X32, \@O32);
|
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 = (
|
my @x38 = (
|
||||||
F, C, 0,
|
F, C, 0,
|
||||||
A, "*FS", "*FS", "*S",
|
A, "*FS", "*FS", "*S",
|
||||||
|
|
15
src/sync.c
15
src/sync.c
|
@ -714,6 +714,8 @@ box_opened2( sync_vars_t *svars, int t )
|
||||||
any_dummies[!srec->uid[F] ? F : N]++;
|
any_dummies[!srec->uid[F] ? F : N]++;
|
||||||
if (!svars->replayed)
|
if (!svars->replayed)
|
||||||
continue;
|
continue;
|
||||||
|
if ((shifted_bit(srec->status, S_EXPIRE, S_EXPIRED) ^ srec->status) & S_EXPIRED)
|
||||||
|
svars->any_expiring = 1;
|
||||||
if (srec->status & S_PURGE) {
|
if (srec->status & S_PURGE) {
|
||||||
any_purges[srec->uid[F] ? F : N]++;
|
any_purges[srec->uid[F] ? F : N]++;
|
||||||
} else if (srec->status & S_PENDING) {
|
} 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.
|
// but it's more natural to treat it as read-only in that case.
|
||||||
// OP_RENEW makes sense only for legacy S_SKIPPED entries.
|
// OP_RENEW makes sense only for legacy S_SKIPPED entries.
|
||||||
if ((chan->ops[N] & (OP_NEW|OP_RENEW|OP_FLAGS)) && chan->max_messages)
|
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;
|
opts[N] |= OPEN_OLD | OPEN_FLAGS;
|
||||||
|
}
|
||||||
svars->opts[F] = svars->drv[F]->prepare_load_box( ctx[F], opts[F] );
|
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] );
|
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.
|
// Note: When this branch is entered, we have loaded all near side messages.
|
||||||
/* Expire excess messages. Important (flagged, unread, or unpropagated) messages
|
/* Expire excess messages. Important (flagged, unread, or unpropagated) messages
|
||||||
* older than the first not expired message are not counted towards the total. */
|
* older than the first not expired message are not counted towards the total. */
|
||||||
|
@ -1585,14 +1590,17 @@ flags_set_p2( sync_vars_t *svars, sync_rec_t *srec, int t )
|
||||||
srec->flags = nflags;
|
srec->flags = nflags;
|
||||||
}
|
}
|
||||||
if (t == N) {
|
if (t == N) {
|
||||||
|
uchar ex = (srec->status / S_EXPIRE) & 1;
|
||||||
|
uchar exd = (srec->status / S_EXPIRED) & 1;
|
||||||
|
if (ex != exd) {
|
||||||
uchar nex = (srec->status / S_NEXPIRE) & 1;
|
uchar nex = (srec->status / S_NEXPIRE) & 1;
|
||||||
if (nex != ((srec->status / S_EXPIRED) & 1)) {
|
if (nex == ex) {
|
||||||
if (nex && svars->maxxfuid < srec->uid[F])
|
if (nex && svars->maxxfuid < srec->uid[F])
|
||||||
svars->maxxfuid = srec->uid[F];
|
svars->maxxfuid = srec->uid[F];
|
||||||
srec->status = (srec->status & ~S_EXPIRED) | (nex * S_EXPIRED);
|
srec->status = (srec->status & ~S_EXPIRED) | (nex * S_EXPIRED);
|
||||||
JLOG( "~ %u %u %d", (srec->uid[F], srec->uid[N], srec->status & S_LOGGED),
|
JLOG( "~ %u %u %d", (srec->uid[F], srec->uid[N], srec->status & S_LOGGED),
|
||||||
"expired %d - commit", nex );
|
"expired %d - commit", nex );
|
||||||
} else if (nex != ((srec->status / S_EXPIRE) & 1)) {
|
} else {
|
||||||
srec->status = (srec->status & ~S_EXPIRE) | (nex * S_EXPIRE);
|
srec->status = (srec->status & ~S_EXPIRE) | (nex * S_EXPIRE);
|
||||||
JLOG( "~ %u %u %d", (srec->uid[F], srec->uid[N], srec->status & S_LOGGED),
|
JLOG( "~ %u %u %d", (srec->uid[F], srec->uid[N], srec->status & S_LOGGED),
|
||||||
"expire %d - cancel", nex );
|
"expire %d - cancel", nex );
|
||||||
|
@ -1600,6 +1608,7 @@ flags_set_p2( sync_vars_t *svars, sync_rec_t *srec, int t )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *aux;
|
void *aux;
|
||||||
|
|
|
@ -53,7 +53,7 @@ typedef struct {
|
||||||
const char *orig_name[2];
|
const char *orig_name[2];
|
||||||
message_t *msgs[2], *new_msgs[2];
|
message_t *msgs[2], *new_msgs[2];
|
||||||
uint_array_alloc_t trashed_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 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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user