Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -196,10 +196,9 @@ protected static class ColumnsCollector

public void update(RegularAndStaticColumns columns)
{
for (ColumnMetadata s : columns.statics)
update(s);
for (ColumnMetadata r : columns.regulars)
update(r);
if (!columns.statics.isEmpty())
columns.statics.apply(this::update);
columns.regulars.apply(this::update);
}

public void update(ColumnsCollector other)
Expand Down Expand Up @@ -253,6 +252,8 @@ public void update(EncodingStats newStats)
{
EncodingStats current = stats.get();
EncodingStats updated = current.mergeWith(newStats);
if (current == updated)
return;
if (stats.compareAndSet(current, updated))
return;
}
Expand Down
7 changes: 4 additions & 3 deletions src/java/org/apache/cassandra/db/rows/AbstractCell.java
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,10 @@ public Cell<?> updateAllTimesWithNewCellPathForComplexColumnData(@Nonnull CellPa
public int dataSize()
{
CellPath path = path();
return TypeSizes.sizeof(timestamp())
+ TypeSizes.sizeof(ttl())
+ TypeSizes.sizeof(localDeletionTime())
// NOTE: TypeSizes.sizeof(localDeletionTime()) - method call like this is not eliminated by JIT in case of a megamorphic call
return TypeSizes.LONG_SIZE // timestamp()
+ TypeSizes.INT_SIZE // ttl()
+ TypeSizes.LONG_SIZE // localDeletionTime()
+ valueSize()
+ (path == null ? 0 : path.dataSize());
}
Expand Down
4 changes: 2 additions & 2 deletions src/java/org/apache/cassandra/db/rows/BTreeRow.java
Original file line number Diff line number Diff line change
Expand Up @@ -525,8 +525,8 @@ public Row transform(Function<ColumnData, ColumnData> function)
@Override
public Row clone(Cloner cloner)
{
Object[] tree = BTree.<ColumnData, ColumnData>transform(btree, c -> c.clone(cloner));
return BTreeRow.create(cloner.clone(clustering), primaryKeyLivenessInfo, deletion, tree);
Object[] tree = BTree.<ColumnData, Cloner,ColumnData>transform(btree, ColumnData::clone, cloner);
return BTreeRow.create(cloner.clone(clustering), primaryKeyLivenessInfo, deletion, tree, minLocalDeletionTime);
}

public int dataSize()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ public <V> ComplexColumnData transform(Function<? super Cell<?>, ? extends Cell<
@Override
public ColumnData clone(Cloner cloner)
{
return transform(c -> cloner.clone(c));
return transform(cloner::clone);
}

public int estimateCloneSize(Cloner cloner)
Expand Down
17 changes: 17 additions & 0 deletions src/java/org/apache/cassandra/db/rows/NativeCell.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import org.apache.cassandra.db.TypeSizes;
import org.apache.cassandra.db.marshal.AddressBasedNativeData;
import org.apache.cassandra.db.marshal.ByteArrayAccessor;
import org.apache.cassandra.db.marshal.NativeAccessor;
Expand Down Expand Up @@ -198,6 +199,16 @@ public int valueSize()
return NativeEndianMemoryUtil.getInt(peer + LENGTH);
}

public int dataSize()
{
// NOTE: TypeSizes.sizeof(localDeletionTime()) - method calls like these are not eliminated by JIT in case of a megamorphic call
return TypeSizes.LONG_SIZE // timestamp()
+ TypeSizes.INT_SIZE // ttl()
+ TypeSizes.LONG_SIZE // localDeletionTime()
+ valueSize()
+ (hasPath() ? pathDataSize() : 0);
}

public CellPath path()
{
if (!hasPath())
Expand All @@ -208,6 +219,12 @@ public CellPath path()
return CellPath.create(MemoryUtil.getByteBuffer(offset + 4, size, ByteOrder.BIG_ENDIAN));
}

private int pathDataSize()
{
long offset = getAddress() + valueSize();
return NativeEndianMemoryUtil.getInt(offset);
}

public Cell<?> withUpdatedValue(ByteBuffer newValue)
{
throw new UnsupportedOperationException();
Expand Down
75 changes: 75 additions & 0 deletions src/java/org/apache/cassandra/utils/btree/BTree.java
Original file line number Diff line number Diff line change
Expand Up @@ -1273,6 +1273,7 @@ private static <I, I2, O> Object[] transformAndFilterLeaf(Object[] leaf, BiFunct
* The result of any transformation must sort identically as their originals, wrt other results.
* <p>
* If no modifications are made, the original is returned.
* NOTE: codewise *identical* to {@link #transform(Object[], BiFunction, Object)}
*/
public static <I, O> Object[] transform(Object[] tree, Function<? super I, ? extends O> function)
{
Expand Down Expand Up @@ -1316,6 +1317,55 @@ public static <I, O> Object[] transform(Object[] tree, Function<? super I, ? ext
return result;
}

/**
* Takes a tree and transforms it using the provided function.
* The result of any transformation must sort identically as their originals, wrt other results.
* <p>
* If no modifications are made, the original is returned.
* NOTE: codewise *identical* to {@link #transform(Object[], Function)}
*/
public static <I, I2, O> Object[] transform(Object[] tree, BiFunction<? super I, ? super I2, ? extends O> function, I2 param)
{
if (isEmpty(tree)) // isEmpty determined by identity; must return input
return tree;

if (isLeaf(tree)) // escape hatch for fast leaf transformation
return transformLeaf(tree, function, param);

Object[] result = tree; // optimistically assume we'll return our input unmodified
int keyCount = shallowSizeOfBranch(tree);
for (int i = 0; i < keyCount; ++i)
{
// operate on a pair of (child,key) each loop
Object[] curChild = (Object[]) tree[keyCount + i];
Object[] updChild = transform(curChild, function, param);
Object curKey = tree[i];
Object updKey = function.apply((I) curKey, param);
if (result == tree)
{
if (curChild == updChild && curKey == updKey)
continue; // if output still same as input, loop

// otherwise initialise output to a copy of input up to this point
result = transformCopyBranchHelper(tree, keyCount, i, i);
}
result[keyCount + i] = updChild;
result[i] = updKey;
}
// final unrolled copy of loop for last child only (unbalanced with keys)
Object[] curChild = (Object[]) tree[2 * keyCount];
Object[] updChild = transform(curChild, function, param);
if (result == tree)
{
if (curChild == updChild)
return tree;
result = transformCopyBranchHelper(tree, keyCount, keyCount, keyCount);
}
result[2 * keyCount] = updChild;
result[2 * keyCount + 1] = tree[2 * keyCount + 1]; // take the original sizeMap, as we are exactly the same shape
return result;
}

// create a copy of a branch, with the exact same size, copying the specified number of keys and children
private static Object[] transformCopyBranchHelper(Object[] branch, int keyCount, int copyKeyCount, int copyChildCount)
{
Expand All @@ -1326,6 +1376,7 @@ private static Object[] transformCopyBranchHelper(Object[] branch, int keyCount,
}

// an efficient transformAndFilter implementation suitable for a tree consisting of a single leaf root
// NOTE: codewise *identical* to {@link #transformLeaf(Object[], BiFunction, Object)}
private static <I, O> Object[] transformLeaf(Object[] leaf, Function<? super I, ? extends O> apply)
{
Object[] result = leaf; // optimistically assume we'll return our input unmodified
Expand All @@ -1348,6 +1399,30 @@ private static <I, O> Object[] transformLeaf(Object[] leaf, Function<? super I,
return result;
}

// an efficient transformAndFilter implementation suitable for a tree consisting of a single leaf root
// NOTE: codewise *identical* to {@link #transformLeaf(Object[], Function)}
private static <I, I2, O> Object[] transformLeaf(Object[] leaf, BiFunction<? super I, ? super I2, ? extends O> apply, I2 param)
{
Object[] result = leaf; // optimistically assume we'll return our input unmodified
int size = sizeOfLeaf(leaf);
for (int i = 0; i < size; ++i)
{
Object current = leaf[i];
Object updated = apply.apply((I) current, param);
if (result == leaf)
{
if (current == updated)
continue; // if output still same as input, loop

// otherwise initialise output to a copy of input up to this point
result = new Object[leaf.length];
System.arraycopy(leaf, 0, result, 0, i);
}
result[i] = updated;
}
return result;
}

public static boolean equals(Object[] a, Object[] b)
{
return size(a) == size(b) && Iterators.elementsEqual(iterator(a), iterator(b));
Expand Down