You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by jo...@apache.org on 2025/04/22 22:09:27 UTC
(cassandra) 04/05: Merge branch 'cassandra-4.1' into cassandra-5.0
This is an automated email from the ASF dual-hosted git repository.
jonmeredith pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/cassandra.git
commit 32cfd477df72eab261eaf4a6f16aeb3a892b1e52
Merge: 17cb89208c 2ac701629b
Author: Jon Meredith <jo...@apache.org>
AuthorDate: Tue Apr 22 14:42:56 2025 -0600
Merge branch 'cassandra-4.1' into cassandra-5.0
CHANGES.txt | 1 +
src/java/org/apache/cassandra/db/LivenessInfo.java | 11 ++-
src/java/org/apache/cassandra/db/rows/Cells.java | 10 +++
test/unit/org/apache/cassandra/db/CellTest.java | 84 ++++++++++++++++++++++
.../org/apache/cassandra/db/LivenessInfoTest.java | 5 ++
.../org/apache/cassandra/db/rows/RowsTest.java | 54 ++++++++++++++
6 files changed, 163 insertions(+), 2 deletions(-)
diff --cc CHANGES.txt
index 2e5aeed0b5,afb99c4d0b..462d3ed74f
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -1,35 -1,5 +1,36 @@@
-4.1.9
+5.0.5
* Grant permission on keyspaces system_views and system_virtual_schema not possible (CASSANDRA-20171)
+ * Fix marking an SSTable as suspected and BufferPool leakage in case of a corrupted SSTable read during a compaction (CASSANDRA-20396)
+ * Introduce SSTableSimpleScanner for compaction (CASSANDRA-20092)
+ * Avoid purging deletions in RowFilter when reconciliation is required (CASSANDRA-20541)
+ * Fixed multiple single-node SAI query bugs relating to static columns (CASSANDRA-20338)
+ * Upgrade com.datastax.cassandra:cassandra-driver-core:3.11.5 to org.apache.cassandra:cassandra-driver-core:3.12.1 (CASSANDRA-17231)
+Merged from 4.0:
++ * Updating a column with a new TTL but same expiration time is non-deterministic and causes repair mismatches. (CASSANDRA-20561)
+ * Avoid computing prepared statement size for unprepared batches (CASSANDRA-20556)
+ * Fix Dropwizard Meter causes timeouts when infrequently used (CASSANDRA-19332)
+
+
+5.0.4
+ * Update netty to 4.1.119.Final and netty-tcnative to 2.0.70.Final (CASSANDRA-20314)
+ * Serialization can lose complex deletions in a mutation with multiple collections in a row (CASSANDRA-20449)
+ * Improve error messages when initializing auth classes (CASSANDRA-20368)
+ * Prioritize legacy 2i over SAI for columns with multiple indexes (CASSANDRA-20334)
+ * Ensure only offline tools can build IntervalTrees without first/last key fields (CASSANDRA-20407)
+ * Improve disk access patterns during compaction and range reads (CASSANDRA-15452)
+ * Improve IntervalTree build throughput (CASSANDRA-19596)
+ * Avoid limit on RFP fetch in the case of an unresolved static row (CASSANDRA-20323)
+ * Include materialized views to the output of DESCRIBE TABLE statements (CASSANDRA-20365)
+ * Heap and GC jvm flags improvements (CASSANDRA-20296)
+ * Fix unparseable YAML in default cassandra.yaml when uncommented for downstream tooling (CASSANDRA-20359)
+ * Avoid fetching entire partitions on unresolved static rows in RFP when no static column predicates exist (CASSANDRA-20243)
+ * Avoid indexing empty values for non-literals and types that do not allow them (CASSANDRA-20313)
+ * Fix incorrect results of min / max in-built functions on clustering columns in descending order (CASSANDRA-20295)
+ * Avoid possible consistency violations for SAI intersection queries over repaired index matches and multiple non-indexed column matches (CASSANDRA-20189)
+ * Skip check for DirectIO when initializing tools (CASSANDRA-20289)
+ * Avoid under-skipping during intersections when an iterator has mixed STATIC and WIDE keys (CASSANDRA-20258)
+ * Correct the default behavior of compareTo() when comparing WIDE and STATIC PrimaryKeys (CASSANDRA-20238)
+Merged from 4.1:
* Fix mixed mode paxos ttl commit hang (CASSANDRA-20514)
* Fix paxos mixed mode infinite loop (CASSANDRA-20493)
* Optionally skip exception logging on invalid legacy protocol magic exception (CASSANDRA-19483)
diff --cc test/unit/org/apache/cassandra/db/CellTest.java
index 3a9e0d0dc0,b4cca19920..b9ab25fe50
--- a/test/unit/org/apache/cassandra/db/CellTest.java
+++ b/test/unit/org/apache/cassandra/db/CellTest.java
@@@ -48,10 -39,10 +48,12 @@@ import org.apache.cassandra.schema.Keys
import org.apache.cassandra.schema.TableMetadata;
import org.apache.cassandra.serializers.MarshalException;
import org.apache.cassandra.utils.ByteBufferUtil;
+ import org.apache.cassandra.utils.FBUtilities;
+import org.assertj.core.api.Assertions;
+import org.assertj.core.api.ThrowableAssert;
import static java.util.Arrays.asList;
+ import static org.junit.Assert.assertEquals;
public class CellTest
{
@@@ -282,11 -276,91 +286,91 @@@
Assert.assertEquals(-1, testExpiring("val", "b", 2, 1, null, "a", null, 1));
}
+
+ public static void assertCellsEqual(Cell<?> cellA, Cell<?> cellB)
+ {
+ assertEquals(cellA.timestamp(), cellB.timestamp());
+ assertEquals(cellA.ttl(), cellB.ttl());
+ assertEquals(cellA.localDeletionTime(), cellB.localDeletionTime());
+ assertEquals(cellA.buffer(), cellB.buffer());
+ }
+
- static void checkCommutes(ColumnMetadata cmd, long timestamp, long tsDiff, int ttl, int ttlDiff, int nowInSeconds, int nowDiff)
++ static void checkCommutes(ColumnMetadata cmd, long timestamp, long tsDiff, int ttl, int ttlDiff, long nowInSeconds, int nowDiff)
+ {
+ long timestampA = timestamp;
+ long timestampB = timestampA + tsDiff;
+ int ttlA = ttl;
+ int ttlB = ttl + ttlDiff;
- int nowInSecsA = nowInSeconds;
- int nowInSecsB = nowInSecsA + nowDiff;
++ long nowInSecsA = nowInSeconds;
++ long nowInSecsB = nowInSecsA + nowDiff;
+ if (nowInSecsA < 0 || nowInSecsB < 0)
+ return;
+
+ Cell<?> cellA = ttlA == 0 ? BufferCell.tombstone(cmd, timestampA, nowInSecsA) :
+ ttlA < 0 ? BufferCell.live(cmd, timestampA, TEST_VALUE) :
+ BufferCell.expiring(cmd, timestampA, ttlA, nowInSecsA, TEST_VALUE);
+ Cell<?> cellB = ttlB == 0 ? BufferCell.tombstone(cmd, timestampB, nowInSecsB) :
+ ttlB < 0 ? BufferCell.live(cmd, timestampB, TEST_VALUE) :
+ BufferCell.expiring(cmd, timestampB, ttlB, nowInSecsB, TEST_VALUE);
+
+ Cell<?> cellAB = Cells.reconcile(cellA, cellB);
+ Cell<?> cellBA = Cells.reconcile(cellB, cellA);
+
+ assertCellsEqual(cellAB, cellBA);
+ }
+
+ @Test
+ public void checkSameValueDifferentLivenessCommutes()
+ {
+ ColumnMetadata cmd = fakeColumn("c", UTF8Type.instance);
+ long[] tsDiffs = new long[] {0L,
+ 1L, // microsecond
+ 1000L, // millisecond
+ 1000000L, // second
+ 60000000L}; // minute
+ int[] ttls = new int[] { -1, 0, 1, 3600, 24 * 3600, 7 * 24 * 3600, 60 * 24 * 3600, 366 * 24 * 3600 };
+ int[] ttlDiffs = new int[] { 0, 1, 60, 3600, 24 * 3600, 7 * 24 * 3600, 60 * 24 * 3600, 366 * 24 * 3600 };
+
- int nowInSeconds = FBUtilities.nowInSeconds();
++ long nowInSeconds = FBUtilities.nowInSeconds();
+ long timestamp = FBUtilities.timestampMicros();
+
+ for (long tsDiff: tsDiffs)
+ {
+ for (int ttl: ttls)
+ {
+ for (int ttlDiff : ttlDiffs)
+ {
+ for (Integer nowDiff : ttlDiffs)
+ checkCommutes(cmd, timestamp, tsDiff, ttl, ttlDiff, nowInSeconds, nowDiff);
+ }
+ }
+ }
+ }
+
+ // Checks that reconciling a cell with a smaller TTL reconcile commutatively
+ // Similar to rewriting data retrieved with SELECT v, TTL(v), WRITETIMESTAMP(v) with
+ // INSERT SET v=? USING TTL ? AND TIMESTAMP ?
+ @Test
+ public void rewriteCellWithSmallerTTL()
+ {
+ ColumnMetadata cmd = fakeColumn("c", UTF8Type.instance);
+ int[] nowDiffs = new int[] { 0, 1, 60, 3600, 24 * 3600, 7 * 24 * 3600, 60 * 24 * 3600, 366 * 24 * 3600 };
+ long timestamp = FBUtilities.timestampMicros();
- int nowInSeconds = FBUtilities.nowInSeconds();
++ long nowInSeconds = FBUtilities.nowInSeconds();
+ int ttl = 3600;
+
+ for (Integer nowDiff : nowDiffs)
+ {
+ checkCommutes(cmd, timestamp, 0L, ttl, -nowDiff, nowInSeconds, nowDiff);
+ }
+ }
+
+
class SimplePurger implements DeletionPurger
{
- private final int gcBefore;
+ private final long gcBefore;
- public SimplePurger(int gcBefore)
+ public SimplePurger(long gcBefore)
{
this.gcBefore = gcBefore;
}
diff --cc test/unit/org/apache/cassandra/db/rows/RowsTest.java
index a4436da88a,47e42b2542..865d33a8b6
--- a/test/unit/org/apache/cassandra/db/rows/RowsTest.java
+++ b/test/unit/org/apache/cassandra/db/rows/RowsTest.java
@@@ -526,6 -522,58 +528,58 @@@ public class RowsTes
Assert.assertEquals(0, merged.columns().size());
}
+
- public static BufferCell expiringWithExpirationTime(ColumnMetadata column, long timestamp, int ttl, int localDeletionTime, ByteBuffer value)
++ public static BufferCell expiringWithExpirationTime(ColumnMetadata column, long timestamp, int ttl, long localDeletionTime, ByteBuffer value)
+ {
+ return expiringWithExpirationTime(column, timestamp, ttl, localDeletionTime, value, null);
+ }
+
- public static BufferCell expiringWithExpirationTime(ColumnMetadata column, long timestamp, int ttl, int localDeletionTime, ByteBuffer value, CellPath path)
++ public static BufferCell expiringWithExpirationTime(ColumnMetadata column, long timestamp, int ttl, long localDeletionTime, ByteBuffer value, CellPath path)
+ {
+ assert ttl != Cell.NO_TTL;
+ return new BufferCell(column, timestamp, ttl, localDeletionTime, value, path);
+ }
+
+ @Test
+ public void mergeRowsWithSameExpiryDifferentTTLCommutesLiveness()
+ {
- int now1 = FBUtilities.nowInSeconds();
++ long now1 = FBUtilities.nowInSeconds();
+ long ts1 = secondToTs(now1);
- int ldt = now1 + 1000;
++ long ldt = now1 + 1000;
+
+ Row.Builder r1Builder = BTreeRow.unsortedBuilder();
+ r1Builder.newRow(c1);
+ LivenessInfo originalLiveness = LivenessInfo.withExpirationTime(ts1, 100, ldt);
+ r1Builder.addPrimaryKeyLivenessInfo(originalLiveness);
+
+ Row.Builder r2Builder = BTreeRow.unsortedBuilder();
+ r2Builder.newRow(c1);
+ LivenessInfo loweredTTL = LivenessInfo.withExpirationTime(ts1, 50, ldt);
+ r2Builder.addPrimaryKeyLivenessInfo(loweredTTL);
+
+ Cell<?> r2v = expiringWithExpirationTime(v, ts1, 75, ldt, BB1);
+ Cell<?> r2m2 = expiringWithExpirationTime(m, ts1, 50, ldt, BB1, CellPath.create(BB2));
+ Cell<?> r2m3 = expiringWithExpirationTime(m, ts1, 75, ldt, BB2, CellPath.create(BB3));
+ Cell<?> r2m4 = expiringWithExpirationTime(m, ts1, 100, ldt, BB3, CellPath.create(BB4));
+ List<Cell<?>> expectedCells = Lists.newArrayList(r2v, r2m2, r2m3, r2m4);
+
+ expectedCells.forEach(r1Builder::addCell);
+ expectedCells.forEach(r2Builder::addCell);
+
+ Row r1 = r1Builder.build();
+ Row r2 = r2Builder.build();
+
+ Row r1r2 = Rows.merge(r1, r2);
+ Row r2r1 = Rows.merge(r2, r1);
+
+ DiffListener mergedListener = new DiffListener();
+ Rows.diff(mergedListener, r1r2, r2r1);
+
+ mergedListener.liveness.forEach(pair -> Assert.assertEquals(pair.merged, pair.original));
+ mergedListener.cells.forEach(pair -> assertCellsEqual(pair.merged, pair.original));
+ }
+
+
// Creates a dummy cell for a (regular) column for the provided name and without a cellPath.
private static Cell<?> liveCell(ColumnMetadata name)
{
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org