This is an automated email from the ASF dual-hosted git repository.
marcuse pushed a commit to branch cassandra-4.0
in repository https://gitbox.apache.org/repos/asf/cassandra.git
The following commit(s) were added to refs/heads/cassandra-4.0 by this push:
new 76a7e43613 ArrayIndexOutOfBoundsException with repaired data tracking
and counters
76a7e43613 is described below
commit 76a7e43613e0810eefb53046254c8f48ad1adf50
Author: Marcus Eriksson <[email protected]>
AuthorDate: Fri Aug 29 09:11:41 2025 +0200
ArrayIndexOutOfBoundsException with repaired data tracking and counters
Patch by marcuse; reviewed by Sam Tunnicliffe for CASSANDRA-20871
---
CHANGES.txt | 1 +
src/java/org/apache/cassandra/db/Digest.java | 5 +++
.../cassandra/distributed/test/CountersTest.java | 49 ++++++++++++++++++++++
3 files changed, 55 insertions(+)
diff --git a/CHANGES.txt b/CHANGES.txt
index cc845d3588..5b4a438d09 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
4.0.20
+ * ArrayIndexOutOfBoundsException with repaired data tracking and counters
(CASSANDRA-20871)
* Fix cleanup of old incremental repair sessions in case of owned token range
changes or a table deleting (CASSANDRA-20877)
* Fix memory leak in BufferPoolAllocator when a capacity needs to be extended
(CASSANDRA-20753)
* Leveled Compaction doesn't validate maxBytesForLevel when the table is
altered/created (CASSANDRA-20570)
diff --git a/src/java/org/apache/cassandra/db/Digest.java
b/src/java/org/apache/cassandra/db/Digest.java
index 6a4ecd8fd1..6123af816f 100644
--- a/src/java/org/apache/cassandra/db/Digest.java
+++ b/src/java/org/apache/cassandra/db/Digest.java
@@ -69,6 +69,11 @@ public class Digest
// for the purposes of repaired data tracking on the read
path, exclude
// contexts with legacy shards as these may be irrevocably
different on
// different replicas
+
+ // see super.updateWithCounterContext +
CountersTest.testEmptyContext - counter context can be empty
+ if (accessor.isEmpty(context))
+ return this;
+
if (CounterContext.instance().hasLegacyShards(context,
accessor))
return this;
diff --git
a/test/distributed/org/apache/cassandra/distributed/test/CountersTest.java
b/test/distributed/org/apache/cassandra/distributed/test/CountersTest.java
index 7cc632f4aa..493db328ad 100644
--- a/test/distributed/org/apache/cassandra/distributed/test/CountersTest.java
+++ b/test/distributed/org/apache/cassandra/distributed/test/CountersTest.java
@@ -18,11 +18,17 @@
package org.apache.cassandra.distributed.test;
+import java.io.IOException;
+import java.util.Iterator;
+
import org.junit.Test;
+import org.apache.cassandra.db.Keyspace;
import org.apache.cassandra.distributed.Cluster;
import org.apache.cassandra.distributed.api.ConsistencyLevel;
import org.apache.cassandra.distributed.api.ICoordinator;
+import org.apache.cassandra.io.sstable.Descriptor;
+import org.apache.cassandra.io.sstable.format.SSTableReader;
import static org.apache.cassandra.distributed.api.Feature.GOSSIP;
import static org.apache.cassandra.distributed.api.Feature.NATIVE_PROTOCOL;
@@ -75,4 +81,47 @@ public class CountersTest extends TestBaseImpl
}
}
}
+
+ @Test
+ public void testEmptyContext() throws IOException
+ {
+ try (Cluster cluster = init(Cluster.build(3)
+ .withConfig(c -> c.with(GOSSIP,
NATIVE_PROTOCOL)
+
.set("repaired_data_tracking_for_partition_reads_enabled", true)
+
.set("repaired_data_tracking_for_range_reads_enabled", true))
+ .start()))
+ {
+ cluster.schemaChange(withKeyspace("CREATE TABLE %s.t (a ascii, b
ascii, c counter, d counter, PRIMARY KEY(a, b))"));
+ cluster.get(1).executeInternal(withKeyspace("UPDATE %s.t SET c = c
+ 1, d = d + 1 WHERE a = 'a1' AND b = 'b1'"));
+ cluster.get(2).executeInternal(withKeyspace("UPDATE %s.t SET c = c
+ 2, d = d + 2 WHERE a = 'a1' AND b = 'b1'"));
+ cluster.get(3).executeInternal(withKeyspace("UPDATE %s.t SET c = c
+ 3, d = d + 3 WHERE a = 'a1' AND b = 'b1'"));
+
+ cluster.forEach(i -> i.flush(KEYSPACE));
+
+ cluster.forEach(i -> i.runOnInstance(() -> {
+ Iterator<SSTableReader> sstables = Keyspace.open(KEYSPACE)
+
.getColumnFamilyStore("t")
+ .getLiveSSTables()
+ .iterator();
+ while (sstables.hasNext())
+ {
+ SSTableReader sstable = sstables.next();
+ Descriptor descriptor = sstable.descriptor;
+ try
+ {
+ descriptor.getMetadataSerializer()
+ .mutateRepairMetadata(descriptor,
System.currentTimeMillis(), null, false);
+ sstable.reloadSSTableMetadata();
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+ }));
+ cluster.coordinator(1).execute(withKeyspace("select a,d from %s.t
where a = 'a1'"), ConsistencyLevel.ALL);
+ cluster.coordinator(2).execute(withKeyspace("select a,d from %s.t
where a = 'a1'"), ConsistencyLevel.QUORUM);
+ cluster.coordinator(3).execute(withKeyspace("select a,d from %s.t
where a = 'a1'"), ConsistencyLevel.QUORUM);
+ }
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]