Browse Source

orphan/prune sync entries also if messages were expunged externally

deletions we propagated ourselves are implicitly covered by that as
well, so we don't need to record them separately anymore.
wip/maildir-path-under-inbox
Oswald Buddenhagen 3 years ago
parent
commit
eab3874918
  1. 24
      src/run-tests.pl
  2. 44
      src/sync.c
  3. 1
      src/sync_p.h

24
src/run-tests.pl

@ -941,6 +941,7 @@ sub test($$$$)
my @x01 = ( my @x01 = (
I, 0, I, I, 0, I,
P, "_", "*", "_",
R, "*", "", "", # Skipped/failed messages to prevent maxuid topping R, "*", "", "", # Skipped/failed messages to prevent maxuid topping
S, "", "", "*", S, "", "", "*",
A, "*F", "*", "*", A, "*F", "*", "*",
@ -949,6 +950,8 @@ my @x01 = (
D, "*", "*", "*", D, "*", "*", "*",
E, "*T", "*", "*", E, "*T", "*", "*",
F, "*", "*", "*T", F, "*", "*", "*T",
O, "*T", "*T", "*T",
Q, "_", "*T", "*T",
G, "*F", "*", "_", G, "*F", "*", "_",
H, "*FT", "*", "*", H, "*FT", "*", "*",
I, "_", "*", "*", I, "_", "*", "*",
@ -961,11 +964,13 @@ my @x01 = (
my @O01 = ("", "", ""); my @O01 = ("", "", "");
my @X01 = ( my @X01 = (
M, 0, K, M, 0, K,
P, "", "/", "",
A, "", "+F", "+F", A, "", "+F", "+F",
B, "+F", "+F", "", B, "+F", "+F", "",
C, "", "+FS", "+S", C, "", "+FS", "+S",
E, "", "+T", "+T", E, "", "+T", "+T",
F, "+T", "+T", "", F, "+T", "+T", "",
Q, "", "<", "",
G, "+T", ">", "", G, "+T", ">", "",
H, "", "+FT", "+FT", H, "", "+FT", "+FT",
I, "", "<", "+T", I, "", "<", "+T",
@ -979,11 +984,14 @@ test("full", \@x01, \@X01, \@O01);
my @O02 = ("", "", "Expunge Both\n"); my @O02 = ("", "", "Expunge Both\n");
my @X02 = ( my @X02 = (
M, 0, K, M, 0, K,
P, "", "/", "",
A, "", "+F", "+F", A, "", "+F", "+F",
B, "+F", "+F", "", B, "+F", "+F", "",
C, "", "+FS", "+S", C, "", "+FS", "+S",
E, "/", "/", "/", E, "/", "/", "/",
F, "/", "/", "/", F, "/", "/", "/",
O, "/", "/", "/",
Q, "", "/", "/",
G, "/", "/", "", G, "/", "/", "",
H, "/", "/", "/", H, "/", "/", "/",
I, "", "/", "/", I, "", "/", "/",
@ -997,11 +1005,14 @@ test("full + expunge both", \@x01, \@X02, \@O02);
my @O03 = ("", "", "Expunge Near\n"); my @O03 = ("", "", "Expunge Near\n");
my @X03 = ( my @X03 = (
M, 0, K, M, 0, K,
P, "", "/", "",
A, "", "+F", "+F", A, "", "+F", "+F",
B, "+F", "+F", "", B, "+F", "+F", "",
C, "", "+FS", "+S", C, "", "+FS", "+S",
E, "", ">+T", "/", E, "", ">+T", "/",
F, "+T", ">+T", "/", F, "+T", ">+T", "/",
O, "", ">", "/",
Q, "", "/", "/",
G, "+T", ">", "", G, "+T", ">", "",
H, "", ">+T", "/", H, "", ">+T", "/",
I, "", "/", "/", I, "", "/", "/",
@ -1014,9 +1025,11 @@ test("full + expunge near side", \@x01, \@X03, \@O03);
my @O04 = ("", "", "Sync Pull\n"); my @O04 = ("", "", "Sync Pull\n");
my @X04 = ( my @X04 = (
K, 0, I, K, 0, I,
P, "", "/", "", # Only because test uses Maildir driver
A, "", "+F", "+F", A, "", "+F", "+F",
C, "", "+FS", "+S", C, "", "+FS", "+S",
E, "", "+T", "+T", E, "", "+T", "+T",
Q, "", "<", "",
H, "", "+FT", "+FT", H, "", "+FT", "+FT",
I, "", "<", "+T", I, "", "<", "+T",
J, "", "*T", "*T", J, "", "*T", "*T",
@ -1027,11 +1040,13 @@ test("pull", \@x01, \@X04, \@O04);
my @O05 = ("", "", "Sync Flags\n"); my @O05 = ("", "", "Sync Flags\n");
my @X05 = ( my @X05 = (
I, 0, I, I, 0, I,
P, "", "/", "",
A, "", "+F", "+F", A, "", "+F", "+F",
B, "+F", "+F", "", B, "+F", "+F", "",
C, "", "+FS", "+S", C, "", "+FS", "+S",
E, "", "+T", "+T", E, "", "+T", "+T",
F, "+T", "+T", "", F, "+T", "+T", "",
Q, "", "<", "",
H, "", "+FT", "+FT", H, "", "+FT", "+FT",
); );
test("flags", \@x01, \@X05, \@O05); test("flags", \@x01, \@X05, \@O05);
@ -1039,7 +1054,9 @@ test("flags", \@x01, \@X05, \@O05);
my @O06 = ("", "", "Sync Delete\n"); my @O06 = ("", "", "Sync Delete\n");
my @X06 = ( my @X06 = (
I, 0, I, I, 0, I,
P, "", "/", "",
G, "+T", ">", "", G, "+T", ">", "",
Q, "", "<", "",
I, "", "<", "+T", I, "", "<", "+T",
); );
test("deletions", \@x01, \@X06, \@O06); test("deletions", \@x01, \@X06, \@O06);
@ -1057,9 +1074,11 @@ test("new", \@x01, \@X07, \@O07);
my @O08 = ("", "", "Sync PushFlags PullDelete\n"); my @O08 = ("", "", "Sync PushFlags PullDelete\n");
my @X08 = ( my @X08 = (
I, 0, I, I, 0, I,
P, "", "/", "",
B, "+F", "+F", "", B, "+F", "+F", "",
C, "", "+F", "", C, "", "+F", "",
F, "+T", "+T", "", F, "+T", "+T", "",
Q, "", "<", "",
I, "", "<", "+T", I, "", "<", "+T",
); );
test("push flags + pull deletions", \@x01, \@X08, \@O08); test("push flags + pull deletions", \@x01, \@X08, \@O08);
@ -1067,8 +1086,11 @@ test("push flags + pull deletions", \@x01, \@X08, \@O08);
my @O09 = ("", "", "Sync None\nExpunge Both\n"); my @O09 = ("", "", "Sync None\nExpunge Both\n");
my @X09 = ( my @X09 = (
I, 0, I, I, 0, I,
P, "", "/", "",
E, "/", "", "", E, "/", "", "",
F, "", "", "/", F, "", "", "/",
O, "/", "/", "/",
Q, "", "/", "/",
H, "/", "", "", H, "/", "", "",
J, "/", "", "", J, "/", "", "",
L, "", "", "/", L, "", "", "/",
@ -1080,6 +1102,8 @@ my @O0A = ("", "", "Sync None\nExpunge Near\n");
my @X0A = ( my @X0A = (
I, 0, I, I, 0, I,
F, "", "", "/", F, "", "", "/",
O, "", "", "/",
Q, "", "", "/",
L, "", "", "/", L, "", "", "/",
); );
test("noop + expunge near side", \@x01, \@X0A, \@O0A); test("noop + expunge near side", \@x01, \@X0A, \@O0A);

44
src/sync.c

@ -1036,6 +1036,7 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux
} else if (del[t]) { } else if (del[t]) {
// The target was newly expunged, so there is nothing to update. // The target was newly expunged, so there is nothing to update.
// The deletion is propagated in the opposite iteration. // The deletion is propagated in the opposite iteration.
srec->status |= S_GONE(t);
} else if (!srec->uid[t]) { } else if (!srec->uid[t]) {
// The target was never stored, or was previously expunged, so there // The target was never stored, or was previously expunged, so there
// is nothing to update. // is nothing to update.
@ -1340,7 +1341,7 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux
for (t = 0; t < 2; t++) { for (t = 0; t < 2; t++) {
if (!srec->uid[t]) if (!srec->uid[t])
continue; continue;
if (!srec->msg[t] && (svars->opts[t] & OPEN_OLD)) { if (srec->status & S_GONE(t)) {
// The message was expunged. No need to call flags_set(), because: // The message was expunged. No need to call flags_set(), because:
// - for S_DELETE and S_PURGE, the entry will be pruned due to both sides being gone // - for S_DELETE and S_PURGE, the entry will be pruned due to both sides being gone
// - for regular flag propagations, there is nothing to do // - for regular flag propagations, there is nothing to do
@ -1571,10 +1572,7 @@ flags_set_p2( sync_vars_t *svars, sync_rec_t *srec, int t )
if (srec->status & S_PURGE) { if (srec->status & S_PURGE) {
JLOG( "P %u %u", (srec->uid[F], srec->uid[N]), "deleted dummy" ); JLOG( "P %u %u", (srec->uid[F], srec->uid[N]), "deleted dummy" );
srec->status = (srec->status & ~S_PURGE) | S_PURGED; srec->status = (srec->status & ~S_PURGE) | S_PURGED;
} else if (srec->status & S_DELETE) { } else if (!(srec->status & S_DELETE)) {
JLOG( "%c %u %u 0", ("><"[t], srec->uid[F], srec->uid[N]), "%sed deletion", str_hl[t] );
srec->uid[t^1] = 0;
} else {
uchar nflags = (srec->flags | srec->aflags[t]) & ~srec->dflags[t]; uchar nflags = (srec->flags | srec->aflags[t]) & ~srec->dflags[t];
if (srec->flags != nflags) { if (srec->flags != nflags) {
JLOG( "* %u %u %u", (srec->uid[F], srec->uid[N], nflags), "%sed flags %s; were %s", JLOG( "* %u %u %u", (srec->uid[F], srec->uid[N], nflags), "%sed flags %s; were %s",
@ -1802,24 +1800,26 @@ box_closed_p2( sync_vars_t *svars, int t )
PC_JLOG( "N %d %u", (t, svars->maxuid[t]), "up maxuid of %s", str_fn[t] ); PC_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) { debug( "purging obsolete entries\n" );
debug( "purging obsolete entries\n" ); for (srec = svars->srecs; srec; srec = srec->next) {
for (srec = svars->srecs; srec; srec = srec->next) { if (srec->status & S_DEAD)
if (srec->status & S_DEAD) continue;
continue; if ((srec->status & S_DEL(F)) && (svars->state[F] & ST_DID_EXPUNGE))
if (!srec->uid[N] || ((srec->status & S_DEL(N)) && (svars->state[N] & ST_DID_EXPUNGE))) { srec->status |= S_GONE(F);
if (!srec->uid[F] || ((srec->status & S_DEL(F)) && (svars->state[F] & ST_DID_EXPUNGE)) || if ((srec->status & S_DEL(N)) && (svars->state[N] & ST_DID_EXPUNGE))
((srec->status & S_EXPIRED) && svars->maxuid[F] >= srec->uid[F] && svars->maxxfuid >= srec->uid[F])) { srec->status |= S_GONE(N);
PC_JLOG( "- %u %u", (srec->uid[F], srec->uid[N]), "killing" ); if (!srec->uid[N] || (srec->status & S_GONE(N))) {
srec->status = S_DEAD; if (!srec->uid[F] || (srec->status & S_GONE(F)) ||
} else if (srec->uid[N] && (srec->status & S_DEL(F))) { ((srec->status & S_EXPIRED) && svars->maxuid[F] >= srec->uid[F] && svars->maxxfuid >= srec->uid[F])) {
PC_JLOG( "> %u %u 0", (srec->uid[F], srec->uid[N]), "orphaning" ); PC_JLOG( "- %u %u", (srec->uid[F], srec->uid[N]), "killing" );
srec->uid[N] = 0; srec->status = S_DEAD;
} } else if (srec->uid[N] && (srec->status & S_DEL(F))) {
} else if (srec->uid[F] && ((srec->status & S_DEL(F)) && (svars->state[F] & ST_DID_EXPUNGE)) && (srec->status & S_DEL(N))) { PC_JLOG( "> %u %u 0", (srec->uid[F], srec->uid[N]), "orphaning" );
PC_JLOG( "< %u %u 0", (srec->uid[F], srec->uid[N]), "orphaning" ); srec->uid[N] = 0;
srec->uid[F] = 0;
} }
} else if (srec->uid[F] && (srec->status & S_GONE(F)) && (srec->status & S_DEL(N))) {
PC_JLOG( "< %u %u 0", (srec->uid[F], srec->uid[N]), "orphaning" );
srec->uid[F] = 0;
} }
} }

1
src/sync_p.h

@ -17,6 +17,7 @@ BIT_ENUM(
S_PENDING, // the entry is new and awaits propagation (possibly a retry) S_PENDING, // the entry is new and awaits propagation (possibly a retry)
S_DUMMY(2), // f/n message is only a placeholder S_DUMMY(2), // f/n message is only a placeholder
S_SKIPPED, // pre-1.4 legacy: the entry was not propagated (message is too big) S_SKIPPED, // pre-1.4 legacy: the entry was not propagated (message is too big)
S_GONE(2), // ephemeral: f/n message has been expunged
S_DEL(2), // ephemeral: f/n message would be subject to expunge S_DEL(2), // ephemeral: f/n message would be subject to expunge
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

Loading…
Cancel
Save