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

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

commit fe2893205c96ae679c1a94e2cca3255cc38f624f
Merge: 82c70e066a e8b7eac7ed
Author: Brandon Williams <[email protected]>
AuthorDate: Mon Sep 28 11:09:35 2026 -0500

    Merge branch 'cassandra-5.0' into cassandra-6.0
    
    * cassandra-5.0:
      Bound and chunk the BTI partition index preload

 CHANGES.txt                                        |  1 +
 .../config/CassandraRelevantProperties.java        |  2 +
 .../io/sstable/format/bti/PartitionIndex.java      | 78 +++++++++++++++++++---
 .../io/sstable/format/bti/PartitionIndexTest.java  | 45 +++++++++++++
 4 files changed, 115 insertions(+), 11 deletions(-)

diff --cc CHANGES.txt
index 606531247b,1cdbf799c1..875fccd0c7
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -1,54 -1,6 +1,55 @@@
 -5.0.10
 +6.0-alpha3
 + * Preserve the original exception when an in-memory local response fails to 
close (CASSANDRA-21710)
 + * Generate autocompletion scripts for the nodetool command during the build 
(CASSANDRA-20794)
 + * Implement Zstd compression level guardrail (CASSANDRA-21021)
 + * Fix Compression dictionary distribution silently leaving a node on a stale 
dictionary (CASSANDRA-21681)
 + * ZstdCompressionDictionary reference leak when opening 
dictionary-compressed SSTables concurrently (CASSANDRA-21680)
 + * Avoid ZstdDictionary to allocate a native zstd context per chunk 
(CASSANDRA-21677)
 + * Avoid ZstdDictionaryCompressor to allocate a native zstd context per chunk 
(CASSANDRA-21672)
 + * Don't replicate transformations to LEFT nodes (CASSANDRA-21652)
 + * Don't fail host specific repairs against system_cluster_metadata 
(CASSANDRA-21651)
 + * During major upgrade, if a node has replacement arguments it attempts to 
bootstrap even if already bootstrapped (CASSANDRA-21634)
 + * Node with empty data directory is allowed to rejoin the ring on the second 
start after the first start is correctly rejected (CASSANDRA-21633)
 + * Megamorphic call in ClusteringPrefix.Deserializer.deserializeOne slows 
down reads (CASSANDRA-21587)
 + * Throw InvalidRequestException instead of crashing on malformed IN marker 
values (CASSANDRA-21648)
 + * Avoid serialization and deserialization for coordinator-local single 
partition data read (CASSANDRA-21354)
 + * Allow nodetool cms reconfigure to ignore nodes via --ignore, excluding 
them from the new CMS (CASSANDRA-21627)
 + * Accord: Compute Dependencies Incrementally (CASSANDRA-21682)
 + * Avoid double chunk read for BTI small partitions during a select query 
execution (CASSANDRA-21637)
 + * Report the number of rows replica filtering protection cached when it 
warns (CASSANDRA-21623)
 + * Fix non-printable characters in Gossiper log for TOKENS (CASSANDRA-21417)
 + * Fix compression dictionary training failing with "insufficient samples" on 
large-chunk tables (CASSANDRA-21666)
 + * AccordExecutor improvements (CASSANDRA-21662)
 + * Upgrade async-profiler to 4.5 (CASSANDRA-21630)
 + * Guardrail configurations of zero are now treated as zero instead of 
unlimited (CASSANDRA-21517)
 + * Support multi-cell columns in cursor compaction (CASSANDRA-21463)
 + * Optimize authorization logic for BatchStatement and TransactionStatement 
when a single table is updated (CASSANDRA-21606)
 + * Upgrade lz4-java to 1.11.2 (CASSANDRA-21564)
 + * Encode the CQL as raw bytes to avoid utf string serialization length 
limitation (CASSANDRA-21599)
 + * Add a guardrail to disallow reconfiguring CMS below a minimum size 
(CASSANDRA-19195)
 + * Node can report DECOMMISSION_FAILED while actively leaving after a 
rejected decommission attempt (CASSANDRA-21583)
 + * Make NoSpamLogger to use Caffeine cache instead of unbounded cache that 
could lead to memory exhaustion (CASSANDRA-21474)
 + * Reduce overheads of isOrdinaryUser check performed by Guardrail.enabled 
(CASSANDRA-21589)
 + * MultiStepOperations should not encode range movements using endpoints 
(CASSANDRA-21582)
 + * Avoid "During operation execution,... at ONE the ring has changed from 
epoch1 to epoch2 error" with counter writes (CASSANDRA-21585)
 + * Reject LIKE patterns with a wildcard (%) anywhere other than the start or 
end (CASSANDRA-21068)
 + * Stabilize cursor-based compaction (CASSANDRA-21462)
 + * Stop using Java streams in CIDRPermissions.SubsetPermissions#canAccessFrom 
hot method (CASSANDRA-21588)
 + * Enable trickle fsync by default (CASSANDRA-21572)
 + * Protect uncaught_exceptions virtual table against the crash path 
(CASSANDRA-21578)
 + * Optimize ServerConnection.requests for both reads and writes 
(CASSANDRA-21569)
 + * Ensure transferred_ranges reset on decommision re-attempt when pending 
ranges cannot be proven continous (CASSANDRA-16290)
 + * Add blob type support to SAI (CASSANDRA-20012)
 + * Fix deserialization of column masks in cluster metadata (CASSANDRA-21549)
 + * Caffeine caches in CompressionDictionaryCache and ZstdDictionaryCompressor 
should specify an executor explicitly (CASSANDRA-21557)
 + * Make cqlsh prompt to reset to no keyspace set by USE after dropping that 
keyspace (CASSANDRA-21548)
 + * Implement CMS rediscovery and recovery protocol (CASSANDRA-20476)
 + * Apply performance optimizations for rows merging logic (CASSANDRA-21524)
 + * Fix operationMode reporting DECOMMISSION_FAILED instead of LEAVING when 
resuming a failed decommission (CASSANDRA-21493)
 + * Avoid megamorphic calls when serializing and deserializing fixed-length 
values (CASSANDRA-21536)
 + * Avoid megamorphic calls for 
Cell.timestamp/ttl/path/localDeletionTimeAsUnsignedInt methods (CASSANDRA-21526)
 +Merged from 5.0:
+  * Bound and chunk the BTI partition index preload (CASSANDRA-21632)
 - * Restore volatile on CommitLogSegment.cdcState dropped in merge 
(CASSANDRA-21665)
   * Fix compressed scan read-ahead buffer Block leak and chunk-cache pollution 
by scans (CASSANDRA-21671)
   * A read on a replica that does not know the index yet fails with a 
NullPointerException (CASSANDRA-21658)
   * Release hints write buffer when the write executor shuts down 
(CASSANDRA-21657)
diff --cc src/java/org/apache/cassandra/config/CassandraRelevantProperties.java
index bdb07ed68b,1a9e2dfa43..510cae8fb3
--- a/src/java/org/apache/cassandra/config/CassandraRelevantProperties.java
+++ b/src/java/org/apache/cassandra/config/CassandraRelevantProperties.java
@@@ -90,9 -74,10 +90,11 @@@ public enum CassandraRelevantPropertie
       */
      BOOTSTRAP_SKIP_SCHEMA_CHECK("cassandra.skip_schema_check"),
      BROADCAST_INTERVAL_MS("cassandra.broadcast_interval_ms", "60000"),
+     /** Caps how much of a BTI partition index is preloaded, e.g. "16MiB". 0B 
disables preloading; negative (default) preloads it all. */
+     
BTI_PARTITION_INDEX_PRELOAD_SIZE("cassandra.bti.partition_index_preload_size", 
"-1B"),
      BTREE_BRANCH_SHIFT("cassandra.btree.branchshift", "5"),
      BTREE_FAN_FACTOR("cassandra.btree.fanfactor"),
 +    BUILD_DATE("cassandra.buildDate"),
      /** Represents the maximum size (in bytes) of a serialized mutation that 
can be cached **/
      
CACHEABLE_MUTATION_SIZE_LIMIT("cassandra.cacheable_mutation_size_limit_bytes", 
convertToString(1_000_000)),
      CASSANDRA_ALLOW_SIMPLE_STRATEGY("cassandra.allow_simplestrategy"),
diff --cc 
src/java/org/apache/cassandra/io/sstable/format/bti/PartitionIndex.java
index 4c6ac0f28e,a082547607..456fbd9ba5
--- a/src/java/org/apache/cassandra/io/sstable/format/bti/PartitionIndex.java
+++ b/src/java/org/apache/cassandra/io/sstable/format/bti/PartitionIndex.java
@@@ -46,6 -47,6 +48,7 @@@ import org.apache.cassandra.utils.Pair
  import org.apache.cassandra.utils.bytecomparable.ByteSource;
  import org.apache.cassandra.utils.concurrent.Ref;
  import org.apache.cassandra.utils.concurrent.SharedCloseable;
++import org.apache.cassandra.utils.memory.MemoryUtil;
  
  /**
   * This class holds the partition index as an on-disk trie mapping unique 
prefixes of decorated keys to:
@@@ -212,6 -211,61 +213,61 @@@ public class PartitionIndex implements 
          }
      }
  
+     /**
+      * Warms the partition index so trie lookups don't each fault it in.
+      *
+      * Chunked positioned reads on the channel, not one byte per page through 
a {@link FileDataInput},
+      * which follows {@code disk_access_mode} and so costs a pread or a page 
fault per page. A
+      * positioned read is unaffected by access mode, and page cache is shared 
between the buffered and
+      * mapped views of a file, so a mapped lookup afterwards still finds the 
data resident.
+      *
+      * When bounded, warms the trie's tail, since the trie is written 
bottom-up and every lookup
+      * traverses the upper levels that end up there. The bound is relative to 
{@code firstPos} (the
+      * trie's end), not the file's end, since the file tail past it isn't 
trie data.
+      *
+      * @param firstPos offset where the trie ends and the first/last key data 
begins
+      * @return the number of bytes read
+      * @see CassandraRelevantProperties#BTI_PARTITION_INDEX_PRELOAD_SIZE
+      */
+     @VisibleForTesting
+     static long warmIndex(FileHandle fh, long firstPos) throws EOFException
+     {
+         long limit = 
CassandraRelevantProperties.BTI_PARTITION_INDEX_PRELOAD_SIZE.getSizeInBytes();
+         if (limit == 0)
+         {
+             logger.trace("Partition index warming is disabled, not warming 
{}", fh.path());
+             return 0;
+         }
+ 
+         if (firstPos <= 0)
+             return 0;
+ 
+         long start = limit > 0 && limit < firstPos ? firstPos - limit : 0;
+ 
+         ByteBuffer buffer = ByteBuffer.allocateDirect((int) 
Math.min(PRELOAD_CHUNK_SIZE, firstPos - start));
+         try
+         {
+             long pos = start;
+             while (pos < firstPos)
+             {
+                 buffer.clear();
+                 buffer.limit((int) Math.min(buffer.capacity(), firstPos - 
pos));
+ 
+                 // ChannelProxy.read may return a short read; advance by what 
was actually read.
+                 int read = fh.channel.read(buffer, pos);
+                 if (read < 0)
+                     throw new EOFException("Failed to read " + fh.path() + " 
at position " + pos);
+ 
+                 pos += read;
+             }
+             return pos - start;
+         }
+         finally
+         {
 -            FileUtils.clean(buffer);
++            MemoryUtil.clean(buffer);
+         }
+     }
+ 
      @Override
      public void close()
      {


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

Reply via email to