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

asf-gitbox-commits pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/cassandra.git

commit 78817fa41b32edaff85f5fe4ff6663503f540dd8
Merge: a621de992a 60b833a8f4
Author: Caleb Rackliffe <[email protected]>
AuthorDate: Mon Aug 17 15:09:41 2026 -0500

    Merge branch 'cassandra-6.0' into trunk
    
    * cassandra-6.0:
      Make runWithCompactionsDisabled return non-null on success

 CHANGES.txt                                        |   1 +
 .../org/apache/cassandra/db/ColumnFamilyStore.java |  84 +++++---
 .../cassandra/db/compaction/CompactionManager.java |   5 +-
 .../cassandra/exceptions/RequestFailure.java       |   5 +
 .../cassandra/exceptions/RequestFailureReason.java |   2 +
 src/java/org/apache/cassandra/net/InboundSink.java |   4 +-
 .../apache/cassandra/service/StorageService.java   |   2 +
 .../apache/cassandra/db/TruncateBlockingTest.java  | 226 +++++++++++++++++++++
 .../db/compaction/CancelCompactionsTest.java       | 112 ++++++++++
 .../exceptions/RequestFailureReasonTest.java       |   1 +
 10 files changed, 415 insertions(+), 27 deletions(-)

diff --cc CHANGES.txt
index 3114310058,dfa56b6881..9d19ee6e61
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -78,34 -83,6 +78,35 @@@ Merged from 6.0
   * Differentiate between legitimate cases where the first entry is the same 
as the last entry and empty bounds in SSTableCursorWriter#addIndexBlock() 
(CASSANDRA-21255)
   * Introduce minimum_threshold for data resurrection startup check 
(CASSANDRA-21293)
   * Synchronously publish changes to local gossip state following metadata 
updates (CASSANDRA-21239)
 +Merged from 5.0:
 + * Avoid rebuilding per-SSTable SAI components unless missing or corrupted 
(CASSANDRA-21515)
 + * Propagate trickle_fsync settings to compressed SSTable writers 
(CASSANDRA-21487)
 + * Allow setCompressedReadAheadBufferSizeInKb(0) to disable read-ahead buffer 
(CASSANDRA-21522)
 + * Fix ThreadLocalReadAheadBuffer#fill() to throw a CorruptBlockException if 
chunk metadata and file size are out of sync (CASSANDRA-21519)
 + * Support Python 3.12 and 3.13 in cqlsh (CASSANDRA-20997)
 + * Make synchronization on VectorMemoryIndex inserts more granular 
(CASSANDRA-21160)
 + * Fix RequestFailureReason serializer and nits in a few others 
(CASSANDRA-21437)
 + * Remove golang dependency in gen-doc and replace with python implementation 
(CASSANDRA-21432)
 + * Use estimated compressed size for tables to check if there is enough free 
space for a compaction (CASSANDRA-21245)
 + * Fix failing select on system_views.settings for non-string keys 
(CASSANDRA-21348)
 +Merged from 4.0:
++ * Make runWithCompactionsDisabled return non-null on success 
(CASSANDRA-21527)
 + * Validate authz before performing role check in LIST ROLES/PERMISSIONS 
(CASSANDRA-21560)
 + * Add validation to uncompressed length during decompression 
(CASSANDRA-21567)
 + * Fix regression in PasswordObfuscator for dollar-quoted passwords 
(CASSANDRA-21559)
 + * Do not make DNS lookup when querying system_views.clients for hostname 
column by removing it (CASSANDRA-21539)
 + * Fix memtable on-heap accounting drift in BTree.update and BTreeRow.merge 
(CASSANDRA-21472)
 + * Bound declared value length against readable bytes in CBUtil 
(CASSANDRA-21521)
 + * Verify extension type before initializing reflectively-loaded classes 
(CASSANDRA-21525)
 + * Rename conflicting nodetool import --copy-data short option from -p to -cd 
(CASSANDRA-20214)
 + * Fix PasswordObfuscator failing to obfuscate certain passwords 
(CASSANDRA-21113)
 + * Fix negative memtable allocator ownership when an update is shadowed by an 
existing row deletion (CASSANDRA-21469)
 + * Consider first token of SSTable when calculating SSTable intersection in 
LeveledScanner  (CASSANDRA-21369)
 + * Remove inFlightEcho entry on ECHO_REQ failure (CASSANDRA-21428)
 + * Validate snapshot names (CASSANDRA-21389)
 +
 +
 +6.0-alpha2
   * Change default for cassandra.set_sep_thread_name to false to reduce CPU 
usage (CASSANDRA-21089)
   * Avoid permission checks for masked columns when the table doesn't have any 
(CASSANDRA-21299)
   * Reduce allocations and array copies due to buffer resizing in 
LocalDataResponse during row serialization (CASSANDRA-21285)
diff --cc src/java/org/apache/cassandra/db/ColumnFamilyStore.java
index db15db6729,50e962ac04..5e9e2ac520
--- a/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
+++ b/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
@@@ -1957,8 -1961,15 +1966,15 @@@ public class ColumnFamilyStore implemen
                  TimeUUID session = sst.getPendingRepair();
                  return session != null && sessions.contains(session);
              };
-             return runWithCompactionsDisabled(() -> 
compactionStrategyManager.releaseRepairData(sessions),
-                                               predicate, 
OperationType.STREAM, false, true, true);
+             CleanupSummary summary = runWithCompactionsDisabled(() -> 
compactionStrategyManager.releaseRepairData(sessions),
 -                                                                predicate, 
OperationType.STREAM, false, true, true);
++                                                                 predicate, 
OperationType.STREAM, false, true, true);
+             if (summary == null)
+             {
+                 logger.warn("Unable to cancel in-progress compactions for 
{}.{}, could not force release repair data for sessions {}",
+                             getKeyspaceName(), name, sessions);
+                 return new CleanupSummary(this, Collections.emptySet(), new 
HashSet<>(sessions));
+             }
+             return summary;
          }
          else
          {
diff --cc test/unit/org/apache/cassandra/db/TruncateBlockingTest.java
index 0000000000,6d464a42e9..76c3ccc071
mode 000000,100644..100644
--- a/test/unit/org/apache/cassandra/db/TruncateBlockingTest.java
+++ b/test/unit/org/apache/cassandra/db/TruncateBlockingTest.java
@@@ -1,0 -1,226 +1,226 @@@
+ /*
+  * Licensed to the Apache Software Foundation (ASF) under one
+  * or more contributor license agreements.  See the NOTICE file
+  * distributed with this work for additional information
+  * regarding copyright ownership.  The ASF licenses this file
+  * to you under the Apache License, Version 2.0 (the
+  * "License"); you may not use this file except in compliance
+  * with the License.  You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+ package org.apache.cassandra.db;
+ 
+ import java.util.Collections;
+ 
+ import org.assertj.core.api.Assertions;
+ import org.jboss.byteman.contrib.bmunit.BMRule;
+ import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
+ import org.junit.Test;
+ import org.junit.runner.RunWith;
+ 
+ import org.apache.cassandra.cql3.CQLTester;
+ import org.apache.cassandra.db.compaction.CompactionInfo;
+ import org.apache.cassandra.db.compaction.CompactionManager;
+ import org.apache.cassandra.db.compaction.OperationType;
+ import org.apache.cassandra.db.lifecycle.LifecycleTransaction;
+ import org.apache.cassandra.exceptions.TruncateException;
+ import org.apache.cassandra.io.sstable.format.SSTableReader;
+ import org.apache.cassandra.service.StorageService;
+ 
+ import static org.apache.cassandra.utils.TimeUUID.Generator.nextTimeUUID;
+ import static org.junit.Assert.assertFalse;
+ import static org.junit.Assert.assertNotNull;
+ 
+ @RunWith(BMUnitRunner.class)
+ public class TruncateBlockingTest extends CQLTester
+ {
+     @Test
+     public void testTruncateFailsWhenCompactionsCannotBeDisabled()
+     {
+         createTable("CREATE TABLE %s (id int PRIMARY KEY, v text)");
+ 
+         execute("INSERT INTO %s (id, v) VALUES (1, 'a')");
+         execute("INSERT INTO %s (id, v) VALUES (2, 'b')");
+         execute("INSERT INTO %s (id, v) VALUES (3, 'c')");
+         flush();
+ 
+         ColumnFamilyStore cfs = getCurrentColumnFamilyStore();
+ 
+         // Register a P0-priority compaction holder for this table to force
+         // runWithCompactionsDisabled to return null immediately.
+         CompactionInfo.Holder holder = new CompactionInfo.Holder()
+         {
+             public CompactionInfo getCompactionInfo()
+             {
+                 return new CompactionInfo(cfs.metadata(),
+                                           OperationType.P0,
+                                           0,
+                                           100,
+                                           100,
+                                           nextTimeUUID(),
+                                           Collections.emptySet());
+             }
+ 
+             public boolean isGlobal()
+             {
+                 return false;
+             }
+         };
+ 
+         CompactionManager.instance.active.beginCompaction(holder);
+         try
+         {
+             Assertions.assertThatThrownBy(cfs::truncateBlocking)
+                       .as("Unable to stop compaction. Usually retrying 
truncate will work")
+                       .isInstanceOf(TruncateException.class);
+ 
+             assertRows(execute("SELECT * FROM %s WHERE id = 1"), row(1, "a"));
+             assertRows(execute("SELECT * FROM %s WHERE id = 2"), row(2, "b"));
+             assertRows(execute("SELECT * FROM %s WHERE id = 3"), row(3, "c"));
+             assertFalse("SSTables should still be present after truncation 
failure",
+                         cfs.getLiveSSTables().isEmpty());
+ 
+         }
+         finally
+         {
+             CompactionManager.instance.active.finishCompaction(holder);
+         }
+     }
+ 
+     @Test
+     @BMRule(name = "no-op waitForCessation",
+             targetClass = 
"org.apache.cassandra.db.compaction.CompactionManager",
+             targetMethod = "waitForCessation",
+             action = "return;")
+     public void testTruncateFailsWhenCompactionsDoNotStopInTime()
+     {
+         createTable("CREATE TABLE %s (id int PRIMARY KEY, v text)");
+ 
+         execute("INSERT INTO %s (id, v) VALUES (1, 'a')");
+         execute("INSERT INTO %s (id, v) VALUES (2, 'b')");
+         execute("INSERT INTO %s (id, v) VALUES (3, 'c')");
+         flush();
+ 
+         ColumnFamilyStore cfs = getCurrentColumnFamilyStore();
+         SSTableReader sstable = cfs.getLiveSSTables().iterator().next();
+ 
+         // Mark the sstable as compacting directly in the tracker, without 
registering a
+         // CompactionInfo.Holder. There is nothing for 
interruptCompactionForCFs to stop, so
+         // runWithCompactionsDisabled falls through to waitForCessation, then 
finds the sstable
+         // still in the compacting set and returns null.
+         try (LifecycleTransaction txn = cfs.getTracker().tryModify(sstable, 
OperationType.ANTICOMPACTION))
+         {
+             assertNotNull("Unable to mark sstable compacting", txn);
+ 
+             Assertions.assertThatThrownBy(cfs::truncateBlocking)
+                       .as("Unable to stop compaction. Usually retrying 
truncate will work")
+                       .isInstanceOf(TruncateException.class);
+ 
+             assertRows(execute("SELECT * FROM %s WHERE id = 1"), row(1, "a"));
+             assertRows(execute("SELECT * FROM %s WHERE id = 2"), row(2, "b"));
+             assertRows(execute("SELECT * FROM %s WHERE id = 3"), row(3, "c"));
+             assertFalse("SSTables should still be present after truncation 
failure",
+                         cfs.getLiveSSTables().isEmpty());
+         }
+     }
+ 
+     @Test
+     public void testRebuildOnFailedScrubReturnsFalseWhenTruncateFails()
+     {
+         createTable("CREATE TABLE %s (id int PRIMARY KEY, v text)");
+         // rebuildOnFailedScrub only applies to indexes with their own 
backing table
+         createIndex("CREATE INDEX ON %s (v) USING 'legacy_local_table'");
+ 
+         execute("INSERT INTO %s (id, v) VALUES (1, 'a')");
+         flush();
+ 
+         ColumnFamilyStore baseCfs = getCurrentColumnFamilyStore();
+         ColumnFamilyStore indexCfs = 
baseCfs.indexManager.getAllIndexColumnFamilyStores().iterator().next();
+ 
+         // Register a P0-priority compaction holder for the index cfs to 
force truncateBlocking to fail.
+         CompactionInfo.Holder holder = new CompactionInfo.Holder()
+         {
+             public CompactionInfo getCompactionInfo()
+             {
+                 return new CompactionInfo(indexCfs.metadata(),
+                                           OperationType.P0,
+                                           0,
+                                           100,
+                                           100,
+                                           nextTimeUUID(),
+                                           Collections.emptySet());
+             }
+ 
+             public boolean isGlobal()
+             {
+                 return false;
+             }
+         };
+ 
+         CompactionManager.instance.active.beginCompaction(holder);
+         try
+         {
+             RuntimeException scrubFailure = new RuntimeException("original 
scrub failure");
+             // rebuildOnFailedScrub should report the rebuild as unsuccessful
+             assertFalse("rebuildOnFailedScrub should return false when it 
can't truncate the index",
+                         indexCfs.rebuildOnFailedScrub(scrubFailure));
+         }
+         finally
+         {
+             CompactionManager.instance.active.finishCompaction(holder);
+         }
+     }
+ 
+     @Test
+     public void 
testMutateSSTableRepairedStateThrowsWhenCompactionsCannotBeDisabled()
+     {
+         createTable("CREATE TABLE %s (id int PRIMARY KEY, v text)");
+ 
+         execute("INSERT INTO %s (id, v) VALUES (1, 'a')");
+         flush();
+ 
+         ColumnFamilyStore cfs = getCurrentColumnFamilyStore();
+ 
+         // Register a P0-priority compaction holder for this table to force 
runWithCompactionsDisabled
+         // to return null
+         CompactionInfo.Holder holder = new CompactionInfo.Holder()
+         {
+             public CompactionInfo getCompactionInfo()
+             {
+                 return new CompactionInfo(cfs.metadata(),
+                                           OperationType.P0,
+                                           0,
+                                           100,
+                                           100,
+                                           nextTimeUUID(),
+                                           Collections.emptySet());
+             }
+ 
+             public boolean isGlobal()
+             {
+                 return false;
+             }
+         };
+ 
+         CompactionManager.instance.active.beginCompaction(holder);
+         try
+         {
+             // mutateSSTableRepairedState should report the null 
runWithCompactionsDisabled result as a
+             // failure to the caller
+             Assertions.assertThatThrownBy(() -> 
StorageService.instance.mutateSSTableRepairedState(true, false, keyspace(), 
Collections.singletonList(currentTable())))
+                       .as("Unable to cancel in-progress compactions. Usually 
retrying will work")
+                       .isInstanceOf(RuntimeException.class);
+         }
+         finally
+         {
+             CompactionManager.instance.active.finishCompaction(holder);
+         }
+     }
 -}
++}


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

Reply via email to