exclude placeholders from trashing

it makes no sense to trash the placeholders, and in fact the common
case is that they are deleted due to being replaced by the full
message.

a separate S_PURGED state needed to be added, as S_PURGE needs to be
reset after setting F_DELETED (so the operation doesn't count as still
pending after journal replay), yet trashing needs an indicator. logging
is now done via a separate command, as piggy-backing it on flag updates
just makes things less legible for no benefit.

this is mostly academical, as trashing being done on the side where
placeholders reside is rather unlikely.
This commit is contained in:
Oswald Buddenhagen 2022-04-04 21:41:18 +02:00
parent 8363dbf2d1
commit 01329bdf82
4 changed files with 51 additions and 6 deletions

View File

@ -605,10 +605,14 @@ sub cmptrash($$$)
print STDERR "Missing message $bn:".mn($num)."\n"; print STDERR "Missing message $bn:".mn($num)."\n";
$ret = 1; $ret = 1;
} }
if ($ph) {
print STDERR "Message $bn:".mn($num)." is placeholder\n";
$ret = 1;
}
} }
for my $num (sort { $a <=> $b } keys %$ms) { for my $num (sort { $a <=> $b } keys %$ms) {
if (!defined($$ref_ms{$num})) { if (!defined($$ref_ms{$num})) {
print STDERR "Excess message $bn:".mn($num)."\n"; print STDERR "Excess message $bn:".mn($num).($$ms{$num} ? " (is placeholder)" : "")."\n";
$ret = 1; $ret = 1;
} }
} }
@ -1057,7 +1061,7 @@ my @X22 = (
B, "", ">->", "^*", B, "", ">->", "^*",
B, "", "", "&1/", B, "", "", "&1/",
C, "^F*", "<-<+F", "", C, "^F*", "<-<+F", "",
C, "&1+T", "^T", "&", C, "&1+T", "^", "&",
); );
test("max size + flagging", \@x22, \@X22, \@O21); test("max size + flagging", \@x22, \@X22, \@O21);
@ -1145,12 +1149,16 @@ test("max messages + expunge", \@x38, \@X38, \@O38);
# Trashing # Trashing
my @x10 = ( my @x10 = (
E, A, E, K, A, K,
A, "*", "*~", "*T", A, "*", "*~", "*T",
B, "*T", "*^", "", B, "*T", "*^", "",
C, "*T", "*", "*T", C, "*T", "*", "*T",
D, "_", "*", "*", D, "_", "*", "*",
E, "*", "*", "_", E, "*", "*", "_",
F, "**", "*>", "*T?",
G, "*T?", "*<", "**",
J, "**", "*>", "*F?",
K, "*F?", "*<", "**",
L, "*T", "", "", L, "*T", "", "",
M, "", "", "*T", M, "", "", "*T",
R, "", "", "*", # Force maxuid in the interrupt-resume test. R, "", "", "*", # Force maxuid in the interrupt-resume test.
@ -1166,6 +1174,12 @@ my @X11 = (
C, "#/", "/", "#/", C, "#/", "/", "#/",
D, "", "/", "#/", D, "", "/", "#/",
E, "#/", "/", "", E, "#/", "/", "",
F, "#/", "/", "/",
G, "/", "/", "#/",
J, "", ">->", "^*",
J, "", "", "&1/",
K, "^*", "<-<", "",
K, "&1/", "", "",
L, "#/", "", "", L, "#/", "", "",
M, "", "", "#/", M, "", "", "#/",
R, "*", "*", "", R, "*", "*", "",
@ -1182,6 +1196,12 @@ my @X12 = (
C, "#/", "/", "/", C, "#/", "/", "/",
D, "", "/", "/", D, "", "/", "/",
E, "#/", "/", "", E, "#/", "/", "",
F, "#/", "/", "/",
G, "/", "/", "#/",
J, "", ">->", "^*",
J, "", "", "&1/",
K, "^*", "<-<", "",
K, "&1/", "", "",
L, "#/", "", "", L, "#/", "", "",
M, "", "", "#/", M, "", "", "#/",
R, "*", "*", "", R, "*", "*", "",
@ -1198,6 +1218,12 @@ my @X13 = (
C, "#/", "/", "/", C, "#/", "/", "/",
D, "", "/", "/", D, "", "/", "/",
E, "#/", "/", "", E, "#/", "/", "",
F, "#/", "/", "/",
G, "#/", "/", "/",
J, "", ">->", "^*",
J, "", "", "&1/",
K, "^*", "<-<", "",
K, "&1/", "", "",
L, "#/", "", "", L, "#/", "", "",
M, "#", "", "/", M, "#", "", "/",
R, "*", "*", "", R, "*", "*", "",

View File

@ -1498,7 +1498,10 @@ flags_set( int sts, void *aux )
static void static void
flags_set_p2( sync_vars_t *svars, sync_rec_t *srec, int t ) flags_set_p2( sync_vars_t *svars, sync_rec_t *srec, int t )
{ {
if (srec->status & S_DELETE) { if (srec->status & S_PURGE) {
JLOG( "P %u %u", (srec->uid[F], srec->uid[N]), "deleted dummy" );
srec->status = (srec->status & ~S_PURGE) | S_PURGED;
} else if (srec->status & S_DELETE) {
JLOG( "%c %u %u 0", ("><"[t], srec->uid[F], srec->uid[N]), "%sed deletion", str_hl[t] ); JLOG( "%c %u %u 0", ("><"[t], srec->uid[F], srec->uid[N]), "%sed deletion", str_hl[t] );
srec->uid[t^1] = 0; srec->uid[t^1] = 0;
} else { } else {
@ -1570,6 +1573,17 @@ msgs_flags_set( sync_vars_t *svars, int t )
debug( "is expired\n" ); debug( "is expired\n" );
continue; continue;
} }
if (srec->status & S_DUMMY(t)) {
// This is mostly academical, as trashing being done on the side
// where placeholders reside is rather unlikely.
debug( "is dummy\n" );
continue;
}
if (srec->status & S_PURGED) {
// As above.
debug( "is deleted dummy\n" );
continue;
}
if (only_new && !(srec->status & (S_PENDING | S_DUMMY(t^1) | S_SKIPPED))) { if (only_new && !(srec->status & (S_PENDING | S_DUMMY(t^1) | S_SKIPPED))) {
debug( "is not new\n" ); debug( "is not new\n" );
continue; continue;

View File

@ -21,6 +21,7 @@ BIT_ENUM(
S_DELETE, // ephemeral: flags propagation is a deletion S_DELETE, // ephemeral: flags propagation is a deletion
S_UPGRADE, // ephemeral: upgrading placeholder, do not apply MaxSize S_UPGRADE, // ephemeral: upgrading placeholder, do not apply MaxSize
S_PURGE, // ephemeral: placeholder is being nuked S_PURGE, // ephemeral: placeholder is being nuked
S_PURGED, // ephemeral: placeholder was nuked
) )
// This is the persistent status of the sync record, with regard to the journal. // This is the persistent status of the sync record, with regard to the journal.

View File

@ -292,6 +292,7 @@ load_state( sync_vars_t *svars )
case 'N': case 'N':
case 'F': case 'F':
case 'T': case 'T':
case 'P':
case '+': case '+':
case '&': case '&':
case '-': case '-':
@ -378,8 +379,11 @@ load_state( sync_vars_t *svars )
case '*': case '*':
debug( "flags now %u\n", t3 ); debug( "flags now %u\n", t3 );
srec->flags = (uchar)t3; srec->flags = (uchar)t3;
srec->aflags[F] = srec->aflags[N] = 0; // Clear F_DELETED from purge break;
srec->status &= ~S_PURGE; case 'P':
debug( "deleted dummy\n" );
srec->aflags[F] = srec->aflags[N] = 0; // Clear F_DELETED
srec->status = (srec->status & ~S_PURGE) | S_PURGED;
break; break;
case '~': case '~':
srec->status = (srec->status & ~S_LOGGED) | t3; srec->status = (srec->status & ~S_LOGGED) | t3;