This is an automated email from the ASF dual-hosted git repository.
benedict pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/cassandra-accord.git
The following commit(s) were added to refs/heads/trunk by this push:
new 2b80b023 Erase should consistently erase all content associated with a
transaction Also Fix: - Erased SaveStatus can be reported for all queried
owned participants on a replica (the saved participants have been erased)
2b80b023 is described below
commit 2b80b0233f96464430058d70f7398df11066c3a6
Author: Benedict Elliott Smith <[email protected]>
AuthorDate: Wed Jun 18 13:02:41 2025 +0100
Erase should consistently erase all content associated with a transaction
Also Fix:
- Erased SaveStatus can be reported for all queried owned participants on
a replica (the saved participants have been erased)
patch by Benedict; reviewed by Alex Petrov for CASSANDRA-20722
---
.../src/main/java/accord/impl/CommandChange.java | 6 +++++-
accord-core/src/main/java/accord/local/Command.java | 19 ++++++-------------
accord-core/src/main/java/accord/local/Commands.java | 4 ++--
.../main/java/accord/local/cfk/CommandsForKey.java | 3 ++-
.../src/main/java/accord/messages/CheckStatus.java | 5 ++++-
.../src/main/java/accord/utils/Invariants.java | 12 ++++++++++++
.../test/java/accord/impl/basic/InMemoryJournal.java | 9 +++++++++
7 files changed, 40 insertions(+), 18 deletions(-)
diff --git a/accord-core/src/main/java/accord/impl/CommandChange.java
b/accord-core/src/main/java/accord/impl/CommandChange.java
index a623dc67..291e19db 100644
--- a/accord-core/src/main/java/accord/impl/CommandChange.java
+++ b/accord-core/src/main/java/accord/impl/CommandChange.java
@@ -459,6 +459,7 @@ public class CommandChange
if (cleanup != null && addCleanup.compareTo(cleanup) <= 0)
return false;
+ hasUpdate = true;
cleanup = addCleanup;
if (!cleanup.appliesTo(saveStatus))
return false;
@@ -574,7 +575,7 @@ public class CommandChange
return vestigial(txnId, participants);
case Erased:
// TODO (expected): why are we saving Durability here for
erased commands?
- return erased(txnId, durability, participants);
+ return erased(txnId);
case Invalidated:
return invalidated(txnId, participants);
}
@@ -709,6 +710,9 @@ public class CommandChange
}
flags |= eraseKnownFieldsMask[saveStatus.ordinal()];
+ if (saveStatus.compareTo(SaveStatus.Erased) >= 0 && (before == null ||
before.saveStatus() != saveStatus))
+ flags |= setChanged(CLEANUP, flags);
+
return flags;
}
diff --git a/accord-core/src/main/java/accord/local/Command.java
b/accord-core/src/main/java/accord/local/Command.java
index 456dfdc6..8b67c087 100644
--- a/accord-core/src/main/java/accord/local/Command.java
+++ b/accord-core/src/main/java/accord/local/Command.java
@@ -67,6 +67,7 @@ import static accord.primitives.Routable.Domain.Key;
import static accord.primitives.Routable.Domain.Range;
import static accord.primitives.Routables.Slice;
import static accord.primitives.SaveStatus.AcceptedInvalidate;
+import static accord.primitives.SaveStatus.Erased;
import static accord.primitives.SaveStatus.TruncatedApply;
import static accord.primitives.SaveStatus.TruncatedApplyWithOutcome;
import static accord.primitives.SaveStatus.TruncatedUnapplied;
@@ -398,20 +399,9 @@ public abstract class Command implements ICommand
public static class Truncated extends Command
{
- public static Truncated erased(Command command)
+ public static Truncated erased(TxnId txnId)
{
- return erased(command, command.participants());
- }
-
- public static Truncated erased(Command command, StoreParticipants
participants)
- {
- Durability durability =
Durability.mergeAtLeast(command.durability(), UniversalOrInvalidated);
- return erased(command.txnId(), durability, participants);
- }
-
- public static Truncated erased(TxnId txnId, Status.Durability
durability, StoreParticipants participants)
- {
- return validate(new Truncated(txnId, SaveStatus.Erased,
durability, participants, null, null, null, null));
+ return validate(new Truncated(txnId, SaveStatus.Erased,
UniversalOrInvalidated, StoreParticipants.empty(txnId), null, null, null,
null));
}
public static Truncated vestigial(Command command)
@@ -1587,6 +1577,9 @@ public abstract class Command implements ICommand
Invariants.require(txnId.hasOnlyIdentityFlags(), "%s has non-identity
flags", txnId);
SaveStatus saveStatus = validate.saveStatus();
+ if (saveStatus == Erased)
+ return validate;
+
StoreParticipants participants = validate.participants();
Invariants.require(!participants.hasTouched().isEmpty() || saveStatus
== Uninitialised, "%s(%s): hasTouched is empty. %s", txnId, saveStatus,
participants);
Known known = validate.known();
diff --git a/accord-core/src/main/java/accord/local/Commands.java
b/accord-core/src/main/java/accord/local/Commands.java
index 7f6bbfb4..12b4a4ce 100644
--- a/accord-core/src/main/java/accord/local/Commands.java
+++ b/accord-core/src/main/java/accord/local/Commands.java
@@ -435,7 +435,7 @@ public class Commands
if (command.hasBeen(Truncated))
return;
- safeCommand.set(erased(command));
+ safeCommand.set(erased(txnId));
}
public static void commitInvalidate(SafeCommandStore safeStore,
SafeCommand safeCommand, Unseekables<?> scope)
@@ -957,7 +957,7 @@ public class Commands
Invariants.require(command.saveStatus() != Erased);
case EXPUNGE:
- result = erased(command, newParticipants);
+ result = erased(command.txnId());
break;
}
return result;
diff --git a/accord-core/src/main/java/accord/local/cfk/CommandsForKey.java
b/accord-core/src/main/java/accord/local/cfk/CommandsForKey.java
index 0bbfa735..19ecabab 100644
--- a/accord-core/src/main/java/accord/local/cfk/CommandsForKey.java
+++ b/accord-core/src/main/java/accord/local/cfk/CommandsForKey.java
@@ -76,6 +76,7 @@ import static
accord.local.cfk.CommandsForKey.InternalStatus.ACCEPTED;
import static accord.local.cfk.CommandsForKey.InternalStatus.APPLIED_DURABLE;
import static
accord.local.cfk.CommandsForKey.InternalStatus.APPLIED_NOT_DURABLE;
import static accord.local.cfk.CommandsForKey.InternalStatus.COMMITTED;
+import static accord.local.cfk.CommandsForKey.InternalStatus.ERASED;
import static accord.local.cfk.CommandsForKey.InternalStatus.PRUNED;
import static accord.local.cfk.CommandsForKey.InternalStatus.STABLE;
import static accord.local.cfk.CommandsForKey.InternalStatus.TO_SUMMARY_STATUS;
@@ -1573,7 +1574,7 @@ public class CommandsForKey extends CommandsForKeyUpdate
private CommandsForKeyUpdate update(InternalStatus newStatus, Command
updated, @Nullable LoadingPruned loading)
{
TxnId txnId = updated.txnId();
- Invariants.requireArgument(updated.participants().hasTouched(key) ||
!manages(txnId));
+ Invariants.requireArgument(updated.participants().hasTouched(key) ||
!manages(txnId) || newStatus.compareTo(ERASED) >= 0);
if (txnId.compareTo(redundantBefore()) < 0)
return this;
diff --git a/accord-core/src/main/java/accord/messages/CheckStatus.java
b/accord-core/src/main/java/accord/messages/CheckStatus.java
index 688b2f91..eb76f021 100644
--- a/accord-core/src/main/java/accord/messages/CheckStatus.java
+++ b/accord-core/src/main/java/accord/messages/CheckStatus.java
@@ -178,7 +178,10 @@ public class CheckStatus extends
AbstractRequest<CheckStatus.CheckStatusReply>
SaveStatus saveStatus = command.saveStatus();
if (command.participants().isPureOwns() ||
(!saveStatus.known.deps().hasProposedOrDecidedDeps() &&
saveStatus.known.definition() != DefinitionKnown))
{
- Participants<?> validFor =
query.owns().intersecting(command.participants().owns());
+ Participants<?> validFor = query.owns();
+ if (saveStatus != SaveStatus.Erased) // no StoreParticipants for
Erased commands
+ validFor =
validFor.intersecting(command.participants().owns());
+
KnownMap result = KnownMap.create(validFor, saveStatus.known);
if (validFor != query.owns())
result = KnownMap.merge(result, KnownMap.create(query.owns(),
saveStatus.known.validForAll()));
diff --git a/accord-core/src/main/java/accord/utils/Invariants.java
b/accord-core/src/main/java/accord/utils/Invariants.java
index c306156a..7044892f 100644
--- a/accord-core/src/main/java/accord/utils/Invariants.java
+++ b/accord-core/src/main/java/accord/utils/Invariants.java
@@ -200,6 +200,12 @@ public class Invariants
onUnexpected.accept(illegalState(format(fmt, p1, p2, p3)));
}
+ public static void expect(boolean condition, String fmt, @Nullable Object
p1, @Nullable Object p2, long p3)
+ {
+ if (!condition)
+ onUnexpected.accept(illegalState(format(fmt, p1, p2, p3)));
+ }
+
public static <P> void expect(boolean condition, String fmt, @Nullable
Object p1, @Nullable Object p2, @Nullable P p3, Function<? super P, Object>
transformP3)
{
if (!condition)
@@ -278,6 +284,12 @@ public class Invariants
throw illegalState(format(fmt, p1, p2, p3, p4));
}
+ public static void require(boolean condition, String fmt, long p1, long
p2, long p3, Object p4, Object p5)
+ {
+ if (!condition)
+ throw illegalState(format(fmt, p1, p2, p3, p4, p5));
+ }
+
public static void require(boolean condition, String fmt, @Nullable Object
p1)
{
if (!condition)
diff --git a/accord-core/src/test/java/accord/impl/basic/InMemoryJournal.java
b/accord-core/src/test/java/accord/impl/basic/InMemoryJournal.java
index c057489b..33cf5816 100644
--- a/accord-core/src/test/java/accord/impl/basic/InMemoryJournal.java
+++ b/accord-core/src/test/java/accord/impl/basic/InMemoryJournal.java
@@ -97,6 +97,7 @@ import static accord.impl.CommandChange.unsetIterable;
import static accord.impl.CommandChange.validateFlags;
import static accord.local.Cleanup.ERASE;
import static accord.local.Cleanup.EXPUNGE;
+import static accord.local.Cleanup.INVALIDATE;
import static accord.local.Cleanup.Input;
import static accord.local.Cleanup.Input.FULL;
import static accord.local.Cleanup.Input.PARTIAL;
@@ -813,6 +814,14 @@ public class InMemoryJournal implements Journal
case RESULT:
changes.put(RESULT, after.result());
break;
+ case CLEANUP:
+ switch (after.saveStatus())
+ {
+ default: throw new
UnhandledEnum(after.saveStatus());
+ case Erased: changes.put(CLEANUP, ERASE); break;
+ case Invalidated: changes.put(CLEANUP,
INVALIDATE); break;
+ }
+ break;
default: throw new UnhandledEnum(field);
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]