Merge branch 'cassandra-2.1' into trunk

Conflicts:
	src/java/org/apache/cassandra/cql/QueryProcessor.java
This commit is contained in:
Sylvain Lebresne 2014-04-29 14:07:34 +02:00
commit 7d7610fdb3
184 changed files with 4087 additions and 1687 deletions

View File

@ -283,6 +283,7 @@ memtable_cleanup_threshold: 0.4
# Options are:
# heap_buffers: on heap nio buffers
# offheap_buffers: off heap (direct) nio buffers
# offheap_objects: native memory, eliminating nio buffer heap overhead
memtable_allocation_type: heap_buffers
# Total space to use for commitlogs. Since commitlog segments are

View File

@ -37,7 +37,7 @@ public class RowCacheKey implements CacheKey, Comparable<RowCacheKey>
public RowCacheKey(UUID cfId, DecoratedKey key)
{
this(cfId, key.key);
this(cfId, key.getKey());
}
public RowCacheKey(UUID cfId, ByteBuffer key)

View File

@ -55,6 +55,7 @@ import org.apache.cassandra.cql3.QueryProcessor;
import org.apache.cassandra.cql3.UntypedResultSet;
import org.apache.cassandra.cql3.statements.CFStatement;
import org.apache.cassandra.cql3.statements.CreateTableStatement;
import org.apache.cassandra.db.AbstractCell;
import org.apache.cassandra.db.AtomDeserializer;
import org.apache.cassandra.db.CFRowAdder;
import org.apache.cassandra.db.Cell;
@ -1317,7 +1318,7 @@ public final class CFMetaData
*/
public ColumnDefinition getColumnDefinition(CellName cellName)
{
ColumnIdentifier id = cellName.cql3ColumnName();
ColumnIdentifier id = cellName.cql3ColumnName(this);
ColumnDefinition def = id == null
? getColumnDefinition(cellName.toByteBuffer()) // Means a dense layout, try the full column name
: getColumnDefinition(id);
@ -1398,7 +1399,7 @@ public final class CFMetaData
public Iterator<OnDiskAtom> getOnDiskIterator(DataInput in, ColumnSerializer.Flag flag, int expireBefore, Descriptor.Version version)
{
return Cell.onDiskIterator(in, flag, expireBefore, version, comparator);
return AbstractCell.onDiskIterator(in, flag, expireBefore, version, comparator);
}
public AtomDeserializer getOnDiskDeserializer(DataInput in, Descriptor.Version version)

View File

@ -290,7 +290,8 @@ public class Config
{
unslabbed_heap_buffers,
heap_buffers,
offheap_buffers
offheap_buffers,
offheap_objects
}
public static enum DiskFailurePolicy

View File

@ -66,7 +66,8 @@ import org.apache.cassandra.service.CacheService;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.memory.HeapPool;
import org.apache.cassandra.utils.memory.Pool;
import org.apache.cassandra.utils.memory.NativePool;
import org.apache.cassandra.utils.memory.MemtablePool;
import org.apache.cassandra.utils.memory.SlabPool;
public class DatabaseDescriptor
@ -1487,7 +1488,7 @@ public class DatabaseDescriptor
return conf.inter_dc_tcp_nodelay;
}
public static Pool getMemtableAllocatorPool()
public static MemtablePool getMemtableAllocatorPool()
{
long heapLimit = ((long) conf.memtable_heap_space_in_mb) << 20;
long offHeapLimit = ((long) conf.memtable_offheap_space_in_mb) << 20;
@ -1504,6 +1505,8 @@ public class DatabaseDescriptor
System.exit(-1);
}
return new SlabPool(heapLimit, offHeapLimit, conf.memtable_cleanup_threshold, new ColumnFamilyStore.FlushLargestColumnFamily());
case offheap_objects:
return new NativePool(heapLimit, offHeapLimit, conf.memtable_cleanup_threshold, new ColumnFamilyStore.FlushLargestColumnFamily());
default:
throw new AssertionError();
}

View File

@ -416,7 +416,7 @@ public class Schema
{
try
{
return systemKeyspaceNames.contains(ByteBufferUtil.string(row.key.key));
return systemKeyspaceNames.contains(ByteBufferUtil.string(row.key.getKey()));
}
catch (CharacterCodingException e)
{

View File

@ -50,7 +50,7 @@ public class ColumnIdentifier implements Selectable, IMeasurableMemory
this.text = type.getString(bytes);
}
private ColumnIdentifier(ByteBuffer bytes, String text)
public ColumnIdentifier(ByteBuffer bytes, String text)
{
this.bytes = bytes;
this.text = text;

View File

@ -55,13 +55,13 @@ public class UpdateParameters
public Cell makeColumn(CellName name, ByteBuffer value) throws InvalidRequestException
{
QueryProcessor.validateCellName(name, metadata.comparator);
return Cell.create(name, value, timestamp, ttl, metadata);
return AbstractCell.create(name, value, timestamp, ttl, metadata);
}
public Cell makeTombstone(CellName name) throws InvalidRequestException
{
QueryProcessor.validateCellName(name, metadata.comparator);
return new DeletedCell(name, localDeletionTime, timestamp);
return new BufferDeletedCell(name, localDeletionTime, timestamp);
}
public RangeTombstone makeRangeTombstone(ColumnSlice slice) throws InvalidRequestException

View File

@ -32,12 +32,9 @@ import org.apache.cassandra.db.*;
import org.apache.cassandra.db.composites.CBuilder;
import org.apache.cassandra.db.composites.Composite;
import org.apache.cassandra.db.filter.ColumnSlice;
import org.apache.cassandra.db.filter.IDiskAtomFilter;
import org.apache.cassandra.db.filter.SliceQueryFilter;
import org.apache.cassandra.db.marshal.ListType;
import org.apache.cassandra.db.marshal.BooleanType;
import org.apache.cassandra.exceptions.*;
import org.apache.cassandra.service.CASConditions;
import org.apache.cassandra.service.ClientState;
import org.apache.cassandra.service.QueryState;
import org.apache.cassandra.service.StorageProxy;
@ -449,10 +446,10 @@ public abstract class ModificationStatement implements CQLStatement, MeasurableF
if (row.cf == null || row.cf.isEmpty())
continue;
Iterator<CQL3Row> iter = cfm.comparator.CQL3RowBuilder(now).group(row.cf.getSortedColumns().iterator());
Iterator<CQL3Row> iter = cfm.comparator.CQL3RowBuilder(cfm, now).group(row.cf.getSortedColumns().iterator());
if (iter.hasNext())
{
map.put(row.key.key, iter.next());
map.put(row.key.getKey(), iter.next());
// We can only update one CQ3Row per partition key at a time (we don't allow IN for clustering key)
assert !iter.hasNext();
}

View File

@ -400,8 +400,8 @@ public class SelectStatement implements CQLStatement, MeasurableForPreparedCache
ByteBuffer startKeyBytes = getKeyBound(Bound.START, variables);
ByteBuffer finishKeyBytes = getKeyBound(Bound.END, variables);
RowPosition startKey = RowPosition.forKey(startKeyBytes, p);
RowPosition finishKey = RowPosition.forKey(finishKeyBytes, p);
RowPosition startKey = RowPosition.ForKey.get(startKeyBytes, p);
RowPosition finishKey = RowPosition.ForKey.get(finishKeyBytes, p);
if (startKey.compareTo(finishKey) > 0 && !finishKey.isMinimum(p))
return null;
@ -1007,7 +1007,7 @@ public class SelectStatement implements CQLStatement, MeasurableForPreparedCache
if (row.cf == null)
continue;
processColumnFamily(row.key.key, row.cf, variables, now, result);
processColumnFamily(row.key.getKey(), row.cf, variables, now, result);
}
ResultSet cqlRows = result.build();
@ -1042,7 +1042,7 @@ public class SelectStatement implements CQLStatement, MeasurableForPreparedCache
if (sliceRestriction != null)
cells = applySliceRestriction(cells, variables);
CQL3Row.RowIterator iter = cfm.comparator.CQL3RowBuilder(now).group(cells);
CQL3Row.RowIterator iter = cfm.comparator.CQL3RowBuilder(cfm, now).group(cells);
// If there is static columns but there is no non-static row, then provided the select was a full
// partition selection (i.e. not a 2ndary index search and there was no condition on clustering columns)

View File

@ -0,0 +1,265 @@
/**
* 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.io.DataInput;
import java.io.IOError;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.util.Iterator;
import com.google.common.collect.AbstractIterator;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.composites.CellName;
import org.apache.cassandra.db.composites.CellNameType;
import org.apache.cassandra.db.context.CounterContext;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.io.sstable.Descriptor;
import org.apache.cassandra.serializers.MarshalException;
import org.apache.cassandra.utils.FBUtilities;
public abstract class AbstractCell implements Cell
{
public static Iterator<OnDiskAtom> onDiskIterator(final DataInput in,
final ColumnSerializer.Flag flag,
final int expireBefore,
final Descriptor.Version version,
final CellNameType type)
{
return new AbstractIterator<OnDiskAtom>()
{
protected OnDiskAtom computeNext()
{
OnDiskAtom atom;
try
{
atom = type.onDiskAtomSerializer().deserializeFromSSTable(in, flag, expireBefore, version);
}
catch (IOException e)
{
throw new IOError(e);
}
if (atom == null)
return endOfData();
return atom;
}
};
}
@Override
public boolean isMarkedForDelete(long now)
{
return false;
}
@Override
public boolean isLive(long now)
{
return !isMarkedForDelete(now);
}
// Don't call unless the column is actually marked for delete.
@Override
public long getMarkedForDeleteAt()
{
return Long.MAX_VALUE;
}
@Override
public int cellDataSize()
{
return name().dataSize() + value().remaining() + TypeSizes.NATIVE.sizeof(timestamp());
}
@Override
public int serializedSize(CellNameType type, TypeSizes typeSizes)
{
/*
* Size of a column is =
* size of a name (short + length of the string)
* + 1 byte to indicate if the column has been deleted
* + 8 bytes for timestamp
* + 4 bytes which basically indicates the size of the byte array
* + entire byte array.
*/
int valueSize = value().remaining();
return ((int)type.cellSerializer().serializedSize(name(), typeSizes)) + 1 + typeSizes.sizeof(timestamp()) + typeSizes.sizeof(valueSize) + valueSize;
}
@Override
public int serializationFlags()
{
return 0;
}
@Override
public Cell diff(Cell cell)
{
if (timestamp() < cell.timestamp())
return cell;
return null;
}
@Override
public void updateDigest(MessageDigest digest)
{
digest.update(name().toByteBuffer().duplicate());
digest.update(value().duplicate());
FBUtilities.updateWithLong(digest, timestamp());
FBUtilities.updateWithByte(digest, serializationFlags());
}
@Override
public int getLocalDeletionTime()
{
return Integer.MAX_VALUE;
}
@Override
public Cell reconcile(Cell cell)
{
// tombstones take precedence. (if both are tombstones, then it doesn't matter which one we use.)
if (isMarkedForDelete(System.currentTimeMillis()))
return timestamp() < cell.timestamp() ? cell : this;
if (cell.isMarkedForDelete(System.currentTimeMillis()))
return timestamp() > cell.timestamp() ? this : cell;
// break ties by comparing values.
if (timestamp() == cell.timestamp())
return value().compareTo(cell.value()) < 0 ? cell : this;
// neither is tombstoned and timestamps are different
return timestamp() < cell.timestamp() ? cell : this;
}
@Override
public boolean equals(Object o)
{
return this == o || (o instanceof Cell && equals((Cell) o));
}
public boolean equals(Cell cell)
{
return timestamp() == cell.timestamp() && name().equals(cell.name()) && value().equals(cell.value());
}
public int hashCode()
{
throw new UnsupportedOperationException();
}
@Override
public String getString(CellNameType comparator)
{
return String.format("%s:%b:%d@%d",
comparator.getString(name()),
isMarkedForDelete(System.currentTimeMillis()),
value().remaining(),
timestamp());
}
@Override
public void validateName(CFMetaData metadata) throws MarshalException
{
metadata.comparator.validate(name());
}
@Override
public void validateFields(CFMetaData metadata) throws MarshalException
{
validateName(metadata);
AbstractType<?> valueValidator = metadata.getValueValidator(name());
if (valueValidator != null)
valueValidator.validate(value());
}
public static Cell create(CellName name, ByteBuffer value, long timestamp, int ttl, CFMetaData metadata)
{
if (ttl <= 0)
ttl = metadata.getDefaultTimeToLive();
return ttl > 0
? new BufferExpiringCell(name, value, timestamp, ttl)
: new BufferCell(name, value, timestamp);
}
public static Cell diff(CounterCell a, Cell b)
{
if (a.timestamp() < b.timestamp())
return b;
// Note that if at that point, cell can't be a tombstone. Indeed,
// cell is the result of merging us with other nodes results, and
// merging a CounterCell with a tombstone never return a tombstone
// unless that tombstone timestamp is greater that the CounterCell
// one.
assert b instanceof CounterCell : "Wrong class type: " + b.getClass();
if (a.timestampOfLastDelete() < ((CounterCell) b).timestampOfLastDelete())
return b;
CounterContext.Relationship rel = CounterCell.contextManager.diff(b.value(), a.value());
return (rel == CounterContext.Relationship.GREATER_THAN || rel == CounterContext.Relationship.DISJOINT) ? b : null;
}
/** This is temporary until we start creating Cells of the different type (buffer vs. native) */
public static Cell reconcile(CounterCell a, Cell b)
{
assert (b instanceof CounterCell) || (b instanceof DeletedCell) : "Wrong class type: " + b.getClass();
// live + tombstone: track last tombstone
if (b.isMarkedForDelete(Long.MIN_VALUE)) // cannot be an expired cell, so the current time is irrelevant
{
// live < tombstone
if (a.timestamp() < b.timestamp())
return b;
// live last delete >= tombstone
if (a.timestampOfLastDelete() >= b.timestamp())
return a;
// live last delete < tombstone
return new BufferCounterCell(a.name(), a.value(), a.timestamp(), b.timestamp());
}
assert b instanceof CounterCell : "Wrong class type: " + b.getClass();
// live < live last delete
if (a.timestamp() < ((CounterCell) b).timestampOfLastDelete())
return b;
// live last delete > live
if (a.timestampOfLastDelete() > b.timestamp())
return a;
// live + live. return one of the cells if its context is a superset of the other's, or merge them otherwise
ByteBuffer context = CounterCell.contextManager.merge(a.value(), b.value());
if (context == a.value() && a.timestamp() >= b.timestamp() && a.timestampOfLastDelete() >= ((CounterCell) b).timestampOfLastDelete())
return a;
else if (context == b.value() && b.timestamp() >= a.timestamp() && ((CounterCell) b).timestampOfLastDelete() >= a.timestampOfLastDelete())
return b;
else // merge clocks and timsestamps.
return new BufferCounterCell(a.name(),
context,
Math.max(a.timestamp(), b.timestamp()),
Math.max(a.timestampOfLastDelete(), ((CounterCell) b).timestampOfLastDelete()));
}
}

View File

@ -0,0 +1,647 @@
/*
* 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.nio.ByteBuffer;
import java.security.MessageDigest;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.config.ColumnDefinition;
import org.apache.cassandra.cql3.ColumnIdentifier;
import org.apache.cassandra.db.composites.*;
import org.apache.cassandra.db.filter.ColumnSlice;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.CompositeType;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.concurrent.OpOrder;
import org.apache.cassandra.utils.memory.*;
/**
* Packs a CellName AND a Cell into one off-heap representation.
* Layout is:
*
* Note we store the ColumnIdentifier in full as bytes. This seems an okay tradeoff for now, as we just
* look it back up again when we need to, and in the near future we hope to switch to ints, longs or
* UUIDs representing column identifiers on disk, at which point we can switch that here as well.
*
* [timestamp][value offset][name size]][name extra][name offset deltas][cell names][value][Descendants]
* [ 8b ][ 4b ][ 2b ][ 1b ][ each 2b ][ arb < 64k][ arb ][ arbitrary ]
*
* descendants: any overriding classes will put their state here
* name offsets are deltas from their base offset, and don't include the first offset, or the end position of the final entry,
* i.e. there will be size - 1 entries, and each is a delta that is added to the offset of the position of the first name
* (which is always CELL_NAME_OFFSETS_OFFSET + (2 * (size - 1))). The length of the final name fills up any remaining
* space upto the value offset
* name extra: lowest 2 bits indicate the clustering size delta (i.e. how many name items are NOT part of the clustering key)
* the next 2 bits indicate the CellNameType
* the next bit indicates if the column is a static or clustered/dynamic column
*/
public abstract class AbstractNativeCell extends AbstractCell implements CellName
{
static final int TIMESTAMP_OFFSET = 4;
private static final int VALUE_OFFSET_OFFSET = 12;
private static final int CELL_NAME_SIZE_OFFSET = 16;
private static final int CELL_NAME_EXTRA_OFFSET = 18;
private static final int CELL_NAME_OFFSETS_OFFSET = 19;
private static final int CELL_NAME_SIZE_DELTA_MASK = 3;
private static final int CELL_NAME_TYPE_SHIFT = 2;
private static final int CELL_NAME_TYPE_MASK = 7;
private static enum NameType
{
COMPOUND_DENSE(0 << 2), COMPOUND_SPARSE(1 << 2), COMPOUND_SPARSE_STATIC(2 << 2), SIMPLE_DENSE(3 << 2), SIMPLE_SPARSE(4 << 2);
static final NameType[] TYPES = NameType.values();
final int bits;
NameType(int bits)
{
this.bits = bits;
}
static NameType typeOf(CellName name)
{
if (name instanceof CompoundDenseCellName)
{
assert !name.isStatic();
return COMPOUND_DENSE;
}
if (name instanceof CompoundSparseCellName)
return name.isStatic() ? COMPOUND_SPARSE_STATIC : COMPOUND_SPARSE;
if (name instanceof SimpleDenseCellName)
{
assert !name.isStatic();
return SIMPLE_DENSE;
}
if (name instanceof SimpleSparseCellName)
{
assert !name.isStatic();
return SIMPLE_SPARSE;
}
if (name instanceof NativeCell)
return ((NativeCell) name).nametype();
throw new AssertionError();
}
}
private final long peer; // peer is assigned by peer updater in setPeer method
AbstractNativeCell()
{
peer = -1;
}
public AbstractNativeCell(NativeAllocator allocator, OpOrder.Group writeOp, Cell copyOf)
{
int size = sizeOf(copyOf);
peer = allocator.allocate(size, writeOp);
MemoryUtil.setInt(peer, size);
construct(copyOf);
}
protected int sizeOf(Cell cell)
{
int size = CELL_NAME_OFFSETS_OFFSET + Math.max(0, cell.name().size() - 1) * 2 + cell.value().remaining();
CellName name = cell.name();
for (int i = 0; i < name.size(); i++)
size += name.get(i).remaining();
return size;
}
protected void construct(Cell from)
{
setLong(TIMESTAMP_OFFSET, from.timestamp());
CellName name = from.name();
int nameSize = name.size();
int offset = CELL_NAME_SIZE_OFFSET;
setShort(offset, (short) nameSize);
assert nameSize - name.clusteringSize() <= 2;
byte cellNameExtraBits = (byte) ((nameSize - name.clusteringSize()) | NameType.typeOf(name).bits);
setByte(offset += 2, cellNameExtraBits);
offset += 1;
short cellNameDelta = 0;
for (int i = 1; i < nameSize; i++)
{
cellNameDelta += name.get(i - 1).remaining();
setShort(offset, cellNameDelta);
offset += 2;
}
for (int i = 0; i < nameSize; i++)
{
ByteBuffer bb = name.get(i);
setBytes(offset, bb);
offset += bb.remaining();
}
setInt(VALUE_OFFSET_OFFSET, offset);
setBytes(offset, from.value());
}
// the offset at which to read the short that gives the names
private int nameDeltaOffset(int i)
{
return CELL_NAME_OFFSETS_OFFSET + ((i - 1) * 2);
}
int valueStartOffset()
{
return getInt(VALUE_OFFSET_OFFSET);
}
private int valueEndOffset()
{
return (int) (internalSize() - postfixSize());
}
protected int postfixSize()
{
return 0;
}
@Override
public ByteBuffer value()
{
long offset = valueStartOffset();
return getByteBuffer(offset, (int) (internalSize() - (postfixSize() + offset)));
}
private int clusteringSizeDelta()
{
return getByte(CELL_NAME_EXTRA_OFFSET) & CELL_NAME_SIZE_DELTA_MASK;
}
public boolean isStatic()
{
return nametype() == NameType.COMPOUND_SPARSE_STATIC;
}
NameType nametype()
{
return NameType.TYPES[(((int) this.getByte(CELL_NAME_EXTRA_OFFSET)) >> CELL_NAME_TYPE_SHIFT) & CELL_NAME_TYPE_MASK];
}
public long minTimestamp()
{
return timestamp();
}
public long maxTimestamp()
{
return timestamp();
}
public int clusteringSize()
{
return size() - clusteringSizeDelta();
}
@Override
public ColumnIdentifier cql3ColumnName(CFMetaData metadata)
{
switch (nametype())
{
case SIMPLE_SPARSE:
return getIdentifier(metadata, get(clusteringSize()));
case COMPOUND_SPARSE_STATIC:
case COMPOUND_SPARSE:
ByteBuffer buffer = get(clusteringSize());
if (buffer.remaining() == 0)
return CompoundSparseCellNameType.rowMarkerId;
return getIdentifier(metadata, buffer);
case SIMPLE_DENSE:
case COMPOUND_DENSE:
return null;
default:
throw new AssertionError();
}
}
public ByteBuffer collectionElement()
{
return isCollectionCell() ? get(size() - 1) : null;
}
// we always have a collection element if our clustering size is 2 less than our total size,
// and we never have one otherwiss
public boolean isCollectionCell()
{
return clusteringSizeDelta() == 2;
}
public boolean isSameCQL3RowAs(CellNameType type, CellName other)
{
switch (nametype())
{
case SIMPLE_DENSE:
case COMPOUND_DENSE:
return type.compare(this, other) == 0;
case COMPOUND_SPARSE_STATIC:
case COMPOUND_SPARSE:
int clusteringSize = clusteringSize();
if (clusteringSize != other.clusteringSize() || other.isStatic() != isStatic())
return false;
for (int i = 0; i < clusteringSize; i++)
if (type.subtype(i).compare(get(i), other.get(i)) != 0)
return false;
return true;
case SIMPLE_SPARSE:
return true;
default:
throw new AssertionError();
}
}
public int size()
{
return getShort(CELL_NAME_SIZE_OFFSET);
}
public boolean isEmpty()
{
return size() == 0;
}
public ByteBuffer get(int i)
{
// remember to take dense/sparse into account, and only return EOC when not dense
int size = size();
assert i >= 0 && i < size();
int cellNamesOffset = nameDeltaOffset(size);
int startDelta = i == 0 ? 0 : getShort(nameDeltaOffset(i));
int endDelta = i < size - 1 ? getShort(nameDeltaOffset(i + 1)) : valueStartOffset() - cellNamesOffset;
return getByteBuffer(cellNamesOffset + startDelta, endDelta - startDelta);
}
private static final ThreadLocal<byte[]> BUFFER = new ThreadLocal<byte[]>()
{
protected byte[] initialValue()
{
return new byte[256];
}
};
protected void writeComponentTo(MessageDigest digest, int i, boolean includeSize)
{
// remember to take dense/sparse into account, and only return EOC when not dense
int size = size();
assert i >= 0 && i < size();
int cellNamesOffset = nameDeltaOffset(size);
int startDelta = i == 0 ? 0 : getShort(nameDeltaOffset(i));
int endDelta = i < size - 1 ? getShort(nameDeltaOffset(i + 1)) : valueStartOffset() - cellNamesOffset;
int componentStart = cellNamesOffset + startDelta;
int count = endDelta - startDelta;
if (includeSize)
FBUtilities.updateWithShort(digest, count);
writeMemoryTo(digest, componentStart, count);
}
protected void writeMemoryTo(MessageDigest digest, int from, int count)
{
// only batch if we have more than 16 bytes remaining to transfer, otherwise fall-back to single-byte updates
int i = 0, batchEnd = count - 16;
if (i < batchEnd)
{
byte[] buffer = BUFFER.get();
while (i < batchEnd)
{
int transfer = Math.min(count - i, 256);
getBytes(from + i, buffer, 0, transfer);
digest.update(buffer, 0, transfer);
i += transfer;
}
}
while (i < count)
digest.update(getByte(from + i++));
}
public EOC eoc()
{
return EOC.NONE;
}
public Composite withEOC(EOC eoc)
{
throw new UnsupportedOperationException();
}
public Composite start()
{
throw new UnsupportedOperationException();
}
public Composite end()
{
throw new UnsupportedOperationException();
}
public ColumnSlice slice()
{
throw new UnsupportedOperationException();
}
public boolean isPrefixOf(CType type, Composite c)
{
if (size() > c.size() || isStatic() != c.isStatic())
return false;
for (int i = 0; i < size(); i++)
{
if (type.subtype(i).compare(get(i), c.get(i)) != 0)
return false;
}
return true;
}
public ByteBuffer toByteBuffer()
{
// for simple sparse we just return our one name buffer
switch (nametype())
{
case SIMPLE_DENSE:
case SIMPLE_SPARSE:
return get(0);
case COMPOUND_DENSE:
case COMPOUND_SPARSE_STATIC:
case COMPOUND_SPARSE:
// This is the legacy format of composites.
// See org.apache.cassandra.db.marshal.CompositeType for details.
ByteBuffer result = ByteBuffer.allocate(cellDataSize());
if (isStatic())
ByteBufferUtil.writeShortLength(result, CompositeType.STATIC_MARKER);
for (int i = 0; i < size(); i++)
{
ByteBuffer bb = get(i);
ByteBufferUtil.writeShortLength(result, bb.remaining());
result.put(bb);
result.put((byte) 0);
}
result.flip();
return result;
default:
throw new AssertionError();
}
}
protected void updateWithName(MessageDigest digest)
{
// for simple sparse we just return our one name buffer
switch (nametype())
{
case SIMPLE_DENSE:
case SIMPLE_SPARSE:
writeComponentTo(digest, 0, false);
break;
case COMPOUND_DENSE:
case COMPOUND_SPARSE_STATIC:
case COMPOUND_SPARSE:
// This is the legacy format of composites.
// See org.apache.cassandra.db.marshal.CompositeType for details.
if (isStatic())
FBUtilities.updateWithShort(digest, CompositeType.STATIC_MARKER);
for (int i = 0; i < size(); i++)
{
writeComponentTo(digest, i, true);
digest.update((byte) 0);
}
break;
default:
throw new AssertionError();
}
}
protected void updateWithValue(MessageDigest digest)
{
int offset = valueStartOffset();
int length = valueEndOffset() - offset;
writeMemoryTo(digest, offset, length);
}
@Override // this is the NAME dataSize, only!
public int dataSize()
{
switch (nametype())
{
case SIMPLE_DENSE:
case SIMPLE_SPARSE:
return valueStartOffset() - nameDeltaOffset(size());
case COMPOUND_DENSE:
case COMPOUND_SPARSE_STATIC:
case COMPOUND_SPARSE:
int size = size();
return valueStartOffset() - nameDeltaOffset(size) + 3 * size + (isStatic() ? 2 : 0);
default:
throw new AssertionError();
}
}
public boolean equals(Object obj)
{
if (obj == this)
return true;
if (obj instanceof CellName)
return equals((CellName) obj);
if (obj instanceof Cell)
return equals((Cell) obj);
return false;
}
public boolean equals(CellName that)
{
int size = this.size();
if (size != that.size())
return false;
for (int i = 0 ; i < size ; i++)
if (!get(i).equals(that.get(i)))
return false;
return true;
}
private static final ByteBuffer[] EMPTY = new ByteBuffer[0];
@Override
public CellName copy(CFMetaData cfm, AbstractAllocator allocator)
{
ByteBuffer[] r;
switch (nametype())
{
case SIMPLE_DENSE:
return CellNames.simpleDense(allocator.clone(get(0)));
case COMPOUND_DENSE:
r = new ByteBuffer[size()];
for (int i = 0; i < r.length; i++)
r[i] = allocator.clone(get(i));
return CellNames.compositeDense(r);
case COMPOUND_SPARSE_STATIC:
case COMPOUND_SPARSE:
int clusteringSize = clusteringSize();
r = clusteringSize == 0 ? EMPTY : new ByteBuffer[clusteringSize()];
for (int i = 0; i < clusteringSize; i++)
r[i] = allocator.clone(get(i));
ByteBuffer nameBuffer = get(r.length);
ColumnIdentifier name;
if (nameBuffer.remaining() == 0)
{
name = CompoundSparseCellNameType.rowMarkerId;
}
else
{
name = getIdentifier(cfm, nameBuffer);
}
if (clusteringSizeDelta() == 2)
{
ByteBuffer element = allocator.clone(get(size() - 1));
return CellNames.compositeSparseWithCollection(r, element, name, isStatic());
}
return CellNames.compositeSparse(r, name, isStatic());
case SIMPLE_SPARSE:
return CellNames.simpleSparse(getIdentifier(cfm, get(0)));
}
throw new IllegalStateException();
}
private static ColumnIdentifier getIdentifier(CFMetaData cfMetaData, ByteBuffer name)
{
ColumnDefinition def = cfMetaData.getColumnDefinition(name);
if (def != null)
{
return def.name;
}
else
{
// it's safe to simply grab based on clusteringPrefixSize() as we are only called if not a dense type
AbstractType<?> type = cfMetaData.comparator.subtype(cfMetaData.comparator.clusteringPrefixSize());
return new ColumnIdentifier(HeapAllocator.instance.clone(name), type);
}
}
@Override
public Cell withUpdatedName(CellName newName)
{
throw new UnsupportedOperationException();
}
@Override
public Cell withUpdatedTimestamp(long newTimestamp)
{
throw new UnsupportedOperationException();
}
protected long internalSize()
{
return MemoryUtil.getInt(peer);
}
private void checkPosition(long offset, long size)
{
assert size >= 0;
assert peer > 0 : "Memory was freed";
assert offset >= 0 && offset + size <= internalSize() : String.format("Illegal range: [%d..%d), size: %s", offset, offset + size, internalSize());
}
protected final void setByte(long offset, byte b)
{
checkPosition(offset, 1);
MemoryUtil.setByte(peer + offset, b);
}
protected final void setShort(long offset, short s)
{
checkPosition(offset, 1);
MemoryUtil.setShort(peer + offset, s);
}
protected final void setInt(long offset, int l)
{
checkPosition(offset, 4);
MemoryUtil.setInt(peer + offset, l);
}
protected final void setLong(long offset, long l)
{
checkPosition(offset, 8);
MemoryUtil.setLong(peer + offset, l);
}
protected final void setBytes(long offset, ByteBuffer buffer)
{
int start = buffer.position();
int count = buffer.limit() - start;
if (count == 0)
return;
checkPosition(offset, count);
MemoryUtil.setBytes(peer + offset, buffer);
}
protected final byte getByte(long offset)
{
checkPosition(offset, 1);
return MemoryUtil.getByte(peer + offset);
}
protected final void getBytes(long offset, byte[] trg, int trgOffset, int count)
{
checkPosition(offset, count);
MemoryUtil.getBytes(peer + offset, trg, trgOffset, count);
}
protected final int getShort(long offset)
{
checkPosition(offset, 2);
return MemoryUtil.getShort(peer + offset);
}
protected final int getInt(long offset)
{
checkPosition(offset, 4);
return MemoryUtil.getInt(peer + offset);
}
protected final long getLong(long offset)
{
checkPosition(offset, 8);
return MemoryUtil.getLong(peer + offset);
}
protected final ByteBuffer getByteBuffer(long offset, int length)
{
checkPosition(offset, length);
return MemoryUtil.getByteBuffer(peer + offset, length);
}
}

View File

@ -91,7 +91,7 @@ public class ArrayBackedSortedColumns extends ColumnFamily
{
ArrayBackedSortedColumns copy = new ArrayBackedSortedColumns(original.metadata, false, new Cell[original.getColumnCount()], 0, 0);
for (Cell cell : original)
copy.internalAdd(cell.localCopy(allocator));
copy.internalAdd(cell.localCopy(original.metadata, allocator));
copy.sortedSize = copy.size; // internalAdd doesn't update sortedSize.
copy.delete(original);
return copy;
@ -139,7 +139,7 @@ public class ArrayBackedSortedColumns extends ColumnFamily
Arrays.sort(cells, sortedSize, size, comparator);
// Determine the merge start position for that segment
int pos = binarySearch(0, sortedSize, cells[sortedSize].name, internalComparator());
int pos = binarySearch(0, sortedSize, cells[sortedSize].name(), internalComparator());
if (pos < 0)
pos = -pos - 1;
@ -421,7 +421,7 @@ public class ArrayBackedSortedColumns extends ColumnFamily
{
public CellName apply(Cell cell)
{
return cell.name;
return cell.name();
}
});
}

View File

@ -19,7 +19,6 @@ package org.apache.cassandra.db;
import java.util.AbstractCollection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
@ -28,19 +27,21 @@ import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.collect.*;
import com.google.common.collect.Iterators;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.composites.CellName;
import org.apache.cassandra.db.composites.Composite;
import org.apache.cassandra.db.index.SecondaryIndexManager;
import org.apache.cassandra.db.filter.ColumnSlice;
import org.apache.cassandra.db.index.SecondaryIndexManager;
import org.apache.cassandra.utils.ObjectSizes;
import org.apache.cassandra.utils.SearchIterator;
import org.apache.cassandra.utils.btree.BTree;
import org.apache.cassandra.utils.btree.BTreeSearchIterator;
import org.apache.cassandra.utils.btree.BTreeSet;
import org.apache.cassandra.utils.btree.UpdateFunction;
import org.apache.cassandra.utils.concurrent.OpOrder;
import org.apache.cassandra.utils.memory.MemtableAllocator;
import static org.apache.cassandra.db.index.SecondaryIndexManager.Updater;
@ -55,14 +56,14 @@ import static org.apache.cassandra.db.index.SecondaryIndexManager.Updater;
*/
public class AtomicBTreeColumns extends ColumnFamily
{
static final long HEAP_SIZE = ObjectSizes.measure(new AtomicBTreeColumns(CFMetaData.IndexCf, null))
static final long EMPTY_SIZE = ObjectSizes.measure(new AtomicBTreeColumns(CFMetaData.IndexCf, null))
+ ObjectSizes.measure(new Holder(null, null));
private static final Function<Cell, CellName> NAME = new Function<Cell, CellName>()
{
public CellName apply(Cell column)
{
return column.name;
return column.name();
}
};
@ -162,110 +163,40 @@ public class AtomicBTreeColumns extends ColumnFamily
}
}
// the function we provide to the btree utilities to perform any column replacements
private static final class ColumnUpdater implements UpdateFunction<Cell>
{
final AtomicBTreeColumns updating;
final Holder ref;
final Function<Cell, Cell> transform;
final Updater indexer;
final Delta delta;
private ColumnUpdater(AtomicBTreeColumns updating, Holder ref, Function<Cell, Cell> transform, Updater indexer, Delta delta)
{
this.updating = updating;
this.ref = ref;
this.transform = transform;
this.indexer = indexer;
this.delta = delta;
}
public Cell apply(Cell inserted)
{
indexer.insert(inserted);
delta.insert(inserted);
return transform.apply(inserted);
}
public Cell apply(Cell existing, Cell update)
{
Cell reconciled = update.reconcile(existing);
indexer.update(existing, reconciled);
if (existing != reconciled)
delta.swap(existing, reconciled);
else
delta.abort(update);
return transform.apply(reconciled);
}
public boolean abortEarly()
{
return updating.ref != ref;
}
public void allocated(long heapSize)
{
delta.addHeapSize(heapSize);
}
}
private static Collection<Cell> transform(Comparator<Cell> cmp, ColumnFamily cf, Function<Cell, Cell> transformation, boolean sort)
{
Cell[] tmp = new Cell[cf.getColumnCount()];
int i = 0;
for (Cell c : cf)
tmp[i++] = transformation.apply(c);
if (sort)
Arrays.sort(tmp, cmp);
return Arrays.asList(tmp);
}
/**
* This is only called by Memtable.resolve, so only AtomicBTreeColumns needs to implement it.
*
* @return the difference in size seen after merging the given columns
*/
public Delta addAllWithSizeDelta(final ColumnFamily cm, Function<Cell, Cell> transformation, Updater indexer, Delta delta)
public long addAllWithSizeDelta(final ColumnFamily cm, MemtableAllocator allocator, OpOrder.Group writeOp, Updater indexer)
{
boolean transformed = false;
Collection<Cell> insert = cm.getSortedColumns();
ColumnUpdater updater = new ColumnUpdater(this, cm.metadata, allocator, writeOp, indexer);
while (true)
{
Holder current = ref;
updater.ref = current;
updater.reset();
delta.reset();
DeletionInfo deletionInfo;
if (cm.deletionInfo().mayModify(current.deletionInfo))
{
deletionInfo = current.deletionInfo.copy().add(cm.deletionInfo());
delta.addHeapSize(deletionInfo.unsharedHeapSize() - current.deletionInfo.unsharedHeapSize());
updater.allocated(deletionInfo.unsharedHeapSize() - current.deletionInfo.unsharedHeapSize());
}
else
{
deletionInfo = current.deletionInfo;
}
ColumnUpdater updater = new ColumnUpdater(this, current, transformation, indexer, delta);
Object[] tree = BTree.update(current.tree, metadata.comparator.columnComparator(), insert, true, updater);
Object[] tree = BTree.update(current.tree, metadata.comparator.columnComparator(), cm, cm.getColumnCount(), true, updater);
if (tree != null && refUpdater.compareAndSet(this, current, new Holder(tree, deletionInfo)))
{
indexer.updateRowLevelIndexes();
return updater.delta;
}
if (!transformed)
{
// After failing once, transform Columns into a new collection to avoid repeatedly allocating Slab space
insert = transform(metadata.comparator.columnComparator(), cm, transformation, false);
transformed = true;
updater.finish();
return updater.dataSize;
}
}
}
// no particular reason not to implement these next methods, we just haven't needed them yet
@ -297,7 +228,7 @@ public class AtomicBTreeColumns extends ColumnFamily
{
public int compare(Object o1, Object o2)
{
return cmp.compare((CellName) o1, ((Cell) o2).name);
return cmp.compare((CellName) o1, ((Cell) o2).name());
}
};
}
@ -359,7 +290,7 @@ public class AtomicBTreeColumns extends ColumnFamily
return false;
}
private static class Holder
private static final class Holder
{
final DeletionInfo deletionInfo;
// the btree of columns
@ -382,69 +313,96 @@ public class AtomicBTreeColumns extends ColumnFamily
}
}
// TODO: create a stack-allocation-friendly list to help optimise garbage for updates to rows with few columns
/**
* tracks the size changes made while merging a new group of cells in
*/
public static final class Delta
// the function we provide to the btree utilities to perform any column replacements
private static final class ColumnUpdater implements UpdateFunction<Cell>
{
private long dataSize;
private long heapSize;
final AtomicBTreeColumns updating;
final CFMetaData metadata;
final MemtableAllocator allocator;
final OpOrder.Group writeOp;
final Updater indexer;
Holder ref;
long dataSize;
long heapSize;
final MemtableAllocator.DataReclaimer reclaimer;
List<Cell> inserted; // TODO: replace with walk of aborted BTree
// we track the discarded cells (cells that were in the btree, but replaced by new ones)
// separately from aborted ones (were part of an update but older than existing cells)
// since we need to reset the former when we race on the btree update, but not the latter
private List<Cell> discarded = new ArrayList<>();
private List<Cell> aborted;
private ColumnUpdater(AtomicBTreeColumns updating, CFMetaData metadata, MemtableAllocator allocator, OpOrder.Group writeOp, Updater indexer)
{
this.updating = updating;
this.allocator = allocator;
this.writeOp = writeOp;
this.indexer = indexer;
this.metadata = metadata;
this.reclaimer = allocator.reclaimer();
}
public Cell apply(Cell insert)
{
indexer.insert(insert);
insert = insert.localCopy(metadata, allocator, writeOp);
this.dataSize += insert.cellDataSize();
this.heapSize += insert.excessHeapSizeExcludingData();
if (inserted == null)
inserted = new ArrayList<>();
inserted.add(insert);
return insert;
}
public Cell apply(Cell existing, Cell update)
{
Cell reconciled = existing.reconcile(update);
indexer.update(existing, reconciled);
if (existing != reconciled)
{
reconciled = reconciled.localCopy(metadata, allocator, writeOp);
dataSize += reconciled.cellDataSize() - existing.cellDataSize();
heapSize += reconciled.excessHeapSizeExcludingData() - existing.excessHeapSizeExcludingData();
if (inserted == null)
inserted = new ArrayList<>();
inserted.add(reconciled);
discard(existing);
}
return reconciled;
}
protected void reset()
{
this.dataSize = 0;
this.heapSize = 0;
discarded.clear();
if (inserted != null)
{
for (Cell cell : inserted)
abort(cell);
inserted.clear();
}
reclaimer.cancel();
}
protected void addHeapSize(long heapSize)
protected void abort(Cell abort)
{
reclaimer.reclaimImmediately(abort);
}
protected void discard(Cell discard)
{
reclaimer.reclaim(discard);
}
public boolean abortEarly()
{
return updating.ref != ref;
}
public void allocated(long heapSize)
{
this.heapSize += heapSize;
}
protected void swap(Cell old, Cell updated)
protected void finish()
{
dataSize += updated.dataSize() - old.dataSize();
heapSize += updated.excessHeapSizeExcludingData() - old.excessHeapSizeExcludingData();
discarded.add(old);
}
protected void insert(Cell insert)
{
this.dataSize += insert.dataSize();
this.heapSize += insert.excessHeapSizeExcludingData();
}
private void abort(Cell neverUsed)
{
if (aborted == null)
aborted = new ArrayList<>();
aborted.add(neverUsed);
}
public long dataSize()
{
return dataSize;
}
public long excessHeapSize()
{
return heapSize;
}
public Iterable<Cell> reclaimed()
{
if (aborted == null)
return discarded;
return Iterables.concat(discarded, aborted);
allocator.onHeap().allocate(heapSize, writeOp);
reclaimer.commit();
}
}
}

View File

@ -0,0 +1,103 @@
/*
* 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.nio.ByteBuffer;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.composites.CellName;
import org.apache.cassandra.db.composites.CellNames;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.ObjectSizes;
import org.apache.cassandra.utils.concurrent.OpOrder;
import org.apache.cassandra.utils.memory.AbstractAllocator;
import org.apache.cassandra.utils.memory.MemtableAllocator;
public class BufferCell extends AbstractCell
{
private static final long EMPTY_SIZE = ObjectSizes.measure(new BufferCell(CellNames.simpleDense(ByteBuffer.allocate(1))));
protected final CellName name;
protected final ByteBuffer value;
protected final long timestamp;
BufferCell(CellName name)
{
this(name, ByteBufferUtil.EMPTY_BYTE_BUFFER);
}
public BufferCell(CellName name, ByteBuffer value)
{
this(name, value, 0);
}
public BufferCell(CellName name, ByteBuffer value, long timestamp)
{
assert name != null;
assert value != null;
this.name = name;
this.value = value;
this.timestamp = timestamp;
}
@Override
public Cell withUpdatedName(CellName newName)
{
return new BufferCell(newName, value, timestamp);
}
@Override
public Cell withUpdatedTimestamp(long newTimestamp)
{
return new BufferCell(name, value, newTimestamp);
}
@Override
public CellName name() {
return name;
}
@Override
public ByteBuffer value() {
return value;
}
@Override
public long timestamp() {
return timestamp;
}
@Override
public long excessHeapSizeExcludingData()
{
return EMPTY_SIZE + name.excessHeapSizeExcludingData() + ObjectSizes.sizeOnHeapExcludingData(value);
}
@Override
public Cell localCopy(CFMetaData metadata, AbstractAllocator allocator)
{
return new BufferCell(name.copy(metadata, allocator), allocator.clone(value), timestamp);
}
@Override
public Cell localCopy(CFMetaData metadata, MemtableAllocator allocator, OpOrder.Group opGroup)
{
return allocator.clone(this, metadata, opGroup);
}
}

View File

@ -0,0 +1,181 @@
/*
* 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.nio.ByteBuffer;
import java.security.MessageDigest;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.composites.CellName;
import org.apache.cassandra.db.composites.CellNameType;
import org.apache.cassandra.serializers.MarshalException;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.concurrent.OpOrder;
import org.apache.cassandra.utils.memory.AbstractAllocator;
import org.apache.cassandra.utils.memory.MemtableAllocator;
public class BufferCounterCell extends BufferCell implements CounterCell
{
private final long timestampOfLastDelete;
public BufferCounterCell(CellName name, ByteBuffer value, long timestamp)
{
this(name, value, timestamp, Long.MIN_VALUE);
}
public BufferCounterCell(CellName name, ByteBuffer value, long timestamp, long timestampOfLastDelete)
{
super(name, value, timestamp);
this.timestampOfLastDelete = timestampOfLastDelete;
}
public static CounterCell create(CellName name, ByteBuffer value, long timestamp, long timestampOfLastDelete, ColumnSerializer.Flag flag)
{
if (flag == ColumnSerializer.Flag.FROM_REMOTE || (flag == ColumnSerializer.Flag.LOCAL && contextManager.shouldClearLocal(value)))
value = contextManager.clearAllLocal(value);
return new BufferCounterCell(name, value, timestamp, timestampOfLastDelete);
}
// For use by tests of compatibility with pre-2.1 counter only.
public static CounterCell createLocal(CellName name, long value, long timestamp, long timestampOfLastDelete)
{
return new BufferCounterCell(name, contextManager.createLocal(value), timestamp, timestampOfLastDelete);
}
@Override
public Cell withUpdatedName(CellName newName)
{
return new BufferCounterCell(newName, value, timestamp, timestampOfLastDelete);
}
@Override
public long timestampOfLastDelete()
{
return timestampOfLastDelete;
}
@Override
public long total()
{
return contextManager.total(value);
}
@Override
public int cellDataSize()
{
// A counter column adds 8 bytes for timestampOfLastDelete to Cell.
return super.cellDataSize() + TypeSizes.NATIVE.sizeof(timestampOfLastDelete);
}
@Override
public int serializedSize(CellNameType type, TypeSizes typeSizes)
{
return super.serializedSize(type, typeSizes) + typeSizes.sizeof(timestampOfLastDelete);
}
@Override
public Cell diff(Cell cell)
{
return diff(this, cell);
}
/*
* We have to special case digest creation for counter column because
* we don't want to include the information about which shard of the
* context is a delta or not, since this information differs from node to
* node.
*/
@Override
public void updateDigest(MessageDigest digest)
{
digest.update(name().toByteBuffer().duplicate());
// We don't take the deltas into account in a digest
contextManager.updateDigest(digest, value());
FBUtilities.updateWithLong(digest, timestamp);
FBUtilities.updateWithByte(digest, serializationFlags());
FBUtilities.updateWithLong(digest, timestampOfLastDelete);
}
@Override
public Cell reconcile(Cell cell)
{
return reconcile(this, cell);
}
@Override
public boolean hasLegacyShards()
{
return contextManager.hasLegacyShards(value);
}
@Override
public CounterCell localCopy(CFMetaData metadata, AbstractAllocator allocator)
{
return new BufferCounterCell(name.copy(metadata, allocator), allocator.clone(value), timestamp, timestampOfLastDelete);
}
@Override
public CounterCell localCopy(CFMetaData metadata, MemtableAllocator allocator, OpOrder.Group opGroup)
{
return allocator.clone(this, metadata, opGroup);
}
@Override
public String getString(CellNameType comparator)
{
return String.format("%s:false:%s@%d!%d",
comparator.getString(name()),
contextManager.toString(value()),
timestamp(),
timestampOfLastDelete);
}
@Override
public int serializationFlags()
{
return ColumnSerializer.COUNTER_MASK;
}
@Override
public void validateFields(CFMetaData metadata) throws MarshalException
{
validateName(metadata);
// We cannot use the value validator as for other columns as the CounterColumnType validate a long,
// which is not the internal representation of counters
contextManager.validateContext(value());
}
@Override
public Cell markLocalToBeCleared()
{
ByteBuffer marked = contextManager.markLocalToBeCleared(value());
return marked == value() ? this : new BufferCounterCell(name(), marked, timestamp(), timestampOfLastDelete);
}
@Override
public boolean equals(Cell cell)
{
return cell instanceof CounterCell && equals((CounterCell) cell);
}
public boolean equals(CounterCell cell)
{
return super.equals(cell) && timestampOfLastDelete == cell.timestampOfLastDelete();
}
}

View File

@ -0,0 +1,93 @@
/*
* 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.nio.ByteBuffer;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.composites.CellName;
import org.apache.cassandra.db.composites.CellNameType;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.concurrent.OpOrder;
import org.apache.cassandra.utils.memory.AbstractAllocator;
import org.apache.cassandra.utils.memory.MemtableAllocator;
public class BufferCounterUpdateCell extends BufferCell implements CounterUpdateCell
{
public BufferCounterUpdateCell(CellName name, long value, long timestamp)
{
this(name, ByteBufferUtil.bytes(value), timestamp);
}
public BufferCounterUpdateCell(CellName name, ByteBuffer value, long timestamp)
{
super(name, value, timestamp);
}
public long delta()
{
return value().getLong(value.position());
}
@Override
public Cell diff(Cell cell)
{
// Diff is used during reads, but we should never read those columns
throw new UnsupportedOperationException("This operation is unsupported on CounterUpdateCell.");
}
@Override
public Cell reconcile(Cell cell)
{
// The only time this could happen is if a batchAdd ships two
// increment for the same cell. Hence we simply sums the delta.
// tombstones take precedence
if (cell.isMarkedForDelete(Long.MIN_VALUE)) // can't be an expired cell, so the current time is irrelevant
return timestamp > cell.timestamp() ? this : cell;
// neither is tombstoned
assert cell instanceof CounterUpdateCell : "Wrong class type.";
CounterUpdateCell c = (CounterUpdateCell) cell;
return new BufferCounterUpdateCell(name, delta() + c.delta(), Math.max(timestamp, c.timestamp()));
}
@Override
public int serializationFlags()
{
return ColumnSerializer.COUNTER_UPDATE_MASK;
}
@Override
public Cell localCopy(CFMetaData metadata, AbstractAllocator allocator)
{
throw new UnsupportedOperationException();
}
@Override
public Cell localCopy(CFMetaData metadata, MemtableAllocator allocator, OpOrder.Group opGroup)
{
throw new UnsupportedOperationException();
}
@Override
public String getString(CellNameType comparator)
{
return String.format("%s:%s@%d", comparator.getString(name()), ByteBufferUtil.toLong(value), timestamp());
}
}

View File

@ -0,0 +1,39 @@
/*
* 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.nio.ByteBuffer;
import org.apache.cassandra.dht.Token;
public class BufferDecoratedKey extends DecoratedKey
{
private final ByteBuffer key;
public BufferDecoratedKey(Token token, ByteBuffer key)
{
super(token);
assert key != null;
this.key = key;
}
public ByteBuffer getKey()
{
return key;
}
}

View File

@ -0,0 +1,123 @@
/*
* 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.nio.ByteBuffer;
import java.security.MessageDigest;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.composites.CellName;
import org.apache.cassandra.serializers.MarshalException;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.concurrent.OpOrder;
import org.apache.cassandra.utils.memory.AbstractAllocator;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.memory.MemtableAllocator;
public class BufferDeletedCell extends BufferCell implements DeletedCell
{
public BufferDeletedCell(CellName name, int localDeletionTime, long timestamp)
{
this(name, ByteBufferUtil.bytes(localDeletionTime), timestamp);
}
public BufferDeletedCell(CellName name, ByteBuffer value, long timestamp)
{
super(name, value, timestamp);
}
@Override
public Cell withUpdatedName(CellName newName)
{
return new BufferDeletedCell(newName, value, timestamp);
}
@Override
public Cell withUpdatedTimestamp(long newTimestamp)
{
return new BufferDeletedCell(name, value, newTimestamp);
}
@Override
public boolean isMarkedForDelete(long now)
{
return true;
}
@Override
public long getMarkedForDeleteAt()
{
return timestamp;
}
@Override
public int getLocalDeletionTime()
{
return value().getInt(value.position());
}
@Override
public Cell reconcile(Cell cell)
{
if (cell instanceof DeletedCell)
return super.reconcile(cell);
return cell.reconcile(this);
}
@Override
public DeletedCell localCopy(CFMetaData metadata, AbstractAllocator allocator)
{
return new BufferDeletedCell(name.copy(metadata, allocator), allocator.clone(value), timestamp);
}
@Override
public DeletedCell localCopy(CFMetaData metadata, MemtableAllocator allocator, OpOrder.Group opGroup)
{
return allocator.clone(this, metadata, opGroup);
}
@Override
public int serializationFlags()
{
return ColumnSerializer.DELETION_MASK;
}
@Override
public void validateFields(CFMetaData metadata) throws MarshalException
{
validateName(metadata);
if (value().remaining() != 4)
throw new MarshalException("A tombstone value should be 4 bytes long");
if (getLocalDeletionTime() < 0)
throw new MarshalException("The local deletion time should not be negative");
}
public boolean equals(Cell cell)
{
return timestamp() == cell.timestamp() && getLocalDeletionTime() == cell.getLocalDeletionTime() && name().equals(cell.name());
}
@Override
public void updateDigest(MessageDigest digest)
{
digest.update(name().toByteBuffer().duplicate());
FBUtilities.updateWithLong(digest, timestamp());
FBUtilities.updateWithByte(digest, serializationFlags());
}
}

View File

@ -0,0 +1,170 @@
/*
* 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.nio.ByteBuffer;
import java.security.MessageDigest;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.composites.CellName;
import org.apache.cassandra.db.composites.CellNameType;
import org.apache.cassandra.serializers.MarshalException;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.concurrent.OpOrder;
import org.apache.cassandra.utils.memory.AbstractAllocator;
import org.apache.cassandra.utils.memory.MemtableAllocator;
public class BufferExpiringCell extends BufferCell implements ExpiringCell
{
private final int localExpirationTime;
private final int timeToLive;
public BufferExpiringCell(CellName name, ByteBuffer value, long timestamp, int timeToLive)
{
this(name, value, timestamp, timeToLive, (int) (System.currentTimeMillis() / 1000) + timeToLive);
}
public BufferExpiringCell(CellName name, ByteBuffer value, long timestamp, int timeToLive, int localExpirationTime)
{
super(name, value, timestamp);
assert timeToLive > 0 : timeToLive;
assert localExpirationTime > 0 : localExpirationTime;
this.timeToLive = timeToLive;
this.localExpirationTime = localExpirationTime;
}
public int getTimeToLive()
{
return timeToLive;
}
@Override
public Cell withUpdatedName(CellName newName)
{
return new BufferExpiringCell(newName, value(), timestamp(), timeToLive, localExpirationTime);
}
@Override
public Cell withUpdatedTimestamp(long newTimestamp)
{
return new BufferExpiringCell(name(), value(), newTimestamp, timeToLive, localExpirationTime);
}
@Override
public int cellDataSize()
{
return super.cellDataSize() + TypeSizes.NATIVE.sizeof(localExpirationTime) + TypeSizes.NATIVE.sizeof(timeToLive);
}
@Override
public int serializedSize(CellNameType type, TypeSizes typeSizes)
{
/*
* An expired column adds to a Cell :
* 4 bytes for the localExpirationTime
* + 4 bytes for the timeToLive
*/
return super.serializedSize(type, typeSizes) + typeSizes.sizeof(localExpirationTime) + typeSizes.sizeof(timeToLive);
}
@Override
public void updateDigest(MessageDigest digest)
{
super.updateDigest(digest);
FBUtilities.updateWithInt(digest, timeToLive);
}
@Override
public int getLocalDeletionTime()
{
return localExpirationTime;
}
@Override
public ExpiringCell localCopy(CFMetaData metadata, AbstractAllocator allocator)
{
return new BufferExpiringCell(name.copy(metadata, allocator), allocator.clone(value), timestamp, timeToLive, localExpirationTime);
}
@Override
public ExpiringCell localCopy(CFMetaData metadata, MemtableAllocator allocator, OpOrder.Group opGroup)
{
return allocator.clone(this, metadata, opGroup);
}
@Override
public String getString(CellNameType comparator)
{
return String.format("%s!%d", super.getString(comparator), timeToLive);
}
@Override
public boolean isMarkedForDelete(long now)
{
return (int) (now / 1000) >= getLocalDeletionTime();
}
@Override
public long getMarkedForDeleteAt()
{
return timestamp;
}
@Override
public int serializationFlags()
{
return ColumnSerializer.EXPIRATION_MASK;
}
@Override
public void validateFields(CFMetaData metadata) throws MarshalException
{
super.validateFields(metadata);
if (timeToLive <= 0)
throw new MarshalException("A column TTL should be > 0");
if (localExpirationTime < 0)
throw new MarshalException("The local expiration time should not be negative");
}
@Override
public boolean equals(Cell cell)
{
return cell instanceof ExpiringCell && equals((ExpiringCell) cell);
}
public boolean equals(ExpiringCell cell)
{
// super.equals() returns false if o is not a CounterCell
return super.equals(cell)
&& getLocalDeletionTime() == cell.getLocalDeletionTime()
&& getTimeToLive() == cell.getTimeToLive();
}
/** @return Either a DeletedCell, or an ExpiringCell. */
public static Cell create(CellName name, ByteBuffer value, long timestamp, int timeToLive, int localExpirationTime, int expireBefore, ColumnSerializer.Flag flag)
{
if (localExpirationTime >= expireBefore || flag == ColumnSerializer.Flag.PRESERVE_SIZE)
return new BufferExpiringCell(name, value, timestamp, timeToLive, localExpirationTime);
// The column is now expired, we can safely return a simple tombstone. Note that
// as long as the expiring column and the tombstone put together live longer than GC grace seconds,
// we'll fulfil our responsibility to repair. See discussion at
// http://cassandra-user-incubator-apache-org.3065146.n2.nabble.com/repair-compaction-and-tombstone-rows-td7583481.html
return new BufferDeletedCell(name, localExpirationTime - timeToLive, timestamp);
}
}

View File

@ -52,7 +52,7 @@ public class CFRowAdder
// If a CQL3 table, add the row marker
if (cf.metadata().isCQL3Table() && !prefix.isStatic())
cf.addColumn(new Cell(cf.getComparator().rowMarker(prefix), ByteBufferUtil.EMPTY_BYTE_BUFFER, timestamp));
cf.addColumn(new BufferCell(cf.getComparator().rowMarker(prefix), ByteBufferUtil.EMPTY_BYTE_BUFFER, timestamp));
}
public CFRowAdder add(String cql3ColumnName, Object value)
@ -96,14 +96,14 @@ public class CFRowAdder
{
if (value == null)
{
cf.addColumn(new DeletedCell(name, ldt, timestamp));
cf.addColumn(new BufferDeletedCell(name, ldt, timestamp));
}
else
{
AbstractType valueType = def.type.isCollection()
? ((CollectionType) def.type).valueComparator()
: def.type;
cf.addColumn(new Cell(name, value instanceof ByteBuffer ? (ByteBuffer)value : valueType.decompose(value), timestamp));
cf.addColumn(new BufferCell(name, value instanceof ByteBuffer ? (ByteBuffer)value : valueType.decompose(value), timestamp));
}
return this;
}

View File

@ -17,261 +17,58 @@
*/
package org.apache.cassandra.db;
import java.io.DataInput;
import java.io.IOError;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.util.Iterator;
import com.google.common.collect.AbstractIterator;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.composites.CellName;
import org.apache.cassandra.db.composites.CellNameType;
import org.apache.cassandra.db.composites.CellNames;
import org.apache.cassandra.db.marshal.*;
import org.apache.cassandra.io.sstable.Descriptor;
import org.apache.cassandra.io.util.DataOutputBuffer;
import org.apache.cassandra.serializers.MarshalException;
import org.apache.cassandra.utils.ObjectSizes;
import org.apache.cassandra.utils.concurrent.OpOrder;
import org.apache.cassandra.utils.memory.AbstractAllocator;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.memory.MemtableAllocator;
/**
* Cell is immutable, which prevents all kinds of confusion in a multithreaded environment.
*/
public class Cell implements OnDiskAtom
public interface Cell extends OnDiskAtom
{
public static final int MAX_NAME_LENGTH = FBUtilities.MAX_UNSIGNED_SHORT;
private static final long EMPTY_SIZE = ObjectSizes.measure(new Cell(CellNames.simpleDense(ByteBuffer.allocate(1))));
public Cell withUpdatedName(CellName newName);
public static Iterator<OnDiskAtom> onDiskIterator(final DataInput in,
final ColumnSerializer.Flag flag,
final int expireBefore,
final Descriptor.Version version,
final CellNameType type)
{
return new AbstractIterator<OnDiskAtom>()
{
protected OnDiskAtom computeNext()
{
OnDiskAtom atom;
try
{
atom = type.onDiskAtomSerializer().deserializeFromSSTable(in, flag, expireBefore, version);
}
catch (IOException e)
{
throw new IOError(e);
}
if (atom == null)
return endOfData();
public Cell withUpdatedTimestamp(long newTimestamp);
return atom;
}
};
}
@Override
public CellName name();
protected final CellName name;
protected final ByteBuffer value;
protected final long timestamp;
public ByteBuffer value();
Cell(CellName name)
{
this(name, ByteBufferUtil.EMPTY_BYTE_BUFFER);
}
public boolean isMarkedForDelete(long now);
public Cell(CellName name, ByteBuffer value)
{
this(name, value, 0);
}
public Cell(CellName name, ByteBuffer value, long timestamp)
{
assert name != null;
assert value != null;
this.name = name;
this.value = value;
this.timestamp = timestamp;
}
public Cell withUpdatedName(CellName newName)
{
return new Cell(newName, value, timestamp);
}
public Cell withUpdatedTimestamp(long newTimestamp)
{
return new Cell(name, value, newTimestamp);
}
public CellName name()
{
return name;
}
public ByteBuffer value()
{
return value;
}
public long timestamp()
{
return timestamp;
}
public boolean isMarkedForDelete(long now)
{
return false;
}
public boolean isLive(long now)
{
return !isMarkedForDelete(now);
}
public boolean isLive(long now);
// Don't call unless the column is actually marked for delete.
public long getMarkedForDeleteAt()
{
return Long.MAX_VALUE;
}
public long getMarkedForDeleteAt();
public int dataSize()
{
return name.dataSize() + value.remaining() + TypeSizes.NATIVE.sizeof(timestamp);
}
public int cellDataSize();
// returns the size of the Cell and all references on the heap, excluding any costs associated with byte arrays
// that would be allocated by a localCopy, as these will be accounted for by the allocator
public long excessHeapSizeExcludingData()
{
return EMPTY_SIZE + name.excessHeapSizeExcludingData() + ObjectSizes.sizeOnHeapExcludingData(value);
}
public long excessHeapSizeExcludingData();
public int serializedSize(CellNameType type, TypeSizes typeSizes)
{
/*
* Size of a column is =
* size of a name (short + length of the string)
* + 1 byte to indicate if the column has been deleted
* + 8 bytes for timestamp
* + 4 bytes which basically indicates the size of the byte array
* + entire byte array.
*/
int valueSize = value.remaining();
return ((int)type.cellSerializer().serializedSize(name, typeSizes)) + 1 + typeSizes.sizeof(timestamp) + typeSizes.sizeof(valueSize) + valueSize;
}
public int serializedSize(CellNameType type, TypeSizes typeSizes);
public int serializationFlags();
public int serializationFlags()
{
return 0;
}
public Cell diff(Cell cell);
public Cell diff(Cell cell)
{
if (timestamp() < cell.timestamp())
return cell;
return null;
}
public Cell reconcile(Cell cell);
public void updateDigest(MessageDigest digest)
{
digest.update(name.toByteBuffer().duplicate());
digest.update(value.duplicate());
public Cell localCopy(CFMetaData metadata, AbstractAllocator allocator);
DataOutputBuffer buffer = new DataOutputBuffer();
try
{
buffer.writeLong(timestamp);
buffer.writeByte(serializationFlags());
}
catch (IOException e)
{
throw new RuntimeException(e);
}
digest.update(buffer.getData(), 0, buffer.getLength());
}
public Cell localCopy(CFMetaData metaData, MemtableAllocator allocator, OpOrder.Group opGroup);
public int getLocalDeletionTime()
{
return Integer.MAX_VALUE;
}
public String getString(CellNameType comparator);
public Cell reconcile(Cell cell)
{
// tombstones take precedence. (if both are tombstones, then it doesn't matter which one we use.)
if (isMarkedForDelete(System.currentTimeMillis()))
return timestamp() < cell.timestamp() ? cell : this;
if (cell.isMarkedForDelete(System.currentTimeMillis()))
return timestamp() > cell.timestamp() ? this : cell;
// break ties by comparing values.
if (timestamp() == cell.timestamp())
return value().compareTo(cell.value()) < 0 ? cell : this;
// neither is tombstoned and timestamps are different
return timestamp() < cell.timestamp() ? cell : this;
}
@Override
public boolean equals(Object o)
{
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Cell cell = (Cell)o;
return timestamp == cell.timestamp && name.equals(cell.name) && value.equals(cell.value);
}
@Override
public int hashCode()
{
int result = name != null ? name.hashCode() : 0;
result = 31 * result + (value != null ? value.hashCode() : 0);
result = 31 * result + (int)(timestamp ^ (timestamp >>> 32));
return result;
}
public Cell localCopy(AbstractAllocator allocator)
{
return new Cell(name.copy(allocator), allocator.clone(value), timestamp);
}
public String getString(CellNameType comparator)
{
return String.format("%s:%b:%d@%d",
comparator.getString(name),
isMarkedForDelete(System.currentTimeMillis()),
value.remaining(),
timestamp);
}
protected void validateName(CFMetaData metadata) throws MarshalException
{
metadata.comparator.validate(name());
}
public void validateFields(CFMetaData metadata) throws MarshalException
{
validateName(metadata);
AbstractType<?> valueValidator = metadata.getValueValidator(name());
if (valueValidator != null)
valueValidator.validate(value());
}
public static Cell create(CellName name, ByteBuffer value, long timestamp, int ttl, CFMetaData metadata)
{
if (ttl <= 0)
ttl = metadata.getDefaultTimeToLive();
return ttl > 0
? new ExpiringCell(name, value, timestamp, ttl)
: new Cell(name, value, timestamp);
}
void validateName(CFMetaData metadata) throws MarshalException;
}

View File

@ -87,7 +87,7 @@ public class CollationController
{
OnDiskAtom atom = iter.next();
if (copyOnHeap)
atom = ((Cell) atom).localCopy(HeapAllocator.instance);
atom = ((Cell) atom).localCopy(cfs.metadata, HeapAllocator.instance);
container.addAtom(atom);
}
}
@ -148,7 +148,7 @@ public class CollationController
&& cfs.getCompactionStrategy() instanceof SizeTieredCompactionStrategy)
{
Tracing.trace("Defragmenting requested data");
Mutation mutation = new Mutation(cfs.keyspace.getName(), filter.key.key, returnCF.cloneMe());
Mutation mutation = new Mutation(cfs.keyspace.getName(), filter.key.getKey(), returnCF.cloneMe());
// skipping commitlog and index updates is fine since we're just de-fragmenting existing data
Keyspace.open(mutation.getKeyspaceName()).apply(mutation, false, false);
}
@ -206,7 +206,7 @@ public class CollationController
ColumnFamily newCf = cf.cloneMeShallow(ArrayBackedSortedColumns.factory, false);
for (Cell cell : cf)
{
newCf.addColumn(cell.localCopy(HeapAllocator.instance));
newCf.addColumn(cell.localCopy(cfs.metadata, HeapAllocator.instance));
}
cf = newCf;
iter = filter.getColumnFamilyIterator(cf);

View File

@ -128,23 +128,23 @@ public abstract class ColumnFamily implements Iterable<Cell>, IRowCacheEntry
public void addColumn(CellName name, ByteBuffer value, long timestamp, int timeToLive)
{
assert !metadata().isCounter();
Cell cell = Cell.create(name, value, timestamp, timeToLive, metadata());
Cell cell = AbstractCell.create(name, value, timestamp, timeToLive, metadata());
addColumn(cell);
}
public void addCounter(CellName name, long value)
{
addColumn(new CounterUpdateCell(name, value, System.currentTimeMillis()));
addColumn(new BufferCounterUpdateCell(name, value, System.currentTimeMillis()));
}
public void addTombstone(CellName name, ByteBuffer localDeletionTime, long timestamp)
{
addColumn(new DeletedCell(name, localDeletionTime, timestamp));
addColumn(new BufferDeletedCell(name, localDeletionTime, timestamp));
}
public void addTombstone(CellName name, int localDeletionTime, long timestamp)
{
addColumn(new DeletedCell(name, localDeletionTime, timestamp));
addColumn(new BufferDeletedCell(name, localDeletionTime, timestamp));
}
public void addAtom(OnDiskAtom atom)
@ -327,7 +327,7 @@ public abstract class ColumnFamily implements Iterable<Cell>, IRowCacheEntry
{
long size = 0;
for (Cell cell : this)
size += cell.dataSize();
size += cell.cellDataSize();
return size;
}
@ -426,8 +426,8 @@ public abstract class ColumnFamily implements Iterable<Cell>, IRowCacheEntry
int deletionTime = cell.getLocalDeletionTime();
if (deletionTime < Integer.MAX_VALUE)
tombstones.update(deletionTime);
minColumnNamesSeen = ColumnNameHelper.minComponents(minColumnNamesSeen, cell.name, metadata.comparator);
maxColumnNamesSeen = ColumnNameHelper.maxComponents(maxColumnNamesSeen, cell.name, metadata.comparator);
minColumnNamesSeen = ColumnNameHelper.minComponents(minColumnNamesSeen, cell.name(), metadata.comparator);
maxColumnNamesSeen = ColumnNameHelper.maxComponents(maxColumnNamesSeen, cell.name(), metadata.comparator);
if (cell instanceof CounterCell)
hasLegacyCounterShards = hasLegacyCounterShards || ((CounterCell) cell).hasLegacyShards();
}
@ -476,7 +476,7 @@ public abstract class ColumnFamily implements Iterable<Cell>, IRowCacheEntry
{
ImmutableMap.Builder<CellName, ByteBuffer> builder = ImmutableMap.builder();
for (Cell cell : this)
builder.put(cell.name, cell.value);
builder.put(cell.name(), cell.value());
return builder.build();
}

View File

@ -75,6 +75,7 @@ import org.apache.cassandra.streaming.StreamLockfile;
import org.apache.cassandra.tracing.Tracing;
import org.apache.cassandra.utils.*;
import org.apache.cassandra.utils.concurrent.OpOrder;
import org.apache.cassandra.utils.memory.MemtableAllocator;
public class ColumnFamilyStore implements ColumnFamilyStoreMBean
{
@ -843,12 +844,13 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
for (SecondaryIndex index : indexManager.getIndexes())
{
if (index.getAllocator() != null)
if (index.getIndexCfs() != null)
{
onHeapRatio += index.getAllocator().onHeap().ownershipRatio();
offHeapRatio += index.getAllocator().offHeap().ownershipRatio();
onHeapTotal += index.getAllocator().onHeap().owns();
offHeapTotal += index.getAllocator().offHeap().owns();
MemtableAllocator allocator = index.getIndexCfs().getDataTracker().getView().getCurrentMemtable().getAllocator();
onHeapRatio += allocator.onHeap().ownershipRatio();
offHeapRatio += allocator.offHeap().ownershipRatio();
onHeapTotal += allocator.onHeap().owns();
offHeapTotal += allocator.offHeap().owns();
}
}
@ -1095,10 +1097,11 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
for (SecondaryIndex index : cfs.indexManager.getIndexes())
{
if (index.getAllocator() != null)
if (index.getIndexCfs() != null)
{
onHeap += index.getAllocator().onHeap().ownershipRatio();
offHeap += index.getAllocator().offHeap().ownershipRatio();
MemtableAllocator allocator = index.getIndexCfs().getDataTracker().getView().getCurrentMemtable().getAllocator();
onHeap += allocator.onHeap().ownershipRatio();
offHeap += allocator.offHeap().ownershipRatio();
}
}
@ -1213,7 +1216,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
// 2. if it has been re-added since then, this particular column was inserted before the last drop
private static boolean isDroppedColumn(Cell c, CFMetaData meta)
{
Long droppedAt = meta.getDroppedColumns().get(c.name().cql3ColumnName());
Long droppedAt = meta.getDroppedColumns().get(c.name().cql3ColumnName(meta));
return droppedAt != null && c.timestamp() <= droppedAt;
}
@ -1869,7 +1872,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
ColumnFamily columns;
try (OpOrder.Group op = readOrdering.start())
{
columns = controller.getTopLevelColumns(Memtable.memoryPool.needToCopyOnHeap());
columns = controller.getTopLevelColumns(Memtable.MEMORY_POOL.needToCopyOnHeap());
}
metric.updateSSTableIterated(controller.getSstablesIterated());
return columns;
@ -1882,7 +1885,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
for (RowCacheKey key : CacheService.instance.rowCache.getKeySet())
{
DecoratedKey dk = partitioner.decorateKey(ByteBuffer.wrap(key.key));
if (key.cfId == metadata.cfId && !Range.isInRanges(dk.token, ranges))
if (key.cfId == metadata.cfId && !Range.isInRanges(dk.getToken(), ranges))
invalidateCachedRow(dk);
}
@ -1891,7 +1894,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
for (CounterCacheKey key : CacheService.instance.counterCache.getKeySet())
{
DecoratedKey dk = partitioner.decorateKey(ByteBuffer.wrap(key.partitionKey));
if (key.cfId == metadata.cfId && !Range.isInRanges(dk.token, ranges))
if (key.cfId == metadata.cfId && !Range.isInRanges(dk.getToken(), ranges))
CacheService.instance.counterCache.remove(key);
}
}
@ -1939,7 +1942,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
return computeNext();
if (logger.isTraceEnabled())
logger.trace("scanned {}", metadata.getKeyValidator().getString(key.key));
logger.trace("scanned {}", metadata.getKeyValidator().getString(key.getKey()));
return current;
}

View File

@ -116,7 +116,7 @@ public class ColumnSerializer implements ISerializer<Cell>
long timestampOfLastDelete = in.readLong();
long ts = in.readLong();
ByteBuffer value = ByteBufferUtil.readWithLength(in);
return CounterCell.create(name, value, ts, timestampOfLastDelete, flag);
return BufferCounterCell.create(name, value, ts, timestampOfLastDelete, flag);
}
else if ((mask & EXPIRATION_MASK) != 0)
{
@ -124,17 +124,17 @@ public class ColumnSerializer implements ISerializer<Cell>
int expiration = in.readInt();
long ts = in.readLong();
ByteBuffer value = ByteBufferUtil.readWithLength(in);
return ExpiringCell.create(name, value, ts, ttl, expiration, expireBefore, flag);
return BufferExpiringCell.create(name, value, ts, ttl, expiration, expireBefore, flag);
}
else
{
long ts = in.readLong();
ByteBuffer value = ByteBufferUtil.readWithLength(in);
return (mask & COUNTER_UPDATE_MASK) != 0
? new CounterUpdateCell(name, value, ts)
? new BufferCounterUpdateCell(name, value, ts)
: ((mask & DELETION_MASK) == 0
? new Cell(name, value, ts)
: new DeletedCell(name, value, ts));
? new BufferCell(name, value, ts)
: new BufferDeletedCell(name, value, ts));
}
}

View File

@ -17,223 +17,28 @@
*/
package org.apache.cassandra.db;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import org.apache.cassandra.serializers.MarshalException;
import org.apache.cassandra.utils.memory.AbstractAllocator;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.composites.CellName;
import org.apache.cassandra.db.composites.CellNameType;
import org.apache.cassandra.db.context.CounterContext;
import org.apache.cassandra.io.util.DataOutputBuffer;
import org.apache.cassandra.utils.concurrent.OpOrder;
import org.apache.cassandra.utils.memory.AbstractAllocator;
import org.apache.cassandra.utils.memory.MemtableAllocator;
/**
* A column that represents a partitioned counter.
*/
public class CounterCell extends Cell
public interface CounterCell extends Cell
{
protected static final CounterContext contextManager = CounterContext.instance();
static final CounterContext contextManager = CounterContext.instance();
private final long timestampOfLastDelete;
public long timestampOfLastDelete();
public CounterCell(CellName name, ByteBuffer value, long timestamp)
{
this(name, value, timestamp, Long.MIN_VALUE);
}
public long total();
public CounterCell(CellName name, ByteBuffer value, long timestamp, long timestampOfLastDelete)
{
super(name, value, timestamp);
this.timestampOfLastDelete = timestampOfLastDelete;
}
public boolean hasLegacyShards();
public static CounterCell create(CellName name, ByteBuffer value, long timestamp, long timestampOfLastDelete, ColumnSerializer.Flag flag)
{
if (flag == ColumnSerializer.Flag.FROM_REMOTE || (flag == ColumnSerializer.Flag.LOCAL && contextManager.shouldClearLocal(value)))
value = contextManager.clearAllLocal(value);
return new CounterCell(name, value, timestamp, timestampOfLastDelete);
}
public Cell markLocalToBeCleared();
// For use by tests of compatibility with pre-2.1 counter only.
public static CounterCell createLocal(CellName name, long value, long timestamp, long timestampOfLastDelete)
{
return new CounterCell(name, contextManager.createLocal(value), timestamp, timestampOfLastDelete);
}
CounterCell localCopy(CFMetaData metadata, AbstractAllocator allocator);
@Override
public Cell withUpdatedName(CellName newName)
{
return new CounterCell(newName, value, timestamp, timestampOfLastDelete);
}
public long timestampOfLastDelete()
{
return timestampOfLastDelete;
}
public long total()
{
return contextManager.total(value);
}
@Override
public int dataSize()
{
// A counter column adds 8 bytes for timestampOfLastDelete to Cell.
return super.dataSize() + TypeSizes.NATIVE.sizeof(timestampOfLastDelete);
}
@Override
public int serializedSize(CellNameType type, TypeSizes typeSizes)
{
return super.serializedSize(type, typeSizes) + typeSizes.sizeof(timestampOfLastDelete);
}
@Override
public Cell diff(Cell cell)
{
assert (cell instanceof CounterCell) || (cell instanceof DeletedCell) : "Wrong class type: " + cell.getClass();
if (timestamp() < cell.timestamp())
return cell;
// Note that if at that point, cell can't be a tombstone. Indeed,
// cell is the result of merging us with other nodes results, and
// merging a CounterCell with a tombstone never return a tombstone
// unless that tombstone timestamp is greater that the CounterCell
// one.
assert cell instanceof CounterCell : "Wrong class type: " + cell.getClass();
if (timestampOfLastDelete() < ((CounterCell) cell).timestampOfLastDelete())
return cell;
CounterContext.Relationship rel = contextManager.diff(cell.value(), value());
if (rel == CounterContext.Relationship.GREATER_THAN || rel == CounterContext.Relationship.DISJOINT)
return cell;
return null;
}
/*
* We have to special case digest creation for counter column because
* we don't want to include the information about which shard of the
* context is a delta or not, since this information differs from node to
* node.
*/
@Override
public void updateDigest(MessageDigest digest)
{
digest.update(name.toByteBuffer().duplicate());
// We don't take the deltas into account in a digest
contextManager.updateDigest(digest, value);
DataOutputBuffer buffer = new DataOutputBuffer();
try
{
buffer.writeLong(timestamp);
buffer.writeByte(serializationFlags());
buffer.writeLong(timestampOfLastDelete);
}
catch (IOException e)
{
throw new RuntimeException(e);
}
digest.update(buffer.getData(), 0, buffer.getLength());
}
@Override
public Cell reconcile(Cell cell)
{
// live + tombstone: track last tombstone
if (cell.isMarkedForDelete(Long.MIN_VALUE)) // cannot be an expired cell, so the current time is irrelevant
{
// live < tombstone
if (timestamp() < cell.timestamp())
{
return cell;
}
// live last delete >= tombstone
if (timestampOfLastDelete() >= cell.timestamp())
{
return this;
}
// live last delete < tombstone
return new CounterCell(name(), value(), timestamp(), cell.timestamp());
}
assert cell instanceof CounterCell : "Wrong class type: " + cell.getClass();
// live < live last delete
if (timestamp() < ((CounterCell) cell).timestampOfLastDelete())
return cell;
// live last delete > live
if (timestampOfLastDelete() > cell.timestamp())
return this;
// live + live. return one of the cells if its context is a superset of the other's, or merge them otherwise
ByteBuffer context = contextManager.merge(value(), cell.value());
if (context == value() && timestamp() >= cell.timestamp() && timestampOfLastDelete() >= ((CounterCell) cell).timestampOfLastDelete())
return this;
else if (context == cell.value() && cell.timestamp() >= timestamp() && ((CounterCell) cell).timestampOfLastDelete() >= timestampOfLastDelete())
return cell;
else // merge clocks and timsestamps.
return new CounterCell(name(),
context,
Math.max(timestamp(), cell.timestamp()),
Math.max(timestampOfLastDelete(), ((CounterCell) cell).timestampOfLastDelete()));
}
public boolean hasLegacyShards()
{
return contextManager.hasLegacyShards(value);
}
@Override
public boolean equals(Object o)
{
// super.equals() returns false if o is not a CounterCell
return super.equals(o) && timestampOfLastDelete == ((CounterCell)o).timestampOfLastDelete;
}
@Override
public int hashCode()
{
return 31 * super.hashCode() + (int)(timestampOfLastDelete ^ (timestampOfLastDelete >>> 32));
}
@Override
public Cell localCopy(AbstractAllocator allocator)
{
return new CounterCell(name.copy(allocator), allocator.clone(value), timestamp, timestampOfLastDelete);
}
@Override
public String getString(CellNameType comparator)
{
return String.format("%s:false:%s@%d!%d",
comparator.getString(name),
contextManager.toString(value),
timestamp,
timestampOfLastDelete);
}
@Override
public int serializationFlags()
{
return ColumnSerializer.COUNTER_MASK;
}
@Override
public void validateFields(CFMetaData metadata) throws MarshalException
{
validateName(metadata);
// We cannot use the value validator as for other columns as the CounterColumnType validate a long,
// which is not the internal representation of counters
contextManager.validateContext(value());
}
public Cell markLocalToBeCleared()
{
ByteBuffer marked = contextManager.markLocalToBeCleared(value);
return marked == value ? this : new CounterCell(name, marked, timestamp, timestampOfLastDelete);
}
CounterCell localCopy(CFMetaData metaData, MemtableAllocator allocator, OpOrder.Group opGroup);
}

View File

@ -200,9 +200,9 @@ public class CounterMutation implements IMutation
long clock = currentValue.clock + 1L;
long count = currentValue.count + update.delta();
resultCF.addColumn(new CounterCell(update.name(),
CounterContext.instance().createGlobal(CounterId.getLocalId(), clock, count),
update.timestamp()));
resultCF.addColumn(new BufferCounterCell(update.name(),
CounterContext.instance().createGlobal(CounterId.getLocalId(), clock, count),
update.timestamp()));
}
return resultCF;
@ -253,7 +253,7 @@ public class CounterMutation implements IMutation
SortedSet<CellName> names = new TreeSet<>(cfs.metadata.comparator);
for (int i = 0; i < currentValues.length; i++)
if (currentValues[i] == null)
names.add(counterUpdateCells.get(i).name);
names.add(counterUpdateCells.get(i).name());
ReadCommand cmd = new SliceByNamesReadCommand(getKeyspaceName(), key(), cfs.metadata.cfName, Long.MIN_VALUE, new NamesQueryFilter(names));
Row row = cmd.getRow(cfs.keyspace);

View File

@ -17,13 +17,6 @@
*/
package org.apache.cassandra.db;
import java.nio.ByteBuffer;
import org.apache.cassandra.db.composites.CellName;
import org.apache.cassandra.utils.memory.AbstractAllocator;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.db.composites.CellNameType;
/**
* A counter update while it hasn't been applied yet by the leader replica.
*
@ -31,61 +24,7 @@ import org.apache.cassandra.db.composites.CellNameType;
* is transformed to a relevant CounterCell. This Cell is a temporary data
* structure that should never be stored inside a memtable or an sstable.
*/
public class CounterUpdateCell extends Cell
public interface CounterUpdateCell extends Cell
{
public CounterUpdateCell(CellName name, long value, long timestamp)
{
this(name, ByteBufferUtil.bytes(value), timestamp);
}
public CounterUpdateCell(CellName name, ByteBuffer value, long timestamp)
{
super(name, value, timestamp);
}
public long delta()
{
return value().getLong(value().position());
}
@Override
public Cell diff(Cell cell)
{
// Diff is used during reads, but we should never read those columns
throw new UnsupportedOperationException("This operation is unsupported on CounterUpdateCell.");
}
@Override
public Cell reconcile(Cell cell)
{
// The only time this could happen is if a batchAdd ships two
// increment for the same cell. Hence we simply sums the delta.
// tombstones take precedence
if (cell.isMarkedForDelete(Long.MIN_VALUE)) // can't be an expired cell, so the current time is irrelevant
return timestamp() > cell.timestamp() ? this : cell;
// neither is tombstoned
assert cell instanceof CounterUpdateCell : "Wrong class type.";
CounterUpdateCell c = (CounterUpdateCell) cell;
return new CounterUpdateCell(name(), delta() + c.delta(), Math.max(timestamp(), c.timestamp()));
}
@Override
public int serializationFlags()
{
return ColumnSerializer.COUNTER_UPDATE_MASK;
}
@Override
public Cell localCopy(AbstractAllocator allocator)
{
throw new UnsupportedOperationException();
}
@Override
public String getString(CellNameType comparator)
{
return String.format("%s:%s@%d", comparator.getString(name), ByteBufferUtil.toLong(value), timestamp);
}
public long delta();
}

View File

@ -163,7 +163,7 @@ public class DataRange
private boolean equals(RowPosition pos, ByteBuffer rowKey)
{
return pos instanceof DecoratedKey && ((DecoratedKey)pos).key.equals(rowKey);
return pos instanceof DecoratedKey && ((DecoratedKey)pos).getKey().equals(rowKey);
}
@Override

View File

@ -22,6 +22,7 @@ import java.util.Comparator;
import org.apache.cassandra.dht.IPartitioner;
import org.apache.cassandra.dht.Token;
import org.apache.cassandra.service.StorageService;
import org.apache.cassandra.utils.ByteBufferUtil;
/**
@ -33,7 +34,7 @@ import org.apache.cassandra.utils.ByteBufferUtil;
* if this matters, you can subclass RP to use a stronger hash, or use a non-lossy tokenization scheme (as in the
* OrderPreservingPartitioner classes).
*/
public class DecoratedKey extends RowPosition
public abstract class DecoratedKey implements RowPosition
{
public static final Comparator<DecoratedKey> comparator = new Comparator<DecoratedKey>()
{
@ -43,20 +44,18 @@ public class DecoratedKey extends RowPosition
}
};
public final Token token;
public final ByteBuffer key;
private final Token token;
public DecoratedKey(Token token, ByteBuffer key)
public DecoratedKey(Token token)
{
assert token != null && key != null;
assert token != null;
this.token = token;
this.key = key;
}
@Override
public int hashCode()
{
return key.hashCode(); // hash of key is enough
return getKey().hashCode(); // hash of key is enough
}
@Override
@ -64,12 +63,11 @@ public class DecoratedKey extends RowPosition
{
if (this == obj)
return true;
if (obj == null || this.getClass() != obj.getClass())
if (obj == null || !(obj instanceof DecoratedKey))
return false;
DecoratedKey other = (DecoratedKey)obj;
return ByteBufferUtil.compareUnsigned(key, other.key) == 0; // we compare faster than BB.equals for array backed BB
return ByteBufferUtil.compareUnsigned(getKey(), other.getKey()) == 0; // we compare faster than BB.equals for array backed BB
}
public int compareTo(RowPosition pos)
@ -82,8 +80,8 @@ public class DecoratedKey extends RowPosition
return -pos.compareTo(this);
DecoratedKey otherKey = (DecoratedKey) pos;
int cmp = token.compareTo(otherKey.getToken());
return cmp == 0 ? ByteBufferUtil.compareUnsigned(key, otherKey.key) : cmp;
int cmp = getToken().compareTo(otherKey.getToken());
return cmp == 0 ? ByteBufferUtil.compareUnsigned(getKey(), otherKey.getKey()) : cmp;
}
public static int compareTo(IPartitioner partitioner, ByteBuffer key, RowPosition position)
@ -94,7 +92,7 @@ public class DecoratedKey extends RowPosition
DecoratedKey otherKey = (DecoratedKey) position;
int cmp = partitioner.getToken(key).compareTo(otherKey.getToken());
return cmp == 0 ? ByteBufferUtil.compareUnsigned(key, otherKey.key) : cmp;
return cmp == 0 ? ByteBufferUtil.compareUnsigned(key, otherKey.getKey()) : cmp;
}
public boolean isMinimum(IPartitioner partitioner)
@ -103,6 +101,11 @@ public class DecoratedKey extends RowPosition
return false;
}
public boolean isMinimum()
{
return isMinimum(StorageService.getPartitioner());
}
public RowPosition.Kind kind()
{
return RowPosition.Kind.ROW_KEY;
@ -111,12 +114,14 @@ public class DecoratedKey extends RowPosition
@Override
public String toString()
{
String keystring = key == null ? "null" : ByteBufferUtil.bytesToHex(key);
return "DecoratedKey(" + token + ", " + keystring + ")";
String keystring = getKey() == null ? "null" : ByteBufferUtil.bytesToHex(getKey());
return "DecoratedKey(" + getToken() + ", " + keystring + ")";
}
public Token getToken()
{
return token;
}
public abstract ByteBuffer getKey();
}

View File

@ -248,7 +248,7 @@ public class DefsTables
if (newState.hasColumns())
updateKeyspace(KSMetaData.fromSchema(new Row(key, newState), Collections.<CFMetaData>emptyList(), new UTMetaData()));
else
keyspacesToDrop.add(AsciiType.instance.getString(key.key));
keyspacesToDrop.add(AsciiType.instance.getString(key.getKey()));
}
return keyspacesToDrop;
@ -297,7 +297,7 @@ public class DefsTables
}
else // has modifications in the nested ColumnFamilies, need to perform nested diff to determine what was really changed
{
String ksName = AsciiType.instance.getString(keyspace.key);
String ksName = AsciiType.instance.getString(keyspace.getKey());
Map<String, CFMetaData> oldCfDefs = new HashMap<String, CFMetaData>();
for (CFMetaData cfm : Schema.instance.getKSMetaData(ksName).cfMetaData().values())

View File

@ -17,104 +17,14 @@
*/
package org.apache.cassandra.db;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.composites.CellName;
import org.apache.cassandra.io.util.DataOutputBuffer;
import org.apache.cassandra.serializers.MarshalException;
import org.apache.cassandra.utils.concurrent.OpOrder;
import org.apache.cassandra.utils.memory.AbstractAllocator;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.memory.MemtableAllocator;
public class DeletedCell extends Cell
public interface DeletedCell extends Cell
{
public DeletedCell(CellName name, int localDeletionTime, long timestamp)
{
this(name, ByteBufferUtil.bytes(localDeletionTime), timestamp);
}
DeletedCell localCopy(CFMetaData metadata, AbstractAllocator allocator);
public DeletedCell(CellName name, ByteBuffer value, long timestamp)
{
super(name, value, timestamp);
}
@Override
public Cell withUpdatedName(CellName newName)
{
return new DeletedCell(newName, value, timestamp);
}
@Override
public Cell withUpdatedTimestamp(long newTimestamp)
{
return new DeletedCell(name, value, newTimestamp);
}
@Override
public boolean isMarkedForDelete(long now)
{
return true;
}
@Override
public long getMarkedForDeleteAt()
{
return timestamp;
}
@Override
public void updateDigest(MessageDigest digest)
{
digest.update(name.toByteBuffer().duplicate());
DataOutputBuffer buffer = new DataOutputBuffer();
try
{
buffer.writeLong(timestamp);
buffer.writeByte(serializationFlags());
}
catch (IOException e)
{
throw new RuntimeException(e);
}
digest.update(buffer.getData(), 0, buffer.getLength());
}
@Override
public int getLocalDeletionTime()
{
return value.getInt(value.position());
}
@Override
public Cell reconcile(Cell cell)
{
if (cell instanceof DeletedCell)
return super.reconcile(cell);
return cell.reconcile(this);
}
@Override
public Cell localCopy(AbstractAllocator allocator)
{
return new DeletedCell(name.copy(allocator), allocator.clone(value), timestamp);
}
@Override
public int serializationFlags()
{
return ColumnSerializer.DELETION_MASK;
}
@Override
public void validateFields(CFMetaData metadata) throws MarshalException
{
validateName(metadata);
if (value().remaining() != 4)
throw new MarshalException("A tombstone value should be 4 bytes long");
if (getLocalDeletionTime() < 0)
throw new MarshalException("The local deletion time should not be negative");
}
DeletedCell localCopy(CFMetaData metaData, MemtableAllocator allocator, OpOrder.Group opGroup);
}

View File

@ -17,16 +17,10 @@
*/
package org.apache.cassandra.db;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.composites.CellName;
import org.apache.cassandra.db.composites.CellNameType;
import org.apache.cassandra.io.util.DataOutputBuffer;
import org.apache.cassandra.serializers.MarshalException;
import org.apache.cassandra.utils.concurrent.OpOrder;
import org.apache.cassandra.utils.memory.AbstractAllocator;
import org.apache.cassandra.utils.memory.MemtableAllocator;
/**
* Alternative to Cell that have an expiring time.
@ -38,154 +32,13 @@ import org.apache.cassandra.utils.memory.AbstractAllocator;
* we can't mix it with the timestamp field, which is client-supplied and whose resolution we
* can't assume anything about.)
*/
public class ExpiringCell extends Cell
public interface ExpiringCell extends Cell
{
public static final int MAX_TTL = 20 * 365 * 24 * 60 * 60; // 20 years in seconds
private final int localExpirationTime;
private final int timeToLive;
public int getTimeToLive();
public ExpiringCell(CellName name, ByteBuffer value, long timestamp, int timeToLive)
{
this(name, value, timestamp, timeToLive, (int) (System.currentTimeMillis() / 1000) + timeToLive);
}
ExpiringCell localCopy(CFMetaData metadata, AbstractAllocator allocator);
public ExpiringCell(CellName name, ByteBuffer value, long timestamp, int timeToLive, int localExpirationTime)
{
super(name, value, timestamp);
assert timeToLive > 0 : timeToLive;
assert localExpirationTime > 0 : localExpirationTime;
this.timeToLive = timeToLive;
this.localExpirationTime = localExpirationTime;
}
/** @return Either a DeletedCell, or an ExpiringCell. */
public static Cell create(CellName name, ByteBuffer value, long timestamp, int timeToLive, int localExpirationTime, int expireBefore, ColumnSerializer.Flag flag)
{
if (localExpirationTime >= expireBefore || flag == ColumnSerializer.Flag.PRESERVE_SIZE)
return new ExpiringCell(name, value, timestamp, timeToLive, localExpirationTime);
// The column is now expired, we can safely return a simple tombstone. Note that
// as long as the expiring column and the tombstone put together live longer than GC grace seconds,
// we'll fulfil our responsibility to repair. See discussion at
// http://cassandra-user-incubator-apache-org.3065146.n2.nabble.com/repair-compaction-and-tombstone-rows-td7583481.html
return new DeletedCell(name, localExpirationTime - timeToLive, timestamp);
}
public int getTimeToLive()
{
return timeToLive;
}
@Override
public Cell withUpdatedName(CellName newName)
{
return new ExpiringCell(newName, value, timestamp, timeToLive, localExpirationTime);
}
@Override
public Cell withUpdatedTimestamp(long newTimestamp)
{
return new ExpiringCell(name, value, newTimestamp, timeToLive, localExpirationTime);
}
@Override
public int dataSize()
{
return super.dataSize() + TypeSizes.NATIVE.sizeof(localExpirationTime) + TypeSizes.NATIVE.sizeof(timeToLive);
}
@Override
public int serializedSize(CellNameType type, TypeSizes typeSizes)
{
/*
* An expired column adds to a Cell :
* 4 bytes for the localExpirationTime
* + 4 bytes for the timeToLive
*/
return super.serializedSize(type, typeSizes) + typeSizes.sizeof(localExpirationTime) + typeSizes.sizeof(timeToLive);
}
@Override
public void updateDigest(MessageDigest digest)
{
digest.update(name.toByteBuffer().duplicate());
digest.update(value.duplicate());
DataOutputBuffer buffer = new DataOutputBuffer();
try
{
buffer.writeLong(timestamp);
buffer.writeByte(serializationFlags());
buffer.writeInt(timeToLive);
}
catch (IOException e)
{
throw new RuntimeException(e);
}
digest.update(buffer.getData(), 0, buffer.getLength());
}
@Override
public int getLocalDeletionTime()
{
return localExpirationTime;
}
@Override
public Cell localCopy(AbstractAllocator allocator)
{
return new ExpiringCell(name.copy(allocator), allocator.clone(value), timestamp, timeToLive, localExpirationTime);
}
@Override
public String getString(CellNameType comparator)
{
return String.format("%s!%d", super.getString(comparator), timeToLive);
}
@Override
public boolean isMarkedForDelete(long now)
{
return (int) (now / 1000) >= getLocalDeletionTime();
}
@Override
public long getMarkedForDeleteAt()
{
return timestamp;
}
@Override
public int serializationFlags()
{
return ColumnSerializer.EXPIRATION_MASK;
}
@Override
public void validateFields(CFMetaData metadata) throws MarshalException
{
super.validateFields(metadata);
if (timeToLive <= 0)
throw new MarshalException("A column TTL should be > 0");
if (localExpirationTime < 0)
throw new MarshalException("The local expiration time should not be negative");
}
@Override
public boolean equals(Object o)
{
// super.equals() returns false if o is not a CounterCell
return super.equals(o)
&& localExpirationTime == ((ExpiringCell)o).localExpirationTime
&& timeToLive == ((ExpiringCell)o).timeToLive;
}
@Override
public int hashCode()
{
int result = super.hashCode();
result = 31 * result + localExpirationTime;
result = 31 * result + timeToLive;
return result;
}
ExpiringCell localCopy(CFMetaData metaData, MemtableAllocator allocator, OpOrder.Group opGroup);
}

View File

@ -514,7 +514,7 @@ public class HintedHandOffManager implements HintedHandOffManagerMBean
List<Row> rows = hintStore.getRangeSlice(range, null, filter, Integer.MAX_VALUE, System.currentTimeMillis());
for (Row row : rows)
{
UUID hostId = UUIDGen.getUUID(row.key.key);
UUID hostId = UUIDGen.getUUID(row.key.getKey());
InetAddress target = StorageService.instance.getTokenMetadata().getEndpointForHostId(hostId);
// token may have since been removed (in which case we have just read back a tombstone)
if (target != null)
@ -573,7 +573,7 @@ public class HintedHandOffManager implements HintedHandOffManagerMBean
for (Row row : getHintsSlice(1))
{
if (row.cf != null) //ignore removed rows
result.addFirst(tokenFactory.toString(row.key.token));
result.addFirst(tokenFactory.toString(row.key.getToken()));
}
return result;
}

View File

@ -410,13 +410,13 @@ public class Keyspace
public static void indexRow(DecoratedKey key, ColumnFamilyStore cfs, Set<String> idxNames)
{
if (logger.isDebugEnabled())
logger.debug("Indexing row {} ", cfs.metadata.getKeyValidator().getString(key.key));
logger.debug("Indexing row {} ", cfs.metadata.getKeyValidator().getString(key.getKey()));
try (OpOrder.Group opGroup = cfs.keyspace.writeOrder.start())
{
Set<SecondaryIndex> indexes = cfs.indexManager.getIndexesByNames(idxNames);
Iterator<ColumnFamily> pager = QueryPagers.pageRowLocally(cfs, key.key, DEFAULT_PAGE_SIZE);
Iterator<ColumnFamily> pager = QueryPagers.pageRowLocally(cfs, key.getKey(), DEFAULT_PAGE_SIZE);
while (pager.hasNext())
{
ColumnFamily cf = pager.next();
@ -426,7 +426,7 @@ public class Keyspace
if (cfs.indexManager.indexes(cell.name(), indexes))
cf2.addColumn(cell);
}
cfs.indexManager.indexRow(key.key, cf2, opGroup);
cfs.indexManager.indexRow(key.getKey(), cf2, opGroup);
}
}
}

View File

@ -46,19 +46,16 @@ import org.apache.cassandra.service.ActiveRepairService;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.ObjectSizes;
import org.apache.cassandra.utils.concurrent.OpOrder;
import org.apache.cassandra.utils.memory.ContextAllocator;
import org.apache.cassandra.utils.memory.HeapAllocator;
import org.apache.cassandra.utils.memory.Pool;
import org.apache.cassandra.utils.memory.PoolAllocator;
import org.apache.cassandra.utils.memory.*;
public class Memtable
{
private static final Logger logger = LoggerFactory.getLogger(Memtable.class);
static final Pool memoryPool = DatabaseDescriptor.getMemtableAllocatorPool();
static final MemtablePool MEMORY_POOL = DatabaseDescriptor.getMemtableAllocatorPool();
private static final int ROW_OVERHEAD_HEAP_SIZE;
private final PoolAllocator allocator;
private final MemtableAllocator allocator;
private final AtomicLong liveDataSize = new AtomicLong(0);
private final AtomicLong currentOperations = new AtomicLong(0);
@ -85,12 +82,12 @@ public class Memtable
public Memtable(ColumnFamilyStore cfs)
{
this.cfs = cfs;
this.allocator = memoryPool.newAllocator();
this.allocator = MEMORY_POOL.newAllocator();
this.initialComparator = cfs.metadata.comparator;
this.cfs.scheduleFlush();
}
public PoolAllocator getAllocator()
public MemtableAllocator getAllocator()
{
return allocator;
}
@ -177,7 +174,7 @@ public class Memtable
if (previous == null)
{
AtomicBTreeColumns empty = cf.cloneMeShallow(AtomicBTreeColumns.factory, false);
final DecoratedKey cloneKey = new DecoratedKey(key.token, allocator.clone(key.key, opGroup));
final DecoratedKey cloneKey = allocator.clone(key, opGroup);
// We'll add the columns later. This avoids wasting works if we get beaten in the putIfAbsent
previous = rows.putIfAbsent(cloneKey, empty);
if (previous == null)
@ -185,27 +182,17 @@ public class Memtable
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) (cfs.partitioner.getHeapSizeOf(key.token) + ROW_OVERHEAD_HEAP_SIZE);
allocator.allocate(overhead, opGroup);
int overhead = (int) (cfs.partitioner.getHeapSizeOf(key.getToken()) + ROW_OVERHEAD_HEAP_SIZE);
allocator.onHeap().allocate(overhead, opGroup);
}
else
{
allocator.free(cloneKey.key);
allocator.reclaimer().reclaimImmediately(cloneKey);
}
}
ContextAllocator contextAllocator = allocator.wrap(opGroup);
AtomicBTreeColumns.Delta delta = previous.addAllWithSizeDelta(cf, contextAllocator, indexer, new AtomicBTreeColumns.Delta());
liveDataSize.addAndGet(delta.dataSize());
liveDataSize.addAndGet(previous.addAllWithSizeDelta(cf, allocator, opGroup, indexer));
currentOperations.addAndGet(cf.getColumnCount() + (cf.isMarkedForDelete() ? 1 : 0) + cf.deletionInfo().rangeCount());
// allocate or free the delta in column overhead after the fact
for (Cell cell : delta.reclaimed())
{
cell.name.free(allocator);
allocator.free(cell.value);
}
allocator.allocate((int) delta.excessHeapSize(), opGroup);
}
// for debugging
@ -256,10 +243,10 @@ public class Memtable
Map.Entry<? extends RowPosition, ? extends ColumnFamily> entry = iter.next();
// Actual stored key should be true DecoratedKey
assert entry.getKey() instanceof DecoratedKey;
if (memoryPool.needToCopyOnHeap())
if (MEMORY_POOL.needToCopyOnHeap())
{
DecoratedKey key = (DecoratedKey) entry.getKey();
key = new DecoratedKey(key.token, HeapAllocator.instance.clone(key.key));
key = new BufferDecoratedKey(key.getToken(), HeapAllocator.instance.clone(key.getKey()));
ColumnFamily cells = ArrayBackedSortedColumns.localCopy(entry.getValue(), HeapAllocator.instance);
entry = new AbstractMap.SimpleImmutableEntry<>(key, cells);
}
@ -307,7 +294,7 @@ public class Memtable
{
// make sure we don't write non-sensical keys
assert key instanceof DecoratedKey;
keySize += ((DecoratedKey)key).key.remaining();
keySize += ((DecoratedKey)key).getKey().remaining();
}
estimatedSize = (long) ((keySize // index entries
+ keySize // keys in data file
@ -410,16 +397,20 @@ public class Memtable
static
{
// calculate row overhead
final OpOrder.Group group = new OpOrder().start();
int rowOverhead;
MemtableAllocator allocator = MEMORY_POOL.newAllocator();
ConcurrentNavigableMap<RowPosition, Object> rows = new ConcurrentSkipListMap<>();
final int count = 100000;
final Object val = new Object();
for (int i = 0 ; i < count ; i++)
rows.put(new DecoratedKey(new LongToken((long) i), ByteBufferUtil.EMPTY_BYTE_BUFFER), val);
rows.put(allocator.clone(new BufferDecoratedKey(new LongToken((long) i), ByteBufferUtil.EMPTY_BYTE_BUFFER), group), val);
double avgSize = ObjectSizes.measureDeep(rows) / (double) count;
rowOverhead = (int) ((avgSize - Math.floor(avgSize)) < 0.05 ? Math.floor(avgSize) : Math.ceil(avgSize));
rowOverhead -= ObjectSizes.measureDeep(new LongToken((long) 0));
rowOverhead += AtomicBTreeColumns.HEAP_SIZE;
rowOverhead += AtomicBTreeColumns.EMPTY_SIZE;
allocator.setDiscarding();
allocator.setDiscarded();
ROW_OVERHEAD_HEAP_SIZE = rowOverhead;
}
}

View File

@ -64,7 +64,7 @@ public class Mutation implements IMutation
public Mutation(String keyspaceName, Row row)
{
this(keyspaceName, row.key.key, row.cf);
this(keyspaceName, row.key.getKey(), row.cf);
}
protected Mutation(String keyspaceName, ByteBuffer key, Map<UUID, ColumnFamily> modifications)

View File

@ -0,0 +1,88 @@
/*
* 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.security.MessageDigest;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.composites.CellName;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.ObjectSizes;
import org.apache.cassandra.utils.concurrent.OpOrder;
import org.apache.cassandra.utils.memory.AbstractAllocator;
import org.apache.cassandra.utils.memory.MemtableAllocator;
import org.apache.cassandra.utils.memory.NativeAllocator;
public class NativeCell extends AbstractNativeCell
{
private static final long SIZE = ObjectSizes.measure(new NativeCell());
NativeCell()
{}
public NativeCell(NativeAllocator allocator, OpOrder.Group writeOp, Cell copyOf)
{
super(allocator, writeOp, copyOf);
}
@Override
public CellName name()
{
return this;
}
@Override
public long timestamp()
{
return getLong(TIMESTAMP_OFFSET);
}
@Override
public Cell localCopy(CFMetaData metadata, AbstractAllocator allocator)
{
return new BufferCell(copy(metadata, allocator), allocator.clone(value()), timestamp());
}
@Override
public Cell localCopy(CFMetaData metadata, MemtableAllocator allocator, OpOrder.Group opGroup)
{
return allocator.clone(this, metadata, opGroup);
}
@Override
public void updateDigest(MessageDigest digest)
{
updateWithName(digest); // name
updateWithValue(digest); // value
FBUtilities.updateWithLong(digest, timestamp());
FBUtilities.updateWithByte(digest, serializationFlags());
}
@Override
public long excessHeapSizeExcludingData()
{
return SIZE;
}
@Override
public long unsharedHeapSize()
{
return SIZE;
}
}

View File

@ -0,0 +1,190 @@
/*
* 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.security.MessageDigest;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.composites.CellNameType;
import org.apache.cassandra.serializers.MarshalException;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.ObjectSizes;
import org.apache.cassandra.utils.concurrent.OpOrder;
import org.apache.cassandra.utils.memory.AbstractAllocator;
import org.apache.cassandra.utils.memory.MemtableAllocator;
import org.apache.cassandra.utils.memory.NativeAllocator;
public class NativeCounterCell extends NativeCell implements CounterCell
{
private static final long SIZE = ObjectSizes.measure(new NativeCounterCell());
private NativeCounterCell()
{}
public NativeCounterCell(NativeAllocator allocator, OpOrder.Group writeOp, CounterCell copyOf)
{
super(allocator, writeOp, copyOf);
}
@Override
protected void construct(Cell from)
{
super.construct(from);
setLong(internalSize() - 8, ((CounterCell) from).timestampOfLastDelete());
}
@Override
protected int postfixSize()
{
return 8;
}
@Override
protected int sizeOf(Cell cell)
{
return 8 + super.sizeOf(cell);
}
@Override
public long timestampOfLastDelete()
{
return getLong(internalSize() - 8);
}
@Override
public long total()
{
return contextManager.total(value());
}
@Override
public boolean hasLegacyShards()
{
return contextManager.hasLegacyShards(value());
}
@Override
public Cell markLocalToBeCleared()
{
throw new UnsupportedOperationException();
}
@Override
public Cell diff(Cell cell)
{
return diff(this, cell);
}
@Override
public Cell reconcile(Cell cell)
{
return reconcile(this, cell);
}
@Override
public int serializationFlags()
{
return ColumnSerializer.COUNTER_MASK;
}
@Override
public int cellDataSize()
{
// A counter column adds 8 bytes for timestampOfLastDelete to Cell.
return super.cellDataSize() + TypeSizes.NATIVE.sizeof(timestampOfLastDelete());
}
@Override
public int serializedSize(CellNameType type, TypeSizes typeSizes)
{
return super.serializedSize(type, typeSizes) + typeSizes.sizeof(timestampOfLastDelete());
}
@Override
public void validateFields(CFMetaData metadata) throws MarshalException
{
validateName(metadata);
// We cannot use the value validator as for other columns as the CounterColumnType validate a long,
// which is not the internal representation of counters
contextManager.validateContext(value());
}
/*
* We have to special case digest creation for counter column because
* we don't want to include the information about which shard of the
* context is a delta or not, since this information differs from node to
* node.
*/
@Override
public void updateDigest(MessageDigest digest)
{
updateWithName(digest);
// We don't take the deltas into account in a digest
contextManager.updateDigest(digest, value());
FBUtilities.updateWithLong(digest, timestamp());
FBUtilities.updateWithByte(digest, serializationFlags());
FBUtilities.updateWithLong(digest, timestampOfLastDelete());
}
@Override
public String getString(CellNameType comparator)
{
return String.format("%s(%s:false:%s@%d!%d)",
getClass().getSimpleName(),
comparator.getString(name()),
contextManager.toString(value()),
timestamp(),
timestampOfLastDelete());
}
@Override
public CounterCell localCopy(CFMetaData metadata, AbstractAllocator allocator)
{
return new BufferCounterCell(copy(metadata, allocator), allocator.clone(value()), timestamp(), timestampOfLastDelete());
}
@Override
public CounterCell localCopy(CFMetaData metadata, MemtableAllocator allocator, OpOrder.Group opGroup)
{
return allocator.clone(this, metadata, opGroup);
}
@Override
public long excessHeapSizeExcludingData()
{
return SIZE;
}
@Override
public long unsharedHeapSize()
{
return SIZE;
}
public boolean equals(Cell cell)
{
return cell instanceof CounterCell && equals((CounterCell) this);
}
public boolean equals(CounterCell cell)
{
return super.equals(cell) && timestampOfLastDelete() == cell.timestampOfLastDelete();
}
}

View File

@ -0,0 +1,45 @@
/*
* 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.nio.ByteBuffer;
import org.apache.cassandra.dht.Token;
import org.apache.cassandra.utils.concurrent.OpOrder;
import org.apache.cassandra.utils.memory.MemoryUtil;
import org.apache.cassandra.utils.memory.NativeAllocator;
public class NativeDecoratedKey extends DecoratedKey
{
private final long peer;
public NativeDecoratedKey(Token token, NativeAllocator allocator, OpOrder.Group writeOp, ByteBuffer key)
{
super(token);
assert key != null;
int size = key.remaining();
this.peer = allocator.allocate(4 + size, writeOp);
MemoryUtil.setInt(peer, size);
MemoryUtil.setBytes(peer + 4, key);
}
public ByteBuffer getKey()
{
return MemoryUtil.getByteBuffer(peer + 4, MemoryUtil.getInt(peer));
}
}

View File

@ -0,0 +1,125 @@
/*
* 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.security.MessageDigest;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.serializers.MarshalException;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.ObjectSizes;
import org.apache.cassandra.utils.concurrent.OpOrder;
import org.apache.cassandra.utils.memory.AbstractAllocator;
import org.apache.cassandra.utils.memory.MemoryUtil;
import org.apache.cassandra.utils.memory.MemtableAllocator;
import org.apache.cassandra.utils.memory.NativeAllocator;
public class NativeDeletedCell extends NativeCell implements DeletedCell
{
private static final long SIZE = ObjectSizes.measure(new NativeDeletedCell());
private NativeDeletedCell()
{}
public NativeDeletedCell(NativeAllocator allocator, OpOrder.Group writeOp, DeletedCell copyOf)
{
super(allocator, writeOp, copyOf);
}
@Override
public Cell reconcile(Cell cell)
{
if (cell instanceof DeletedCell)
return super.reconcile(cell);
return cell.reconcile(this);
}
@Override
public boolean isMarkedForDelete(long now)
{
return true;
}
@Override
public long getMarkedForDeleteAt()
{
return timestamp();
}
@Override
public int getLocalDeletionTime()
{
int v = getInt(valueStartOffset());
return MemoryUtil.INVERTED_ORDER ? Integer.reverseBytes(v) : v;
}
@Override
public int serializationFlags()
{
return ColumnSerializer.DELETION_MASK;
}
@Override
public void validateFields(CFMetaData metadata) throws MarshalException
{
validateName(metadata);
if ((int) (internalSize() - valueStartOffset()) != 4)
throw new MarshalException("A tombstone value should be 4 bytes long");
if (getLocalDeletionTime() < 0)
throw new MarshalException("The local deletion time should not be negative");
}
@Override
public void updateDigest(MessageDigest digest)
{
updateWithName(digest);
FBUtilities.updateWithLong(digest, timestamp());
FBUtilities.updateWithByte(digest, serializationFlags());
}
@Override
public DeletedCell localCopy(CFMetaData metadata, AbstractAllocator allocator)
{
return new BufferDeletedCell(copy(metadata, allocator), allocator.clone(value()), timestamp());
}
@Override
public DeletedCell localCopy(CFMetaData metadata, MemtableAllocator allocator, OpOrder.Group opGroup)
{
return allocator.clone(this, metadata, opGroup);
}
@Override
public boolean equals(Cell cell)
{
return timestamp() == cell.timestamp() && getLocalDeletionTime() == cell.getLocalDeletionTime() && name().equals(cell.name());
}
@Override
public long excessHeapSizeExcludingData()
{
return SIZE;
}
@Override
public long unsharedHeapSize()
{
return SIZE;
}
}

View File

@ -0,0 +1,173 @@
/*
* 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.security.MessageDigest;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.composites.CellNameType;
import org.apache.cassandra.serializers.MarshalException;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.ObjectSizes;
import org.apache.cassandra.utils.concurrent.OpOrder;
import org.apache.cassandra.utils.memory.AbstractAllocator;
import org.apache.cassandra.utils.memory.MemtableAllocator;
import org.apache.cassandra.utils.memory.NativeAllocator;
public class NativeExpiringCell extends NativeCell implements ExpiringCell
{
private static final long SIZE = ObjectSizes.measure(new NativeExpiringCell());
private NativeExpiringCell()
{}
public NativeExpiringCell(NativeAllocator allocator, OpOrder.Group writeOp, ExpiringCell copyOf)
{
super(allocator, writeOp, copyOf);
}
@Override
protected int sizeOf(Cell cell)
{
return super.sizeOf(cell) + 8;
}
@Override
protected void construct(Cell from)
{
ExpiringCell expiring = (ExpiringCell) from;
setInt(internalSize() - 4, expiring.getTimeToLive());
setInt(internalSize() - 8, expiring.getLocalDeletionTime());
super.construct(from);
}
@Override
protected int postfixSize()
{
return 8;
}
@Override
public int getTimeToLive()
{
return getInt(internalSize() - 4);
}
@Override
public int getLocalDeletionTime()
{
return getInt(internalSize() - 8);
}
@Override
public boolean isMarkedForDelete(long now)
{
return (int) (now / 1000) >= getLocalDeletionTime();
}
@Override
public long getMarkedForDeleteAt()
{
return timestamp();
}
@Override
public int serializationFlags()
{
return ColumnSerializer.EXPIRATION_MASK;
}
@Override
public int cellDataSize()
{
return super.cellDataSize() + TypeSizes.NATIVE.sizeof(getLocalDeletionTime()) + TypeSizes.NATIVE.sizeof(getTimeToLive());
}
@Override
public int serializedSize(CellNameType type, TypeSizes typeSizes)
{
/*
* An expired column adds to a Cell :
* 4 bytes for the localExpirationTime
* + 4 bytes for the timeToLive
*/
return super.serializedSize(type, typeSizes) + typeSizes.sizeof(getLocalDeletionTime()) + typeSizes.sizeof(getTimeToLive());
}
@Override
public void validateFields(CFMetaData metadata) throws MarshalException
{
super.validateFields(metadata);
if (getTimeToLive() <= 0)
throw new MarshalException("A column TTL should be > 0");
if (getLocalDeletionTime() < 0)
throw new MarshalException("The local expiration time should not be negative");
}
@Override
public void updateDigest(MessageDigest digest)
{
super.updateDigest(digest);
FBUtilities.updateWithInt(digest, getTimeToLive());
}
public boolean equals(Cell cell)
{
return cell instanceof ExpiringCell && equals((ExpiringCell) this);
}
protected boolean equals(ExpiringCell cell)
{
// super.equals() returns false if o is not a CounterCell
return super.equals(cell)
&& getLocalDeletionTime() == cell.getLocalDeletionTime()
&& getTimeToLive() == cell.getTimeToLive();
}
@Override
public String getString(CellNameType comparator)
{
return String.format("%s(%s!%d)", getClass().getSimpleName(), super.getString(comparator), getTimeToLive());
}
@Override
public ExpiringCell localCopy(CFMetaData metadata, AbstractAllocator allocator)
{
return new BufferExpiringCell(name().copy(metadata, allocator), allocator.clone(value()), timestamp(), getTimeToLive(), getLocalDeletionTime());
}
@Override
public ExpiringCell localCopy(CFMetaData metadata, MemtableAllocator allocator, OpOrder.Group opGroup)
{
return allocator.clone(this, metadata, opGroup);
}
@Override
public long excessHeapSizeExcludingData()
{
return SIZE;
}
@Override
public long unsharedHeapSize()
{
return SIZE;
}
}

View File

@ -64,7 +64,7 @@ public class Row
{
public void serialize(Row row, DataOutputPlus out, int version) throws IOException
{
ByteBufferUtil.writeWithShortLength(row.key.key, out);
ByteBufferUtil.writeWithShortLength(row.key.getKey(), out);
ColumnFamily.serializer.serialize(row.cf, out, version);
}
@ -81,7 +81,7 @@ public class Row
public long serializedSize(Row row, int version)
{
int keySize = row.key.key.remaining();
int keySize = row.key.getKey().remaining();
return TypeSizes.NATIVE.sizeof((short) keySize) + keySize + ColumnFamily.serializer.serializedSize(row.cf, TypeSizes.NATIVE, version);
}
}

View File

@ -96,7 +96,7 @@ public class RowIteratorFactory
{
// First check if this row is in the rowCache. If it is and it covers our filter, we can skip the rest
ColumnFamily cached = cfs.getRawCachedRow(key);
IDiskAtomFilter filter = range.columnFilter(key.key);
IDiskAtomFilter filter = range.columnFilter(key.getKey());
if (cached == null || !cfs.isFilterFullyCoveredBy(filter, cached, now))
{
@ -150,7 +150,7 @@ public class RowIteratorFactory
{
public OnDiskAtomIterator create()
{
return range.columnFilter(entry.getKey().key).getColumnFamilyIterator(entry.getKey(), entry.getValue());
return range.columnFilter(entry.getKey().getKey()).getColumnFamilyIterator(entry.getKey(), entry.getValue());
}
});
}

View File

@ -27,7 +27,7 @@ import org.apache.cassandra.io.util.DataOutputPlus;
import org.apache.cassandra.service.StorageService;
import org.apache.cassandra.utils.ByteBufferUtil;
public abstract class RowPosition implements RingPosition<RowPosition>
public interface RowPosition extends RingPosition<RowPosition>
{
public static enum Kind
{
@ -43,20 +43,18 @@ public abstract class RowPosition implements RingPosition<RowPosition>
}
}
public static final class ForKey
{
public static RowPosition get(ByteBuffer key, IPartitioner p)
{
return key == null || key.remaining() == 0 ? p.getMinimumToken().minKeyBound() : p.decorateKey(key);
}
}
public static final RowPositionSerializer serializer = new RowPositionSerializer();
public static RowPosition forKey(ByteBuffer key, IPartitioner p)
{
return key == null || key.remaining() == 0 ? p.getMinimumToken().minKeyBound() : p.decorateKey(key);
}
public abstract Token getToken();
public abstract Kind kind();
public boolean isMinimum()
{
return isMinimum(StorageService.getPartitioner());
}
public Kind kind();
public boolean isMinimum();
public static class RowPositionSerializer implements ISerializer<RowPosition>
{
@ -76,7 +74,7 @@ public abstract class RowPosition implements RingPosition<RowPosition>
Kind kind = pos.kind();
out.writeByte(kind.ordinal());
if (kind == Kind.ROW_KEY)
ByteBufferUtil.writeWithShortLength(((DecoratedKey)pos).key, out);
ByteBufferUtil.writeWithShortLength(((DecoratedKey)pos).getKey(), out);
else
Token.serializer.serialize(pos.getToken(), out);
}
@ -102,7 +100,7 @@ public abstract class RowPosition implements RingPosition<RowPosition>
int size = 1; // 1 byte for enum
if (kind == Kind.ROW_KEY)
{
int keySize = ((DecoratedKey)pos).key.remaining();
int keySize = ((DecoratedKey)pos).getKey().remaining();
size += typeSizes.sizeof((short) keySize) + keySize;
}
else

View File

@ -696,7 +696,7 @@ public class SystemKeyspace
public static void setIndexBuilt(String keyspaceName, String indexName)
{
ColumnFamily cf = ArrayBackedSortedColumns.factory.create(Keyspace.SYSTEM_KS, INDEX_CF);
cf.addColumn(new Cell(cf.getComparator().makeCellName(indexName), ByteBufferUtil.EMPTY_BYTE_BUFFER, FBUtilities.timestampMicros()));
cf.addColumn(new BufferCell(cf.getComparator().makeCellName(indexName), ByteBufferUtil.EMPTY_BYTE_BUFFER, FBUtilities.timestampMicros()));
new Mutation(Keyspace.SYSTEM_KS, ByteBufferUtil.bytes(keyspaceName), cf).apply();
}
@ -774,7 +774,7 @@ public class SystemKeyspace
ByteBuffer ip = ByteBuffer.wrap(FBUtilities.getBroadcastAddress().getAddress());
ColumnFamily cf = ArrayBackedSortedColumns.factory.create(Keyspace.SYSTEM_KS, COUNTER_ID_CF);
cf.addColumn(new Cell(cf.getComparator().makeCellName(newCounterId.bytes()), ip, now));
cf.addColumn(new BufferCell(cf.getComparator().makeCellName(newCounterId.bytes()), ip, now));
new Mutation(Keyspace.SYSTEM_KS, ALL_LOCAL_NODE_ID_KEY, cf).apply();
forceBlockingFlush(COUNTER_ID_CF);
}
@ -833,7 +833,7 @@ public class SystemKeyspace
Mutation mutation = mutationMap.get(schemaRow.key);
if (mutation == null)
{
mutation = new Mutation(Keyspace.SYSTEM_KS, schemaRow.key.key);
mutation = new Mutation(Keyspace.SYSTEM_KS, schemaRow.key.getKey());
mutationMap.put(schemaRow.key, mutation);
}

View File

@ -315,7 +315,7 @@ public abstract class AbstractCompactionStrategy
long keys = sstable.estimatedKeys();
Set<Range<Token>> ranges = new HashSet<Range<Token>>(overlaps.size());
for (SSTableReader overlap : overlaps)
ranges.add(new Range<Token>(overlap.first.token, overlap.last.token, overlap.partitioner));
ranges.add(new Range<Token>(overlap.first.getToken(), overlap.last.getToken(), overlap.partitioner));
long remainingKeys = keys - sstable.estimatedKeysForRanges(ranges);
// next, calculate what percentage of columns we have within those keys
long columns = sstable.getEstimatedColumnCount().mean() * remainingKeys;

View File

@ -156,7 +156,7 @@ public class CompactionController implements AutoCloseable
// we check index file instead.
if (sstable.getBloomFilter() instanceof AlwaysPresentFilter && sstable.getPosition(key, SSTableReader.Operator.EQ, false) != null)
min = Math.min(min, sstable.getMinTimestamp());
else if (sstable.getBloomFilter().isPresent(key.key))
else if (sstable.getBloomFilter().isPresent(key.getKey()))
min = Math.min(min, sstable.getMinTimestamp());
}
return min;

View File

@ -406,7 +406,7 @@ public class CompactionManager implements CompactionManagerMBean
SSTableReader sstable = sstableIterator.next();
for (Range<Token> r : Range.normalize(ranges))
{
Range<Token> sstableRange = new Range<>(sstable.first.token, sstable.last.token, sstable.partitioner);
Range<Token> sstableRange = new Range<>(sstable.first.getToken(), sstable.last.getToken(), sstable.partitioner);
if (r.contains(sstableRange))
{
logger.info("SSTable {} fully contained in range {}, mutating repairedAt instead of anticompacting", sstable, r);
@ -602,7 +602,7 @@ public class CompactionManager implements CompactionManagerMBean
// see if there are any keys LTE the token for the start of the first range
// (token range ownership is exclusive on the LHS.)
Range<Token> firstRange = sortedRanges.get(0);
if (sstable.first.token.compareTo(firstRange.left) <= 0)
if (sstable.first.getToken().compareTo(firstRange.left) <= 0)
return true;
// then, iterate over all owned ranges and see if the next key beyond the end of the owned
@ -631,7 +631,7 @@ public class CompactionManager implements CompactionManagerMBean
}
Range<Token> nextRange = sortedRanges.get(i + 1);
if (!nextRange.contains(firstBeyondRange.token))
if (!nextRange.contains(firstBeyondRange.getToken()))
{
// we found a key in between the owned ranges
return true;
@ -651,7 +651,7 @@ public class CompactionManager implements CompactionManagerMBean
{
assert !cfs.isIndex();
if (!hasIndexes && !new Bounds<>(sstable.first.token, sstable.last.token).intersects(ranges))
if (!hasIndexes && !new Bounds<>(sstable.first.getToken(), sstable.last.getToken()).intersects(ranges))
{
cfs.getDataTracker().markCompactedSSTablesReplaced(Arrays.asList(sstable), Collections.<SSTableReader>emptyList(), OperationType.CLEANUP);
return;
@ -796,7 +796,7 @@ public class CompactionManager implements CompactionManagerMBean
@Override
public SSTableIdentityIterator cleanup(SSTableIdentityIterator row)
{
if (Range.isInRanges(row.getKey().token, ranges))
if (Range.isInRanges(row.getKey().getToken(), ranges))
return row;
cfs.invalidateCachedRow(row.getKey());
@ -972,7 +972,7 @@ public class CompactionManager implements CompactionManagerMBean
{
AbstractCompactedRow row = iter.next();
// if current range from sstable is repaired, save it into the new repaired sstable
if (Range.isInRanges(row.key.token, ranges))
if (Range.isInRanges(row.key.getToken(), ranges))
{
repairedSSTableWriter.append(row);
repairedKeyCount++;

View File

@ -106,7 +106,7 @@ public class LazilyCompactedRow extends AbstractCompactedRow
ColumnIndex columnsIndex;
try
{
indexBuilder = new ColumnIndex.Builder(emptyColumnFamily, key.key, out);
indexBuilder = new ColumnIndex.Builder(emptyColumnFamily, key.getKey(), out);
columnsIndex = indexBuilder.buildForCompaction(merger);
// if there aren't any columns or tombstones, return null
@ -156,7 +156,7 @@ public class LazilyCompactedRow extends AbstractCompactedRow
}
// initialize indexBuilder for the benefit of its tombstoneTracker, used by our reducing iterator
indexBuilder = new ColumnIndex.Builder(emptyColumnFamily, key.key, out);
indexBuilder = new ColumnIndex.Builder(emptyColumnFamily, key.getKey(), out);
while (merger.hasNext())
merger.next().updateDigest(digest);
close();

View File

@ -456,13 +456,13 @@ public class LeveledManifest
*/
Iterator<SSTableReader> iter = candidates.iterator();
SSTableReader sstable = iter.next();
Token first = sstable.first.token;
Token last = sstable.last.token;
Token first = sstable.first.getToken();
Token last = sstable.last.getToken();
while (iter.hasNext())
{
sstable = iter.next();
first = first.compareTo(sstable.first.token) <= 0 ? first : sstable.first.token;
last = last.compareTo(sstable.last.token) >= 0 ? last : sstable.last.token;
first = first.compareTo(sstable.first.getToken()) <= 0 ? first : sstable.first.getToken();
last = last.compareTo(sstable.last.getToken()) >= 0 ? last : sstable.last.getToken();
}
return overlapping(first, last, others);
}
@ -470,7 +470,7 @@ public class LeveledManifest
@VisibleForTesting
static Set<SSTableReader> overlapping(SSTableReader sstable, Iterable<SSTableReader> others)
{
return overlapping(sstable.first.token, sstable.last.token, others);
return overlapping(sstable.first.getToken(), sstable.last.getToken(), others);
}
/**
@ -483,7 +483,7 @@ public class LeveledManifest
Bounds<Token> promotedBounds = new Bounds<Token>(start, end);
for (SSTableReader candidate : sstables)
{
Bounds<Token> candidateBounds = new Bounds<Token>(candidate.first.token, candidate.last.token);
Bounds<Token> candidateBounds = new Bounds<Token>(candidate.first.getToken(), candidate.last.getToken());
if (candidateBounds.intersects(promotedBounds))
overlapped.add(candidate);
}

View File

@ -163,7 +163,7 @@ public class Scrubber implements Closeable
dataSize = dataSizeFromIndex;
// avoid an NPE if key is null
String keyName = key == null ? "(unreadable key)" : ByteBufferUtil.bytesToHex(key.key);
String keyName = key == null ? "(unreadable key)" : ByteBufferUtil.bytesToHex(key.getKey());
outputHandler.debug(String.format("row %s is %s bytes", keyName, dataSize));
assert currentIndexKey != null || indexFile.isEOF();
@ -188,7 +188,7 @@ public class Scrubber implements Closeable
else
goodRows++;
prevKey = key;
if (!key.key.equals(currentIndexKey) || dataStart != dataStartFromIndex)
if (!key.getKey().equals(currentIndexKey) || dataStart != dataStartFromIndex)
outputHandler.warn("Index file contained a different key or row size; using key from data file");
}
catch (Throwable th)
@ -197,7 +197,7 @@ public class Scrubber implements Closeable
outputHandler.warn("Error reading row (stacktrace follows):", th);
if (currentIndexKey != null
&& (key == null || !key.key.equals(currentIndexKey) || dataStart != dataStartFromIndex || dataSize != dataSizeFromIndex))
&& (key == null || !key.getKey().equals(currentIndexKey) || dataStart != dataStartFromIndex || dataSize != dataSizeFromIndex))
{
outputHandler.output(String.format("Retrying from row index; data is %s bytes starting at %s",
dataSizeFromIndex, dataStartFromIndex));

View File

@ -23,6 +23,7 @@ import java.nio.ByteBuffer;
import java.util.*;
import com.google.common.collect.AbstractIterator;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.config.ColumnDefinition;
import org.apache.cassandra.cql3.CQL3Row;
import org.apache.cassandra.cql3.ColumnIdentifier;
@ -294,19 +295,20 @@ public abstract class AbstractCellNameType extends AbstractCType implements Cell
}
}
protected static CQL3Row.Builder makeSparseCQL3RowBuilder(final CellNameType type, final long now)
protected static CQL3Row.Builder makeSparseCQL3RowBuilder(final CFMetaData cfMetaData, final CellNameType type, final long now)
{
return new CQL3Row.Builder()
{
public CQL3Row.RowIterator group(Iterator<Cell> cells)
{
return new SparseRowIterator(type, cells, now);
return new SparseRowIterator(cfMetaData, type, cells, now);
}
};
}
private static class SparseRowIterator extends AbstractIterator<CQL3Row> implements CQL3Row.RowIterator
{
private final CFMetaData cfMetaData;
private final CellNameType type;
private final Iterator<Cell> cells;
private final long now;
@ -316,8 +318,9 @@ public abstract class AbstractCellNameType extends AbstractCType implements Cell
private CellName previous;
private CQL3RowOfSparse currentRow;
public SparseRowIterator(CellNameType type, Iterator<Cell> cells, long now)
public SparseRowIterator(CFMetaData cfMetaData, CellNameType type, Iterator<Cell> cells, long now)
{
this.cfMetaData = cfMetaData;
this.type = type;
this.cells = cells;
this.now = now;
@ -357,7 +360,7 @@ public abstract class AbstractCellNameType extends AbstractCType implements Cell
if (currentRow == null || !current.isSameCQL3RowAs(type, previous))
{
toReturn = currentRow;
currentRow = new CQL3RowOfSparse(current);
currentRow = new CQL3RowOfSparse(cfMetaData, current);
}
currentRow.add(nextCell);
nextCell = null;
@ -378,12 +381,14 @@ public abstract class AbstractCellNameType extends AbstractCType implements Cell
private static class CQL3RowOfSparse implements CQL3Row
{
private final CFMetaData cfMetaData;
private final CellName cell;
private Map<ColumnIdentifier, Cell> columns;
private Map<ColumnIdentifier, List<Cell>> collections;
CQL3RowOfSparse(CellName cell)
CQL3RowOfSparse(CFMetaData metadata, CellName cell)
{
this.cfMetaData = metadata;
this.cell = cell;
}
@ -395,7 +400,7 @@ public abstract class AbstractCellNameType extends AbstractCType implements Cell
void add(Cell cell)
{
CellName cellName = cell.name();
ColumnIdentifier columnName = cellName.cql3ColumnName();
ColumnIdentifier columnName = cellName.cql3ColumnName(cfMetaData);
if (cellName.isCollectionCell())
{
if (collections == null)

View File

@ -20,7 +20,6 @@ package org.apache.cassandra.db.composites;
import java.nio.ByteBuffer;
import org.apache.cassandra.db.filter.ColumnSlice;
import org.apache.cassandra.db.marshal.AbstractCompositeType;
import org.apache.cassandra.db.marshal.CompositeType;
import org.apache.cassandra.utils.ByteBufferUtil;

View File

@ -19,9 +19,9 @@ package org.apache.cassandra.db.composites;
import java.nio.ByteBuffer;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.utils.memory.AbstractAllocator;
import org.apache.cassandra.utils.ObjectSizes;
import org.apache.cassandra.utils.memory.PoolAllocator;
public class BoundedComposite extends AbstractComposite
{
@ -94,14 +94,8 @@ public class BoundedComposite extends AbstractComposite
return EMPTY_SIZE + wrapped.unsharedHeapSize();
}
public Composite copy(AbstractAllocator allocator)
public Composite copy(CFMetaData cfm, AbstractAllocator allocator)
{
return new BoundedComposite(wrapped.copy(allocator), isStart);
}
@Override
public void free(PoolAllocator allocator)
{
wrapped.free(allocator);
return new BoundedComposite(wrapped.copy(cfm, allocator), isStart);
}
}

View File

@ -19,6 +19,7 @@ package org.apache.cassandra.db.composites;
import java.nio.ByteBuffer;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.cql3.ColumnIdentifier;
import org.apache.cassandra.utils.memory.AbstractAllocator;
@ -52,8 +53,9 @@ public interface CellName extends Composite
* The name of the CQL3 column this cell represents.
*
* Will be null for cells of "dense" tables.
* @param metadata
*/
public ColumnIdentifier cql3ColumnName();
public ColumnIdentifier cql3ColumnName(CFMetaData metadata);
/**
* The value of the collection element, or null if the cell is not part
@ -70,7 +72,7 @@ public interface CellName extends Composite
// If cellnames were sharing some prefix components, this will break it, so
// we might want to try to do better.
@Override
public CellName copy(AbstractAllocator allocator);
public CellName copy(CFMetaData cfm, AbstractAllocator allocator);
public long excessHeapSizeExcludingData();
}

View File

@ -22,6 +22,7 @@ import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Comparator;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.config.ColumnDefinition;
import org.apache.cassandra.cql3.CQL3Row;
import org.apache.cassandra.cql3.ColumnIdentifier;
@ -152,7 +153,7 @@ public interface CellNameType extends CType
/**
* Creates a new CQL3Row builder for this type. See CQL3Row for details.
*/
public CQL3Row.Builder CQL3RowBuilder(long now);
public CQL3Row.Builder CQL3RowBuilder(CFMetaData metadata, long now);
// The two following methods are used to pass the declared regular column names (in CFMetaData)
// to the CellNameType. This is only used for optimization sake, see SparseCellNameType.

View File

@ -20,6 +20,7 @@ package org.apache.cassandra.db.composites;
import java.nio.ByteBuffer;
import java.util.List;
import org.apache.cassandra.cql3.ColumnIdentifier;
import org.apache.cassandra.db.Cell;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.ColumnToCollectionType;
@ -75,6 +76,11 @@ public abstract class CellNames
return new SimpleDenseCellName(bb);
}
public static CellName simpleSparse(ColumnIdentifier identifier)
{
return new SimpleSparseCellName(identifier);
}
// Mainly for tests and a few cases where we know what we need and didn't wanted to pass the type around
// Avoid in general, prefer the CellNameType methods.
public static CellName compositeDense(ByteBuffer... bbs)
@ -82,6 +88,16 @@ public abstract class CellNames
return new CompoundDenseCellName(bbs);
}
public static CellName compositeSparse(ByteBuffer[] bbs, ColumnIdentifier identifier, boolean isStatic)
{
return new CompoundSparseCellName(bbs, identifier, isStatic);
}
public static CellName compositeSparseWithCollection(ByteBuffer[] bbs, ByteBuffer collectionElement, ColumnIdentifier identifier, boolean isStatic)
{
return new CompoundSparseCellName.WithCollection(bbs, identifier, collectionElement, isStatic);
}
public static String getColumnsString(CellNameType type, Iterable<Cell> columns)
{
StringBuilder builder = new StringBuilder();

View File

@ -20,9 +20,9 @@ package org.apache.cassandra.db.composites;
import java.nio.ByteBuffer;
import org.apache.cassandra.cache.IMeasurableMemory;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.filter.ColumnSlice;
import org.apache.cassandra.utils.memory.AbstractAllocator;
import org.apache.cassandra.utils.memory.PoolAllocator;
/**
* A composite value.
@ -75,6 +75,5 @@ public interface Composite extends IMeasurableMemory
public ByteBuffer toByteBuffer();
public int dataSize();
public Composite copy(AbstractAllocator allocator);
public void free(PoolAllocator allocator);
public Composite copy(CFMetaData cfm, AbstractAllocator allocator);
}

View File

@ -19,10 +19,10 @@ package org.apache.cassandra.db.composites;
import java.nio.ByteBuffer;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.filter.ColumnSlice;
import org.apache.cassandra.utils.memory.AbstractAllocator;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.memory.PoolAllocator;
public abstract class Composites
{
@ -108,15 +108,9 @@ public abstract class Composites
return true;
}
public Composite copy(AbstractAllocator allocator)
public Composite copy(CFMetaData cfm, AbstractAllocator allocator)
{
return this;
}
@Override
public void free(PoolAllocator allocator)
{
}
}
}

View File

@ -19,9 +19,9 @@ package org.apache.cassandra.db.composites;
import java.nio.ByteBuffer;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.utils.ObjectSizes;
import org.apache.cassandra.utils.memory.AbstractAllocator;
import org.apache.cassandra.utils.memory.PoolAllocator;
/**
* A "truly-composite" Composite.
@ -81,16 +81,8 @@ public class CompoundComposite extends AbstractComposite
return EMPTY_SIZE + ObjectSizes.sizeOnHeapExcludingData(elements);
}
public Composite copy(AbstractAllocator allocator)
public Composite copy(CFMetaData cfm, AbstractAllocator allocator)
{
return new CompoundComposite(elementsCopy(allocator), size, isStatic);
}
@Override
public void free(PoolAllocator allocator)
{
for (ByteBuffer element : elements)
allocator.free(element);
}
}

View File

@ -19,6 +19,7 @@ package org.apache.cassandra.db.composites;
import java.nio.ByteBuffer;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.cql3.ColumnIdentifier;
import org.apache.cassandra.utils.memory.AbstractAllocator;
import org.apache.cassandra.utils.ObjectSizes;
@ -44,7 +45,7 @@ public class CompoundDenseCellName extends CompoundComposite implements CellName
return size;
}
public ColumnIdentifier cql3ColumnName()
public ColumnIdentifier cql3ColumnName(CFMetaData metadata)
{
return null;
}
@ -77,7 +78,7 @@ public class CompoundDenseCellName extends CompoundComposite implements CellName
return HEAP_SIZE + ObjectSizes.sizeOnHeapExcludingData(elements);
}
public CellName copy(AbstractAllocator allocator)
public CellName copy(CFMetaData cfm, AbstractAllocator allocator)
{
return new CompoundDenseCellName(elementsCopy(allocator));
}

View File

@ -21,6 +21,7 @@ import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.List;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.config.ColumnDefinition;
import org.apache.cassandra.cql3.CQL3Row;
import org.apache.cassandra.cql3.ColumnIdentifier;
@ -80,7 +81,7 @@ public class CompoundDenseCellNameType extends AbstractCompoundCellNameType
public void addCQL3Column(ColumnIdentifier id) {}
public void removeCQL3Column(ColumnIdentifier id) {}
public CQL3Row.Builder CQL3RowBuilder(long now)
public CQL3Row.Builder CQL3RowBuilder(CFMetaData metadata, long now)
{
return makeDenseCQL3RowBuilder(now);
}

View File

@ -19,11 +19,11 @@ package org.apache.cassandra.db.composites;
import java.nio.ByteBuffer;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.cql3.ColumnIdentifier;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.memory.AbstractAllocator;
import org.apache.cassandra.utils.ObjectSizes;
import org.apache.cassandra.utils.memory.PoolAllocator;
public class CompoundSparseCellName extends CompoundComposite implements CellName
{
@ -65,7 +65,7 @@ public class CompoundSparseCellName extends CompoundComposite implements CellNam
return size;
}
public ColumnIdentifier cql3ColumnName()
public ColumnIdentifier cql3ColumnName(CFMetaData metadata)
{
return columnName;
}
@ -93,7 +93,7 @@ public class CompoundSparseCellName extends CompoundComposite implements CellNam
return true;
}
public CellName copy(AbstractAllocator allocator)
public CellName copy(CFMetaData cfm, AbstractAllocator allocator)
{
if (elements.length == 0)
return this;
@ -147,7 +147,7 @@ public class CompoundSparseCellName extends CompoundComposite implements CellNam
}
@Override
public CellName copy(AbstractAllocator allocator)
public CellName copy(CFMetaData cfm, AbstractAllocator allocator)
{
// We don't copy columnName because it's interned in SparseCellNameType
return new CompoundSparseCellName.WithCollection(elements.length == 0 ? elements : elementsCopy(allocator), size, columnName, allocator.clone(collectionElement), isStatic());
@ -164,12 +164,5 @@ public class CompoundSparseCellName extends CompoundComposite implements CellNam
{
return super.excessHeapSizeExcludingData() + ObjectSizes.sizeOnHeapExcludingData(collectionElement);
}
@Override
public void free(PoolAllocator allocator)
{
super.free(allocator);
allocator.free(collectionElement);
}
}
}

View File

@ -20,6 +20,7 @@ package org.apache.cassandra.db.composites;
import java.nio.ByteBuffer;
import java.util.*;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.config.ColumnDefinition;
import org.apache.cassandra.cql3.CQL3Row;
import org.apache.cassandra.cql3.ColumnIdentifier;
@ -29,11 +30,10 @@ import org.apache.cassandra.db.marshal.ColumnToCollectionType;
import org.apache.cassandra.db.marshal.UTF8Type;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.memory.AbstractAllocator;
import org.apache.cassandra.utils.memory.PoolAllocator;
public class CompoundSparseCellNameType extends AbstractCompoundCellNameType
{
private static final ColumnIdentifier rowMarkerId = new ColumnIdentifier(ByteBufferUtil.EMPTY_BYTE_BUFFER, UTF8Type.instance);
public static final ColumnIdentifier rowMarkerId = new ColumnIdentifier(ByteBufferUtil.EMPTY_BYTE_BUFFER, UTF8Type.instance);
private static final CellName rowMarkerNoPrefix = new CompoundSparseCellName(rowMarkerId, false);
// For CQL3 columns, this is always UTF8Type. However, for compatibility with super columns, we need to allow it to be non-UTF8.
@ -87,15 +87,10 @@ public class CompoundSparseCellNameType extends AbstractCompoundCellNameType
}
@Override
public Composite copy(AbstractAllocator allocator)
public Composite copy(CFMetaData cfm, AbstractAllocator allocator)
{
return this;
}
@Override
public void free(PoolAllocator allocator)
{
}
};
}
@ -204,9 +199,9 @@ public class CompoundSparseCellNameType extends AbstractCompoundCellNameType
internedIds.remove(id.bytes);
}
public CQL3Row.Builder CQL3RowBuilder(long now)
public CQL3Row.Builder CQL3RowBuilder(CFMetaData metadata, long now)
{
return makeSparseCQL3RowBuilder(this, now);
return makeSparseCQL3RowBuilder(metadata, this, now);
}
public static class WithCollection extends CompoundSparseCellNameType

View File

@ -19,9 +19,9 @@ package org.apache.cassandra.db.composites;
import java.nio.ByteBuffer;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.utils.memory.AbstractAllocator;
import org.apache.cassandra.utils.ObjectSizes;
import org.apache.cassandra.utils.memory.PoolAllocator;
/**
* A "simple" (not-truly-composite) Composite.
@ -72,14 +72,8 @@ public class SimpleComposite extends AbstractComposite
return EMPTY_SIZE + ObjectSizes.sizeOnHeapOf(element);
}
public Composite copy(AbstractAllocator allocator)
public Composite copy(CFMetaData cfm, AbstractAllocator allocator)
{
return new SimpleComposite(allocator.clone(element));
}
@Override
public void free(PoolAllocator allocator)
{
allocator.free(element);
}
}

View File

@ -19,6 +19,7 @@ package org.apache.cassandra.db.composites;
import java.nio.ByteBuffer;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.cql3.ColumnIdentifier;
import org.apache.cassandra.utils.memory.AbstractAllocator;
import org.apache.cassandra.utils.ObjectSizes;
@ -38,7 +39,7 @@ public class SimpleDenseCellName extends SimpleComposite implements CellName
return 1;
}
public ColumnIdentifier cql3ColumnName()
public ColumnIdentifier cql3ColumnName(CFMetaData metadata)
{
return null;
}
@ -74,7 +75,7 @@ public class SimpleDenseCellName extends SimpleComposite implements CellName
// If cellnames were sharing some prefix components, this will break it, so
// we might want to try to do better.
@Override
public CellName copy(AbstractAllocator allocator)
public CellName copy(CFMetaData cfm, AbstractAllocator allocator)
{
return new SimpleDenseCellName(allocator.clone(element));
}

View File

@ -19,6 +19,7 @@ package org.apache.cassandra.db.composites;
import java.nio.ByteBuffer;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.config.ColumnDefinition;
import org.apache.cassandra.cql3.CQL3Row;
import org.apache.cassandra.cql3.ColumnIdentifier;
@ -72,7 +73,7 @@ public class SimpleDenseCellNameType extends AbstractSimpleCellNameType
public void addCQL3Column(ColumnIdentifier id) {}
public void removeCQL3Column(ColumnIdentifier id) {}
public CQL3Row.Builder CQL3RowBuilder(long now)
public CQL3Row.Builder CQL3RowBuilder(CFMetaData metadata, long now)
{
return makeDenseCQL3RowBuilder(now);
}

View File

@ -19,10 +19,10 @@ package org.apache.cassandra.db.composites;
import java.nio.ByteBuffer;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.cql3.ColumnIdentifier;
import org.apache.cassandra.utils.memory.AbstractAllocator;
import org.apache.cassandra.utils.ObjectSizes;
import org.apache.cassandra.utils.memory.PoolAllocator;
public class SimpleSparseCellName extends AbstractComposite implements CellName
{
@ -67,7 +67,7 @@ public class SimpleSparseCellName extends AbstractComposite implements CellName
return 0;
}
public ColumnIdentifier cql3ColumnName()
public ColumnIdentifier cql3ColumnName(CFMetaData metadata)
{
return columnName;
}
@ -97,13 +97,8 @@ public class SimpleSparseCellName extends AbstractComposite implements CellName
return EMPTY_SIZE + columnName.unsharedHeapSize();
}
public CellName copy(AbstractAllocator allocator)
public CellName copy(CFMetaData cfm, AbstractAllocator allocator)
{
return new SimpleSparseCellName(columnName.clone(allocator));
}
public void free(PoolAllocator allocator)
{
allocator.free(columnName.bytes);
}
}

View File

@ -21,6 +21,7 @@ import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.config.ColumnDefinition;
import org.apache.cassandra.cql3.CQL3Row;
import org.apache.cassandra.cql3.ColumnIdentifier;
@ -92,8 +93,8 @@ public class SimpleSparseCellNameType extends AbstractSimpleCellNameType
internedNames.remove(id.bytes);
}
public CQL3Row.Builder CQL3RowBuilder(long now)
public CQL3Row.Builder CQL3RowBuilder(CFMetaData metadata, long now)
{
return makeSparseCQL3RowBuilder(this, now);
return makeSparseCQL3RowBuilder(metadata, this, now);
}
}

View File

@ -17,9 +17,9 @@
*/
package org.apache.cassandra.db.composites;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.cql3.ColumnIdentifier;
import org.apache.cassandra.utils.memory.AbstractAllocator;
import org.apache.cassandra.utils.memory.PoolAllocator;
public class SimpleSparseInternedCellName extends SimpleSparseCellName
{
@ -43,16 +43,9 @@ public class SimpleSparseInternedCellName extends SimpleSparseCellName
}
@Override
public CellName copy(AbstractAllocator allocator)
public CellName copy(CFMetaData cfm, AbstractAllocator allocator)
{
// We're interning those instance in SparceCellNameType so don't need to copy.
return this;
}
@Override
public void free(PoolAllocator allocator)
{
// no-op, never copied
}
}

View File

@ -26,6 +26,7 @@ import java.util.NavigableSet;
import com.google.common.collect.AbstractIterator;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.cql3.ColumnIdentifier;
import org.apache.cassandra.db.*;
import org.apache.cassandra.db.composites.*;
@ -35,7 +36,6 @@ import org.apache.cassandra.io.IVersionedSerializer;
import org.apache.cassandra.io.util.DataOutputPlus;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.memory.AbstractAllocator;
import org.apache.cassandra.utils.memory.PoolAllocator;
public class ColumnSlice
{
@ -219,7 +219,7 @@ public class ColumnSlice
private static Cell fakeCell(Composite name)
{
return new Cell(new FakeCellName(name), ByteBufferUtil.EMPTY_BYTE_BUFFER);
return new BufferCell(new FakeCellName(name), ByteBufferUtil.EMPTY_BYTE_BUFFER);
}
/*
@ -265,7 +265,7 @@ public class ColumnSlice
throw new UnsupportedOperationException();
}
public ColumnIdentifier cql3ColumnName()
public ColumnIdentifier cql3ColumnName(CFMetaData metadata)
{
throw new UnsupportedOperationException();
}
@ -285,7 +285,7 @@ public class ColumnSlice
throw new UnsupportedOperationException();
}
public CellName copy(AbstractAllocator allocator)
public CellName copy(CFMetaData cfm, AbstractAllocator allocator)
{
throw new UnsupportedOperationException();
}
@ -296,12 +296,6 @@ public class ColumnSlice
throw new UnsupportedOperationException();
}
@Override
public void free(PoolAllocator allocator)
{
throw new UnsupportedOperationException();
}
public long unsharedHeapSize()
{
throw new UnsupportedOperationException();

View File

@ -256,7 +256,7 @@ public abstract class ExtendedFilter
assert !(cfs.getComparator().isCompound()) : "Sequential scan with filters is not supported (if you just created an index, you "
+ "need to wait for the creation to be propagated to all nodes before querying it)";
if (!needsExtraQuery(rowKey.key, data))
if (!needsExtraQuery(rowKey.getKey(), data))
return null;
// Note: for counters we must be careful to not add a column that was already there (to avoid overcount). That is
@ -278,7 +278,7 @@ public abstract class ExtendedFilter
return data;
ColumnFamily pruned = data.cloneMeShallow();
IDiskAtomFilter filter = dataRange.columnFilter(rowKey.key);
IDiskAtomFilter filter = dataRange.columnFilter(rowKey.getKey());
OnDiskAtomIterator iter = filter.getColumnFamilyIterator(rowKey, data);
filter.collectReducedColumns(pruned, QueryFilter.gatherTombstones(pruned, iter), cfs.gcBefore(timestamp), timestamp);
return pruned;
@ -311,7 +311,7 @@ public abstract class ExtendedFilter
continue;
}
dataValue = extractDataValue(def, rowKey.key, data, prefix);
dataValue = extractDataValue(def, rowKey.getKey(), data, prefix);
validator = def.type;
}

View File

@ -22,13 +22,7 @@ import java.util.concurrent.Future;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.config.ColumnDefinition;
import org.apache.cassandra.db.ArrayBackedSortedColumns;
import org.apache.cassandra.db.Cell;
import org.apache.cassandra.db.ColumnFamily;
import org.apache.cassandra.db.ColumnFamilyStore;
import org.apache.cassandra.db.DecoratedKey;
import org.apache.cassandra.db.ExpiringCell;
import org.apache.cassandra.db.IndexExpression;
import org.apache.cassandra.db.*;
import org.apache.cassandra.db.composites.CellName;
import org.apache.cassandra.db.composites.CellNameType;
import org.apache.cassandra.db.marshal.AbstractType;
@ -37,7 +31,7 @@ import org.apache.cassandra.dht.LocalToken;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.concurrent.OpOrder;
import org.apache.cassandra.utils.memory.PoolAllocator;
import org.apache.cassandra.utils.memory.MemtableAllocator;
/**
* Implements a secondary index for a column family using a second column family
@ -75,7 +69,7 @@ public abstract class AbstractSimplePerColumnSecondaryIndex extends PerColumnSec
@Override
public DecoratedKey getIndexKeyFor(ByteBuffer value)
{
return new DecoratedKey(new LocalToken(getIndexKeyComparator(), value), value);
return new BufferDecoratedKey(new LocalToken(getIndexKeyComparator(), value), value);
}
protected abstract CellName makeIndexColumnName(ByteBuffer rowKey, Cell cell);
@ -115,14 +109,14 @@ public abstract class AbstractSimplePerColumnSecondaryIndex extends PerColumnSec
if (cell instanceof ExpiringCell)
{
ExpiringCell ec = (ExpiringCell) cell;
cfi.addColumn(new ExpiringCell(name, ByteBufferUtil.EMPTY_BYTE_BUFFER, ec.timestamp(), ec.getTimeToLive(), ec.getLocalDeletionTime()));
cfi.addColumn(new BufferExpiringCell(name, ByteBufferUtil.EMPTY_BYTE_BUFFER, ec.timestamp(), ec.getTimeToLive(), ec.getLocalDeletionTime()));
}
else
{
cfi.addColumn(new Cell(name, ByteBufferUtil.EMPTY_BYTE_BUFFER, cell.timestamp()));
cfi.addColumn(new BufferCell(name, ByteBufferUtil.EMPTY_BYTE_BUFFER, cell.timestamp()));
}
if (logger.isDebugEnabled())
logger.debug("applying index row {} in {}", indexCfs.metadata.getKeyValidator().getString(valueKey.key), cfi);
logger.debug("applying index row {} in {}", indexCfs.metadata.getKeyValidator().getString(valueKey.getKey()), cfi);
indexCfs.apply(valueKey, cfi, SecondaryIndexManager.nullUpdater, opGroup, null);
}
@ -171,11 +165,6 @@ public abstract class AbstractSimplePerColumnSecondaryIndex extends PerColumnSec
return indexCfs.name;
}
public PoolAllocator getAllocator()
{
return indexCfs.getDataTracker().getView().getCurrentMemtable().getAllocator();
}
public void reload()
{
indexCfs.metadata.reloadSecondaryIndexMetadata(baseCfs.metadata);

View File

@ -32,6 +32,7 @@ import org.slf4j.LoggerFactory;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.config.ColumnDefinition;
import org.apache.cassandra.db.BufferDecoratedKey;
import org.apache.cassandra.db.Cell;
import org.apache.cassandra.db.ColumnFamilyStore;
import org.apache.cassandra.db.DecoratedKey;
@ -51,7 +52,7 @@ import org.apache.cassandra.io.sstable.ReducingKeyIterator;
import org.apache.cassandra.io.sstable.SSTableReader;
import org.apache.cassandra.service.StorageService;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.memory.PoolAllocator;
import org.apache.cassandra.utils.memory.MemtableAllocator;
/**
* Abstract base class for different types of secondary indexes.
@ -149,11 +150,6 @@ public abstract class SecondaryIndex
*/
public abstract void forceBlockingFlush();
/**
* Get current amount of memory this index is consuming (in bytes)
*/
public abstract PoolAllocator getAllocator();
/**
* Allow access to the underlying column family store if there is one
* @return the underlying column family store or null
@ -284,7 +280,7 @@ public abstract class SecondaryIndex
{
// FIXME: this imply one column definition per index
ByteBuffer name = columnDefs.iterator().next().name.bytes;
return new DecoratedKey(new LocalToken(baseCfs.metadata.getColumnDefinition(name).type, value), value);
return new BufferDecoratedKey(new LocalToken(baseCfs.metadata.getColumnDefinition(name).type, value), value);
}
/**

View File

@ -496,7 +496,7 @@ public class SecondaryIndexManager
}
else
{
((PerColumnSecondaryIndex) index).delete(key.key, cell, opGroup);
((PerColumnSecondaryIndex) index).delete(key.getKey(), cell, opGroup);
}
}
}
@ -665,7 +665,7 @@ public class SecondaryIndexManager
{
try (OpOrder.Group opGroup = baseCfs.keyspace.writeOrder.start())
{
((PerColumnSecondaryIndex) index).delete(key.key, cell, opGroup);
((PerColumnSecondaryIndex) index).delete(key.getKey(), cell, opGroup);
}
}
}
@ -674,7 +674,7 @@ public class SecondaryIndexManager
public void updateRowLevelIndexes()
{
for (SecondaryIndex index : rowLevelIndexMap.values())
((PerRowSecondaryIndex) index).index(key.key, null);
((PerRowSecondaryIndex) index).index(key.getKey(), null);
}
}
@ -698,7 +698,7 @@ public class SecondaryIndexManager
for (SecondaryIndex index : indexFor(cell.name()))
if (index instanceof PerColumnSecondaryIndex)
((PerColumnSecondaryIndex) index).insert(key.key, cell, opGroup);
((PerColumnSecondaryIndex) index).insert(key.getKey(), cell, opGroup);
}
public void update(Cell oldCell, Cell cell)
@ -711,9 +711,9 @@ public class SecondaryIndexManager
if (index instanceof PerColumnSecondaryIndex)
{
if (!cell.isMarkedForDelete(System.currentTimeMillis()))
((PerColumnSecondaryIndex) index).update(key.key, oldCell, cell, opGroup);
((PerColumnSecondaryIndex) index).update(key.getKey(), oldCell, cell, opGroup);
else
((PerColumnSecondaryIndex) index).delete(key.key, oldCell, opGroup);
((PerColumnSecondaryIndex) index).delete(key.getKey(), oldCell, opGroup);
}
}
}
@ -725,13 +725,13 @@ public class SecondaryIndexManager
for (SecondaryIndex index : indexFor(cell.name()))
if (index instanceof PerColumnSecondaryIndex)
((PerColumnSecondaryIndex) index).delete(key.key, cell, opGroup);
((PerColumnSecondaryIndex) index).delete(key.getKey(), cell, opGroup);
}
public void updateRowLevelIndexes()
{
for (SecondaryIndex index : rowLevelIndexMap.values())
((PerRowSecondaryIndex) index).index(key.key, cf);
((PerRowSecondaryIndex) index).index(key.getKey(), cf);
}
}
}

View File

@ -86,7 +86,7 @@ public class CompositesIndexOnClusteringKey extends CompositesIndex
for (int i = 0; i < columnDef.position(); i++)
builder.add(indexEntry.name().get(i + 1));
builder.add(indexedValue.key);
builder.add(indexedValue.getKey());
for (int i = columnDef.position() + 1; i < ckCount; i++)
builder.add(indexEntry.name().get(i));

View File

@ -99,7 +99,7 @@ public class CompositesIndexOnCollectionKey extends CompositesIndex
public boolean isStale(IndexedEntry entry, ColumnFamily data, long now)
{
CellName name = data.getComparator().create(entry.indexedEntryPrefix, columnDef, entry.indexValue.key);
CellName name = data.getComparator().create(entry.indexedEntryPrefix, columnDef, entry.indexValue.getKey());
Cell liveCell = data.getColumn(name);
return (liveCell == null || liveCell.isMarkedForDelete(now));
}

View File

@ -103,6 +103,6 @@ public class CompositesIndexOnCollectionValue extends CompositesIndex
return true;
ByteBuffer liveValue = liveCell.value();
return ((CollectionType)columnDef.type).valueComparator().compare(entry.indexValue.key, liveValue) != 0;
return ((CollectionType)columnDef.type).valueComparator().compare(entry.indexValue.getKey(), liveValue) != 0;
}
}

View File

@ -95,6 +95,6 @@ public class CompositesIndexOnRegular extends CompositesIndex
return true;
ByteBuffer liveValue = liveCell.value();
return columnDef.type.compare(entry.indexValue.key, liveValue) != 0;
return columnDef.type.compare(entry.indexValue.getKey(), liveValue) != 0;
}
}

View File

@ -111,8 +111,8 @@ public class CompositesSearcher extends SecondaryIndexSearcher
* indexed row.
*/
final AbstractBounds<RowPosition> range = filter.dataRange.keyRange();
ByteBuffer startKey = range.left instanceof DecoratedKey ? ((DecoratedKey)range.left).key : ByteBufferUtil.EMPTY_BYTE_BUFFER;
ByteBuffer endKey = range.right instanceof DecoratedKey ? ((DecoratedKey)range.right).key : ByteBufferUtil.EMPTY_BYTE_BUFFER;
ByteBuffer startKey = range.left instanceof DecoratedKey ? ((DecoratedKey)range.left).getKey() : ByteBufferUtil.EMPTY_BYTE_BUFFER;
ByteBuffer endKey = range.right instanceof DecoratedKey ? ((DecoratedKey)range.right).getKey() : ByteBufferUtil.EMPTY_BYTE_BUFFER;
final CellNameType baseComparator = baseCfs.getComparator();
final CellNameType indexComparator = index.getIndexCfs().getComparator();
@ -243,14 +243,14 @@ public class CompositesSearcher extends SecondaryIndexSearcher
}
else
{
logger.debug("Skipping entry {} before assigned scan range", dk.token);
logger.debug("Skipping entry {} before assigned scan range", dk.getToken());
continue;
}
}
// Check if this entry cannot be a hit due to the original cell filter
Composite start = entry.indexedEntryPrefix;
if (!filter.columnFilter(dk.key).maySelectPrefix(baseComparator, start))
if (!filter.columnFilter(dk.getKey()).maySelectPrefix(baseComparator, start))
continue;
// If we've record the previous prefix, it means we're dealing with an index on the collection value. In

View File

@ -85,8 +85,8 @@ public class KeysSearcher extends SecondaryIndexSearcher
*/
final AbstractBounds<RowPosition> range = filter.dataRange.keyRange();
CellNameType type = index.getIndexCfs().getComparator();
final Composite startKey = range.left instanceof DecoratedKey ? type.make(((DecoratedKey)range.left).key) : Composites.EMPTY;
final Composite endKey = range.right instanceof DecoratedKey ? type.make(((DecoratedKey)range.right).key) : Composites.EMPTY;
final Composite startKey = range.left instanceof DecoratedKey ? type.make(((DecoratedKey)range.left).getKey()) : Composites.EMPTY;
final Composite endKey = range.right instanceof DecoratedKey ? type.make(((DecoratedKey)range.right).getKey()) : Composites.EMPTY;
final CellName primaryColumn = baseCfs.getComparator().cellFromByteBuffer(primary.column);
@ -168,7 +168,7 @@ public class KeysSearcher extends SecondaryIndexSearcher
}
if (!range.contains(dk))
{
logger.trace("Skipping entry {} outside of assigned scan range", dk.token);
logger.trace("Skipping entry {} outside of assigned scan range", dk.getToken());
continue;
}
@ -188,11 +188,11 @@ public class KeysSearcher extends SecondaryIndexSearcher
data.addAll(cf);
}
if (((KeysIndex)index).isIndexEntryStale(indexKey.key, data, filter.timestamp))
if (((KeysIndex)index).isIndexEntryStale(indexKey.getKey(), data, filter.timestamp))
{
// delete the index entry w/ its own timestamp
Cell dummyCell = new Cell(primaryColumn, indexKey.key, cell.timestamp());
((PerColumnSecondaryIndex)index).delete(dk.key, dummyCell, writeOp);
Cell dummyCell = new BufferCell(primaryColumn, indexKey.getKey(), cell.timestamp());
((PerColumnSecondaryIndex)index).delete(dk.getKey(), dummyCell, writeOp);
continue;
}
return new Row(dk, data);

View File

@ -63,7 +63,7 @@ public class LocalByPartionerType<T extends Token> extends AbstractType<ByteBuff
public int compare(ByteBuffer o1, ByteBuffer o2)
{
// o1 and o2 can be empty so we need to use RowPosition, not DecoratedKey
return RowPosition.forKey(o1, partitioner).compareTo(RowPosition.forKey(o2, partitioner));
return RowPosition.ForKey.get(o1, partitioner).compareTo(RowPosition.ForKey.get(o2, partitioner));
}
@Override

View File

@ -18,7 +18,6 @@
package org.apache.cassandra.dht;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.io.Serializable;
import java.util.*;
@ -100,7 +99,7 @@ public abstract class AbstractBounds<T extends RingPosition> implements Serializ
{
if (value instanceof DecoratedKey)
{
return keyValidator.getString(((DecoratedKey)value).key);
return keyValidator.getString(((DecoratedKey)value).getKey());
}
else
{

View File

@ -22,6 +22,7 @@ import java.nio.ByteBuffer;
import java.util.*;
import org.apache.cassandra.config.*;
import org.apache.cassandra.db.BufferDecoratedKey;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.commons.lang3.ArrayUtils;
@ -42,7 +43,7 @@ public abstract class AbstractByteOrderedPartitioner extends AbstractPartitioner
public DecoratedKey decorateKey(ByteBuffer key)
{
return new DecoratedKey(getToken(key), key);
return new BufferDecoratedKey(getToken(key), key);
}
public BytesToken midpoint(Token ltoken, Token rtoken)

View File

@ -22,6 +22,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.apache.cassandra.db.BufferDecoratedKey;
import org.apache.cassandra.db.DecoratedKey;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.utils.ByteBufferUtil;
@ -40,7 +41,7 @@ public class LocalPartitioner extends AbstractPartitioner<LocalToken>
public DecoratedKey decorateKey(ByteBuffer key)
{
return new DecoratedKey(getToken(key), key);
return new BufferDecoratedKey(getToken(key), key);
}
public Token midpoint(Token left, Token right)

View File

@ -25,6 +25,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.cassandra.db.BufferDecoratedKey;
import org.apache.cassandra.db.DecoratedKey;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.LongType;
@ -46,7 +47,7 @@ public class Murmur3Partitioner extends AbstractPartitioner<LongToken>
public DecoratedKey decorateKey(ByteBuffer key)
{
return new DecoratedKey(getToken(key), key);
return new BufferDecoratedKey(getToken(key), key);
}
public Token midpoint(Token lToken, Token rToken)

View File

@ -23,6 +23,7 @@ import java.nio.charset.CharacterCodingException;
import java.util.*;
import org.apache.cassandra.config.*;
import org.apache.cassandra.db.BufferDecoratedKey;
import org.apache.cassandra.db.DecoratedKey;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.UTF8Type;
@ -44,7 +45,7 @@ public class OrderPreservingPartitioner extends AbstractPartitioner<StringToken>
public DecoratedKey decorateKey(ByteBuffer key)
{
return new DecoratedKey(getToken(key), key);
return new BufferDecoratedKey(getToken(key), key);
}
public StringToken midpoint(Token ltoken, Token rtoken)

View File

@ -22,6 +22,7 @@ import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.*;
import org.apache.cassandra.db.BufferDecoratedKey;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.db.DecoratedKey;
import org.apache.cassandra.db.marshal.AbstractType;
@ -45,7 +46,7 @@ public class RandomPartitioner extends AbstractPartitioner<BigIntegerToken>
public DecoratedKey decorateKey(ByteBuffer key)
{
return new DecoratedKey(getToken(key), key);
return new BufferDecoratedKey(getToken(key), key);
}
public Token midpoint(Token ltoken, Token rtoken)

View File

@ -173,7 +173,7 @@ public abstract class Token<T> implements RingPosition<Token<T>>, Serializable
return (R)maxKeyBound();
}
public static class KeyBound extends RowPosition
public static class KeyBound implements RowPosition
{
private final Token token;
public final boolean isMinimumBound;
@ -209,6 +209,11 @@ public abstract class Token<T> implements RingPosition<Token<T>>, Serializable
return getToken().isMinimum(partitioner);
}
public boolean isMinimum()
{
return isMinimum(StorageService.getPartitioner());
}
public RowPosition.Kind kind()
{
return isMinimumBound ? RowPosition.Kind.MIN_BOUND : RowPosition.Kind.MAX_BOUND;

View File

@ -24,6 +24,7 @@ import java.nio.ByteBuffer;
import java.util.*;
import com.google.common.collect.*;
import org.apache.cassandra.db.BufferCell;
import org.apache.cassandra.db.Cell;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -304,14 +305,14 @@ public class ColumnFamilyRecordReader extends RecordReader<ByteBuffer, SortedMap
protected Cell unthriftifySimple(org.apache.cassandra.thrift.Column column)
{
return new Cell(comparator.cellFromByteBuffer(column.name), column.value, column.timestamp);
return new BufferCell(comparator.cellFromByteBuffer(column.name), column.value, column.timestamp);
}
private Cell unthriftifyCounter(CounterColumn column)
{
//CounterColumns read the counterID from the System keyspace, so need the StorageService running and access
//to cassandra.yaml. To avoid a Hadoop needing access to yaml return a regular Cell.
return new Cell(comparator.cellFromByteBuffer(column.name), ByteBufferUtil.bytes(column.value), 0);
return new BufferCell(comparator.cellFromByteBuffer(column.name), ByteBufferUtil.bytes(column.value), 0);
}
private List<Cell> unthriftifySuperCounter(CounterSuperColumn super_column)

View File

@ -24,6 +24,7 @@ import java.util.*;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.config.ColumnDefinition;
import org.apache.cassandra.db.BufferCell;
import org.apache.cassandra.db.composites.CellNames;
import org.apache.cassandra.db.Cell;
import org.apache.cassandra.db.marshal.*;
@ -112,7 +113,7 @@ public class CqlStorage extends AbstractCassandraStorage
ByteBuffer columnValue = columns.get(ByteBufferUtil.string(cdef.name.duplicate()));
if (columnValue != null)
{
Cell cell = new Cell(CellNames.simpleDense(cdef.name), columnValue);
Cell cell = new BufferCell(CellNames.simpleDense(cdef.name), columnValue);
AbstractType<?> validator = getValidatorMap(cfDef).get(cdef.name);
setTupleValue(tuple, i, cqlColumnToObj(cell, cfDef), validator);
}

View File

@ -131,7 +131,7 @@ public abstract class AbstractSSTableSimpleWriter
*/
public void addColumn(ByteBuffer name, ByteBuffer value, long timestamp)
{
addColumn(new Cell(metadata.comparator.cellFromByteBuffer(name), value, timestamp));
addColumn(new BufferCell(metadata.comparator.cellFromByteBuffer(name), value, timestamp));
}
/**
@ -146,7 +146,7 @@ public abstract class AbstractSSTableSimpleWriter
*/
public void addExpiringColumn(ByteBuffer name, ByteBuffer value, long timestamp, int ttl, long expirationTimestampMS)
{
addColumn(new ExpiringCell(metadata.comparator.cellFromByteBuffer(name), value, timestamp, ttl, (int)(expirationTimestampMS / 1000)));
addColumn(new BufferExpiringCell(metadata.comparator.cellFromByteBuffer(name), value, timestamp, ttl, (int)(expirationTimestampMS / 1000)));
}
/**
@ -156,9 +156,9 @@ public abstract class AbstractSSTableSimpleWriter
*/
public void addCounterColumn(ByteBuffer name, long value)
{
addColumn(new CounterCell(metadata.comparator.cellFromByteBuffer(name),
CounterContext.instance().createGlobal(counterid, 1L, value),
System.currentTimeMillis()));
addColumn(new BufferCounterCell(metadata.comparator.cellFromByteBuffer(name),
CounterContext.instance().createGlobal(counterid, 1L, value),
System.currentTimeMillis()));
}
/**

View File

@ -207,7 +207,7 @@ public class CQLSSTableWriter
for (ByteBuffer key: keys)
{
if (writer.currentKey() == null || !key.equals(writer.currentKey().key))
if (writer.currentKey() == null || !key.equals(writer.currentKey().getKey()))
writer.newRow(key);
insert.addUpdateForKey(writer.currentColumnFamily(), key, clusteringPrefix, params);
}

View File

@ -30,6 +30,7 @@ import org.apache.cassandra.db.TypeSizes;
import org.apache.cassandra.dht.IPartitioner;
import static org.apache.cassandra.io.sstable.Downsampling.BASE_SAMPLING_LEVEL;
import static org.apache.cassandra.io.sstable.SSTable.getMinimalKey;
public class IndexSummaryBuilder
{
@ -109,8 +110,8 @@ public class IndexSummaryBuilder
if (!shouldSkip)
{
keys.add(decoratedKey);
offheapSize += decoratedKey.key.remaining();
keys.add(getMinimalKey(decoratedKey));
offheapSize += decoratedKey.getKey().remaining();
positions.add(indexPosition);
offheapSize += TypeSizes.NATIVE.sizeof(indexPosition);
}
@ -143,7 +144,7 @@ public class IndexSummaryBuilder
long offheapSize = this.offheapSize;
if (length < keys.size())
for (int i = length ; i < keys.size() ; i++)
offheapSize -= keys.get(i).key.remaining() + TypeSizes.NATIVE.sizeof(positions.get(i));
offheapSize -= keys.get(i).getKey().remaining() + TypeSizes.NATIVE.sizeof(positions.get(i));
// first we write out the position in the *summary* for each key in the summary,
// then we write out (key, actual index position) pairs
@ -157,7 +158,7 @@ public class IndexSummaryBuilder
idxPosition += TypeSizes.NATIVE.sizeof(keyPosition);
// write the key
ByteBuffer keyBytes = keys.get(i).key;
ByteBuffer keyBytes = keys.get(i).getKey();
memory.setBytes(keyPosition, keyBytes);
keyPosition += keyBytes.remaining();

View File

@ -30,6 +30,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.BufferDecoratedKey;
import org.apache.cassandra.db.DecoratedKey;
import org.apache.cassandra.db.RowIndexEntry;
import org.apache.cassandra.dht.IPartitioner;
@ -123,8 +124,8 @@ public abstract class SSTable
*/
public static DecoratedKey getMinimalKey(DecoratedKey key)
{
return key.key.position() > 0 || key.key.hasRemaining() || !key.key.hasArray()
? new DecoratedKey(key.token, HeapAllocator.instance.clone(key.key))
return key.getKey().position() > 0 || key.getKey().hasRemaining() || !key.getKey().hasArray()
? new BufferDecoratedKey(key.getToken(), HeapAllocator.instance.clone(key.getKey()))
: key;
}

View File

@ -791,7 +791,7 @@ public class SSTableReader extends SSTable
last = decoratedKey;
if (recreateBloomFilter)
bf.add(decoratedKey.key);
bf.add(decoratedKey.getKey());
// if summary was already read from disk we don't want to re-populate it using primary index
if (!summaryLoaded)
@ -879,8 +879,8 @@ public class SSTableReader extends SSTable
{
oStream = new DataOutputStreamAndChannel(new FileOutputStream(summariesFile));
IndexSummary.serializer.serialize(summary, oStream, descriptor.version.hasSamplingLevel);
ByteBufferUtil.writeWithLength(first.key, oStream);
ByteBufferUtil.writeWithLength(last.key, oStream);
ByteBufferUtil.writeWithLength(first.getKey(), oStream);
ByteBufferUtil.writeWithLength(last.getKey(), oStream);
ibuilder.serializeBounds(oStream);
dbuilder.serializeBounds(oStream);
}
@ -1309,7 +1309,7 @@ public class SSTableReader extends SSTable
public void invalidateCacheKey(DecoratedKey key)
{
KeyCacheKey cacheKey = new KeyCacheKey(metadata.cfId, descriptor, key.key);
KeyCacheKey cacheKey = new KeyCacheKey(metadata.cfId, descriptor, key.getKey());
keyCache.remove(cacheKey);
}
@ -1324,14 +1324,14 @@ public class SSTableReader extends SSTable
return;
}
KeyCacheKey cacheKey = new KeyCacheKey(metadata.cfId, descriptor, key.key);
KeyCacheKey cacheKey = new KeyCacheKey(metadata.cfId, descriptor, key.getKey());
logger.trace("Adding cache entry for {} -> {}", cacheKey, info);
keyCache.put(cacheKey, info);
}
public RowIndexEntry getCachedPosition(DecoratedKey key, boolean updateStats)
{
return getCachedPosition(new KeyCacheKey(metadata.cfId, descriptor, key.key), updateStats);
return getCachedPosition(new KeyCacheKey(metadata.cfId, descriptor, key.getKey()), updateStats);
}
private RowIndexEntry getCachedPosition(KeyCacheKey unifiedKey, boolean updateStats)
@ -1375,7 +1375,7 @@ public class SSTableReader extends SSTable
if (op == Operator.EQ)
{
assert key instanceof DecoratedKey; // EQ only make sense if the key is a valid row key
if (!bf.isPresent(((DecoratedKey)key).key))
if (!bf.isPresent(((DecoratedKey)key).getKey()))
{
Tracing.trace("Bloom filter allows skipping sstable {}", descriptor.generation);
return null;
@ -1386,7 +1386,7 @@ public class SSTableReader extends SSTable
if ((op == Operator.EQ || op == Operator.GE) && (key instanceof DecoratedKey))
{
DecoratedKey decoratedKey = (DecoratedKey)key;
KeyCacheKey cacheKey = new KeyCacheKey(metadata.cfId, descriptor, decoratedKey.key);
KeyCacheKey cacheKey = new KeyCacheKey(metadata.cfId, descriptor, decoratedKey.getKey());
RowIndexEntry cachedPosition = getCachedPosition(cacheKey, updateCacheAndStats);
if (cachedPosition != null)
{
@ -1442,7 +1442,7 @@ public class SSTableReader extends SSTable
// Compare raw keys if possible for performance, otherwise compare decorated keys.
if (op == Operator.EQ)
{
opSatisfied = exactMatch = indexKey.equals(((DecoratedKey) key).key);
opSatisfied = exactMatch = indexKey.equals(((DecoratedKey) key).getKey());
}
else
{

View File

@ -257,7 +257,7 @@ public class SSTableScanner implements ICompactionScanner
}
}
if (dataRange == null || dataRange.selectsFullRowFor(currentKey.key))
if (dataRange == null || dataRange.selectsFullRowFor(currentKey.getKey()))
{
dfile.seek(currentEntry.position);
ByteBufferUtil.readWithShortLength(dfile); // key
@ -269,7 +269,7 @@ public class SSTableScanner implements ICompactionScanner
{
public OnDiskAtomIterator create()
{
return dataRange.columnFilter(currentKey.key).getSSTableColumnIterator(sstable, dfile, currentKey, currentEntry);
return dataRange.columnFilter(currentKey.getKey()).getSSTableColumnIterator(sstable, dfile, currentKey, currentEntry);
}
});

View File

@ -99,7 +99,7 @@ public class SSTableSimpleUnsortedWriter extends AbstractSSTableSimpleWriter
protected void writeRow(DecoratedKey key, ColumnFamily columnFamily) throws IOException
{
currentSize += key.key.remaining() + ColumnFamily.serializer.serializedSize(columnFamily, MessagingService.current_version) * 1.2;
currentSize += key.getKey().remaining() + ColumnFamily.serializer.serializedSize(columnFamily, MessagingService.current_version) * 1.2;
if (currentSize > bufferSize)
sync();
@ -118,7 +118,7 @@ public class SSTableSimpleUnsortedWriter extends AbstractSSTableSimpleWriter
{
// We will reuse a CF that we have counted already. But because it will be easier to add the full size
// of the CF in the next writeRow call than to find out the delta, we just remove the size until that next call
currentSize -= currentKey.key.remaining() + ColumnFamily.serializer.serializedSize(previous, MessagingService.current_version) * 1.2;
currentSize -= currentKey.getKey().remaining() + ColumnFamily.serializer.serializedSize(previous, MessagingService.current_version) * 1.2;
}
return previous;
}

Some files were not shown because too many files have changed in this diff Show More