Browse Source

make expiration loops solely far-side-driven

we can do that, as unpaired near-side messages are ignored anyway.

this mildly changes expiration order, as near-side messages that
existed for a long time but were propagated much later will be expired
later. however, that has no practical relevance.
1.4
Oswald Buddenhagen 5 years ago
parent
commit
de6dc699c9
  1. 80
      src/sync.c

80
src/sync.c

@ -1653,77 +1653,65 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux
/* 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. */
debug( "preparing message expiration\n" ); debug( "preparing message expiration\n" );
// Due to looping only over the far side, we completely ignore unpaired
// near-side messages. This is correct, as we cannot expire them without
// data loss anyway; consequently, we also don't count them.
// Note that we also ignore near-side messages we're currently propagating,
// which delays expiration of some messages by one cycle. Otherwise, we'd have
// to sequence flag propagation after message propagation to avoid a race
// with 3rd-party expunging, and that seems unreasonably expensive.
alive = 0; alive = 0;
for (tmsg = svars->msgs[N]; tmsg; tmsg = tmsg->next) { for (tmsg = svars->msgs[F]; tmsg; tmsg = tmsg->next) {
if (tmsg->status & M_DEAD) if (tmsg->status & M_DEAD)
continue; continue;
if (!(srec = tmsg->srec) || !srec->uid[F]) { // We ignore unpaired far-side messages, as there is obviously nothing
// The message was not propagated, so it doesn't count towards the total. // to expire in the first place.
// Note that we also ignore messages we're currently propagating, which if (!(srec = tmsg->srec))
// delays expiry of some messages by one cycle. Otherwise, we'd have to continue;
// sequence flag propagation after message propagation to avoid a race if (!(srec->status & S_PENDING)) {
// with 3rd-party expunging, and that seems unreasonable. if (!srec->msg[N])
} else if (((tmsg->flags | srec->aflags[N]) & ~srec->dflags[N] & F_DELETED) && continue; // Already expired or skipped.
!(srec->status & (S_EXPIRE|S_EXPIRED))) { nflags = (srec->msg[N]->flags | srec->aflags[N]) & ~srec->dflags[N];
// The paired message is being deleted.
} else { } else {
alive++; nflags = tmsg->flags;
}
} }
for (tmsg = svars->msgs[F]; tmsg; tmsg = tmsg->next) { if (!(nflags & F_DELETED) || (srec->status & (S_EXPIRE|S_EXPIRED)))
if (tmsg->status & M_DEAD) // The message is not deleted, or it is, but only due to being expired.
continue;
if ((srec = tmsg->srec) && (srec->status & S_PENDING) && !(tmsg->flags & F_DELETED))
alive++; alive++;
} }
todel = alive - svars->chan->max_messages; todel = alive - svars->chan->max_messages;
debug( "%d alive messages, %d excess - expiring\n", alive, todel ); debug( "%d alive messages, %d excess - expiring\n", alive, todel );
alive = 0; alive = 0;
for (tmsg = svars->msgs[N]; tmsg; tmsg = tmsg->next) { for (tmsg = svars->msgs[F]; tmsg; tmsg = tmsg->next) {
if (tmsg->status & M_DEAD) if (tmsg->status & M_DEAD)
continue; continue;
if (!(srec = tmsg->srec) || !srec->uid[F]) { if (!(srec = tmsg->srec))
/* We did not push the message, so it must be kept. */ continue;
debug( " message %u unpropagated\n", tmsg->uid ); if (!(srec->status & S_PENDING)) {
if (!srec->msg[N])
continue;
nflags = (srec->msg[N]->flags | srec->aflags[N]) & ~srec->dflags[N];
} else { } else {
nflags = (tmsg->flags | srec->aflags[N]) & ~srec->dflags[N]; nflags = tmsg->flags;
}
if (!(nflags & F_DELETED) || (srec->status & (S_EXPIRE|S_EXPIRED))) { if (!(nflags & F_DELETED) || (srec->status & (S_EXPIRE|S_EXPIRED))) {
/* The message is not deleted, or is already (being) expired. */ if ((nflags & F_FLAGGED) ||
if ((nflags & F_FLAGGED) || !((nflags & F_SEEN) || ((void)(todel > 0 && alive++), svars->chan->expire_unread > 0))) { !((nflags & F_SEEN) || ((void)(todel > 0 && alive++), svars->chan->expire_unread > 0))) {
/* Important messages are always kept. */ // Important messages are always fetched/kept.
debug( " old pair(%u,%u) important\n", srec->uid[F], srec->uid[N] ); debug( " pair(%u,%u) is important\n", srec->uid[F], srec->uid[N] );
todel--; todel--;
} else if (todel > 0 || } else if (todel > 0 ||
((srec->status & (S_EXPIRE|S_EXPIRED)) == (S_EXPIRE|S_EXPIRED)) || ((srec->status & (S_EXPIRE|S_EXPIRED)) == (S_EXPIRE|S_EXPIRED)) ||
((srec->status & (S_EXPIRE|S_EXPIRED)) && (tmsg->flags & F_DELETED))) { ((srec->status & (S_EXPIRE|S_EXPIRED)) && (srec->msg[N]->flags & F_DELETED))) {
/* The message is excess or was already (being) expired. */ /* The message is excess or was already (being) expired. */
srec->wstate |= W_NEXPIRE; srec->wstate |= W_NEXPIRE;
debug( " old pair(%u,%u) expired\n", srec->uid[F], srec->uid[N] ); debug( " pair(%u,%u) expired\n", srec->uid[F], srec->uid[N] );
if (svars->maxxfuid < srec->uid[F]) if (svars->maxxfuid < srec->uid[F])
svars->maxxfuid = srec->uid[F]; svars->maxxfuid = srec->uid[F];
todel--; todel--;
} }
} }
} }
}
for (tmsg = svars->msgs[F]; tmsg; tmsg = tmsg->next) {
if (tmsg->status & M_DEAD)
continue;
if ((srec = tmsg->srec) && (srec->status & S_PENDING)) {
nflags = tmsg->flags;
if (!(nflags & F_DELETED)) {
if ((nflags & F_FLAGGED) || !((nflags & F_SEEN) || ((void)(todel > 0 && alive++), svars->chan->expire_unread > 0))) {
/* Important messages are always fetched. */
debug( " new pair(%u,%u) important\n", srec->uid[F], srec->uid[N] );
todel--;
} else if (todel > 0) {
/* The message is excess. */
srec->wstate |= W_NEXPIRE;
todel--;
}
}
}
}
debug( "%d excess messages remain\n", todel ); debug( "%d excess messages remain\n", todel );
if (svars->chan->expire_unread < 0 && alive * 2 > svars->chan->max_messages) { if (svars->chan->expire_unread < 0 && alive * 2 > svars->chan->max_messages) {
error( "%s: %d unread messages in excess of MaxMessages (%d).\n" error( "%s: %d unread messages in excess of MaxMessages (%d).\n"

Loading…
Cancel
Save