/**
   * Should only be called by ColumnFamilyStore.apply via Keyspace.apply, which supplies the
   * appropriate OpOrdering.
   *
   * <p>replayPosition should only be null if this is a secondary index, in which case it is
   * *expected* to be null
   */
  long put(PartitionUpdate update, UpdateTransaction indexer, OpOrder.Group opGroup) {
    AtomicBTreePartition previous = partitions.get(update.partitionKey());

    long initialSize = 0;
    if (previous == null) {
      final DecoratedKey cloneKey = allocator.clone(update.partitionKey(), opGroup);
      AtomicBTreePartition empty = new AtomicBTreePartition(cfs.metadata, cloneKey, allocator);
      // We'll add the columns later. This avoids wasting works if we get beaten in the putIfAbsent
      previous = partitions.putIfAbsent(cloneKey, empty);
      if (previous == null) {
        previous = empty;
        // 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);
        initialSize = 8;
      } else {
        allocator.reclaimer().reclaimImmediately(cloneKey);
      }
    }

    long[] pair = previous.addAllWithSizeDelta(update, opGroup, indexer);
    minTimestamp = Math.min(minTimestamp, previous.stats().minTimestamp);
    liveDataSize.addAndGet(initialSize + pair[0]);
    columnsCollector.update(update.columns());
    statsCollector.update(update.stats());
    currentOperations.addAndGet(update.operationCount());
    return pair[1];
  }
 public String toString() {
   return String.format(
       "Memtable-%s@%s(%s serialized bytes, %s ops, %.0f%%/%.0f%% of on/off-heap limit)",
       cfs.name,
       hashCode(),
       FBUtilities.prettyPrintMemory(liveDataSize.get()),
       currentOperations,
       100 * allocator.onHeap().ownershipRatio(),
       100 * allocator.offHeap().ownershipRatio());
 }
 @VisibleForTesting
 public void setDiscarding(
     OpOrder.Barrier writeBarrier, AtomicReference<ReplayPosition> lastReplayPosition) {
   assert this.writeBarrier == null;
   this.commitLogUpperBound = lastReplayPosition;
   this.writeBarrier = writeBarrier;
   allocator.setDiscarding();
 }
 private static int estimateRowOverhead(final int count) {
   // calculate row overhead
   try (final OpOrder.Group group = new OpOrder().start()) {
     int rowOverhead;
     MemtableAllocator allocator = MEMORY_POOL.newAllocator();
     ConcurrentNavigableMap<PartitionPosition, Object> partitions = new ConcurrentSkipListMap<>();
     final Object val = new Object();
     for (int i = 0; i < count; i++)
       partitions.put(
           allocator.clone(
               new BufferDecoratedKey(new LongToken(i), ByteBufferUtil.EMPTY_BYTE_BUFFER), group),
           val);
     double avgSize = ObjectSizes.measureDeep(partitions) / (double) count;
     rowOverhead =
         (int) ((avgSize - Math.floor(avgSize)) < 0.05 ? Math.floor(avgSize) : Math.ceil(avgSize));
     rowOverhead -= ObjectSizes.measureDeep(new LongToken(0));
     rowOverhead += AtomicBTreePartition.EMPTY_SIZE;
     allocator.setDiscarding();
     allocator.setDiscarded();
     return rowOverhead;
   }
 }
 public boolean isLive() {
   return allocator.isLive();
 }
 void setDiscarded() {
   allocator.setDiscarded();
 }