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

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

commit aa971bc008d00f807e6b79b6183959d383778725
Merge: d2fa1a85e9 18e1ab3701
Author: mck <[email protected]>
AuthorDate: Sun Sep 13 13:04:38 2026 +0200

    Merge branch 'cassandra-6.0' into trunk
    
    * cassandra-6.0:
      Separate memtable memory usage tracking from limit checking

 CHANGES.txt                                        |   1 +
 NEWS.txt                                           |   3 +
 conf/cassandra.yaml                                |   3 +
 .../cassandra/config/DatabaseDescriptor.java       |  43 ++++--
 .../apache/cassandra/db/CassandraWriteContext.java |  31 +++++
 .../org/apache/cassandra/db/ColumnFamilyStore.java |  18 ++-
 .../db/memtable/AbstractAllocatorMemtable.java     |  27 +++-
 .../org/apache/cassandra/db/memtable/Memtable.java |  52 +++++--
 .../db/memtable/ShardedSkipListMemtable.java       |   4 +-
 .../cassandra/db/memtable/SkipListMemtable.java    |   2 +-
 .../apache/cassandra/db/memtable/TrieMemtable.java |   4 +-
 .../db/partitions/BTreePartitionUpdater.java       |   2 +-
 .../cassandra/index/accord/RouteJournalIndex.java  |   3 +-
 .../cassandra/index/sai/StorageAttachedIndex.java  |  18 +--
 .../org/apache/cassandra/index/sasi/SASIIndex.java |   8 +-
 .../cassandra/service/accord/AccordKeyspace.java   |   2 +-
 .../apache/cassandra/utils/memory/HeapPool.java    |   8 +-
 .../cassandra/utils/memory/MemtableAllocator.java  |  72 +++++-----
 .../utils/memory/MemtableBufferAllocator.java      |   4 +-
 .../cassandra/utils/memory/MemtablePool.java       |  36 ++---
 .../cassandra/utils/memory/NativeAllocator.java    |   4 +-
 .../cassandra/utils/memory/SlabAllocator.java      |   2 +-
 .../cassandra/config/DatabaseDescriptorTest.java   |  45 ++++++
 .../apache/cassandra/db/ColumnFamilyStoreTest.java |   4 +-
 .../cassandra/db/NestedMemtableWriteTest.java      | 141 +++++++++++++++++++
 .../memory/MemtableAllocatorAwaitRoomTest.java     | 120 ++++++++++++++++
 .../utils/memory/NativeAllocatorTest.java          |  17 ++-
 .../memory/TrieMemtableShardLockDeadlockTest.java  | 153 +++++++++++++++++++++
 28 files changed, 700 insertions(+), 127 deletions(-)

diff --cc NEWS.txt
index 0032736c90,e506c9dbb1..20c2422b44
--- a/NEWS.txt
+++ b/NEWS.txt
@@@ -74,36 -74,6 +74,39 @@@ restore snapshots created with the prev
  'sstableloader' tool. You can upgrade the file format of your snapshots
  using the provided 'sstableupgrade' tool.
  
 +7.0
 +===
 +
 +New features
 +------------
 +
 +    - CEP-49 - it is possible to implement custom compression providers, e.g.
 +      integrating with a specialized hardware which makes de/compression 
faster.
 +      See CASSANDRA-20975 for more information.
 +    - It is now possible to bootstrap a cluster's initial superuser role 
without
 +      creating the 'cassandra/cassandra' password, by configuring 
'default_role_initializer'
 +      in cassandra.yaml. The new MutualTlsDefaultRoleInitializer creates the 
role
 +      passwordless and maps a client certificate identity onto it instead, for
 +      deployments that authenticate over mutual TLS. 
PasswordDefaultRoleInitializer
 +      remains the default and produces the historical behaviour. See 
CASSANDRA-21546
 +      for more information.
 +
 +Upgrading
 +---------
++    - memtable_offheap_space: 0 is now rejected at startup when 
memtable_allocation_type is 
++    offheap_buffers or offheap_objects. Set a positive 
memtable_offheap_space, or an allocation 
++    type that does not allocate off-heap. See CASSANDRA-21019.
 +
 +    - trickle_fsync is by default set to "true" instead of "false" in 
cassandra.yaml (see CASSANDRA-21572)
 +    - Authorizing a batch or an Accord transaction now performs the table 
permission checks once per run of
 +      consecutive statements on the same table rather than once per 
statement. The permissions required are
 +      unchanged, and the datacenter and CIDR checks that ride along with them 
still run at least once per
 +      request. Auth cache request/hit/miss counts and the 
system_views.cidr_filtering_metrics_* counts and
 +      latencies will therefore report fewer events than before. (see 
CASSANDRA-21606)
 +
 +Deprecation
 +-----------
 +
  
  6.0
  ===
diff --cc 
src/java/org/apache/cassandra/db/memtable/AbstractAllocatorMemtable.java
index 8e296ac604,c74096e601..7cb6f5277b
--- a/src/java/org/apache/cassandra/db/memtable/AbstractAllocatorMemtable.java
+++ b/src/java/org/apache/cassandra/db/memtable/AbstractAllocatorMemtable.java
@@@ -193,14 -212,14 +212,14 @@@ public abstract class AbstractAllocator
          stats.ownsOffHeap += getAllocator().offHeap().owns();
      }
  
--    public void markExtraOnHeapUsed(long additionalSpace, OpOrder.Group 
opGroup)
++    public void markExtraOnHeapUsed(long additionalSpace)
      {
--        getAllocator().onHeap().allocate(additionalSpace, opGroup);
++        getAllocator().onHeap().allocate(additionalSpace);
      }
  
--    public void markExtraOffHeapUsed(long additionalSpace, OpOrder.Group 
opGroup)
++    public void markExtraOffHeapUsed(long additionalSpace)
      {
--        getAllocator().offHeap().allocate(additionalSpace, opGroup);
++        getAllocator().offHeap().allocate(additionalSpace);
      }
  
      void scheduleFlush()
diff --cc src/java/org/apache/cassandra/db/memtable/Memtable.java
index e11fba165b,335648b841..76a43d0185
--- a/src/java/org/apache/cassandra/db/memtable/Memtable.java
+++ b/src/java/org/apache/cassandra/db/memtable/Memtable.java
@@@ -295,23 -325,29 +325,27 @@@ public interface Memtable extends Compa
  
      /**
       * Adjust the used on-heap space by the given size (e.g. to reflect 
memory used by a non-table-based index).
-      * This operation may block until enough memory is available in the 
memory pool.
+      * This records the usage and returns; it does not wait for room, and so 
is safe to call from an indexer
+      * running under a memtable-internal lock, which is how SAI, SASI and the 
Accord route index all reach it.
+      * The recorded total drives cleaning; the memory limit is only enforced 
once per write, in
 -     * {@link #checkSpaceAndPut} (CASSANDRA-21019).
++     * {@link #checkSpaceAndPut} (CASSANDRA-21019). It takes no OpOrder.Group 
for that reason: an
++     * implementation has nothing to wait on, so it cannot park where 
markBlocking() could not release it.
       *
       * @param additionalSpace the number of allocated bytes
-      * @param opGroup write operation group, used to permit the operation to 
complete if it is needed to complete a
-      *                flush to free space.
 -     * @param opGroup write operation group. Unused since CASSANDRA-21019, as 
this call no longer waits; kept for
 -     *                compatibility with memtable implementations built 
against this release series.
       */
--    void markExtraOnHeapUsed(long additionalSpace, OpOrder.Group opGroup);
++    void markExtraOnHeapUsed(long additionalSpace);
  
      /**
       * Adjust the used off-heap space by the given size (e.g. to reflect 
memory used by a non-table-based index).
-      * This operation may block until enough memory is available in the 
memory pool.
+      * This records the usage and returns; it does not wait for room, and so 
is safe to call from an indexer
+      * running under a memtable-internal lock, which is how SAI, SASI and the 
Accord route index all reach it.
+      * The recorded total drives cleaning; the memory limit is only enforced 
once per write, in
 -     * {@link #checkSpaceAndPut} (CASSANDRA-21019).
++     * {@link #checkSpaceAndPut} (CASSANDRA-21019). It takes no OpOrder.Group 
for that reason: an
++     * implementation has nothing to wait on, so it cannot park where 
markBlocking() could not release it.
       *
       * @param additionalSpace the number of allocated bytes
-      * @param opGroup write operation group, used to permit the operation to 
complete if it is needed to complete a
-      *                flush to free space.
 -     * @param opGroup write operation group. Unused since CASSANDRA-21019, as 
this call no longer waits; kept for
 -     *                compatibility with memtable implementations built 
against this release series.
       */
--    void markExtraOffHeapUsed(long additionalSpace, OpOrder.Group opGroup);
++    void markExtraOffHeapUsed(long additionalSpace);
  
  
      // Flushing
diff --cc src/java/org/apache/cassandra/db/memtable/ShardedSkipListMemtable.java
index fefb8eb266,68a7d1be5e..f495730dd4
--- a/src/java/org/apache/cassandra/db/memtable/ShardedSkipListMemtable.java
+++ b/src/java/org/apache/cassandra/db/memtable/ShardedSkipListMemtable.java
@@@ -394,7 -395,7 +395,7 @@@ public class ShardedSkipListMemtable ex
                      // allocate the row overhead after the fact; this saves 
over allocating and having to free after, but
                      // means we can overshoot our declared limit.
                      int overhead = (int) (cloneKey.getToken().getHeapSize() + 
SkipListMemtable.ROW_OVERHEAD_HEAP_SIZE);
--                    allocator.onHeap().allocate(overhead, opGroup);
++                    allocator.onHeap().allocate(overhead);
                      initialSize = 8;
                  }
              }
diff --cc src/java/org/apache/cassandra/db/memtable/SkipListMemtable.java
index 1389b1954b,1389b1954b..81aab3880b
--- a/src/java/org/apache/cassandra/db/memtable/SkipListMemtable.java
+++ b/src/java/org/apache/cassandra/db/memtable/SkipListMemtable.java
@@@ -132,7 -132,7 +132,7 @@@ public class SkipListMemtable extends A
                  // allocate the row overhead after the fact; this saves over 
allocating and having to free after, but
                  // means we can overshoot our declared limit.
                  int overhead = (int) (cloneKey.getToken().getHeapSize() + 
ROW_OVERHEAD_HEAP_SIZE);
--                allocator.onHeap().allocate(overhead, opGroup);
++                allocator.onHeap().allocate(overhead);
                  initialSize = 8;
              }
          }
diff --cc src/java/org/apache/cassandra/db/memtable/TrieMemtable.java
index 3eb55743fe,3eb55743fe..0522f537f6
--- a/src/java/org/apache/cassandra/db/memtable/TrieMemtable.java
+++ b/src/java/org/apache/cassandra/db/memtable/TrieMemtable.java
@@@ -580,8 -580,8 +580,8 @@@ public class TrieMemtable extends Abstr
                                        update,
                                        updater::mergePartitions,
                                        key.getKeyLength() < 
MAX_RECURSIVE_KEY_LENGTH);
--                    allocator.offHeap().adjust(data.sizeOffHeap() - offHeap, 
opGroup);
--                    allocator.onHeap().adjust(data.sizeOnHeap() - onHeap, 
opGroup);
++                    allocator.offHeap().adjust(data.sizeOffHeap() - offHeap);
++                    allocator.onHeap().adjust(data.sizeOnHeap() - onHeap);
                  }
                  finally
                  {
diff --cc src/java/org/apache/cassandra/db/partitions/BTreePartitionUpdater.java
index 9a4d6acaaa,9a4d6acaaa..f55f379b63
--- a/src/java/org/apache/cassandra/db/partitions/BTreePartitionUpdater.java
+++ b/src/java/org/apache/cassandra/db/partitions/BTreePartitionUpdater.java
@@@ -214,7 -214,7 +214,7 @@@ public class BTreePartitionUpdater impl
  
      public void reportAllocatedMemory()
      {
--        allocator.onHeap().adjust(heapSize, writeOp);
++        allocator.onHeap().adjust(heapSize);
          if (contextCloner != null && contextCloner != cloner)
              contextCloner.adjustUnused();
      }
diff --cc src/java/org/apache/cassandra/index/accord/RouteJournalIndex.java
index 2eb346ffef,2eb346ffef..5507132b56
--- a/src/java/org/apache/cassandra/index/accord/RouteJournalIndex.java
+++ b/src/java/org/apache/cassandra/index/accord/RouteJournalIndex.java
@@@ -44,7 -44,7 +44,6 @@@ import accord.primitives.TxnId
  
  import org.apache.cassandra.config.DatabaseDescriptor;
  import org.apache.cassandra.cql3.Operator;
--import org.apache.cassandra.db.CassandraWriteContext;
  import org.apache.cassandra.db.Clustering;
  import org.apache.cassandra.db.ColumnFamilyStore;
  import org.apache.cassandra.db.DecoratedKey;
@@@ -357,7 -357,7 +356,7 @@@ public class RouteJournalIndex implemen
              {
                  long size = memtableIndexManager.index(key, row, memtable);
                  if (size > 0)
--                    memtable.markExtraOnHeapUsed(size, 
CassandraWriteContext.fromContext(ctx).getGroup());
++                    memtable.markExtraOnHeapUsed(size);
              }
  
              @Override
diff --cc src/java/org/apache/cassandra/index/sai/StorageAttachedIndex.java
index 881ca81911,881ca81911..99c008b22f
--- a/src/java/org/apache/cassandra/index/sai/StorageAttachedIndex.java
+++ b/src/java/org/apache/cassandra/index/sai/StorageAttachedIndex.java
@@@ -55,7 -55,7 +55,6 @@@ import org.apache.cassandra.cql3.restri
  import org.apache.cassandra.cql3.restrictions.Restriction;
  import org.apache.cassandra.cql3.restrictions.SimpleRestriction;
  import org.apache.cassandra.cql3.statements.schema.IndexTarget;
--import org.apache.cassandra.db.CassandraWriteContext;
  import org.apache.cassandra.db.ColumnFamilyStore;
  import org.apache.cassandra.db.DecoratedKey;
  import org.apache.cassandra.db.ReadCommand;
@@@ -113,7 -113,7 +112,6 @@@ import org.apache.cassandra.utils.Pair
  import org.apache.cassandra.utils.concurrent.Future;
  import org.apache.cassandra.utils.concurrent.FutureCombiner;
  import org.apache.cassandra.utils.concurrent.ImmediateFuture;
--import org.apache.cassandra.utils.concurrent.OpOrder;
  
  import io.github.jbellis.jvector.vector.VectorSimilarityFunction;
  
@@@ -604,7 -604,7 +602,7 @@@ public class StorageAttachedIndex imple
      {
          if (transactionType == IndexTransaction.Type.UPDATE)
          {
--            return new UpdateIndexer(key, memtable, writeContext);
++            return new UpdateIndexer(key, memtable);
          }
  
          // we are only interested in the data from Memtable
@@@ -1018,34 -1018,34 +1016,30 @@@
      {
          private final DecoratedKey key;
          private final Memtable memtable;
--        private final WriteContext writeContext;
  
--        UpdateIndexer(DecoratedKey key, Memtable memtable, WriteContext 
writeContext)
++        UpdateIndexer(DecoratedKey key, Memtable memtable)
          {
              this.key = key;
              this.memtable = memtable;
--            this.writeContext = writeContext;
          }
  
          @Override
          public void insertRow(Row row)
          {
--            adjustMemtableSize(memtableIndexManager.index(key, row, memtable),
--                               
CassandraWriteContext.fromContext(writeContext).getGroup());
++            adjustMemtableSize(memtableIndexManager.index(key, row, 
memtable));
          }
  
          @Override
          public void updateRow(Row oldRow, Row newRow)
          {
--            adjustMemtableSize(memtableIndexManager.update(key, oldRow, 
newRow, memtable),
--                               
CassandraWriteContext.fromContext(writeContext).getGroup());
++            adjustMemtableSize(memtableIndexManager.update(key, oldRow, 
newRow, memtable));
          }
  
--        void adjustMemtableSize(long additionalSpace, OpOrder.Group opGroup)
++        void adjustMemtableSize(long additionalSpace)
          {
              // The memtable will assert if we try and reduce its memory usage 
so, for now, just don't tell it.
              if (additionalSpace >= 0)
--                memtable.markExtraOnHeapUsed(additionalSpace, opGroup);
++                memtable.markExtraOnHeapUsed(additionalSpace);
          }
      }
  }
diff --cc src/java/org/apache/cassandra/index/sasi/SASIIndex.java
index e4e56b542c,e4e56b542c..8840f15f57
--- a/src/java/org/apache/cassandra/index/sasi/SASIIndex.java
+++ b/src/java/org/apache/cassandra/index/sasi/SASIIndex.java
@@@ -33,7 -33,7 +33,6 @@@ import com.googlecode.concurrenttrees.c
  import org.apache.cassandra.config.DatabaseDescriptor;
  import org.apache.cassandra.cql3.Operator;
  import org.apache.cassandra.cql3.statements.schema.IndexTarget;
--import org.apache.cassandra.db.CassandraWriteContext;
  import org.apache.cassandra.db.ColumnFamilyStore;
  import org.apache.cassandra.db.DecoratedKey;
  import org.apache.cassandra.db.DeletionTime;
@@@ -80,7 -80,7 +79,6 @@@ import org.apache.cassandra.schema.Tabl
  import org.apache.cassandra.service.ClientState;
  import org.apache.cassandra.utils.FBUtilities;
  import org.apache.cassandra.utils.Pair;
--import org.apache.cassandra.utils.concurrent.OpOrder;
  
  import static java.util.concurrent.TimeUnit.MILLISECONDS;
  
@@@ -295,7 -295,7 +293,7 @@@ public class SASIIndex implements Index
              public void insertRow(Row row)
              {
                  if (isNewData())
--                    adjustMemtableSize(index.index(key, row), 
CassandraWriteContext.fromContext(context).getGroup());
++                    adjustMemtableSize(index.index(key, row));
              }
  
              public void updateRow(Row oldRow, Row newRow)
@@@ -316,9 -316,9 +314,9 @@@
                  return transactionType == IndexTransaction.Type.UPDATE;
              }
  
--            public void adjustMemtableSize(long additionalSpace, 
OpOrder.Group opGroup)
++            public void adjustMemtableSize(long additionalSpace)
              {
--                
baseCfs.getTracker().getView().getCurrentMemtable().markExtraOnHeapUsed(additionalSpace,
 opGroup);
++                
baseCfs.getTracker().getView().getCurrentMemtable().markExtraOnHeapUsed(additionalSpace);
              }
          };
      }
diff --cc src/java/org/apache/cassandra/utils/memory/HeapPool.java
index cf1307f11b,cf1307f11b..c652c5e1a5
--- a/src/java/org/apache/cassandra/utils/memory/HeapPool.java
+++ b/src/java/org/apache/cassandra/utils/memory/HeapPool.java
@@@ -69,7 -69,7 +69,7 @@@ public class HeapPool extends MemtableP
  
          public ByteBuffer allocate(int size, OpOrder.Group opGroup)
          {
--            super.onHeap().allocate(size, opGroup);
++            super.onHeap().allocate(size);
              return ByteBuffer.allocate(size);
          }
  
@@@ -105,10 -105,10 +105,10 @@@
              {
                  return new MemtableAllocator.SubAllocator(this)
                  {
--                    public void allocate(long size, OpOrder.Group opGroup)
++                    public void allocate(long size)
                      {
                          onAllocated.accept(size, table);
--                        super.allocate(size, opGroup);
++                        super.allocate(size);
                      }
                  };
              }
@@@ -133,7 -133,7 +133,7 @@@
  
              public ByteBuffer allocate(int size, OpOrder.Group opGroup)
              {
--                super.onHeap().allocate(size, opGroup);
++                super.onHeap().allocate(size);
                  return ByteBuffer.allocate(size);
              }
  
diff --cc src/java/org/apache/cassandra/utils/memory/MemtableAllocator.java
index ee83f92d64,dd80bf8e54..8bfb766e68
--- a/src/java/org/apache/cassandra/utils/memory/MemtableAllocator.java
+++ b/src/java/org/apache/cassandra/utils/memory/MemtableAllocator.java
@@@ -158,16 -165,18 +165,17 @@@ public abstract class MemtableAllocato
          /**
           * Like allocate, but permits allocations to be negative.
           */
--        public void adjust(long size, OpOrder.Group opGroup)
++        public void adjust(long size)
          {
              if (size <= 0)
                  released(-size);
              else
--                allocate(size, opGroup);
++                allocate(size);
          }
  
-         // allocate memory in the tracker, and mark ourselves as owning it
-         public void allocate(long size, OpOrder.Group opGroup)
+         // account memory in the tracker, and mark ourselves as owning it; 
this only tracks usage, which
 -        // still drives cleaning, the limit is enforced in awaitRoom() 
(CASSANDRA-21019). opGroup is unused,
 -        // kept for compatibility within this release series.
 -        public void allocate(long size, OpOrder.Group opGroup)
++        // still drives cleaning, the limit is enforced in awaitRoom() 
(CASSANDRA-21019).
++        public void allocate(long size)
          {
              assert size >= 0;
  
diff --cc 
src/java/org/apache/cassandra/utils/memory/MemtableBufferAllocator.java
index 9680da6693,9680da6693..d5f7d10b55
--- a/src/java/org/apache/cassandra/utils/memory/MemtableBufferAllocator.java
+++ b/src/java/org/apache/cassandra/utils/memory/MemtableBufferAllocator.java
@@@ -99,9 -99,9 +99,9 @@@ public abstract class MemtableBufferAll
              {
                  int remaining = contextSlab.remaining();
                  if (contextSlab.isDirect())
--                    allocator.offHeap().adjust(-remaining, opGroup);
++                    allocator.offHeap().adjust(-remaining);
                  else
--                    allocator.onHeap().adjust(-remaining, opGroup);
++                    allocator.onHeap().adjust(-remaining);
                  contextSlab.position(contextSlab.position() + remaining);
              }
          }
diff --cc src/java/org/apache/cassandra/utils/memory/NativeAllocator.java
index 531c7e1041,531c7e1041..d35101f922
--- a/src/java/org/apache/cassandra/utils/memory/NativeAllocator.java
+++ b/src/java/org/apache/cassandra/utils/memory/NativeAllocator.java
@@@ -198,7 -198,7 +198,7 @@@ public class NativeAllocator extends Me
              int remaining = limit - offset;
              if (remaining > 0)
              {
--                allocator.offHeap().adjust(-remaining, opGroup);
++                allocator.offHeap().adjust(-remaining);
                  offset += remaining;
              }
          }
@@@ -212,7 -212,7 +212,7 @@@
      public long allocate(int size, OpOrder.Group opGroup)
      {
          assert size >= 0;
--        offHeap().allocate(size, opGroup);
++        offHeap().allocate(size);
          // satisfy large allocations directly from JVM since they don't cause 
fragmentation
          // as badly, and fill up our regions quickly
          if (size > MAX_CLONED_SIZE)
diff --cc src/java/org/apache/cassandra/utils/memory/SlabAllocator.java
index 9c0b263f10,9c0b263f10..c99c766d55
--- a/src/java/org/apache/cassandra/utils/memory/SlabAllocator.java
+++ b/src/java/org/apache/cassandra/utils/memory/SlabAllocator.java
@@@ -85,7 -85,7 +85,7 @@@ public class SlabAllocator extends Memt
          if (size == 0)
              return ByteBufferUtil.EMPTY_BYTE_BUFFER;
  
--        (allocateOnHeapOnly ? onHeap() : offHeap()).allocate(size, opGroup);
++        (allocateOnHeapOnly ? onHeap() : offHeap()).allocate(size);
          // satisfy large allocations directly from JVM since they don't cause 
fragmentation
          // as badly, and fill up our regions quickly
          if (size > MAX_CLONED_SIZE)
diff --cc test/unit/org/apache/cassandra/db/ColumnFamilyStoreTest.java
index c8b636c94e,c8b636c94e..f829a2646f
--- a/test/unit/org/apache/cassandra/db/ColumnFamilyStoreTest.java
+++ b/test/unit/org/apache/cassandra/db/ColumnFamilyStoreTest.java
@@@ -868,12 -868,12 +868,12 @@@ public class ColumnFamilyStoreTes
              }
  
              @Override
--            public void markExtraOnHeapUsed(long additionalSpace, Group 
opGroup)
++            public void markExtraOnHeapUsed(long additionalSpace)
              {
              }
  
              @Override
--            public void markExtraOffHeapUsed(long additionalSpace, Group 
opGroup)
++            public void markExtraOffHeapUsed(long additionalSpace)
              {
              }
  
diff --cc 
test/unit/org/apache/cassandra/utils/memory/MemtableAllocatorAwaitRoomTest.java
index 0000000000,b4d59658f7..be40f66e9f
mode 000000,100644..100644
--- 
a/test/unit/org/apache/cassandra/utils/memory/MemtableAllocatorAwaitRoomTest.java
+++ 
b/test/unit/org/apache/cassandra/utils/memory/MemtableAllocatorAwaitRoomTest.java
@@@ -1,0 -1,122 +1,120 @@@
+ /*
+  * 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.utils.memory;
+ 
+ import java.util.concurrent.TimeUnit;
+ 
+ import org.junit.BeforeClass;
+ import org.junit.Test;
+ 
+ import org.apache.cassandra.config.DatabaseDescriptor;
+ import org.apache.cassandra.utils.concurrent.ImmediateFuture;
+ import org.apache.cassandra.utils.concurrent.OpOrder;
+ 
+ import static org.junit.Assert.assertFalse;
+ import static org.junit.Assert.assertTrue;
+ 
+ /**
+  * CASSANDRA-21019: heap_buffers / unslabbed_heap_buffers create their pool 
with an
+  * off-heap limit of 0; a zero-limit sub-pool is never allocated from and 
never
+  * signalled, so awaitRoom() must skip it, and configured limits must still 
gate.
+  * awaitRoom() is also the only place that waits: accounting an allocation 
must not.
+  */
+ public class MemtableAllocatorAwaitRoomTest
+ {
+     @BeforeClass
+     public static void setup()
+     {
+         DatabaseDescriptor.daemonInitialization();
+     }
+ 
+     @Test(timeout = 30_000)
+     public void zeroLimitPoolDoesNotBlock() throws Exception
+     {
+         SlabPool pool = new SlabPool(1 << 20, 0, 1.0f, () -> 
ImmediateFuture.success(true));
+         try
+         {
+             MemtableAllocator allocator = pool.newAllocator("test");
+             OpOrder.Group g = new OpOrder().start();
+             Thread gate = run(() -> allocator.awaitRoomToStart(g));
+             gate.join(5_000);
+             assertFalse("awaitRoomToStart hung on the unused zero-limit 
off-heap pool", gate.isAlive());
+             g.close();
+         }
+         finally
+         {
+             pool.shutdownAndWait(1, TimeUnit.MINUTES);
+         }
+     }
+ 
+     @Test(timeout = 30_000)
+     public void configuredLimitStillGates() throws Exception
+     {
+         SlabPool pool = new SlabPool(1 << 20, 1 << 20, 1.0f, () -> 
ImmediateFuture.success(true));
+         try
+         {
+             MemtableAllocator allocator = pool.newAllocator("test");
+             OpOrder.Group g = new OpOrder().start();
+             pool.onHeap.allocated(pool.onHeap.limit);
+             Thread gate = run(() -> allocator.awaitRoomToStart(g));
+             gate.join(2_000);
+             assertTrue("gate did not wait while the on-heap pool was at its 
limit", gate.isAlive());
+             pool.onHeap.released(pool.onHeap.limit);
+             gate.join(10_000);
+             assertFalse("gate did not wake after room was released", 
gate.isAlive());
+             g.close();
+         }
+         finally
+         {
+             pool.shutdownAndWait(1, TimeUnit.MINUTES);
+         }
+     }
+ 
+     /**
+      * The path Memtable.markExtraOnHeapUsed takes, and with it every 
allocation an already-started mutation
+      * makes. SAI, SASI and the Accord route index all account index memory 
from an indexer callback, under the
+      * base table's memtable-internal locks, so this path must record and 
return however far over the limit the
+      * pool is; parking here is what CASSANDRA-21019 removed.
+      */
+     @Test(timeout = 30_000)
+     public void accountingDoesNotWaitAboveTheLimit() throws Exception
+     {
+         SlabPool pool = new SlabPool(1 << 20, 1 << 20, 1.0f, () -> 
ImmediateFuture.success(true));
+         try
+         {
+             MemtableAllocator allocator = pool.newAllocator("test");
 -            OpOrder.Group g = new OpOrder().start();
+             pool.onHeap.allocated(pool.onHeap.limit);
 -            Thread mark = run(() -> allocator.onHeap().allocate(1024, g));
++            Thread mark = run(() -> allocator.onHeap().allocate(1024));
+             mark.join(5_000);
+             assertFalse("accounting waited for room while the on-heap pool 
was over its limit", mark.isAlive());
+             assertTrue("the accounting was not recorded", 
allocator.onHeap().owns() >= 1024);
 -            g.close();
+         }
+         finally
+         {
+             pool.shutdownAndWait(1, TimeUnit.MINUTES);
+         }
+     }
+ 
+     private static Thread run(Runnable r)
+     {
+         Thread t = new Thread(r, "await-room");
+         t.setDaemon(true);
+         t.start();
+         return t;
+     }
+ }
diff --cc test/unit/org/apache/cassandra/utils/memory/NativeAllocatorTest.java
index 9655e9c250,3a79c19fd4..1e87abca79
--- a/test/unit/org/apache/cassandra/utils/memory/NativeAllocatorTest.java
+++ b/test/unit/org/apache/cassandra/utils/memory/NativeAllocatorTest.java
@@@ -99,17 -99,17 +99,17 @@@ public class NativeAllocatorTes
              verifyUsedReclaiming(10, 0);
  
              // confirm adjustment works
--            allocator.offHeap().adjust(-10, group);
++            allocator.offHeap().adjust(-10);
              verifyUsedReclaiming(0, 0);
  
--            allocator.offHeap().adjust(10, group);
++            allocator.offHeap().adjust(10);
              verifyUsedReclaiming(10, 0);
  
              // confirm we cannot allocate negative
              boolean success = false;
              try
              {
--                allocator.offHeap().allocate(-10, group);
++                allocator.offHeap().allocate(-10);
              }
              catch (AssertionError e)
              {


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

Reply via email to