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]

Reply via email to