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.
This commit is contained in:
parent
f2f519e20b
commit
eab3874918
|
@ -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);
|
||||||
|
|
20
src/sync.c
20
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,13 +1800,16 @@ 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->uid[N] || ((srec->status & S_DEL(N)) && (svars->state[N] & ST_DID_EXPUNGE))) {
|
if ((srec->status & S_DEL(F)) && (svars->state[F] & ST_DID_EXPUNGE))
|
||||||
if (!srec->uid[F] || ((srec->status & S_DEL(F)) && (svars->state[F] & ST_DID_EXPUNGE)) ||
|
srec->status |= S_GONE(F);
|
||||||
|
if ((srec->status & S_DEL(N)) && (svars->state[N] & ST_DID_EXPUNGE))
|
||||||
|
srec->status |= S_GONE(N);
|
||||||
|
if (!srec->uid[N] || (srec->status & S_GONE(N))) {
|
||||||
|
if (!srec->uid[F] || (srec->status & S_GONE(F)) ||
|
||||||
((srec->status & S_EXPIRED) && svars->maxuid[F] >= srec->uid[F] && svars->maxxfuid >= srec->uid[F])) {
|
((srec->status & S_EXPIRED) && svars->maxuid[F] >= srec->uid[F] && svars->maxxfuid >= srec->uid[F])) {
|
||||||
PC_JLOG( "- %u %u", (srec->uid[F], srec->uid[N]), "killing" );
|
PC_JLOG( "- %u %u", (srec->uid[F], srec->uid[N]), "killing" );
|
||||||
srec->status = S_DEAD;
|
srec->status = S_DEAD;
|
||||||
|
@ -1816,12 +1817,11 @@ box_closed_p2( sync_vars_t *svars, int t )
|
||||||
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[N] = 0;
|
||||||
}
|
}
|
||||||
} else if (srec->uid[F] && ((srec->status & S_DEL(F)) && (svars->state[F] & ST_DID_EXPUNGE)) && (srec->status & S_DEL(N))) {
|
} 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" );
|
PC_JLOG( "< %u %u 0", (srec->uid[F], srec->uid[N]), "orphaning" );
|
||||||
srec->uid[F] = 0;
|
srec->uid[F] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
save_state( svars );
|
save_state( svars );
|
||||||
|
|
||||||
|
|
|
@ -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…
Reference in New Issue
Block a user