This is an automated email from the ASF dual-hosted git repository.

belliottsmith 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 ce855de1 Accond: Torn Single Partition Reads
ce855de1 is described below

commit ce855de13902e7e3ebfa4356d265f0c49be1bb8e
Author: Benedict Elliott Smith <[email protected]>
AuthorDate: Fri Oct 9 10:39:52 2026 +0100

    Accond: Torn Single Partition Reads
    
    To support linearizable ephemeral reads, writes to a single partition must 
be atomic, and the ephemeral read must itself be performed atomically against 
the partition state. The former we achieve by merging updates to the same 
partition before submitting them to be written; the latter we achieve by simply 
(for now) disabling single key ephemeral reads if there is more than one read 
to perform. Ephemeral reads for range read compatibility is unaffected, as 
these have weaker isolation g [...]
    
    patch by Benedict; reviewed by Aleksey Yeschenko for CASSANDRA-21741
---
 .../impl/progresslog/DefaultProgressLog.java       | 39 ++++++++++++++++------
 .../java/accord/impl/progresslog/TxnState.java     |  6 ++++
 2 files changed, 34 insertions(+), 11 deletions(-)

diff --git 
a/accord-core/src/main/java/accord/impl/progresslog/DefaultProgressLog.java 
b/accord-core/src/main/java/accord/impl/progresslog/DefaultProgressLog.java
index affba896..c4c55717 100644
--- a/accord-core/src/main/java/accord/impl/progresslog/DefaultProgressLog.java
+++ b/accord-core/src/main/java/accord/impl/progresslog/DefaultProgressLog.java
@@ -136,7 +136,21 @@ public class DefaultProgressLog implements ProgressLog, 
Consumer<SafeCommandStor
     private final Object2ObjectHashMap<TxnId, PendingTask> pendingHome = new 
Object2ObjectHashMap<>();
 
     private final Long2ObjectHashMap<Object> active = new 
Long2ObjectHashMap<>();
-    private final Map<TxnId, TxnState> debugDeleted = Invariants.debug() && 
Invariants.isParanoid() && Invariants.isTesting() ? new 
Object2ObjectHashMap<>() : null;
+    public static final int DEBUG_LEVEL;
+    private static final TxnState DEBUG_SENTINEL = new TxnState(TxnId.NONE);
+    static
+    {
+        int debugLevel = Invariants.debug() ? 1 : 0;
+        String str = System.getProperty("accord.debug.progresslog");
+        if (str != null)
+        {
+            try { debugLevel = Integer.parseInt(str); }
+            catch (Throwable t) { logger.error("Failed to parse system 
property accord.debug.progresslog=" + str); }
+        }
+        DEBUG_LEVEL = debugLevel;
+    }
+
+    private final Map<TxnId, TxnState> debugDeleted = DEBUG_LEVEL > 0 ? new 
Object2ObjectHashMap<>() : null;
 
     // peek into the future by this many micros when picking what to run.
     // this is primarily to handle the fact that we do not support 0 delay 
when scheduling, so tasks that should be run immediately are schedule with 1us 
delay
@@ -200,7 +214,7 @@ public class DefaultProgressLog implements ProgressLog, 
Consumer<SafeCommandStor
         TxnState result = BTree.<TxnId, TxnState>find(stateMap, (id, state) -> 
id.compareTo(state.txnId), txnId);
         if (result == null)
         {
-            Invariants.require(debugDeleted == null || 
!debugDeleted.containsKey(txnId));
+            Invariants.require(DEBUG_LEVEL == 0 || 
!debugDeleted.containsKey(txnId));
             stateMap = BTree.update(stateMap, BTree.singleton(result = new 
TxnState(txnId)), TxnState::compareTo);
         }
         return result;
@@ -208,7 +222,7 @@ public class DefaultProgressLog implements ProgressLog, 
Consumer<SafeCommandStor
 
     private TxnState insert(TxnId txnId)
     {
-        Invariants.require(debugDeleted == null || 
!debugDeleted.containsKey(txnId));
+        Invariants.require(DEBUG_LEVEL == 0 || 
!debugDeleted.containsKey(txnId));
         TxnState result = new TxnState(txnId);
         stateMap = BTree.update(stateMap, BTree.singleton(result), 
TxnState::compareTo);
         return result;
@@ -447,7 +461,7 @@ public class DefaultProgressLog implements ProgressLog, 
Consumer<SafeCommandStor
 
         pendingWaiting.clear();
         pendingHome.clear();
-        if (debugDeleted != null)
+        if (DEBUG_LEVEL > 0)
             debugDeleted.clear();
 
         runBuffer = EMPTY_RUN_BUFFER;
@@ -465,10 +479,13 @@ public class DefaultProgressLog implements ProgressLog, 
Consumer<SafeCommandStor
     void remove(TxnState state)
     {
         stateMap = BTreeRemoval.<TxnId, TxnState>remove(stateMap, (id, s) -> 
id.compareTo(s.txnId), state.txnId);
-        if (debugDeleted != null)
+        if (DEBUG_LEVEL > 0)
         {
-            DeletedTxnState copy = new DeletedTxnState(state);
-            debugDeleted.put(copy.txnId, copy);
+            TxnState save;
+            if (DEBUG_LEVEL == 1) save = DEBUG_SENTINEL;
+            else if (debugDeletion == null) save = new TxnState(state);
+            else save = new DeletedTxnState(state);
+            debugDeleted.put(save.txnId, save);
         }
     }
 
@@ -1202,13 +1219,13 @@ public class DefaultProgressLog implements ProgressLog, 
Consumer<SafeCommandStor
         final Object debug;
         protected DeletedTxnState(TxnState copy)
         {
-            super(copy.txnId);
-            this.encodedState = copy.encodedState;
-            this.debug = debugDeletion.apply(copy.txnId);
+            super(copy);
+            Function<TxnId, ?> f = debugDeletion;
+            this.debug = f == null ? null : debugDeletion.apply(copy.txnId);
         }
     }
 
-    private static volatile Function<TxnId, ?> debugDeletion = id -> null;
+    private static volatile Function<TxnId, ?> debugDeletion = null;
     public static void setDebugDeletion(Function<TxnId, ?> newDebugDeletion)
     {
         debugDeletion = newDebugDeletion;
diff --git a/accord-core/src/main/java/accord/impl/progresslog/TxnState.java 
b/accord-core/src/main/java/accord/impl/progresslog/TxnState.java
index acc8e85b..6456e8a5 100644
--- a/accord-core/src/main/java/accord/impl/progresslog/TxnState.java
+++ b/accord-core/src/main/java/accord/impl/progresslog/TxnState.java
@@ -49,6 +49,12 @@ public class TxnState extends WaitingState implements 
ExecutionContext
         super(txnId);
     }
 
+    protected TxnState(TxnState copy)
+    {
+        super(copy.txnId);
+        this.encodedState = copy.encodedState;
+    }
+
     final void updateScheduling(SafeCommandStore safeStore, DefaultProgressLog 
owner, TxnStateKind updated, @Nullable BlockedUntil blockedUntil, Progress 
newProgress)
     {
         long newDelay;


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to