Replace supercolumns internally by composites

patch by slebresne; reviewed by Vijay for CASSANDRA-3237
This commit is contained in:
Sylvain Lebresne 2012-12-12 13:59:34 +01:00
parent 565f675b16
commit 3a005df397
200 changed files with 2595 additions and 3859 deletions

View File

@ -2,6 +2,7 @@
* make index_interval configurable per columnfamily (CASSANDRA-3961)
* add default_tim_to_live (CASSANDRA-3974)
* add memtable_flush_period_in_ms (CASSANDRA-4237)
* replace supercolumns internally by composites (CASSANDRA-3237)
1.2.1

View File

@ -20,7 +20,7 @@ import java.nio.ByteBuffer;
import java.util.*;
import org.apache.cassandra.db.*;
import org.apache.cassandra.db.filter.QueryPath;
import org.apache.cassandra.db.filter.NamesQueryFilter;
import org.apache.cassandra.service.StorageProxy;
import org.apache.cassandra.service.StorageService;
import org.apache.cassandra.thrift.*;
@ -64,8 +64,7 @@ public class ClientOnlyExample
for (int i = 0; i < 100; i++)
{
RowMutation change = new RowMutation(KEYSPACE, ByteBufferUtil.bytes(("key" + i)));
ColumnPath cp = new ColumnPath(COLUMN_FAMILY).setColumn(("colb").getBytes());
change.add(new QueryPath(cp), ByteBufferUtil.bytes(("value" + i)), 0);
change.add(COLUMN_FAMILY, ByteBufferUtil.bytes("colb"), ByteBufferUtil.bytes(("value" + i)), 0);
// don't call change.apply(). The reason is that is makes a static call into Table, which will perform
// local storage initialization, which creates local directories.
@ -80,15 +79,10 @@ public class ClientOnlyExample
private static void testReading() throws Exception
{
// do some queries.
Collection<ByteBuffer> cols = new ArrayList<ByteBuffer>()
{{
add(ByteBufferUtil.bytes("colb"));
}};
for (int i = 0; i < 100; i++)
{
List<ReadCommand> commands = new ArrayList<ReadCommand>();
SliceByNamesReadCommand readCommand = new SliceByNamesReadCommand(KEYSPACE, ByteBufferUtil.bytes(("key" + i)),
new QueryPath(COLUMN_FAMILY, null, null), cols);
SliceByNamesReadCommand readCommand = new SliceByNamesReadCommand(KEYSPACE, ByteBufferUtil.bytes(("key" + i)), COLUMN_FAMILY, new NamesQueryFilter(ByteBufferUtil.bytes("colb")));
readCommand.setDigestQuery(false);
commands.add(readCommand);
List<Row> rows = StorageProxy.read(commands, ConsistencyLevel.ONE);

View File

@ -17,11 +17,13 @@
*/
package org.apache.cassandra.config;
import java.io.DataInput;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.nio.ByteBuffer;
import java.util.*;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.MapDifference;
import com.google.common.collect.Maps;
import org.apache.commons.lang.ArrayUtils;
@ -47,9 +49,9 @@ import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.exceptions.InvalidRequestException;
import org.apache.cassandra.exceptions.RequestValidationException;
import org.apache.cassandra.exceptions.SyntaxException;
import org.apache.cassandra.io.IColumnSerializer;
import org.apache.cassandra.io.compress.CompressionParameters;
import org.apache.cassandra.io.compress.SnappyCompressor;
import org.apache.cassandra.io.sstable.Descriptor;
import org.apache.cassandra.thrift.IndexType;
import org.apache.cassandra.tracing.Tracing;
import org.apache.cassandra.utils.ByteBufferUtil;
@ -251,7 +253,6 @@ public final class CFMetaData
public final String cfName; // name of this column family
public final ColumnFamilyType cfType; // standard, super
public volatile AbstractType<?> comparator; // bytes, long, timeuuid, utf8, etc.
public volatile AbstractType<?> subcolumnComparator; // like comparator, for supercolumns
//OPTIONAL
private volatile String comment = "";
@ -308,17 +309,22 @@ public final class CFMetaData
public CFMetaData(String keyspace, String name, ColumnFamilyType type, AbstractType<?> comp, AbstractType<?> subcc)
{
this(keyspace, name, type, comp, subcc, getId(keyspace, name));
this(keyspace, name, type, makeComparator(type, comp, subcc));
}
CFMetaData(String keyspace, String name, ColumnFamilyType type, AbstractType<?> comp, AbstractType<?> subcc, UUID id)
public CFMetaData(String keyspace, String name, ColumnFamilyType type, AbstractType<?> comp)
{
this(keyspace, name, type, comp, getId(keyspace, name));
}
@VisibleForTesting
CFMetaData(String keyspace, String name, ColumnFamilyType type, AbstractType<?> comp, UUID id)
{
// Final fields must be set in constructor
ksName = keyspace;
cfName = name;
cfType = type;
comparator = comp;
subcolumnComparator = enforceSubccDefault(type, subcc);
cfId = id;
updateCfDef(); // init cqlCfDef
@ -344,9 +350,11 @@ public final class CFMetaData
return compile(id, cql, Table.SYSTEM_KS);
}
private AbstractType<?> enforceSubccDefault(ColumnFamilyType cftype, AbstractType<?> subcc)
private static AbstractType<?> makeComparator(ColumnFamilyType cftype, AbstractType<?> comp, AbstractType<?> subcc)
{
return (subcc == null) && (cftype == ColumnFamilyType.Super) ? BytesType.instance : subcc;
return cftype == ColumnFamilyType.Super
? CompositeType.getInstance(comp, subcc == null ? BytesType.instance : subcc)
: comp;
}
private static String enforceCommentNotNull (CharSequence comment)
@ -386,7 +394,7 @@ public final class CFMetaData
? Caching.KEYS_ONLY
: Caching.NONE;
return new CFMetaData(parent.ksName, parent.indexColumnFamilyName(info), ColumnFamilyType.Standard, columnComparator, null)
return new CFMetaData(parent.ksName, parent.indexColumnFamilyName(info), ColumnFamilyType.Standard, columnComparator, (AbstractType)null)
.keyValidator(info.getValidator())
.readRepairChance(0.0)
.dcLocalReadRepairChance(0.0)
@ -409,13 +417,13 @@ public final class CFMetaData
public CFMetaData clone()
{
return copyOpts(new CFMetaData(ksName, cfName, cfType, comparator, subcolumnComparator, cfId), this);
return copyOpts(new CFMetaData(ksName, cfName, cfType, comparator, cfId), this);
}
// Create a new CFMD by changing just the cfName
public static CFMetaData rename(CFMetaData cfm, String newName)
{
return copyOpts(new CFMetaData(cfm.ksName, newName, cfm.cfType, cfm.comparator, cfm.subcolumnComparator, cfm.cfId), cfm);
return copyOpts(new CFMetaData(cfm.ksName, newName, cfm.cfType, cfm.comparator, cfm.cfId), cfm);
}
static CFMetaData copyOpts(CFMetaData newCFMD, CFMetaData oldCFMD)
@ -468,6 +476,11 @@ public final class CFMetaData
return comment;
}
public boolean isSuper()
{
return cfType == ColumnFamilyType.Super;
}
public double getReadRepairChance()
{
return readRepairChance;
@ -542,11 +555,6 @@ public final class CFMetaData
return Collections.unmodifiableMap(column_metadata);
}
public AbstractType<?> getComparatorFor(ByteBuffer superColumnName)
{
return superColumnName == null ? comparator : subcolumnComparator;
}
public double getBloomFilterFpChance()
{
return bloomFilterFpChance == null
@ -591,7 +599,6 @@ public final class CFMetaData
.append(cfName, rhs.cfName)
.append(cfType, rhs.cfType)
.append(comparator, rhs.comparator)
.append(subcolumnComparator, rhs.subcolumnComparator)
.append(comment, rhs.comment)
.append(readRepairChance, rhs.readRepairChance)
.append(dcLocalReadRepairChance, rhs.dcLocalReadRepairChance)
@ -624,7 +631,6 @@ public final class CFMetaData
.append(cfName)
.append(cfType)
.append(comparator)
.append(subcolumnComparator)
.append(comment)
.append(readRepairChance)
.append(dcLocalReadRepairChance)
@ -739,7 +745,7 @@ public final class CFMetaData
.replicateOnWrite(cf_def.replicate_on_write)
.defaultValidator(TypeParser.parse(cf_def.default_validation_class))
.keyValidator(TypeParser.parse(cf_def.key_validation_class))
.columnMetadata(ColumnDefinition.fromThrift(cf_def.column_metadata))
.columnMetadata(ColumnDefinition.fromThrift(cf_def.column_metadata, newCFMD.isSuper()))
.compressionParameters(cp);
}
catch (SyntaxException e)
@ -783,10 +789,9 @@ public final class CFMetaData
validateCompatility(cfm);
// TODO: this method should probably return a new CFMetaData so that
// 1) we can keep comparator and subcolumnComparator final
// 1) we can keep comparator final
// 2) updates are applied atomically
comparator = cfm.comparator;
subcolumnComparator = cfm.subcolumnComparator;
// compaction thresholds are checked by ThriftValidation. We shouldn't be doing
// validation on the apply path; it's too late for that.
@ -859,14 +864,6 @@ public final class CFMetaData
if (!cfm.comparator.isCompatibleWith(comparator))
throw new ConfigurationException("comparators do not match or are not compatible.");
if (cfm.subcolumnComparator == null)
{
if (subcolumnComparator != null)
throw new ConfigurationException("subcolumncomparators do not match.");
// else, it's null and we're good.
}
else if (!cfm.subcolumnComparator.isCompatibleWith(subcolumnComparator))
throw new ConfigurationException("subcolumncomparators do not match or are note compatible.");
}
public static Class<? extends AbstractCompactionStrategy> createCompactionStrategy(String className) throws ConfigurationException
@ -908,13 +905,18 @@ public final class CFMetaData
{
org.apache.cassandra.thrift.CfDef def = new org.apache.cassandra.thrift.CfDef(ksName, cfName);
def.setColumn_type(cfType.name());
def.setComparator_type(comparator.toString());
if (subcolumnComparator != null)
if (isSuper())
{
assert cfType == ColumnFamilyType.Super
: String.format("%s CF %s should not have subcomparator %s defined", cfType, cfName, subcolumnComparator);
def.setSubcomparator_type(subcolumnComparator.toString());
CompositeType ct = (CompositeType)comparator;
def.setComparator_type(ct.types.get(0).toString());
def.setSubcomparator_type(ct.types.get(1).toString());
}
else
{
def.setComparator_type(comparator.toString());
}
def.setComment(enforceCommentNotNull(comment));
def.setRead_repair_chance(readRepairChance);
def.setDclocal_read_repair_chance(dcLocalReadRepairChance);
@ -961,7 +963,7 @@ public final class CFMetaData
*/
public ColumnDefinition getColumnDefinitionFromColumnName(ByteBuffer columnName)
{
if (comparator instanceof CompositeType)
if (!isSuper() && (comparator instanceof CompositeType))
{
CompositeType composite = (CompositeType)comparator;
ByteBuffer[] components = composite.split(columnName);
@ -1039,18 +1041,16 @@ public final class CFMetaData
return (cfName + "_" + comparator.getString(columnName) + "_idx").replaceAll("\\W", "");
}
public IColumnSerializer getColumnSerializer()
public Iterator<OnDiskAtom> getOnDiskIterator(DataInput dis, int count, Descriptor.Version version)
{
if (cfType == ColumnFamilyType.Standard)
return Column.serializer();
return SuperColumn.serializer(subcolumnComparator);
return getOnDiskIterator(dis, count, ColumnSerializer.Flag.LOCAL, (int) (System.currentTimeMillis() / 1000), version);
}
public OnDiskAtom.Serializer getOnDiskSerializer()
public Iterator<OnDiskAtom> getOnDiskIterator(DataInput dis, int count, ColumnSerializer.Flag flag, int expireBefore, Descriptor.Version version)
{
if (cfType == ColumnFamilyType.Standard)
return Column.onDiskSerializer();
return SuperColumn.onDiskSerializer(subcolumnComparator);
if (version.hasSuperColumns && cfType == ColumnFamilyType.Super)
return SuperColumns.onDiskIterator(dis, count, flag, expireBefore);
return Column.onDiskIterator(dis, count, flag, expireBefore, version);
}
public static boolean isNameValid(String name)
@ -1073,22 +1073,9 @@ public final class CFMetaData
if (cfType == null)
throw new ConfigurationException(String.format("Invalid column family type for %s", cfName));
if (cfType == ColumnFamilyType.Super)
{
if (subcolumnComparator == null)
throw new ConfigurationException(String.format("Missing subcolumn comparator for super column family %s", cfName));
}
else
{
if (subcolumnComparator != null)
throw new ConfigurationException(String.format("Subcolumn comparator (%s) is invalid for standard column family %s", subcolumnComparator, cfName));
}
if (comparator instanceof CounterColumnType)
throw new ConfigurationException("CounterColumnType is not a valid comparator");
if (subcolumnComparator instanceof CounterColumnType)
throw new ConfigurationException("CounterColumnType is not a valid sub-column comparator");
if (keyValidator instanceof CounterColumnType)
throw new ConfigurationException("CounterColumnType is not a valid key validator");
@ -1315,9 +1302,21 @@ public final class CFMetaData
cf.addColumn(Column.create(oldId, timestamp, cfName, "id"));
cf.addColumn(Column.create(cfType.toString(), timestamp, cfName, "type"));
cf.addColumn(Column.create(comparator.toString(), timestamp, cfName, "comparator"));
if (subcolumnComparator != null)
cf.addColumn(Column.create(subcolumnComparator.toString(), timestamp, cfName, "subcomparator"));
if (isSuper())
{
// We need to continue saving the comparator and subcomparator separatly, otherwise
// we won't know at deserialization if the subcomparator should be taken into account
// TODO: we should implement an on-start migration if we want to get rid of that.
CompositeType ct = (CompositeType)comparator;
cf.addColumn(Column.create(ct.types.get(0).toString(), timestamp, cfName, "comparator"));
cf.addColumn(Column.create(ct.types.get(1).toString(), timestamp, cfName, "subcomparator"));
}
else
{
cf.addColumn(Column.create(comparator.toString(), timestamp, cfName, "comparator"));
}
cf.addColumn(comment == null ? DeletedColumn.create(ldt, timestamp, cfName, "comment")
: Column.create(comment, timestamp, cfName, "comment"));
cf.addColumn(Column.create(readRepairChance, timestamp, cfName, "read_repair_chance"));
@ -1462,7 +1461,7 @@ public final class CFMetaData
public AbstractType<?> getColumnDefinitionComparator(Integer componentIndex)
{
AbstractType<?> cfComparator = cfType == ColumnFamilyType.Super ? subcolumnComparator : comparator;
AbstractType<?> cfComparator = cfType == ColumnFamilyType.Super ? ((CompositeType)comparator).types.get(1) : comparator;
if (cfComparator instanceof CompositeType)
{
if (componentIndex == null)
@ -1515,7 +1514,7 @@ public final class CFMetaData
*/
public boolean isThriftIncompatible()
{
if (!cqlCfDef.isComposite)
if (isSuper() || !cqlCfDef.isComposite)
return false;
for (ColumnDefinition columnDef : column_metadata.values())
@ -1535,7 +1534,6 @@ public final class CFMetaData
.append("cfName", cfName)
.append("cfType", cfType)
.append("comparator", comparator)
.append("subcolumncomparator", subcolumnComparator)
.append("comment", comment)
.append("readRepairChance", readRepairChance)
.append("dclocalReadRepairChance", dcLocalReadRepairChance)

View File

@ -25,7 +25,6 @@ import com.google.common.collect.Maps;
import org.apache.cassandra.cql3.QueryProcessor;
import org.apache.cassandra.cql3.UntypedResultSet;
import org.apache.cassandra.db.*;
import org.apache.cassandra.db.filter.QueryPath;
import org.apache.cassandra.db.marshal.*;
import org.apache.cassandra.exceptions.*;
import org.apache.cassandra.service.StorageService;
@ -116,24 +115,25 @@ public class ColumnDefinition
return cd;
}
public static ColumnDefinition fromThrift(ColumnDef thriftColumnDef) throws SyntaxException, ConfigurationException
public static ColumnDefinition fromThrift(ColumnDef thriftColumnDef, boolean isSuper) throws SyntaxException, ConfigurationException
{
// For super columns, the componentIndex is 1 because the ColumnDefinition applies to the column component.
return new ColumnDefinition(ByteBufferUtil.clone(thriftColumnDef.name),
TypeParser.parse(thriftColumnDef.validation_class),
thriftColumnDef.index_type,
thriftColumnDef.index_options,
thriftColumnDef.index_name,
null);
isSuper ? 1 : null);
}
public static Map<ByteBuffer, ColumnDefinition> fromThrift(List<ColumnDef> thriftDefs) throws SyntaxException, ConfigurationException
public static Map<ByteBuffer, ColumnDefinition> fromThrift(List<ColumnDef> thriftDefs, boolean isSuper) throws SyntaxException, ConfigurationException
{
if (thriftDefs == null)
return new HashMap<ByteBuffer,ColumnDefinition>();
Map<ByteBuffer, ColumnDefinition> cds = new TreeMap<ByteBuffer, ColumnDefinition>();
for (ColumnDef thriftColumnDef : thriftDefs)
cds.put(ByteBufferUtil.clone(thriftColumnDef.name), fromThrift(thriftColumnDef));
cds.put(ByteBufferUtil.clone(thriftColumnDef.name), fromThrift(thriftColumnDef, isSuper));
return cds;
}
@ -224,6 +224,9 @@ public class ColumnDefinition
index_name = result.getString("index_name");
if (result.has("component_index"))
componentIndex = result.getInt("component_index");
// A ColumnDefinition for super columns applies to the column component
else if (cfm.isSuper())
componentIndex = 1;
cds.add(new ColumnDefinition(cfm.getColumnDefinitionComparator(componentIndex).fromString(result.getString("column_name")),
TypeParser.parse(result.getString("validator")),
@ -246,7 +249,6 @@ public class ColumnDefinition
DecoratedKey key = StorageService.getPartitioner().decorateKey(SystemTable.getSchemaKSKey(ksName));
ColumnFamilyStore columnsStore = SystemTable.schemaCFS(SystemTable.SCHEMA_COLUMNS_CF);
ColumnFamily cf = columnsStore.getColumnFamily(key,
new QueryPath(SystemTable.SCHEMA_COLUMNS_CF),
DefsTable.searchComposite(cfName, true),
DefsTable.searchComposite(cfName, false),
false,

View File

@ -27,7 +27,6 @@ import org.apache.cassandra.auth.Auth;
import org.apache.cassandra.cql3.QueryProcessor;
import org.apache.cassandra.cql3.UntypedResultSet;
import org.apache.cassandra.db.*;
import org.apache.cassandra.db.filter.QueryPath;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.locator.*;
import org.apache.cassandra.service.StorageService;
@ -234,9 +233,9 @@ public final class KSMetaData
public RowMutation dropFromSchema(long timestamp)
{
RowMutation rm = new RowMutation(Table.SYSTEM_KS, SystemTable.getSchemaKSKey(name));
rm.delete(new QueryPath(SystemTable.SCHEMA_KEYSPACES_CF), timestamp);
rm.delete(new QueryPath(SystemTable.SCHEMA_COLUMNFAMILIES_CF), timestamp);
rm.delete(new QueryPath(SystemTable.SCHEMA_COLUMNS_CF), timestamp);
rm.delete(SystemTable.SCHEMA_KEYSPACES_CF, timestamp);
rm.delete(SystemTable.SCHEMA_COLUMNFAMILIES_CF, timestamp);
rm.delete(SystemTable.SCHEMA_COLUMNS_CF, timestamp);
return rm;
}

View File

@ -235,20 +235,6 @@ public class Schema
return cfmd.comparator;
}
/**
* Get subComparator of the ColumnFamily
*
* @param ksName The keyspace name
* @param cfName The ColumnFamily name
*
* @return The subComparator of the ColumnFamily
*/
public AbstractType<?> getSubComparator(String ksName, String cfName)
{
assert ksName != null;
return getCFMetaData(ksName, cfName).subcolumnComparator;
}
/**
* Get value validator for specific column
*

View File

@ -26,7 +26,6 @@ import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.config.Schema;
import org.apache.cassandra.db.IMutation;
import org.apache.cassandra.db.RowMutation;
import org.apache.cassandra.db.filter.QueryPath;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.exceptions.InvalidRequestException;
import org.apache.cassandra.exceptions.UnauthorizedException;
@ -93,21 +92,19 @@ public class DeleteStatement extends AbstractModification
QueryProcessor.validateKeyAlias(metadata, keyName);
AbstractType<?> comparator = metadata.getComparatorFor(null);
if (columns.size() < 1)
{
// No columns, delete the row
rm.delete(new QueryPath(columnFamily), (timestamp == null) ? getTimestamp(clientState) : timestamp);
rm.delete(columnFamily, (timestamp == null) ? getTimestamp(clientState) : timestamp);
}
else
{
// Delete specific columns
for (Term column : columns)
{
ByteBuffer columnName = column.getByteBuffer(comparator, variables);
ByteBuffer columnName = column.getByteBuffer(metadata.comparator, variables);
validateColumnName(columnName);
rm.delete(new QueryPath(columnFamily, null, columnName), (timestamp == null) ? getTimestamp(clientState) : timestamp);
rm.delete(columnFamily, columnName, (timestamp == null) ? getTimestamp(clientState) : timestamp);
}
}

View File

@ -76,13 +76,12 @@ public class QueryProcessor
private static List<org.apache.cassandra.db.Row> getSlice(CFMetaData metadata, SelectStatement select, List<ByteBuffer> variables)
throws InvalidRequestException, ReadTimeoutException, UnavailableException, IsBootstrappingException
{
QueryPath queryPath = new QueryPath(select.getColumnFamily());
List<ReadCommand> commands = new ArrayList<ReadCommand>();
// ...of a list of column names
if (!select.isColumnRange())
{
Collection<ByteBuffer> columnNames = getColumnNames(select, metadata, variables);
SortedSet<ByteBuffer> columnNames = getColumnNames(select, metadata, variables);
validateColumnNames(columnNames);
for (Term rawKey: select.getKeys())
@ -90,7 +89,7 @@ public class QueryProcessor
ByteBuffer key = rawKey.getByteBuffer(metadata.getKeyValidator(),variables);
validateKey(key);
commands.add(new SliceByNamesReadCommand(metadata.ksName, key, queryPath, columnNames));
commands.add(new SliceByNamesReadCommand(metadata.ksName, key, select.getColumnFamily(), new NamesQueryFilter(columnNames)));
}
}
// ...a range (slice) of column names
@ -108,11 +107,8 @@ public class QueryProcessor
validateSliceFilter(metadata, start, finish, select.isColumnsReversed());
commands.add(new SliceFromReadCommand(metadata.ksName,
key,
queryPath,
start,
finish,
select.isColumnsReversed(),
select.getColumnsLimit()));
select.getColumnFamily(),
new SliceQueryFilter(start, finish, select.isColumnsReversed(), select.getColumnsLimit())));
}
}
@ -191,7 +187,6 @@ public class QueryProcessor
{
rows = StorageProxy.getRangeSlice(new RangeSliceCommand(metadata.ksName,
select.getColumnFamily(),
null,
columnFilter,
bounds,
expressions,
@ -300,10 +295,10 @@ public class QueryProcessor
{
for (ByteBuffer name : columns)
{
if (name.remaining() > IColumn.MAX_NAME_LENGTH)
if (name.remaining() > org.apache.cassandra.db.Column.MAX_NAME_LENGTH)
throw new InvalidRequestException(String.format("column name is too long (%s > %s)",
name.remaining(),
IColumn.MAX_NAME_LENGTH));
org.apache.cassandra.db.Column.MAX_NAME_LENGTH));
if (name.remaining() == 0)
throw new InvalidRequestException("zero-length column name");
}
@ -352,7 +347,7 @@ public class QueryProcessor
private static void validateSliceFilter(CFMetaData metadata, ByteBuffer start, ByteBuffer finish, boolean reversed)
throws InvalidRequestException
{
AbstractType<?> comparator = metadata.getComparatorFor(null);
AbstractType<?> comparator = metadata.comparator;
Comparator<ByteBuffer> orderedComparator = reversed ? comparator.reverseComparator: comparator;
if (start.remaining() > 0 && finish.remaining() > 0 && orderedComparator.compare(start, finish) > 0)
throw new InvalidRequestException("range finish must come after start in traversal order");
@ -456,7 +451,7 @@ public class QueryProcessor
// preserve comparator order
if (row.cf != null)
{
for (IColumn c : row.cf.getSortedColumns())
for (org.apache.cassandra.db.Column c : row.cf.getSortedColumns())
{
if (c.isMarkedForDelete())
continue;
@ -502,7 +497,7 @@ public class QueryProcessor
ColumnDefinition cd = metadata.getColumnDefinitionFromColumnName(name);
if (cd != null)
result.schema.value_types.put(name, TypeParser.getShortName(cd.getValidator()));
IColumn c = row.cf.getColumn(name);
org.apache.cassandra.db.Column c = row.cf.getColumn(name);
if (c == null || c.isMarkedForDelete())
thriftColumns.add(new Column().setName(name));
else
@ -833,7 +828,7 @@ public class QueryProcessor
return cql.hashCode();
}
private static Column thriftify(IColumn c)
private static Column thriftify(org.apache.cassandra.db.Column c)
{
ByteBuffer value = (c instanceof CounterColumn)
? ByteBufferUtil.bytes(CounterContext.instance().total(c.value()))

View File

@ -27,7 +27,6 @@ import org.apache.cassandra.db.CounterMutation;
import org.apache.cassandra.db.ConsistencyLevel;
import org.apache.cassandra.db.IMutation;
import org.apache.cassandra.db.RowMutation;
import org.apache.cassandra.db.filter.QueryPath;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.exceptions.InvalidRequestException;
import org.apache.cassandra.exceptions.UnauthorizedException;
@ -197,7 +196,8 @@ public class UpdateStatement extends AbstractModification
ByteBuffer colValue = op.a.getByteBuffer(getValueValidator(keyspace, colName),variables);
validateColumn(metadata, colName, colValue);
rm.add(new QueryPath(columnFamily, null, colName),
rm.add(columnFamily,
colName,
colValue,
(timestamp == null) ? getTimestamp(clientState) : timestamp,
getTimeToLive());
@ -221,7 +221,7 @@ public class UpdateStatement extends AbstractModification
op.b.getText()));
}
rm.addCounter(new QueryPath(columnFamily, null, colName), value);
rm.addCounter(columnFamily, colName, value);
}
}

View File

@ -90,6 +90,7 @@ public class CFDefinition implements Iterable<CFDefinition.Name>
* We are a "sparse" composite, i.e. a non-compact one, if either:
* - the last type of the composite is a ColumnToCollectionType
* - or we have one less alias than of composite types and the last type is UTF8Type.
* - some metadata are defined
*
* Note that this is not perfect: if someone upgrading from thrift "renames" all but
* the last column alias, the cf will be considered "sparse" and he will be stuck with
@ -98,7 +99,8 @@ public class CFDefinition implements Iterable<CFDefinition.Name>
*/
int last = composite.types.size() - 1;
AbstractType<?> lastType = composite.types.get(last);
if (lastType instanceof ColumnToCollectionType
if (!cfm.getColumn_metadata().isEmpty()
|| lastType instanceof ColumnToCollectionType
|| (cfm.getColumnAliases().size() == last && lastType instanceof UTF8Type))
{
// "sparse" composite

View File

@ -85,10 +85,10 @@ public class QueryProcessor
{
for (ByteBuffer name : columns)
{
if (name.remaining() > IColumn.MAX_NAME_LENGTH)
if (name.remaining() > Column.MAX_NAME_LENGTH)
throw new InvalidRequestException(String.format("column name is too long (%s > %s)",
name.remaining(),
IColumn.MAX_NAME_LENGTH));
Column.MAX_NAME_LENGTH));
if (name.remaining() == 0)
throw new InvalidRequestException("zero-length column name");
}
@ -114,8 +114,7 @@ public class QueryProcessor
{
try
{
AbstractType<?> comparator = metadata.getComparatorFor(null);
ColumnSlice.validate(range.slices, comparator, range.reversed);
ColumnSlice.validate(range.slices, metadata.comparator, range.reversed);
}
catch (IllegalArgumentException e)
{

View File

@ -23,8 +23,7 @@ import java.util.List;
import org.apache.cassandra.cql3.*;
import org.apache.cassandra.db.ColumnFamily;
import org.apache.cassandra.db.IColumn;
import org.apache.cassandra.db.filter.QueryPath;
import org.apache.cassandra.db.Column;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.CollectionType;
import org.apache.cassandra.db.marshal.ListType;
@ -63,7 +62,7 @@ public class ColumnOperation implements Operation
ColumnNameBuilder builder,
AbstractType<?> validator,
UpdateParameters params,
List<Pair<ByteBuffer, IColumn>> list) throws InvalidRequestException
List<Pair<ByteBuffer, Column>> list) throws InvalidRequestException
{
switch (kind)
{
@ -109,7 +108,7 @@ public class ColumnOperation implements Operation
val = -val;
}
cf.addCounter(new QueryPath(cf.metadata().cfName, null, builder.build()), val);
cf.addCounter(builder.build(), val);
}
public void addBoundNames(ColumnSpecification column, ColumnSpecification[] boundNames) throws InvalidRequestException

View File

@ -30,7 +30,7 @@ import org.apache.cassandra.cql3.ColumnSpecification;
import org.apache.cassandra.cql3.Term;
import org.apache.cassandra.cql3.UpdateParameters;
import org.apache.cassandra.db.ColumnFamily;
import org.apache.cassandra.db.IColumn;
import org.apache.cassandra.db.Column;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.CollectionType;
import org.apache.cassandra.db.marshal.Int32Type;
@ -99,7 +99,7 @@ public class ListOperation implements Operation
ColumnNameBuilder builder,
AbstractType<?> validator,
UpdateParameters params,
List<Pair<ByteBuffer, IColumn>> list) throws InvalidRequestException
List<Pair<ByteBuffer, Column>> list) throws InvalidRequestException
{
if (!(validator instanceof ListType || (kind == Kind.SET_IDX && validator instanceof MapType)))
throw new InvalidRequestException("List operations are only supported on List typed columns, but " + validator + " given.");
@ -198,7 +198,7 @@ public class ListOperation implements Operation
}
}
public static void doDiscardFromPrepared(ColumnFamily cf, ColumnNameBuilder builder, ListType validator, Term values, UpdateParameters params, List<Pair<ByteBuffer, IColumn>> list) throws InvalidRequestException
public static void doDiscardFromPrepared(ColumnFamily cf, ColumnNameBuilder builder, ListType validator, Term values, UpdateParameters params, List<Pair<ByteBuffer, Column>> list) throws InvalidRequestException
{
if (!values.isBindMarker())
throw new InvalidRequestException("Can't apply operation on column with " + validator + " type.");
@ -214,9 +214,9 @@ public class ListOperation implements Operation
for (Object elt : l)
toDiscard.add(validator.valueComparator().decompose(elt));
for (Pair<ByteBuffer, IColumn> p : list)
for (Pair<ByteBuffer, Column> p : list)
{
IColumn c = p.right;
Column c = p.right;
if (toDiscard.contains(c.value()))
cf.addColumn(params.makeTombstone(c.name()));
}
@ -227,7 +227,7 @@ public class ListOperation implements Operation
}
}
private void doSet(ColumnFamily cf, ColumnNameBuilder builder, UpdateParameters params, CollectionType validator, List<Pair<ByteBuffer, IColumn>> list) throws InvalidRequestException
private void doSet(ColumnFamily cf, ColumnNameBuilder builder, UpdateParameters params, CollectionType validator, List<Pair<ByteBuffer, Column>> list) throws InvalidRequestException
{
int idx = validateListIdx(values.get(0), list);
Term value = values.get(1);
@ -261,7 +261,7 @@ public class ListOperation implements Operation
}
}
private void doDiscard(ColumnFamily cf, CollectionType validator, UpdateParameters params, List<Pair<ByteBuffer, IColumn>> list) throws InvalidRequestException
private void doDiscard(ColumnFamily cf, CollectionType validator, UpdateParameters params, List<Pair<ByteBuffer, Column>> list) throws InvalidRequestException
{
if (list == null)
return;
@ -271,15 +271,15 @@ public class ListOperation implements Operation
for (Term value : values)
toDiscard.add(value.getByteBuffer(validator.valueComparator(), params.variables));
for (Pair<ByteBuffer, IColumn> p : list)
for (Pair<ByteBuffer, Column> p : list)
{
IColumn c = p.right;
Column c = p.right;
if (toDiscard.contains(c.value()))
cf.addColumn(params.makeTombstone(c.name()));
}
}
private void doDiscardIdx(ColumnFamily cf, UpdateParameters params, List<Pair<ByteBuffer, IColumn>> list) throws InvalidRequestException
private void doDiscardIdx(ColumnFamily cf, UpdateParameters params, List<Pair<ByteBuffer, Column>> list) throws InvalidRequestException
{
int idx = validateListIdx(values.get(0), list);
cf.addColumn(params.makeTombstone(list.get(idx).right.name()));
@ -381,7 +381,7 @@ public class ListOperation implements Operation
return "ListOperation(" + kind + ", " + values + ")";
}
private int validateListIdx(Term value, List<Pair<ByteBuffer, IColumn>> list) throws InvalidRequestException
private int validateListIdx(Term value, List<Pair<ByteBuffer, Column>> list) throws InvalidRequestException
{
try
{

View File

@ -29,7 +29,7 @@ import org.apache.cassandra.cql3.ColumnSpecification;
import org.apache.cassandra.cql3.Term;
import org.apache.cassandra.cql3.UpdateParameters;
import org.apache.cassandra.db.ColumnFamily;
import org.apache.cassandra.db.IColumn;
import org.apache.cassandra.db.Column;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.CollectionType;
import org.apache.cassandra.db.marshal.MapType;
@ -63,7 +63,7 @@ public class MapOperation implements Operation
ColumnNameBuilder builder,
AbstractType<?> validator,
UpdateParameters params,
List<Pair<ByteBuffer, IColumn>> list) throws InvalidRequestException
List<Pair<ByteBuffer, Column>> list) throws InvalidRequestException
{
if (!(validator instanceof MapType))
throw new InvalidRequestException("Map operations are only supported on Map typed columns, but " + validator + " given.");

View File

@ -25,7 +25,7 @@ import org.apache.cassandra.cql3.ColumnSpecification;
import org.apache.cassandra.cql3.Term;
import org.apache.cassandra.cql3.UpdateParameters;
import org.apache.cassandra.db.ColumnFamily;
import org.apache.cassandra.db.IColumn;
import org.apache.cassandra.db.Column;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.CollectionType;
import org.apache.cassandra.exceptions.InvalidRequestException;
@ -39,7 +39,7 @@ public interface Operation
ColumnNameBuilder builder,
AbstractType<?> validator,
UpdateParameters params,
List<Pair<ByteBuffer, IColumn>> list) throws InvalidRequestException;
List<Pair<ByteBuffer, Column>> list) throws InvalidRequestException;
public void addBoundNames(ColumnSpecification column, ColumnSpecification[] boundNames) throws InvalidRequestException;

View File

@ -23,7 +23,7 @@ import java.util.List;
import org.apache.cassandra.cql3.*;
import org.apache.cassandra.db.ColumnFamily;
import org.apache.cassandra.db.IColumn;
import org.apache.cassandra.db.Column;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.CollectionType;
import org.apache.cassandra.db.marshal.ListType;
@ -50,7 +50,7 @@ public class PreparedOperation implements Operation
ColumnNameBuilder builder,
AbstractType<?> validator,
UpdateParameters params,
List<Pair<ByteBuffer, IColumn>> list) throws InvalidRequestException
List<Pair<ByteBuffer, Column>> list) throws InvalidRequestException
{
if (validator instanceof CollectionType)
{

View File

@ -27,7 +27,7 @@ import org.apache.cassandra.cql3.ColumnSpecification;
import org.apache.cassandra.cql3.Term;
import org.apache.cassandra.cql3.UpdateParameters;
import org.apache.cassandra.db.ColumnFamily;
import org.apache.cassandra.db.IColumn;
import org.apache.cassandra.db.Column;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.CollectionType;
import org.apache.cassandra.db.marshal.MarshalException;
@ -53,7 +53,7 @@ public class SetOperation implements Operation
ColumnNameBuilder builder,
AbstractType<?> validator,
UpdateParameters params,
List<Pair<ByteBuffer, IColumn>> list) throws InvalidRequestException
List<Pair<ByteBuffer, Column>> list) throws InvalidRequestException
{
if (!(validator instanceof SetType))
throw new InvalidRequestException("Set operations are only supported on Set typed columns, but " + validator + " given.");

View File

@ -93,6 +93,8 @@ public class AlterTableStatement extends SchemaAlteringStatement
{
if (!cfDef.isComposite)
throw new InvalidRequestException("Cannot use collection types with non-composite PRIMARY KEY");
if (cfDef.cfm.isSuper())
throw new InvalidRequestException("Cannot use collection types with Super column family");
componentIndex--;

View File

@ -24,7 +24,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.cassandra.db.IColumn;
import org.apache.cassandra.db.Column;
import org.apache.cassandra.db.marshal.CompositeType;
import org.apache.cassandra.utils.Pair;
@ -38,7 +38,7 @@ public class ColumnGroupMap
this.fullPath = fullPath;
}
private void add(ByteBuffer[] fullName, int idx, IColumn column)
private void add(ByteBuffer[] fullName, int idx, Column column)
{
ByteBuffer columnName = fullName[idx];
if (fullName.length == idx + 2)
@ -66,7 +66,7 @@ public class ColumnGroupMap
return fullPath[pos];
}
public IColumn getSimple(ByteBuffer key)
public Column getSimple(ByteBuffer key)
{
Value v = map.get(key);
if (v == null)
@ -76,29 +76,29 @@ public class ColumnGroupMap
return ((Simple)v).column;
}
public List<Pair<ByteBuffer, IColumn>> getCollection(ByteBuffer key)
public List<Pair<ByteBuffer, Column>> getCollection(ByteBuffer key)
{
Value v = map.get(key);
if (v == null)
return null;
assert v instanceof Collection;
return (List<Pair<ByteBuffer, IColumn>>)v;
return (List<Pair<ByteBuffer, Column>>)v;
}
private interface Value {};
private static class Simple implements Value
{
public final IColumn column;
public final Column column;
Simple(IColumn column)
Simple(Column column)
{
this.column = column;
}
}
private static class Collection extends ArrayList<Pair<ByteBuffer, IColumn>> implements Value {}
private static class Collection extends ArrayList<Pair<ByteBuffer, Column>> implements Value {}
public static class Builder
{
@ -115,7 +115,7 @@ public class ColumnGroupMap
this.idx = composite.types.size() - (hasCollections ? 2 : 1);
}
public void add(IColumn c)
public void add(Column c)
{
if (c.isMarkedForDelete())
return;

View File

@ -26,7 +26,6 @@ import org.apache.cassandra.auth.Permission;
import org.apache.cassandra.cql3.*;
import org.apache.cassandra.db.*;
import org.apache.cassandra.db.filter.ColumnSlice;
import org.apache.cassandra.db.filter.QueryPath;
import org.apache.cassandra.db.filter.SliceQueryFilter;
import org.apache.cassandra.db.marshal.CompositeType;
import org.apache.cassandra.exceptions.*;
@ -165,7 +164,7 @@ public abstract class ModificationStatement extends CFStatement implements CQLSt
for (ByteBuffer key : keys)
commands.add(new SliceFromReadCommand(keyspace(),
key,
new QueryPath(columnFamily()),
columnFamily(),
new SliceQueryFilter(slices, false, Integer.MAX_VALUE)));
try
@ -181,7 +180,7 @@ public abstract class ModificationStatement extends CFStatement implements CQLSt
continue;
ColumnGroupMap.Builder groupBuilder = new ColumnGroupMap.Builder(composite, true);
for (IColumn column : row.cf)
for (Column column : row.cf)
groupBuilder.add(column);
List<ColumnGroupMap> groups = groupBuilder.groups();

View File

@ -198,7 +198,6 @@ public class SelectStatement implements CQLStatement
private List<ReadCommand> getSliceCommands(List<ByteBuffer> variables) throws RequestValidationException
{
QueryPath queryPath = new QueryPath(columnFamily());
Collection<ByteBuffer> keys = getKeys(variables);
List<ReadCommand> commands = new ArrayList<ReadCommand>(keys.size());
@ -214,7 +213,7 @@ public class SelectStatement implements CQLStatement
// Note that we should not share the slice filter amongst the command, due to SliceQueryFilter not
// being immutable due to its columnCounter used by the lastCounted() method
// (this is fairly ugly and we should change that but that's probably not a tiny refactor to do that cleanly)
commands.add(new SliceFromReadCommand(keyspace(), key, queryPath, (SliceQueryFilter)makeFilter(variables)));
commands.add(new SliceFromReadCommand(keyspace(), key, columnFamily(), (SliceQueryFilter)makeFilter(variables)));
}
}
// ...of a list of column names
@ -225,7 +224,7 @@ public class SelectStatement implements CQLStatement
for (ByteBuffer key: keys)
{
QueryProcessor.validateKey(key);
commands.add(new SliceByNamesReadCommand(keyspace(), key, queryPath, (NamesQueryFilter)filter));
commands.add(new SliceByNamesReadCommand(keyspace(), key, columnFamily(), (NamesQueryFilter)filter));
}
}
return commands;
@ -239,7 +238,6 @@ public class SelectStatement implements CQLStatement
// We want to have getRangeSlice to count the number of columns, not the number of keys.
return new RangeSliceCommand(keyspace(),
columnFamily(),
null,
filter,
getKeyBounds(variables),
expressions,
@ -476,9 +474,9 @@ public class SelectStatement implements CQLStatement
// We need to query the selected column as well as the marker
// column (for the case where the row exists but has no columns outside the PK)
// One exception is "static CF" (non-composite non-compact CF) that
// don't have marker and for which we must query all columns instead
if (cfDef.isComposite)
// Two exceptions are "static CF" (non-composite non-compact CF) and "super CF"
// that don't have marker and for which we must query all columns instead
if (cfDef.isComposite && !cfDef.cfm.isSuper())
{
// marker
columns.add(builder.copy().add(ByteBufferUtil.EMPTY_BYTE_BUFFER).build());
@ -606,14 +604,14 @@ public class SelectStatement implements CQLStatement
}
}
private ByteBuffer value(IColumn c)
private ByteBuffer value(Column c)
{
return (c instanceof CounterColumn)
? ByteBufferUtil.bytes(CounterContext.instance().total(c.value()))
: c.value();
}
private void addReturnValue(ResultSet cqlRows, Selector s, IColumn c)
private void addReturnValue(ResultSet cqlRows, Selector s, Column c)
{
if (c == null || c.isMarkedForDelete())
{
@ -672,7 +670,7 @@ public class SelectStatement implements CQLStatement
return new ResultSet(names);
}
private Iterable<IColumn> columnsInOrder(final ColumnFamily cf, final List<ByteBuffer> variables) throws InvalidRequestException
private Iterable<Column> columnsInOrder(final ColumnFamily cf, final List<ByteBuffer> variables) throws InvalidRequestException
{
// If the restriction for the last column alias is an IN, respect
// requested order
@ -693,18 +691,18 @@ public class SelectStatement implements CQLStatement
requested.add(b.add(t, Relation.Type.EQ, variables).build());
}
return new Iterable<IColumn>()
return new Iterable<Column>()
{
public Iterator<IColumn> iterator()
public Iterator<Column> iterator()
{
return new AbstractIterator<IColumn>()
return new AbstractIterator<Column>()
{
Iterator<ByteBuffer> iter = requested.iterator();
public IColumn computeNext()
public Column computeNext()
{
if (!iter.hasNext())
return endOfData();
IColumn column = cf.getColumn(iter.next());
Column column = cf.getColumn(iter.next());
return column == null ? computeNext() : column;
}
};
@ -736,7 +734,7 @@ public class SelectStatement implements CQLStatement
if (cfDef.isCompact)
{
// One cqlRow per column
for (IColumn c : columnsInOrder(row.cf, variables))
for (Column c : columnsInOrder(row.cf, variables))
{
if (c.isMarkedForDelete())
continue;
@ -797,7 +795,7 @@ public class SelectStatement implements CQLStatement
ColumnGroupMap.Builder builder = new ColumnGroupMap.Builder(composite, cfDef.hasCollections);
for (IColumn c : row.cf)
for (Column c : row.cf)
{
if (c.isMarkedForDelete())
continue;
@ -825,7 +823,7 @@ public class SelectStatement implements CQLStatement
continue;
}
IColumn c = row.cf.getColumn(name.name.key);
Column c = row.cf.getColumn(name.name.key);
addReturnValue(cqlRows, selector, c);
}
}
@ -936,14 +934,14 @@ public class SelectStatement implements CQLStatement
case COLUMN_METADATA:
if (name.type.isCollection())
{
List<Pair<ByteBuffer, IColumn>> collection = columns.getCollection(name.name.key);
List<Pair<ByteBuffer, Column>> collection = columns.getCollection(name.name.key);
if (collection == null)
cqlRows.addColumnValue(null);
else
cqlRows.addColumnValue(((CollectionType)name.type).serialize(collection));
break;
}
IColumn c = columns.getSimple(name.name.key);
Column c = columns.getSimple(name.name.key);
addReturnValue(cqlRows, selector, c);
break;
default:

View File

@ -220,7 +220,9 @@ public class UpdateStatement extends ModificationStatement
// The last query should return one row (but with c == null). Adding
// the marker with the insert make sure the semantic is correct (while making sure a
// 'DELETE FROM t WHERE k = 1' does remove the row entirely)
if (cfDef.isComposite && !cfDef.isCompact)
//
// We never insert markers for Super CF as this would confuse the thrift side.
if (cfDef.isComposite && !cfDef.isCompact && !cfDef.cfm.isSuper())
{
ByteBuffer name = builder.copy().add(ByteBufferUtil.EMPTY_BYTE_BUFFER).build();
cf.addColumn(params.makeColumn(name, ByteBufferUtil.EMPTY_BYTE_BUFFER));

View File

@ -32,7 +32,7 @@ import org.apache.cassandra.io.util.IIterableColumns;
import org.apache.cassandra.utils.Allocator;
import org.apache.cassandra.utils.HeapAllocator;
public abstract class AbstractColumnContainer implements IColumnContainer, IIterableColumns
public abstract class AbstractColumnContainer implements IIterableColumns
{
protected final ISortedColumns columns;
@ -84,37 +84,37 @@ public abstract class AbstractColumnContainer implements IColumnContainer, IIter
columns.maybeResetDeletionTimes(gcBefore);
}
public long addAllWithSizeDelta(AbstractColumnContainer cc, Allocator allocator, Function<IColumn, IColumn> transformation, SecondaryIndexManager.Updater indexer)
public long addAllWithSizeDelta(AbstractColumnContainer cc, Allocator allocator, Function<Column, Column> transformation, SecondaryIndexManager.Updater indexer)
{
return columns.addAllWithSizeDelta(cc.columns, allocator, transformation, indexer);
}
public void addAll(AbstractColumnContainer cc, Allocator allocator, Function<IColumn, IColumn> transformation)
public void addAll(AbstractColumnContainer cc, Allocator allocator, Function<Column, Column> transformation)
{
columns.addAll(cc.columns, allocator, transformation);
}
public void addAll(AbstractColumnContainer cc, Allocator allocator)
{
addAll(cc, allocator, Functions.<IColumn>identity());
addAll(cc, allocator, Functions.<Column>identity());
}
public void addColumn(IColumn column)
public void addColumn(Column column)
{
addColumn(column, HeapAllocator.instance);
}
public void addColumn(IColumn column, Allocator allocator)
public void addColumn(Column column, Allocator allocator)
{
columns.addColumn(column, allocator);
}
public IColumn getColumn(ByteBuffer name)
public Column getColumn(ByteBuffer name)
{
return columns.getColumn(name);
}
public boolean replace(IColumn oldColumn, IColumn newColumn)
public boolean replace(Column oldColumn, Column newColumn)
{
return columns.replace(oldColumn, newColumn);
}
@ -129,12 +129,12 @@ public abstract class AbstractColumnContainer implements IColumnContainer, IIter
return columns.getColumnNames();
}
public Collection<IColumn> getSortedColumns()
public Collection<Column> getSortedColumns()
{
return columns.getSortedColumns();
}
public Collection<IColumn> getReverseSortedColumns()
public Collection<Column> getReverseSortedColumns()
{
return columns.getReverseSortedColumns();
}
@ -166,7 +166,7 @@ public abstract class AbstractColumnContainer implements IColumnContainer, IIter
public boolean hasOnlyTombstones()
{
for (IColumn column : columns)
for (Column column : columns)
{
if (column.isLive())
return false;
@ -174,17 +174,17 @@ public abstract class AbstractColumnContainer implements IColumnContainer, IIter
return true;
}
public Iterator<IColumn> iterator()
public Iterator<Column> iterator()
{
return columns.iterator();
}
public Iterator<IColumn> iterator(ColumnSlice[] slices)
public Iterator<Column> iterator(ColumnSlice[] slices)
{
return columns.iterator(slices);
}
public Iterator<IColumn> reverseIterator(ColumnSlice[] slices)
public Iterator<Column> reverseIterator(ColumnSlice[] slices)
{
return columns.reverseIterator(slices);
}
@ -196,7 +196,7 @@ public abstract class AbstractColumnContainer implements IColumnContainer, IIter
return true;
// Do we have colums that are either deleted by the container or gcable tombstone?
for (IColumn column : columns)
for (Column column : columns)
if (deletionInfo().isDeleted(column) || column.hasIrrelevantData(gcBefore))
return true;

View File

@ -52,21 +52,16 @@ public abstract class AbstractThreadUnsafeSortedColumns implements ISortedColumn
public void retainAll(ISortedColumns columns)
{
Iterator<IColumn> iter = iterator();
Iterator<IColumn> toRetain = columns.iterator();
IColumn current = iter.hasNext() ? iter.next() : null;
IColumn retain = toRetain.hasNext() ? toRetain.next() : null;
Iterator<Column> iter = iterator();
Iterator<Column> toRetain = columns.iterator();
Column current = iter.hasNext() ? iter.next() : null;
Column retain = toRetain.hasNext() ? toRetain.next() : null;
AbstractType<?> comparator = getComparator();
while (current != null && retain != null)
{
int c = comparator.compare(current.name(), retain.name());
if (c == 0)
{
if (current instanceof SuperColumn)
{
assert retain instanceof SuperColumn;
((SuperColumn)current).retainAll((SuperColumn)retain);
}
current = iter.hasNext() ? iter.next() : null;
retain = toRetain.hasNext() ? toRetain.next() : null;
}

View File

@ -40,7 +40,7 @@ public class ArrayBackedSortedColumns extends AbstractThreadUnsafeSortedColumns
{
private final AbstractType<?> comparator;
private final boolean reversed;
private final ArrayList<IColumn> columns;
private final ArrayList<Column> columns;
public static final ISortedColumns.Factory factory = new Factory()
{
@ -49,7 +49,7 @@ public class ArrayBackedSortedColumns extends AbstractThreadUnsafeSortedColumns
return new ArrayBackedSortedColumns(comparator, insertReversed);
}
public ISortedColumns fromSorted(SortedMap<ByteBuffer, IColumn> sortedMap, boolean insertReversed)
public ISortedColumns fromSorted(SortedMap<ByteBuffer, Column> sortedMap, boolean insertReversed)
{
return new ArrayBackedSortedColumns(sortedMap.values(), (AbstractType<?>)sortedMap.comparator(), insertReversed);
}
@ -65,14 +65,14 @@ public class ArrayBackedSortedColumns extends AbstractThreadUnsafeSortedColumns
super();
this.comparator = comparator;
this.reversed = reversed;
this.columns = new ArrayList<IColumn>();
this.columns = new ArrayList<Column>();
}
private ArrayBackedSortedColumns(Collection<IColumn> columns, AbstractType<?> comparator, boolean reversed)
private ArrayBackedSortedColumns(Collection<Column> columns, AbstractType<?> comparator, boolean reversed)
{
this.comparator = comparator;
this.reversed = reversed;
this.columns = new ArrayList<IColumn>(columns);
this.columns = new ArrayList<Column>(columns);
}
public ISortedColumns.Factory getFactory()
@ -100,7 +100,7 @@ public class ArrayBackedSortedColumns extends AbstractThreadUnsafeSortedColumns
return reversed ? comparator.reverseComparator : comparator;
}
public IColumn getColumn(ByteBuffer name)
public Column getColumn(ByteBuffer name)
{
int pos = binarySearch(name);
return pos >= 0 ? columns.get(pos) : null;
@ -116,7 +116,7 @@ public class ArrayBackedSortedColumns extends AbstractThreadUnsafeSortedColumns
* without knowing about (we can revisit that decision later if we have
* use cases where most insert are in sorted order but a few are not).
*/
public void addColumn(IColumn column, Allocator allocator)
public void addColumn(Column column, Allocator allocator)
{
if (columns.isEmpty())
{
@ -154,21 +154,13 @@ public class ArrayBackedSortedColumns extends AbstractThreadUnsafeSortedColumns
* Resolve against element at position i.
* Assume that i is a valid position.
*/
private void resolveAgainst(int i, IColumn column, Allocator allocator)
private void resolveAgainst(int i, Column column, Allocator allocator)
{
IColumn oldColumn = columns.get(i);
if (oldColumn instanceof SuperColumn)
{
// Delegated to SuperColumn
assert column instanceof SuperColumn;
((SuperColumn) oldColumn).putColumn((SuperColumn)column, allocator);
}
else
{
// calculate reconciled col from old (existing) col and new col
IColumn reconciledColumn = column.reconcile(oldColumn, allocator);
columns.set(i, reconciledColumn);
}
Column oldColumn = columns.get(i);
// calculate reconciled col from old (existing) col and new col
Column reconciledColumn = column.reconcile(oldColumn, allocator);
columns.set(i, reconciledColumn);
}
private int binarySearch(ByteBuffer name)
@ -180,9 +172,9 @@ public class ArrayBackedSortedColumns extends AbstractThreadUnsafeSortedColumns
* Simple binary search for a given column name.
* The return value has the exact same meaning that the one of Collections.binarySearch().
* (We don't use Collections.binarySearch() directly because it would require us to create
* a fake IColumn (as well as an IColumn comparator) to do the search, which is ugly.
* a fake Column (as well as an Column comparator) to do the search, which is ugly.
*/
private static int binarySearch(List<IColumn> columns, Comparator<ByteBuffer> comparator, ByteBuffer name, int start)
private static int binarySearch(List<Column> columns, Comparator<ByteBuffer> comparator, ByteBuffer name, int start)
{
int low = start;
int mid = columns.size();
@ -207,21 +199,21 @@ public class ArrayBackedSortedColumns extends AbstractThreadUnsafeSortedColumns
return -mid - (result < 0 ? 1 : 2);
}
public long addAllWithSizeDelta(ISortedColumns cm, Allocator allocator, Function<IColumn, IColumn> transformation, SecondaryIndexManager.Updater indexer)
public long addAllWithSizeDelta(ISortedColumns cm, Allocator allocator, Function<Column, Column> transformation, SecondaryIndexManager.Updater indexer)
{
throw new UnsupportedOperationException();
}
public void addAll(ISortedColumns cm, Allocator allocator, Function<IColumn, IColumn> transformation)
public void addAll(ISortedColumns cm, Allocator allocator, Function<Column, Column> transformation)
{
delete(cm.getDeletionInfo());
if (cm.isEmpty())
return;
IColumn[] copy = columns.toArray(new IColumn[size()]);
Column[] copy = columns.toArray(new Column[size()]);
int idx = 0;
Iterator<IColumn> other = reversed ? cm.reverseIterator(ColumnSlice.ALL_COLUMNS_ARRAY) : cm.iterator();
IColumn otherColumn = other.next();
Iterator<Column> other = reversed ? cm.reverseIterator(ColumnSlice.ALL_COLUMNS_ARRAY) : cm.iterator();
Column otherColumn = other.next();
columns.clear();
@ -257,7 +249,7 @@ public class ArrayBackedSortedColumns extends AbstractThreadUnsafeSortedColumns
}
}
public boolean replace(IColumn oldColumn, IColumn newColumn)
public boolean replace(Column oldColumn, Column newColumn)
{
if (!oldColumn.name().equals(newColumn.name()))
throw new IllegalArgumentException();
@ -271,12 +263,12 @@ public class ArrayBackedSortedColumns extends AbstractThreadUnsafeSortedColumns
return pos >= 0;
}
public Collection<IColumn> getSortedColumns()
public Collection<Column> getSortedColumns()
{
return reversed ? new ReverseSortedCollection() : columns;
}
public Collection<IColumn> getReverseSortedColumns()
public Collection<Column> getReverseSortedColumns()
{
// If reversed, the element are sorted reversely, so we could expect
// to return *this*, but *this* redefine the iterator to be in sorted
@ -307,39 +299,39 @@ public class ArrayBackedSortedColumns extends AbstractThreadUnsafeSortedColumns
return new ColumnNamesSet();
}
public Iterator<IColumn> iterator()
public Iterator<Column> iterator()
{
return reversed ? Lists.reverse(columns).iterator() : columns.iterator();
}
public Iterator<IColumn> iterator(ColumnSlice[] slices)
public Iterator<Column> iterator(ColumnSlice[] slices)
{
return new SlicesIterator(columns, comparator, slices, reversed);
}
public Iterator<IColumn> reverseIterator(ColumnSlice[] slices)
public Iterator<Column> reverseIterator(ColumnSlice[] slices)
{
return new SlicesIterator(columns, comparator, slices, !reversed);
}
private static class SlicesIterator extends AbstractIterator<IColumn>
private static class SlicesIterator extends AbstractIterator<Column>
{
private final List<IColumn> list;
private final List<Column> list;
private final ColumnSlice[] slices;
private final Comparator<ByteBuffer> comparator;
private int idx = 0;
private int previousSliceEnd = 0;
private Iterator<IColumn> currentSlice;
private Iterator<Column> currentSlice;
public SlicesIterator(List<IColumn> list, AbstractType<?> comparator, ColumnSlice[] slices, boolean reversed)
public SlicesIterator(List<Column> list, AbstractType<?> comparator, ColumnSlice[] slices, boolean reversed)
{
this.list = reversed ? Lists.reverse(list) : list;
this.slices = slices;
this.comparator = reversed ? comparator.reverseComparator : comparator;
}
protected IColumn computeNext()
protected Column computeNext()
{
if (currentSlice == null)
{
@ -375,16 +367,16 @@ public class ArrayBackedSortedColumns extends AbstractThreadUnsafeSortedColumns
}
}
private class ReverseSortedCollection extends AbstractCollection<IColumn>
private class ReverseSortedCollection extends AbstractCollection<Column>
{
public int size()
{
return columns.size();
}
public Iterator<IColumn> iterator()
public Iterator<Column> iterator()
{
return new Iterator<IColumn>()
return new Iterator<Column>()
{
int idx = size() - 1;
@ -393,7 +385,7 @@ public class ArrayBackedSortedColumns extends AbstractThreadUnsafeSortedColumns
return idx >= 0;
}
public IColumn next()
public Column next()
{
return columns.get(idx--);
}
@ -406,14 +398,14 @@ public class ArrayBackedSortedColumns extends AbstractThreadUnsafeSortedColumns
}
}
private class ForwardSortedCollection extends AbstractCollection<IColumn>
private class ForwardSortedCollection extends AbstractCollection<Column>
{
public int size()
{
return columns.size();
}
public Iterator<IColumn> iterator()
public Iterator<Column> iterator()
{
return columns.iterator();
}
@ -428,7 +420,7 @@ public class ArrayBackedSortedColumns extends AbstractThreadUnsafeSortedColumns
public Iterator<ByteBuffer> iterator()
{
final Iterator<IColumn> outerIterator = ArrayBackedSortedColumns.this.iterator(); // handles reversed
final Iterator<Column> outerIterator = ArrayBackedSortedColumns.this.iterator(); // handles reversed
return new Iterator<ByteBuffer>()
{
public boolean hasNext()

View File

@ -58,7 +58,7 @@ public class AtomicSortedColumns implements ISortedColumns
return new AtomicSortedColumns(comparator);
}
public ISortedColumns fromSorted(SortedMap<ByteBuffer, IColumn> sortedMap, boolean insertReversed)
public ISortedColumns fromSorted(SortedMap<ByteBuffer, Column> sortedMap, boolean insertReversed)
{
return new AtomicSortedColumns(sortedMap);
}
@ -74,7 +74,7 @@ public class AtomicSortedColumns implements ISortedColumns
this(new Holder(comparator));
}
private AtomicSortedColumns(SortedMap<ByteBuffer, IColumn> columns)
private AtomicSortedColumns(SortedMap<ByteBuffer, Column> columns)
{
this(new Holder(columns));
}
@ -144,7 +144,7 @@ public class AtomicSortedColumns implements ISortedColumns
while (!ref.compareAndSet(current, modified));
}
public void addColumn(IColumn column, Allocator allocator)
public void addColumn(Column column, Allocator allocator)
{
Holder current, modified;
do
@ -156,12 +156,12 @@ public class AtomicSortedColumns implements ISortedColumns
while (!ref.compareAndSet(current, modified));
}
public void addAll(ISortedColumns cm, Allocator allocator, Function<IColumn, IColumn> transformation)
public void addAll(ISortedColumns cm, Allocator allocator, Function<Column, Column> transformation)
{
addAllWithSizeDelta(cm, allocator, transformation, SecondaryIndexManager.nullUpdater);
}
public long addAllWithSizeDelta(ISortedColumns cm, Allocator allocator, Function<IColumn, IColumn> transformation, SecondaryIndexManager.Updater indexer)
public long addAllWithSizeDelta(ISortedColumns cm, Allocator allocator, Function<Column, Column> transformation, SecondaryIndexManager.Updater indexer)
{
/*
* This operation needs to atomicity and isolation. To that end, we
@ -185,7 +185,7 @@ public class AtomicSortedColumns implements ISortedColumns
DeletionInfo newDelInfo = current.deletionInfo.add(cm.getDeletionInfo());
modified = new Holder(current.map.clone(), newDelInfo);
for (IColumn column : cm.getSortedColumns())
for (Column column : cm.getSortedColumns())
{
sizeDelta += modified.addColumn(transformation.apply(column), allocator, indexer);
// bail early if we know we've been beaten
@ -198,7 +198,7 @@ public class AtomicSortedColumns implements ISortedColumns
return sizeDelta;
}
public boolean replace(IColumn oldColumn, IColumn newColumn)
public boolean replace(Column oldColumn, Column newColumn)
{
if (!oldColumn.name().equals(newColumn.name()))
throw new IllegalArgumentException();
@ -238,7 +238,7 @@ public class AtomicSortedColumns implements ISortedColumns
while (!ref.compareAndSet(current, modified));
}
public IColumn getColumn(ByteBuffer name)
public Column getColumn(ByteBuffer name)
{
return ref.get().map.get(name);
}
@ -248,12 +248,12 @@ public class AtomicSortedColumns implements ISortedColumns
return ref.get().map.keySet();
}
public Collection<IColumn> getSortedColumns()
public Collection<Column> getSortedColumns()
{
return ref.get().map.values();
}
public Collection<IColumn> getReverseSortedColumns()
public Collection<Column> getReverseSortedColumns()
{
return ref.get().map.descendingMap().values();
}
@ -273,17 +273,17 @@ public class AtomicSortedColumns implements ISortedColumns
return ref.get().map.isEmpty();
}
public Iterator<IColumn> iterator()
public Iterator<Column> iterator()
{
return getSortedColumns().iterator();
}
public Iterator<IColumn> iterator(ColumnSlice[] slices)
public Iterator<Column> iterator(ColumnSlice[] slices)
{
return new ColumnSlice.NavigableMapIterator(ref.get().map, slices);
}
public Iterator<IColumn> reverseIterator(ColumnSlice[] slices)
public Iterator<Column> reverseIterator(ColumnSlice[] slices)
{
return new ColumnSlice.NavigableMapIterator(ref.get().map.descendingMap(), slices);
}
@ -295,20 +295,20 @@ public class AtomicSortedColumns implements ISortedColumns
private static class Holder
{
final SnapTreeMap<ByteBuffer, IColumn> map;
final SnapTreeMap<ByteBuffer, Column> map;
final DeletionInfo deletionInfo;
Holder(AbstractType<?> comparator)
{
this(new SnapTreeMap<ByteBuffer, IColumn>(comparator), DeletionInfo.LIVE);
this(new SnapTreeMap<ByteBuffer, Column>(comparator), DeletionInfo.LIVE);
}
Holder(SortedMap<ByteBuffer, IColumn> columns)
Holder(SortedMap<ByteBuffer, Column> columns)
{
this(new SnapTreeMap<ByteBuffer, IColumn>(columns), DeletionInfo.LIVE);
this(new SnapTreeMap<ByteBuffer, Column>(columns), DeletionInfo.LIVE);
}
Holder(SnapTreeMap<ByteBuffer, IColumn> map, DeletionInfo deletionInfo)
Holder(SnapTreeMap<ByteBuffer, Column> map, DeletionInfo deletionInfo)
{
this.map = map;
this.deletionInfo = deletionInfo;
@ -324,7 +324,7 @@ public class AtomicSortedColumns implements ISortedColumns
return new Holder(map, info);
}
Holder with(SnapTreeMap<ByteBuffer, IColumn> newMap)
Holder with(SnapTreeMap<ByteBuffer, Column> newMap)
{
return new Holder(newMap, deletionInfo);
}
@ -333,64 +333,49 @@ public class AtomicSortedColumns implements ISortedColumns
// afterwards.
Holder clear()
{
return new Holder(new SnapTreeMap<ByteBuffer, IColumn>(map.comparator()), deletionInfo);
return new Holder(new SnapTreeMap<ByteBuffer, Column>(map.comparator()), deletionInfo);
}
long addColumn(IColumn column, Allocator allocator, SecondaryIndexManager.Updater indexer)
long addColumn(Column column, Allocator allocator, SecondaryIndexManager.Updater indexer)
{
ByteBuffer name = column.name();
while (true)
{
IColumn oldColumn = map.putIfAbsent(name, column);
Column oldColumn = map.putIfAbsent(name, column);
if (oldColumn == null)
{
indexer.insert(column);
return column.dataSize();
}
if (oldColumn instanceof SuperColumn)
Column reconciledColumn = column.reconcile(oldColumn, allocator);
if (map.replace(name, oldColumn, reconciledColumn))
{
assert column instanceof SuperColumn;
long previousSize = oldColumn.dataSize();
((SuperColumn) oldColumn).putColumn((SuperColumn)column, allocator);
return oldColumn.dataSize() - previousSize;
}
else
{
IColumn reconciledColumn = column.reconcile(oldColumn, allocator);
if (map.replace(name, oldColumn, reconciledColumn))
{
// for memtable updates we only care about oldcolumn, reconciledcolumn, but when compacting
// we need to make sure we update indexes no matter the order we merge
if (reconciledColumn == column)
indexer.update(oldColumn, reconciledColumn);
else
indexer.update(column, reconciledColumn);
return reconciledColumn.dataSize() - oldColumn.dataSize();
}
// We failed to replace column due to a concurrent update or a concurrent removal. Keep trying.
// (Currently, concurrent removal should not happen (only updates), but let us support that anyway.)
// for memtable updates we only care about oldcolumn, reconciledcolumn, but when compacting
// we need to make sure we update indexes no matter the order we merge
if (reconciledColumn == column)
indexer.update(oldColumn, reconciledColumn);
else
indexer.update(column, reconciledColumn);
return reconciledColumn.dataSize() - oldColumn.dataSize();
}
// We failed to replace column due to a concurrent update or a concurrent removal. Keep trying.
// (Currently, concurrent removal should not happen (only updates), but let us support that anyway.)
}
}
void retainAll(ISortedColumns columns)
{
Iterator<IColumn> iter = map.values().iterator();
Iterator<IColumn> toRetain = columns.iterator();
IColumn current = iter.hasNext() ? iter.next() : null;
IColumn retain = toRetain.hasNext() ? toRetain.next() : null;
Iterator<Column> iter = map.values().iterator();
Iterator<Column> toRetain = columns.iterator();
Column current = iter.hasNext() ? iter.next() : null;
Column retain = toRetain.hasNext() ? toRetain.next() : null;
Comparator<? super ByteBuffer> comparator = map.comparator();
while (current != null && retain != null)
{
int c = comparator.compare(current.name(), retain.name());
if (c == 0)
{
if (current instanceof SuperColumn)
{
assert retain instanceof SuperColumn;
((SuperColumn)current).retainAll((SuperColumn)retain);
}
current = iter.hasNext() ? iter.next() : null;
retain = toRetain.hasNext() ? toRetain.next() : null;
}

View File

@ -40,7 +40,6 @@ import org.apache.cassandra.db.compaction.CompactionManager;
import org.apache.cassandra.db.filter.IDiskAtomFilter;
import org.apache.cassandra.db.filter.NamesQueryFilter;
import org.apache.cassandra.db.filter.QueryFilter;
import org.apache.cassandra.db.filter.QueryPath;
import org.apache.cassandra.db.marshal.LongType;
import org.apache.cassandra.db.marshal.UTF8Type;
import org.apache.cassandra.db.marshal.UUIDType;
@ -177,7 +176,7 @@ public class BatchlogManager implements BatchlogManagerMBean
if (row.cf == null || row.cf.isMarkedForDelete())
continue;
IColumn writtenAt = row.cf.getColumn(WRITTEN_AT);
Column writtenAt = row.cf.getColumn(WRITTEN_AT);
if (writtenAt == null || System.currentTimeMillis() > LongType.instance.compose(writtenAt.value()) + TIMEOUT)
replayBatch(row.key);
}
@ -199,13 +198,13 @@ public class BatchlogManager implements BatchlogManagerMBean
logger.debug("Replaying batch {}", uuid);
ColumnFamilyStore store = Table.open(Table.SYSTEM_KS).getColumnFamilyStore(SystemTable.BATCHLOG_CF);
QueryFilter filter = QueryFilter.getIdentityFilter(key, new QueryPath(SystemTable.BATCHLOG_CF));
QueryFilter filter = QueryFilter.getIdentityFilter(key, SystemTable.BATCHLOG_CF);
ColumnFamily batch = store.getColumnFamily(filter);
if (batch == null || batch.isMarkedForDelete())
return;
IColumn dataColumn = batch.getColumn(DATA);
Column dataColumn = batch.getColumn(DATA);
try
{
if (dataColumn != null)
@ -246,7 +245,7 @@ public class BatchlogManager implements BatchlogManagerMBean
private static void deleteBatch(DecoratedKey key)
{
RowMutation rm = new RowMutation(Table.SYSTEM_KS, key.key);
rm.delete(new QueryPath(SystemTable.BATCHLOG_CF), FBUtilities.timestampMicros());
rm.delete(SystemTable.BATCHLOG_CF, FBUtilities.timestampMicros());
rm.apply();
}
@ -262,7 +261,7 @@ public class BatchlogManager implements BatchlogManagerMBean
IPartitioner partitioner = StorageService.getPartitioner();
RowPosition minPosition = partitioner.getMinimumToken().minKeyBound();
AbstractBounds<RowPosition> range = new Range<RowPosition>(minPosition, minPosition, partitioner);
return store.getRangeSlice(null, range, Integer.MAX_VALUE, columnFilter, null);
return store.getRangeSlice(range, Integer.MAX_VALUE, columnFilter, null);
}
/** force flush + compaction to reclaim space from replayed batches */

View File

@ -54,16 +54,14 @@ public class CollationController
this.filter = filter;
this.gcBefore = gcBefore;
// AtomicSortedColumns doesn't work for super columns (see #3821)
this.factory = mutableColumns
? cfs.metadata.cfType == ColumnFamilyType.Super ? ThreadSafeSortedColumns.factory() : AtomicSortedColumns.factory()
? AtomicSortedColumns.factory()
: ArrayBackedSortedColumns.factory();
}
public ColumnFamily getTopLevelColumns()
{
return filter.filter instanceof NamesQueryFilter
&& (cfs.metadata.cfType == ColumnFamilyType.Standard || filter.path.superColumnName != null)
&& cfs.metadata.getDefaultValidator() != CounterColumnType.instance
? collectTimeOrderedData()
: collectAllData();
@ -110,7 +108,7 @@ public class CollationController
// (reduceNameFilter removes columns that are known to be irrelevant)
NamesQueryFilter namesFilter = (NamesQueryFilter) filter.filter;
TreeSet<ByteBuffer> filterColumns = new TreeSet<ByteBuffer>(namesFilter.columns);
QueryFilter reducedFilter = new QueryFilter(filter.key, filter.path, namesFilter.withUpdatedColumns(filterColumns));
QueryFilter reducedFilter = new QueryFilter(filter.key, filter.cfName, namesFilter.withUpdatedColumns(filterColumns));
/* add the SSTables on disk */
Collections.sort(view.sstables, SSTable.maxTimestampComparator);
@ -161,7 +159,7 @@ public class CollationController
final ColumnFamily c2 = container;
CloseableIterator<OnDiskAtom> toCollate = new SimpleAbstractColumnIterator()
{
final Iterator<IColumn> iter = c2.iterator();
final Iterator<Column> iter = c2.iterator();
protected OnDiskAtom computeNext()
{
@ -205,13 +203,10 @@ public class CollationController
}
/**
* remove columns from @param filter where we already have data in @param returnCF newer than @param sstableTimestamp
* remove columns from @param filter where we already have data in @param container newer than @param sstableTimestamp
*/
private void reduceNameFilter(QueryFilter filter, ColumnFamily returnCF, long sstableTimestamp)
private void reduceNameFilter(QueryFilter filter, ColumnFamily container, long sstableTimestamp)
{
AbstractColumnContainer container = filter.path.superColumnName == null
? returnCF
: (SuperColumn) returnCF.getColumn(filter.path.superColumnName);
// MIN_VALUE means we don't know any information
if (container == null || sstableTimestamp == Long.MIN_VALUE)
return;
@ -219,7 +214,7 @@ public class CollationController
for (Iterator<ByteBuffer> iterator = ((NamesQueryFilter) filter.filter).columns.iterator(); iterator.hasNext(); )
{
ByteBuffer filterColumn = iterator.next();
IColumn column = container.getColumn(filterColumn);
Column column = container.getColumn(filterColumn);
if (column != null && column.timestamp() > sstableTimestamp)
iterator.remove();
}

View File

@ -17,31 +17,34 @@
*/
package org.apache.cassandra.db;
import java.io.DataInput;
import java.io.IOError;
import java.io.IOException;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.marshal.*;
import org.apache.cassandra.io.sstable.Descriptor;
import org.apache.cassandra.io.util.DataOutputBuffer;
import org.apache.cassandra.utils.Allocator;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.HeapAllocator;
/**
* Column is immutable, which prevents all kinds of confusion in a multithreaded environment.
* (TODO: look at making SuperColumn immutable too. This is trickier but is probably doable
* with something like PCollections -- http://code.google.com
*/
public class Column implements IColumn
public class Column implements OnDiskAtom
{
public static final int MAX_NAME_LENGTH = FBUtilities.MAX_UNSIGNED_SHORT;
private static final ColumnSerializer serializer = new ColumnSerializer();
private static final OnDiskAtom.Serializer onDiskSerializer = new OnDiskAtom.Serializer(serializer);
public static ColumnSerializer serializer()
{
@ -50,7 +53,38 @@ public class Column implements IColumn
public static OnDiskAtom.Serializer onDiskSerializer()
{
return onDiskSerializer;
return OnDiskAtom.Serializer.instance;
}
public static Iterator<OnDiskAtom> onDiskIterator(final DataInput dis, final int count, final ColumnSerializer.Flag flag, final int expireBefore, final Descriptor.Version version)
{
return new Iterator<OnDiskAtom>()
{
int i = 0;
public boolean hasNext()
{
return i < count;
}
public OnDiskAtom next()
{
++i;
try
{
return onDiskSerializer().deserializeFromSSTable(dis, flag, expireBefore, version);
}
catch (IOException e)
{
throw new IOError(e);
}
}
public void remove()
{
throw new UnsupportedOperationException();
}
};
}
protected final ByteBuffer name;
@ -71,32 +105,27 @@ public class Column implements IColumn
{
assert name != null;
assert value != null;
assert name.remaining() <= IColumn.MAX_NAME_LENGTH;
assert name.remaining() <= Column.MAX_NAME_LENGTH;
this.name = name;
this.value = value;
this.timestamp = timestamp;
}
public Column withUpdatedName(ByteBuffer newName)
{
return new Column(newName, value, timestamp);
}
public ByteBuffer name()
{
return name;
}
public Column getSubColumn(ByteBuffer columnName)
{
throw new UnsupportedOperationException("This operation is unsupported on simple columns.");
}
public ByteBuffer value()
{
return value;
}
public Collection<IColumn> getSubColumns()
{
throw new UnsupportedOperationException("This operation is unsupported on simple columns.");
}
public long timestamp()
{
return timestamp;
@ -162,17 +191,7 @@ public class Column implements IColumn
return 0;
}
public void addColumn(IColumn column)
{
addColumn(null, null);
}
public void addColumn(IColumn column, Allocator allocator)
{
throw new UnsupportedOperationException("This operation is not supported for simple columns.");
}
public IColumn diff(IColumn column)
public Column diff(Column column)
{
if (timestamp() < column.timestamp())
{
@ -204,12 +223,12 @@ public class Column implements IColumn
return Integer.MAX_VALUE;
}
public IColumn reconcile(IColumn column)
public Column reconcile(Column column)
{
return reconcile(column, HeapAllocator.instance);
}
public IColumn reconcile(IColumn column, Allocator allocator)
public Column reconcile(Column column, Allocator allocator)
{
// tombstones take precedence. (if both are tombstones, then it doesn't matter which one we use.)
if (isMarkedForDelete())
@ -250,12 +269,12 @@ public class Column implements IColumn
return result;
}
public IColumn localCopy(ColumnFamilyStore cfs)
public Column localCopy(ColumnFamilyStore cfs)
{
return localCopy(cfs, HeapAllocator.instance);
}
public IColumn localCopy(ColumnFamilyStore cfs, Allocator allocator)
public Column localCopy(ColumnFamilyStore cfs, Allocator allocator)
{
return new Column(cfs.internOrCopy(name, allocator), allocator.clone(value), timestamp);
}
@ -280,8 +299,7 @@ public class Column implements IColumn
protected void validateName(CFMetaData metadata) throws MarshalException
{
AbstractType<?> nameValidator = metadata.cfType == ColumnFamilyType.Super ? metadata.subcolumnComparator : metadata.comparator;
nameValidator.validate(name());
metadata.comparator.validate(name());
}
public void validateFields(CFMetaData metadata) throws MarshalException

View File

@ -17,6 +17,7 @@
*/
package org.apache.cassandra.db;
import java.io.DataInput;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.util.UUID;
@ -29,10 +30,9 @@ import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.cassandra.cache.IRowCacheEntry;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.config.Schema;
import org.apache.cassandra.db.filter.QueryPath;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.MarshalException;
import org.apache.cassandra.io.IColumnSerializer;
import org.apache.cassandra.io.sstable.Descriptor;
import org.apache.cassandra.io.sstable.ColumnStats;
public class ColumnFamily extends AbstractColumnContainer implements IRowCacheEntry
@ -90,12 +90,6 @@ public class ColumnFamily extends AbstractColumnContainer implements IRowCacheEn
return cloneMeShallow(columns.getFactory(), columns.isInsertReversed());
}
public AbstractType<?> getSubComparator()
{
IColumnSerializer s = getColumnSerializer();
return (s instanceof SuperColumnSerializer) ? ((SuperColumnSerializer) s).getComparator() : null;
}
public ColumnFamilyType getType()
{
return cfm.cfType;
@ -121,98 +115,38 @@ public class ColumnFamily extends AbstractColumnContainer implements IRowCacheEn
return cfm;
}
public IColumnSerializer getColumnSerializer()
public void addColumn(ByteBuffer name, ByteBuffer value, long timestamp)
{
return cfm.getColumnSerializer();
addColumn(name, value, timestamp, 0);
}
public OnDiskAtom.Serializer getOnDiskSerializer()
public void addColumn(ByteBuffer name, ByteBuffer value, long timestamp, int timeToLive)
{
return cfm.getOnDiskSerializer();
}
public boolean isSuper()
{
return getType() == ColumnFamilyType.Super;
}
/**
* Same as addAll() but do a cloneMe of SuperColumn if necessary to
* avoid keeping references to the structure (see #3957).
*/
public void addAllWithSCCopy(ColumnFamily cf, Allocator allocator)
{
if (cf.isSuper())
{
for (IColumn c : cf)
{
columns.addColumn(((SuperColumn)c).cloneMe(), allocator);
}
delete(cf);
}
else
{
addAll(cf, allocator);
}
}
public void addColumn(QueryPath path, ByteBuffer value, long timestamp)
{
addColumn(path, value, timestamp, 0);
}
public void addColumn(QueryPath path, ByteBuffer value, long timestamp, int timeToLive)
{
assert path.columnName != null : path;
assert !metadata().getDefaultValidator().isCommutative();
Column column = Column.create(path.columnName, value, timestamp, timeToLive, metadata());
addColumn(path.superColumnName, column);
Column column = Column.create(name, value, timestamp, timeToLive, metadata());
addColumn(column);
}
public void addCounter(QueryPath path, long value)
public void addCounter(ByteBuffer name, long value)
{
assert path.columnName != null : path;
addColumn(path.superColumnName, new CounterUpdateColumn(path.columnName, value, System.currentTimeMillis()));
addColumn(new CounterUpdateColumn(name, value, System.currentTimeMillis()));
}
public void addTombstone(QueryPath path, ByteBuffer localDeletionTime, long timestamp)
public void addTombstone(ByteBuffer name, ByteBuffer localDeletionTime, long timestamp)
{
assert path.columnName != null : path;
addColumn(path.superColumnName, new DeletedColumn(path.columnName, localDeletionTime, timestamp));
}
public void addTombstone(QueryPath path, int localDeletionTime, long timestamp)
{
assert path.columnName != null : path;
addColumn(path.superColumnName, new DeletedColumn(path.columnName, localDeletionTime, timestamp));
addColumn(new DeletedColumn(name, localDeletionTime, timestamp));
}
public void addTombstone(ByteBuffer name, int localDeletionTime, long timestamp)
{
addColumn(null, new DeletedColumn(name, localDeletionTime, timestamp));
}
public void addColumn(ByteBuffer superColumnName, Column column)
{
IColumn c;
if (superColumnName == null)
{
c = column;
}
else
{
assert isSuper();
c = new SuperColumn(superColumnName, getSubComparator());
c.addColumn(column); // checks subcolumn name
}
addColumn(c);
addColumn(new DeletedColumn(name, localDeletionTime, timestamp));
}
public void addAtom(OnDiskAtom atom)
{
if (atom instanceof IColumn)
if (atom instanceof Column)
{
addColumn((IColumn)atom);
addColumn((Column)atom);
}
else
{
@ -236,20 +170,20 @@ public class ColumnFamily extends AbstractColumnContainer implements IRowCacheEn
ColumnFamily cfDiff = ColumnFamily.create(cfm);
cfDiff.delete(cfComposite.deletionInfo());
// (don't need to worry about cfNew containing IColumns that are shadowed by
// (don't need to worry about cfNew containing Columns that are shadowed by
// the delete tombstone, since cfNew was generated by CF.resolve, which
// takes care of those for us.)
for (IColumn columnExternal : cfComposite)
for (Column columnExternal : cfComposite)
{
ByteBuffer cName = columnExternal.name();
IColumn columnInternal = this.columns.getColumn(cName);
Column columnInternal = this.columns.getColumn(cName);
if (columnInternal == null)
{
cfDiff.addColumn(columnExternal);
}
else
{
IColumn columnDiff = columnInternal.diff(columnExternal);
Column columnDiff = columnInternal.diff(columnExternal);
if (columnDiff != null)
{
cfDiff.addColumn(columnDiff);
@ -266,7 +200,7 @@ public class ColumnFamily extends AbstractColumnContainer implements IRowCacheEn
int dataSize()
{
int size = deletionInfo().dataSize();
for (IColumn column : columns)
for (Column column : columns)
{
size += column.dataSize();
}
@ -276,7 +210,7 @@ public class ColumnFamily extends AbstractColumnContainer implements IRowCacheEn
public long maxTimestamp()
{
long maxTimestamp = deletionInfo().maxTimestamp();
for (IColumn column : columns)
for (Column column : columns)
maxTimestamp = Math.max(maxTimestamp, column.maxTimestamp());
return maxTimestamp;
}
@ -329,17 +263,10 @@ public class ColumnFamily extends AbstractColumnContainer implements IRowCacheEn
public void updateDigest(MessageDigest digest)
{
for (IColumn column : columns)
for (Column column : columns)
column.updateDigest(digest);
}
public static AbstractType<?> getComparatorFor(String table, String columnFamilyName, ByteBuffer superColumnName)
{
return superColumnName == null
? Schema.instance.getComparator(table, columnFamilyName)
: Schema.instance.getSubComparator(table, columnFamilyName);
}
public static ColumnFamily diff(ColumnFamily cf1, ColumnFamily cf2)
{
if (cf1 == null)
@ -368,7 +295,7 @@ public class ColumnFamily extends AbstractColumnContainer implements IRowCacheEn
public void validateColumnFields() throws MarshalException
{
CFMetaData metadata = metadata();
for (IColumn column : this)
for (Column column : this)
{
column.validateFields(metadata);
}
@ -380,7 +307,7 @@ public class ColumnFamily extends AbstractColumnContainer implements IRowCacheEn
long maxTimestampSeen = deletionInfo().maxTimestamp();
StreamingHistogram tombstones = new StreamingHistogram(SSTable.TOMBSTONE_HISTOGRAM_BIN_SIZE);
for (IColumn column : columns)
for (Column column : columns)
{
minTimestampSeen = Math.min(minTimestampSeen, column.minTimestamp());
maxTimestampSeen = Math.max(maxTimestampSeen, column.maxTimestamp());

View File

@ -20,10 +20,10 @@ package org.apache.cassandra.db;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Iterator;
import java.util.UUID;
import org.apache.cassandra.config.Schema;
import org.apache.cassandra.io.IColumnSerializer;
import org.apache.cassandra.io.ISSTableSerializer;
import org.apache.cassandra.io.IVersionedSerializer;
import org.apache.cassandra.io.sstable.Descriptor;
@ -62,13 +62,18 @@ public class ColumnFamilySerializer implements IVersionedSerializer<ColumnFamily
dos.writeBoolean(true);
serializeCfId(cf.id(), dos, version);
DeletionInfo.serializer().serialize(cf.deletionInfo(), dos, version);
if (cf.metadata().isSuper() && version < MessagingService.VERSION_20)
{
SuperColumns.serializeSuperColumnFamily(cf, dos, version);
return;
}
IColumnSerializer columnSerializer = cf.getColumnSerializer();
DeletionInfo.serializer().serialize(cf.deletionInfo(), dos, version);
ColumnSerializer columnSerializer = Column.serializer();
int count = cf.getColumnCount();
dos.writeInt(count);
int written = 0;
for (IColumn column : cf)
for (Column column : cf)
{
columnSerializer.serialize(column, dos);
written++;
@ -83,32 +88,50 @@ public class ColumnFamilySerializer implements IVersionedSerializer<ColumnFamily
public ColumnFamily deserialize(DataInput dis, int version) throws IOException
{
return deserialize(dis, IColumnSerializer.Flag.LOCAL, TreeMapBackedSortedColumns.factory(), version);
return deserialize(dis, ColumnSerializer.Flag.LOCAL, TreeMapBackedSortedColumns.factory(), version);
}
public ColumnFamily deserialize(DataInput dis, IColumnSerializer.Flag flag, ISortedColumns.Factory factory, int version) throws IOException
public ColumnFamily deserialize(DataInput dis, ColumnSerializer.Flag flag, ISortedColumns.Factory factory, int version) throws IOException
{
if (!dis.readBoolean())
return null;
ColumnFamily cf = ColumnFamily.create(deserializeCfId(dis, version), factory);
IColumnSerializer columnSerializer = cf.getColumnSerializer();
cf.delete(DeletionInfo.serializer().deserialize(dis, version, cf.getComparator()));
int expireBefore = (int) (System.currentTimeMillis() / 1000);
int size = dis.readInt();
for (int i = 0; i < size; ++i)
if (cf.metadata().isSuper() && version < MessagingService.VERSION_20)
{
cf.addColumn(columnSerializer.deserialize(dis, flag, expireBefore));
SuperColumns.deserializerSuperColumnFamily(dis, cf, flag, expireBefore, version);
}
else
{
cf.delete(DeletionInfo.serializer().deserialize(dis, version, cf.getComparator()));
ColumnSerializer columnSerializer = Column.serializer();
int size = dis.readInt();
for (int i = 0; i < size; ++i)
{
cf.addColumn(columnSerializer.deserialize(dis, flag, expireBefore));
}
}
return cf;
}
public long contentSerializedSize(ColumnFamily cf, TypeSizes typeSizes, int version)
{
long size = DeletionInfo.serializer().serializedSize(cf.deletionInfo(), typeSizes, version);
size += typeSizes.sizeof(cf.getColumnCount());
for (IColumn column : cf)
size += column.serializedSize(typeSizes);
long size = 0L;
if (cf.metadata().isSuper() && version < MessagingService.VERSION_20)
{
size += SuperColumns.serializedSize(cf, typeSizes, version);
}
else
{
size += DeletionInfo.serializer().serializedSize(cf.deletionInfo(), typeSizes, version);
size += typeSizes.sizeof(cf.getColumnCount());
for (Column column : cf)
size += column.serializedSize(typeSizes);
}
return size;
}
@ -142,14 +165,14 @@ public class ColumnFamilySerializer implements IVersionedSerializer<ColumnFamily
throw new UnsupportedOperationException();
}
public void deserializeColumnsFromSSTable(DataInput dis, ColumnFamily cf, int size, IColumnSerializer.Flag flag, int expireBefore, Descriptor.Version version) throws IOException
public void deserializeColumnsFromSSTable(DataInput dis, ColumnFamily cf, int size, ColumnSerializer.Flag flag, int expireBefore, Descriptor.Version version) throws IOException
{
OnDiskAtom.Serializer atomSerializer = cf.getOnDiskSerializer();
for (int i = 0; i < size; ++i)
cf.addAtom(atomSerializer.deserializeFromSSTable(dis, flag, expireBefore, version));
Iterator<OnDiskAtom> iter = cf.metadata().getOnDiskIterator(dis, size, flag, expireBefore, version);
while (iter.hasNext())
cf.addAtom(iter.next());
}
public void deserializeFromSSTable(DataInput dis, ColumnFamily cf, IColumnSerializer.Flag flag, Descriptor.Version version) throws IOException
public void deserializeFromSSTable(DataInput dis, ColumnFamily cf, ColumnSerializer.Flag flag, Descriptor.Version version) throws IOException
{
cf.delete(DeletionInfo.serializer().deserializeFromSSTable(dis, version));
int size = dis.readInt();

View File

@ -54,7 +54,6 @@ import org.apache.cassandra.db.compaction.OperationType;
import org.apache.cassandra.db.filter.ExtendedFilter;
import org.apache.cassandra.db.filter.IDiskAtomFilter;
import org.apache.cassandra.db.filter.QueryFilter;
import org.apache.cassandra.db.filter.QueryPath;
import org.apache.cassandra.db.index.SecondaryIndex;
import org.apache.cassandra.db.index.SecondaryIndexManager;
import org.apache.cassandra.db.marshal.AbstractType;
@ -752,10 +751,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
if (cachedRow instanceof RowCacheSentinel)
invalidateCachedRow(cacheKey);
else
// columnFamily is what is written in the commit log. Because of the PeriodicCommitLog, this can be done in concurrency
// with this. So columnFamily shouldn't be modified and if it contains super columns, neither should they. So for super
// columns, we must make sure to clone them when adding to the cache. That's what addAllWithSCCopy does (see #3957)
((ColumnFamily) cachedRow).addAllWithSCCopy(columnFamily, HeapAllocator.instance);
((ColumnFamily) cachedRow).addAll(columnFamily, HeapAllocator.instance);
}
}
@ -820,23 +816,10 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
private static void removeDeletedColumnsOnly(ColumnFamily cf, int gcBefore, SecondaryIndexManager.Updater indexer)
{
if (cf.isSuper())
removeDeletedSuper(cf, gcBefore);
else
removeDeletedStandard(cf, gcBefore, indexer);
}
public static void removeDeletedColumnsOnly(ColumnFamily cf, int gcBefore)
{
removeDeletedColumnsOnly(cf, gcBefore, SecondaryIndexManager.nullUpdater);
}
private static void removeDeletedStandard(ColumnFamily cf, int gcBefore, SecondaryIndexManager.Updater indexer)
{
Iterator<IColumn> iter = cf.iterator();
Iterator<Column> iter = cf.iterator();
while (iter.hasNext())
{
IColumn c = iter.next();
Column c = iter.next();
// remove columns if
// (a) the column itself is gcable or
// (b) the column is shadowed by a CF tombstone
@ -848,36 +831,9 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
}
}
private static void removeDeletedSuper(ColumnFamily cf, int gcBefore)
public static void removeDeletedColumnsOnly(ColumnFamily cf, int gcBefore)
{
// TODO assume deletion means "most are deleted?" and add to clone, instead of remove from original?
// this could be improved by having compaction, or possibly even removeDeleted, r/m the tombstone
// once gcBefore has passed, so if new stuff is added in it doesn't used the wrong algorithm forever
Iterator<IColumn> iter = cf.iterator();
while (iter.hasNext())
{
SuperColumn c = (SuperColumn)iter.next();
Iterator<IColumn> subIter = c.getSubColumns().iterator();
while (subIter.hasNext())
{
IColumn subColumn = subIter.next();
// remove subcolumns if
// (a) the subcolumn itself is gcable or
// (b) the supercolumn is shadowed by the CF and the column is not newer
// (b) the subcolumn is shadowed by the supercolumn
if (subColumn.getLocalDeletionTime() < gcBefore
|| cf.deletionInfo().isDeleted(c.name(), subColumn.timestamp())
|| c.deletionInfo().isDeleted(subColumn))
{
subIter.remove();
}
}
c.maybeResetDeletionTimes(gcBefore);
if (c.getSubColumns().isEmpty() && !c.isMarkedForDelete())
{
iter.remove();
}
}
removeDeletedColumnsOnly(cf, gcBefore, SecondaryIndexManager.nullUpdater);
}
/**
@ -1139,9 +1095,9 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
return metric.writeLatency.recentLatencyHistogram.getBuckets(true);
}
public ColumnFamily getColumnFamily(DecoratedKey key, QueryPath path, ByteBuffer start, ByteBuffer finish, boolean reversed, int limit)
public ColumnFamily getColumnFamily(DecoratedKey key, ByteBuffer start, ByteBuffer finish, boolean reversed, int limit)
{
return getColumnFamily(QueryFilter.getSliceFilter(key, path, start, finish, reversed, limit));
return getColumnFamily(QueryFilter.getSliceFilter(key, name, start, finish, reversed, limit));
}
/**
@ -1195,7 +1151,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
try
{
ColumnFamily data = getTopLevelColumns(QueryFilter.getIdentityFilter(filter.key, new QueryPath(name)),
ColumnFamily data = getTopLevelColumns(QueryFilter.getIdentityFilter(filter.key, name),
Integer.MIN_VALUE,
true);
if (sentinelSuccess && data != null)
@ -1244,9 +1200,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
if (cf == null)
return null;
// TODO this is necessary because when we collate supercolumns together, we don't check
// their subcolumns for relevance, so we need to do a second prune post facto here.
result = cf.isSuper() ? removeDeleted(cf, gcBefore) : removeDeletedCF(cf, gcBefore);
result = removeDeletedCF(cf, gcBefore);
}
}
@ -1268,9 +1222,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
ColumnFamily cf = cached.cloneMeShallow(ArrayBackedSortedColumns.factory(), filter.filter.isReversed());
OnDiskAtomIterator ci = filter.getMemtableColumnIterator(cached, null);
filter.collateOnDiskAtom(cf, Collections.singletonList(ci), gcBefore);
// TODO this is necessary because when we collate supercolumns together, we don't check
// their subcolumns for relevance, so we need to do a second prune post facto here.
return cf.isSuper() ? removeDeleted(cf, gcBefore) : removeDeletedCF(cf, gcBefore);
return removeDeletedCF(cf, gcBefore);
}
/**
@ -1402,14 +1354,14 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
* @param range Either a Bounds, which includes start key, or a Range, which does not.
* @param columnFilter description of the columns we're interested in for each row
*/
public AbstractScanIterator getSequentialIterator(ByteBuffer superColumn, final AbstractBounds<RowPosition> range, IDiskAtomFilter columnFilter)
public AbstractScanIterator getSequentialIterator(final AbstractBounds<RowPosition> range, IDiskAtomFilter columnFilter)
{
assert !(range instanceof Range) || !((Range)range).isWrapAround() || range.right.isMinimum() : range;
final RowPosition startWith = range.left;
final RowPosition stopAt = range.right;
QueryFilter filter = new QueryFilter(null, new QueryPath(name, superColumn, null), columnFilter);
QueryFilter filter = new QueryFilter(null, name, columnFilter);
final ViewFragment view = markReferenced(startWith, stopAt);
Tracing.trace("Executing seq scan across {} sstables for {}", view.sstables.size(), range.getString(metadata.getKeyValidator()));
@ -1439,11 +1391,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
logger.trace("scanned {}", key);
// TODO this is necessary because when we collate supercolumns together, we don't check
// their subcolumns for relevance, so we need to do a second prune post facto here.
return current.cf != null && current.cf.isSuper()
? new Row(current.key, removeDeleted(current.cf, gcBefore))
: current;
return current;
}
public void close() throws IOException
@ -1461,14 +1409,14 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
}
}
public List<Row> getRangeSlice(ByteBuffer superColumn, final AbstractBounds<RowPosition> range, int maxResults, IDiskAtomFilter columnFilter, List<IndexExpression> rowFilter)
public List<Row> getRangeSlice(final AbstractBounds<RowPosition> range, int maxResults, IDiskAtomFilter columnFilter, List<IndexExpression> rowFilter)
{
return getRangeSlice(superColumn, range, maxResults, columnFilter, rowFilter, false, false);
return getRangeSlice(range, maxResults, columnFilter, rowFilter, false, false);
}
public List<Row> getRangeSlice(ByteBuffer superColumn, final AbstractBounds<RowPosition> range, int maxResults, IDiskAtomFilter columnFilter, List<IndexExpression> rowFilter, boolean countCQL3Rows, boolean isPaging)
public List<Row> getRangeSlice(final AbstractBounds<RowPosition> range, int maxResults, IDiskAtomFilter columnFilter, List<IndexExpression> rowFilter, boolean countCQL3Rows, boolean isPaging)
{
return filter(getSequentialIterator(superColumn, range, columnFilter), ExtendedFilter.create(this, columnFilter, rowFilter, maxResults, countCQL3Rows, isPaging));
return filter(getSequentialIterator(range, columnFilter), ExtendedFilter.create(this, columnFilter, rowFilter, maxResults, countCQL3Rows, isPaging));
}
public List<Row> search(List<IndexExpression> clause, AbstractBounds<RowPosition> range, int maxResults, IDiskAtomFilter dataFilter)
@ -1503,8 +1451,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
IDiskAtomFilter extraFilter = filter.getExtraFilter(data);
if (extraFilter != null)
{
QueryPath path = new QueryPath(name);
ColumnFamily cf = filter.cfs.getColumnFamily(new QueryFilter(rawRow.key, path, extraFilter));
ColumnFamily cf = filter.cfs.getColumnFamily(new QueryFilter(rawRow.key, name, extraFilter));
if (cf != null)
data.addAll(cf, HeapAllocator.instance);
}

View File

@ -52,6 +52,8 @@ public class ColumnIndex
*/
public static class Builder
{
private static final OnDiskAtom.Serializer atomSerializer = Column.onDiskSerializer();
private final ColumnIndex result;
private final long indexOffset;
private long startPosition = -1;
@ -62,7 +64,6 @@ public class ColumnIndex
private OnDiskAtom lastBlockClosing;
private final DataOutput output;
private final RangeTombstone.Tracker tombstoneTracker;
private final OnDiskAtom.Serializer atomSerializer;
private int atomCount;
public Builder(ColumnFamily cf,
@ -73,7 +74,6 @@ public class ColumnIndex
this.indexOffset = rowHeaderSize(key, cf.deletionInfo());
this.result = new ColumnIndex(estimatedColumnCount);
this.output = output;
this.atomSerializer = cf.getOnDiskSerializer();
this.tombstoneTracker = new RangeTombstone.Tracker(cf.getComparator());
}
@ -116,7 +116,7 @@ public class ColumnIndex
RangeTombstone tombstone = rangeIter.hasNext() ? rangeIter.next() : null;
Comparator<ByteBuffer> comparator = cf.getComparator();
for (IColumn c : cf)
for (Column c : cf)
{
while (tombstone != null && comparator.compare(c.name(), tombstone.min) >= 0)
{
@ -146,7 +146,7 @@ public class ColumnIndex
{
atomCount++;
if (column instanceof IColumn)
if (column instanceof Column)
result.bloomFilter.add(column.name());
if (firstColumn == null)

View File

@ -22,12 +22,12 @@ import java.io.DataOutput;
import java.io.IOException;
import java.nio.ByteBuffer;
import org.apache.cassandra.io.ISerializer;
import org.apache.cassandra.io.FSReadError;
import org.apache.cassandra.io.IColumnSerializer;
import org.apache.cassandra.io.util.FileDataInput;
import org.apache.cassandra.utils.ByteBufferUtil;
public class ColumnSerializer implements IColumnSerializer
public class ColumnSerializer implements ISerializer<Column>
{
public final static int DELETION_MASK = 0x01;
public final static int EXPIRATION_MASK = 0x02;
@ -35,7 +35,23 @@ public class ColumnSerializer implements IColumnSerializer
public final static int COUNTER_UPDATE_MASK = 0x08;
public final static int RANGE_TOMBSTONE_MASK = 0x10;
public void serialize(IColumn column, DataOutput dos) throws IOException
/**
* Flag affecting deserialization behavior.
* - LOCAL: for deserialization of local data (Expired columns are
* converted to tombstones (to gain disk space)).
* - FROM_REMOTE: for deserialization of data received from remote hosts
* (Expired columns are converted to tombstone and counters have
* their delta cleared)
* - PRESERVE_SIZE: used when no transformation must be performed, i.e,
* when we must ensure that deserializing and reserializing the
* result yield the exact same bytes. Streaming uses this.
*/
public static enum Flag
{
LOCAL, FROM_REMOTE, PRESERVE_SIZE;
}
public void serialize(Column column, DataOutput dos) throws IOException
{
assert column.name().remaining() > 0;
ByteBufferUtil.writeWithShortLength(column.name(), dos);
@ -70,12 +86,12 @@ public class ColumnSerializer implements IColumnSerializer
* deserialize comes from a remote host. If it does, then we must clear
* the delta.
*/
public Column deserialize(DataInput dis, IColumnSerializer.Flag flag) throws IOException
public Column deserialize(DataInput dis, ColumnSerializer.Flag flag) throws IOException
{
return deserialize(dis, flag, (int) (System.currentTimeMillis() / 1000));
}
public Column deserialize(DataInput dis, IColumnSerializer.Flag flag, int expireBefore) throws IOException
public Column deserialize(DataInput dis, ColumnSerializer.Flag flag, int expireBefore) throws IOException
{
ByteBuffer name = ByteBufferUtil.readWithShortLength(dis);
if (name.remaining() <= 0)
@ -85,7 +101,7 @@ public class ColumnSerializer implements IColumnSerializer
return deserializeColumnBody(dis, name, b, flag, expireBefore);
}
Column deserializeColumnBody(DataInput dis, ByteBuffer name, int mask, IColumnSerializer.Flag flag, int expireBefore) throws IOException
Column deserializeColumnBody(DataInput dis, ByteBuffer name, int mask, ColumnSerializer.Flag flag, int expireBefore) throws IOException
{
if ((mask & COUNTER_MASK) != 0)
{
@ -114,7 +130,7 @@ public class ColumnSerializer implements IColumnSerializer
}
}
public long serializedSize(IColumn column, TypeSizes type)
public long serializedSize(Column column, TypeSizes type)
{
return column.serializedSize(type);
}

View File

@ -36,7 +36,6 @@ import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.MarshalException;
import org.apache.cassandra.exceptions.OverloadedException;
import org.apache.cassandra.exceptions.RequestExecutionException;
import org.apache.cassandra.io.IColumnSerializer;
import org.apache.cassandra.io.util.DataOutputBuffer;
import org.apache.cassandra.utils.Allocator;
import org.apache.cassandra.service.AbstractWriteResponseHandler;
@ -75,15 +74,21 @@ public class CounterColumn extends Column
this.timestampOfLastDelete = timestampOfLastDelete;
}
public static CounterColumn create(ByteBuffer name, ByteBuffer value, long timestamp, long timestampOfLastDelete, IColumnSerializer.Flag flag)
public static CounterColumn create(ByteBuffer name, ByteBuffer value, long timestamp, long timestampOfLastDelete, ColumnSerializer.Flag flag)
{
// #elt being negative means we have to clean delta
short count = value.getShort(value.position());
if (flag == IColumnSerializer.Flag.FROM_REMOTE || (flag == IColumnSerializer.Flag.LOCAL && count < 0))
if (flag == ColumnSerializer.Flag.FROM_REMOTE || (flag == ColumnSerializer.Flag.LOCAL && count < 0))
value = CounterContext.instance().clearAllDelta(value);
return new CounterColumn(name, value, timestamp, timestampOfLastDelete);
}
@Override
public Column withUpdatedName(ByteBuffer newName)
{
return new CounterColumn(newName, value, timestamp, timestampOfLastDelete);
}
public long timestampOfLastDelete()
{
return timestampOfLastDelete;
@ -111,7 +116,7 @@ public class CounterColumn extends Column
}
@Override
public IColumn diff(IColumn column)
public Column diff(Column column)
{
assert (column instanceof CounterColumn) || (column instanceof DeletedColumn) : "Wrong class type: " + column.getClass();
@ -160,7 +165,7 @@ public class CounterColumn extends Column
}
@Override
public IColumn reconcile(IColumn column, Allocator allocator)
public Column reconcile(Column column, Allocator allocator)
{
assert (column instanceof CounterColumn) || (column instanceof DeletedColumn) : "Wrong class type: " + column.getClass();
@ -208,13 +213,13 @@ public class CounterColumn extends Column
}
@Override
public IColumn localCopy(ColumnFamilyStore cfs)
public Column localCopy(ColumnFamilyStore cfs)
{
return new CounterColumn(cfs.internOrCopy(name, HeapAllocator.instance), ByteBufferUtil.clone(value), timestamp, timestampOfLastDelete);
}
@Override
public IColumn localCopy(ColumnFamilyStore cfs, Allocator allocator)
public Column localCopy(ColumnFamilyStore cfs, Allocator allocator)
{
return new CounterColumn(cfs.internOrCopy(name, allocator), allocator.clone(value), timestamp, timestampOfLastDelete);
}
@ -299,52 +304,25 @@ public class CounterColumn extends Column
public static void mergeAndRemoveOldShards(DecoratedKey key, ColumnFamily cf, int gcBefore, int mergeBefore, boolean sendToOtherReplica)
{
ColumnFamily remoteMerger = null;
if (!cf.isSuper())
for (Column c : cf)
{
for (IColumn c : cf)
if (!(c instanceof CounterColumn))
continue;
CounterColumn cc = (CounterColumn) c;
CounterColumn shardMerger = cc.computeOldShardMerger(mergeBefore);
CounterColumn merged = cc;
if (shardMerger != null)
{
if (!(c instanceof CounterColumn))
continue;
CounterColumn cc = (CounterColumn) c;
CounterColumn shardMerger = cc.computeOldShardMerger(mergeBefore);
CounterColumn merged = cc;
if (shardMerger != null)
{
merged = (CounterColumn) cc.reconcile(shardMerger);
if (remoteMerger == null)
remoteMerger = cf.cloneMeShallow();
remoteMerger.addColumn(merged);
}
CounterColumn cleaned = merged.removeOldShards(gcBefore);
if (cleaned != cc)
{
cf.replace(cc, cleaned);
}
merged = (CounterColumn) cc.reconcile(shardMerger);
if (remoteMerger == null)
remoteMerger = cf.cloneMeShallow();
remoteMerger.addColumn(merged);
}
}
else
{
for (IColumn col : cf)
CounterColumn cleaned = merged.removeOldShards(gcBefore);
if (cleaned != cc)
{
SuperColumn c = (SuperColumn)col;
for (IColumn subColumn : c.getSubColumns())
{
if (!(subColumn instanceof CounterColumn))
continue;
CounterColumn cc = (CounterColumn) subColumn;
CounterColumn shardMerger = cc.computeOldShardMerger(mergeBefore);
CounterColumn merged = cc;
if (shardMerger != null)
{
merged = (CounterColumn) cc.reconcile(shardMerger);
if (remoteMerger == null)
remoteMerger = cf.cloneMeShallow();
remoteMerger.addColumn(c.name(), merged);
}
CounterColumn cleaned = merged.removeOldShards(gcBefore);
if (cleaned != subColumn)
c.replace(subColumn, cleaned);
}
cf.replace(cc, cleaned);
}
}
@ -361,7 +339,7 @@ public class CounterColumn extends Column
}
}
public IColumn markDeltaToBeCleared()
public Column markDeltaToBeCleared()
{
return new CounterColumn(name, contextManager.markDeltaToBeCleared(value), timestamp, timestampOfLastDelete);
}

View File

@ -24,9 +24,11 @@ import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.UUID;
import org.apache.cassandra.db.filter.QueryPath;
import org.apache.cassandra.db.filter.NamesQueryFilter;
import org.apache.cassandra.io.IVersionedSerializer;
import org.apache.cassandra.net.MessageOut;
import org.apache.cassandra.net.MessagingService;
@ -92,8 +94,6 @@ public class CounterMutation implements IMutation
continue;
ColumnFamily cf = row.cf;
if (cf.isSuper())
cf.retainAll(rowMutation.getColumnFamily(cf.metadata().cfId));
replicationMutation.add(cf);
}
return replicationMutation;
@ -101,8 +101,9 @@ public class CounterMutation implements IMutation
private void addReadCommandFromColumnFamily(String table, ByteBuffer key, ColumnFamily columnFamily, List<ReadCommand> commands)
{
QueryPath queryPath = new QueryPath(columnFamily.metadata().cfName);
commands.add(new SliceByNamesReadCommand(table, key, queryPath, columnFamily.getColumnNames()));
SortedSet s = new TreeSet<ByteBuffer>(columnFamily.metadata().comparator);
s.addAll(columnFamily.getColumnNames());
commands.add(new SliceByNamesReadCommand(table, key, columnFamily.metadata().cfName, new NamesQueryFilter(s)));
}
public MessageOut<CounterMutation> makeMutationMessage() throws IOException
@ -128,7 +129,7 @@ public class CounterMutation implements IMutation
{
ColumnFamily cf = cf_.cloneMeShallow();
ColumnFamilyStore cfs = table.getColumnFamilyStore(cf.id());
for (IColumn column : cf_)
for (Column column : cf_)
{
cf.addColumn(column.localCopy(cfs), HeapAllocator.instance);
}

View File

@ -49,14 +49,14 @@ public class CounterUpdateColumn extends Column
}
@Override
public IColumn diff(IColumn column)
public Column diff(Column column)
{
// Diff is used during reads, but we should never read those columns
throw new UnsupportedOperationException("This operation is unsupported on CounterUpdateColumn.");
}
@Override
public IColumn reconcile(IColumn column, Allocator allocator)
public Column reconcile(Column column, Allocator allocator)
{
// The only time this could happen is if a batchAdd ships two
// increment for the same column. Hence we simply sums the delta.
@ -88,7 +88,7 @@ public class CounterUpdateColumn extends Column
}
@Override
public IColumn localCopy(ColumnFamilyStore cfs, Allocator allocator)
public Column localCopy(ColumnFamilyStore cfs, Allocator allocator)
{
return new CounterColumn(cfs.internOrCopy(name, allocator),
CounterContext.instance().create(delta(), allocator),

View File

@ -37,7 +37,6 @@ import org.apache.avro.specific.SpecificRecord;
import org.apache.cassandra.config.*;
import org.apache.cassandra.db.compaction.CompactionManager;
import org.apache.cassandra.db.filter.QueryFilter;
import org.apache.cassandra.db.filter.QueryPath;
import org.apache.cassandra.db.marshal.AsciiType;
import org.apache.cassandra.db.marshal.UTF8Type;
import org.apache.cassandra.db.migration.avro.KsDef;
@ -181,7 +180,7 @@ public class DefsTable
if (Schema.invalidSchemaRow(row))
continue;
for (IColumn column : row.cf.columns)
for (Column column : row.cf.columns)
{
Date columnDate = new Date(column.timestamp());
@ -233,10 +232,10 @@ public class DefsTable
RowMutation mutation = new RowMutation(Table.SYSTEM_KS, row.key.key);
for (IColumn column : row.cf.columns)
for (Column column : row.cf.columns)
{
if (column.isLive())
mutation.add(new QueryPath(columnFamily, null, column.name()), column.value(), microTimestamp);
mutation.add(columnFamily, column.name(), column.value(), microTimestamp);
}
mutation.apply();
@ -272,7 +271,7 @@ public class DefsTable
private static Row serializedColumnFamilies(DecoratedKey ksNameKey)
{
ColumnFamilyStore cfsStore = SystemTable.schemaCFS(SystemTable.SCHEMA_COLUMNFAMILIES_CF);
return new Row(ksNameKey, cfsStore.getColumnFamily(QueryFilter.getIdentityFilter(ksNameKey, new QueryPath(SystemTable.SCHEMA_COLUMNFAMILIES_CF))));
return new Row(ksNameKey, cfsStore.getColumnFamily(QueryFilter.getIdentityFilter(ksNameKey, SystemTable.SCHEMA_COLUMNFAMILIES_CF)));
}
/**
@ -290,8 +289,8 @@ public class DefsTable
DecoratedKey vkey = StorageService.getPartitioner().decorateKey(toUTF8Bytes(version));
Table defs = Table.open(Table.SYSTEM_KS);
ColumnFamilyStore cfStore = defs.getColumnFamilyStore(OLD_SCHEMA_CF);
ColumnFamily cf = cfStore.getColumnFamily(QueryFilter.getIdentityFilter(vkey, new QueryPath(OLD_SCHEMA_CF)));
IColumn avroschema = cf.getColumn(DEFINITION_SCHEMA_COLUMN_NAME);
ColumnFamily cf = cfStore.getColumnFamily(QueryFilter.getIdentityFilter(vkey, OLD_SCHEMA_CF));
Column avroschema = cf.getColumn(DEFINITION_SCHEMA_COLUMN_NAME);
Collection<KSMetaData> keyspaces = Collections.emptyList();
@ -301,10 +300,10 @@ public class DefsTable
org.apache.avro.Schema schema = org.apache.avro.Schema.parse(ByteBufferUtil.string(value));
// deserialize keyspaces using schema
Collection<IColumn> columns = cf.getSortedColumns();
Collection<Column> columns = cf.getSortedColumns();
keyspaces = new ArrayList<KSMetaData>(columns.size());
for (IColumn column : columns)
for (Column column : columns)
{
if (column.name().equals(DEFINITION_SCHEMA_COLUMN_NAME))
continue;

View File

@ -37,6 +37,12 @@ public class DeletedColumn extends Column
super(name, value, timestamp);
}
@Override
public Column withUpdatedName(ByteBuffer newName)
{
return new DeletedColumn(newName, value, timestamp);
}
@Override
public boolean isMarkedForDelete()
{
@ -58,7 +64,7 @@ public class DeletedColumn extends Column
}
@Override
public IColumn reconcile(IColumn column, Allocator allocator)
public Column reconcile(Column column, Allocator allocator)
{
if (column instanceof DeletedColumn)
return super.reconcile(column, allocator);
@ -66,13 +72,13 @@ public class DeletedColumn extends Column
}
@Override
public IColumn localCopy(ColumnFamilyStore cfs)
public Column localCopy(ColumnFamilyStore cfs)
{
return new DeletedColumn(cfs.internOrCopy(name, HeapAllocator.instance), ByteBufferUtil.clone(value), timestamp);
}
@Override
public IColumn localCopy(ColumnFamilyStore cfs, Allocator allocator)
public Column localCopy(ColumnFamilyStore cfs, Allocator allocator)
{
return new DeletedColumn(cfs.internOrCopy(name, allocator), allocator.clone(value), timestamp);
}

View File

@ -51,8 +51,12 @@ public class DeletionInfo
{
// Pre-1.1 node may return MIN_VALUE for non-deleted container, but the new default is MAX_VALUE
// (see CASSANDRA-3872)
this(new DeletionTime(markedForDeleteAt, localDeletionTime == Integer.MIN_VALUE ? Integer.MAX_VALUE : localDeletionTime),
IntervalTree.<ByteBuffer, DeletionTime, RangeTombstone>emptyTree());
this(new DeletionTime(markedForDeleteAt, localDeletionTime == Integer.MIN_VALUE ? Integer.MAX_VALUE : localDeletionTime));
}
public DeletionInfo(DeletionTime topLevel)
{
this(topLevel, IntervalTree.<ByteBuffer, DeletionTime, RangeTombstone>emptyTree());
}
public DeletionInfo(ByteBuffer start, ByteBuffer end, Comparator<ByteBuffer> comparator, long markedForDeleteAt, int localDeletionTime)
@ -94,7 +98,7 @@ public class DeletionInfo
* @param column the column to check.
* @return true if the column is deleted, false otherwise
*/
public boolean isDeleted(IColumn column)
public boolean isDeleted(Column column)
{
return isDeleted(column.name(), column.mostRecentLiveChangeAt());
}
@ -211,6 +215,11 @@ public class DeletionInfo
return ranges.iterator();
}
public List<DeletionTime> rangeCovering(ByteBuffer name)
{
return ranges.search(name);
}
public int dataSize()
{
int size = TypeSizes.NATIVE.sizeof(topLevel.markedForDeleteAt);
@ -331,7 +340,7 @@ public class DeletionInfo
public DeletionInfo deserialize(DataInput in, int version, Comparator<ByteBuffer> comparator) throws IOException
{
assert comparator != null;
assert version < MessagingService.VERSION_12 || comparator != null;
DeletionTime topLevel = DeletionTime.serializer.deserialize(in);
if (version < MessagingService.VERSION_12)
return new DeletionInfo(topLevel, IntervalTree.<ByteBuffer, DeletionTime, RangeTombstone>emptyTree());

View File

@ -80,7 +80,7 @@ public class DeletionTime implements Comparable<DeletionTime>
return localDeletionTime < gcBefore;
}
public boolean isDeleted(IColumn column)
public boolean isDeleted(Column column)
{
return column.isMarkedForDelete() && column.getMarkedForDeleteAt() <= markedForDeleteAt;
}

View File

@ -24,7 +24,6 @@ import java.security.MessageDigest;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.MarshalException;
import org.apache.cassandra.io.IColumnSerializer;
import org.apache.cassandra.io.util.DataOutputBuffer;
import org.apache.cassandra.utils.Allocator;
import org.apache.cassandra.utils.ByteBufferUtil;
@ -62,9 +61,9 @@ public class ExpiringColumn extends Column
}
/** @return Either a DeletedColumn, or an ExpiringColumn. */
public static Column create(ByteBuffer name, ByteBuffer value, long timestamp, int timeToLive, int localExpirationTime, int expireBefore, IColumnSerializer.Flag flag)
public static Column create(ByteBuffer name, ByteBuffer value, long timestamp, int timeToLive, int localExpirationTime, int expireBefore, ColumnSerializer.Flag flag)
{
if (localExpirationTime >= expireBefore || flag == IColumnSerializer.Flag.PRESERVE_SIZE)
if (localExpirationTime >= expireBefore || flag == ColumnSerializer.Flag.PRESERVE_SIZE)
return new ExpiringColumn(name, value, timestamp, timeToLive, localExpirationTime);
// the column is now expired, we can safely return a simple tombstone
return new DeletedColumn(name, localExpirationTime, timestamp);
@ -75,6 +74,12 @@ public class ExpiringColumn extends Column
return timeToLive;
}
@Override
public Column withUpdatedName(ByteBuffer newName)
{
return new ExpiringColumn(newName, value, timestamp, timeToLive, localExpirationTime);
}
@Override
public int dataSize()
{
@ -119,13 +124,13 @@ public class ExpiringColumn extends Column
}
@Override
public IColumn localCopy(ColumnFamilyStore cfs)
public Column localCopy(ColumnFamilyStore cfs)
{
return new ExpiringColumn(cfs.internOrCopy(name, HeapAllocator.instance), ByteBufferUtil.clone(value), timestamp, timeToLive, localExpirationTime);
}
@Override
public IColumn localCopy(ColumnFamilyStore cfs, Allocator allocator)
public Column localCopy(ColumnFamilyStore cfs, Allocator allocator)
{
ByteBuffer clonedName = cfs.maybeIntern(name);
if (clonedName == null)

View File

@ -129,7 +129,7 @@ public class HintedHandOffManager implements HintedHandOffManagerMBean
private static void deleteHint(ByteBuffer tokenBytes, ByteBuffer columnName, long timestamp) throws IOException
{
RowMutation rm = new RowMutation(Table.SYSTEM_KS, tokenBytes);
rm.delete(new QueryPath(SystemTable.HINTS_CF, null, columnName), timestamp);
rm.delete(SystemTable.HINTS_CF, columnName, timestamp);
rm.applyUnsafe(); // don't bother with commitlog since we're going to flush as soon as we're done with delivery
}
@ -155,7 +155,7 @@ public class HintedHandOffManager implements HintedHandOffManagerMBean
UUID hostId = StorageService.instance.getTokenMetadata().getHostId(endpoint);
ByteBuffer hostIdBytes = ByteBuffer.wrap(UUIDGen.decompose(hostId));
final RowMutation rm = new RowMutation(Table.SYSTEM_KS, hostIdBytes);
rm.delete(new QueryPath(SystemTable.HINTS_CF), System.currentTimeMillis());
rm.delete(SystemTable.HINTS_CF, System.currentTimeMillis());
// execute asynchronously to avoid blocking caller (which may be processing gossip)
Runnable runnable = new Runnable()
@ -303,7 +303,7 @@ public class HintedHandOffManager implements HintedHandOffManagerMBean
while (true)
{
QueryFilter filter = QueryFilter.getSliceFilter(epkey, new QueryPath(SystemTable.HINTS_CF), startColumn, ByteBufferUtil.EMPTY_BYTE_BUFFER, false, pageSize);
QueryFilter filter = QueryFilter.getSliceFilter(epkey, SystemTable.HINTS_CF, startColumn, ByteBufferUtil.EMPTY_BYTE_BUFFER, false, pageSize);
ColumnFamily hintsPage = ColumnFamilyStore.removeDeleted(hintStore.getColumnFamily(filter), (int)(System.currentTimeMillis() / 1000));
if (pagingFinished(hintsPage, startColumn))
{
@ -322,7 +322,7 @@ public class HintedHandOffManager implements HintedHandOffManagerMBean
}
for (final IColumn hint : hintsPage.getSortedColumns())
for (final Column hint : hintsPage.getSortedColumns())
{
// Skip tombstones:
// if we iterate quickly enough, it's possible that we could request a new page in the same millisecond
@ -400,7 +400,7 @@ public class HintedHandOffManager implements HintedHandOffManagerMBean
RowPosition minPos = p.getMinimumToken().minKeyBound();
Range<RowPosition> range = new Range<RowPosition>(minPos, minPos, p);
IDiskAtomFilter filter = new NamesQueryFilter(ImmutableSortedSet.<ByteBuffer>of());
List<Row> rows = hintStore.getRangeSlice(null, range, Integer.MAX_VALUE, filter, null);
List<Row> rows = hintStore.getRangeSlice(range, Integer.MAX_VALUE, filter, null);
for (Row row : rows)
{
UUID hostId = UUIDGen.getUUID(row.key.key);
@ -473,9 +473,6 @@ public class HintedHandOffManager implements HintedHandOffManagerMBean
private List<Row> getHintsSlice(int columnCount)
{
// ColumnParent for HintsCF...
ColumnParent parent = new ColumnParent(SystemTable.HINTS_CF);
// Get count # of columns...
SliceQueryFilter predicate = new SliceQueryFilter(ByteBufferUtil.EMPTY_BYTE_BUFFER,
ByteBufferUtil.EMPTY_BYTE_BUFFER,
@ -491,7 +488,7 @@ public class HintedHandOffManager implements HintedHandOffManagerMBean
List<Row> rows;
try
{
rows = StorageProxy.getRangeSlice(new RangeSliceCommand(Table.SYSTEM_KS, parent, predicate, range, null, LARGE_NUMBER), ConsistencyLevel.ONE);
rows = StorageProxy.getRangeSlice(new RangeSliceCommand(Table.SYSTEM_KS, SystemTable.HINTS_CF, predicate, range, null, LARGE_NUMBER), ConsistencyLevel.ONE);
}
catch (Exception e)
{

View File

@ -1,85 +0,0 @@
/*
* 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.util.Collection;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.MarshalException;
import org.apache.cassandra.utils.Allocator;
import org.apache.cassandra.utils.FBUtilities;
/** TODO: rename */
public interface IColumn extends OnDiskAtom
{
public static final int MAX_NAME_LENGTH = FBUtilities.MAX_UNSIGNED_SHORT;
/**
* @return true if the column has been deleted (is a tombstone). This depends on comparing the server clock
* with getLocalDeletionTime, so it can change during a single request if you're not careful.
*/
public boolean isMarkedForDelete();
public long getMarkedForDeleteAt();
public long mostRecentLiveChangeAt();
public long mostRecentNonGCableChangeAt(int gcbefore);
/** the size of user-provided data, not including internal overhead */
public int dataSize();
public int serializationFlags();
public long timestamp();
public ByteBuffer value();
public Collection<IColumn> getSubColumns();
public IColumn getSubColumn(ByteBuffer columnName);
public void addColumn(IColumn column);
public void addColumn(IColumn column, Allocator allocator);
public IColumn diff(IColumn column);
public IColumn reconcile(IColumn column);
public IColumn reconcile(IColumn column, Allocator allocator);
public String getString(AbstractType<?> comparator);
public void validateFields(CFMetaData metadata) throws MarshalException;
/** clones the column for the row cache, interning column names and making copies of other underlying byte buffers */
IColumn localCopy(ColumnFamilyStore cfs);
/**
* clones the column for the memtable, interning column names and making copies of other underlying byte buffers.
* Unlike the other localCopy, this uses Allocator to allocate values in contiguous memory regions,
* which helps avoid heap fragmentation.
*/
IColumn localCopy(ColumnFamilyStore cfs, Allocator allocator);
/**
* For a simple column, live == !isMarkedForDelete.
* For a supercolumn, live means it has at least one subcolumn whose timestamp is greater than the
* supercolumn deleted-at time.
*/
boolean isLive();
/**
* For a standard column, this is the same as timestamp().
* For a super column, this is the max column timestamp of the sub columns.
*/
public long maxTimestamp();
/**
* @return true if the column or any its subcolumns is no longer relevant after @param gcBefore
*/
public boolean hasIrrelevantData(int gcBefore);
}

View File

@ -1,49 +0,0 @@
/*
* 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.util.Collection;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.utils.Allocator;
public interface IColumnContainer
{
public void addColumn(IColumn column);
public void addColumn(IColumn column, Allocator allocator);
public void remove(ByteBuffer columnName);
/**
* Replace oldColumn if represent by newColumn.
* Returns true if oldColumn was present (and thus replaced)
* oldColumn and newColumn should have the same name.
* !NOTE! This should only be used if you know this is what you need. To
* add a column such that it use the usual column resolution rules in a
* thread safe manner, use addColumn.
*/
public boolean replace(IColumn oldColumn, IColumn newColumn);
public boolean isMarkedForDelete();
public DeletionInfo deletionInfo();
public boolean hasIrrelevantData(int gcBefore);
public AbstractType<?> getComparator();
public Collection<IColumn> getSortedColumns();
}

View File

@ -62,7 +62,7 @@ public interface ISortedColumns extends IIterableColumns
* If a column with the same name is already present in the map, it will
* be replaced by the newly added column.
*/
public void addColumn(IColumn column, Allocator allocator);
public void addColumn(Column column, Allocator allocator);
/**
* Adds all the columns of a given column map to this column map.
@ -75,19 +75,19 @@ public interface ISortedColumns extends IIterableColumns
*
* @return the difference in size seen after merging the given columns
*/
public long addAllWithSizeDelta(ISortedColumns cm, Allocator allocator, Function<IColumn, IColumn> transformation, SecondaryIndexManager.Updater indexer);
public long addAllWithSizeDelta(ISortedColumns cm, Allocator allocator, Function<Column, Column> transformation, SecondaryIndexManager.Updater indexer);
/**
* Adds the columns without necessarily computing the size delta
*/
public void addAll(ISortedColumns cm, Allocator allocator, Function<IColumn, IColumn> transformation);
public void addAll(ISortedColumns cm, Allocator allocator, Function<Column, Column> transformation);
/**
* Replace oldColumn if present by newColumn.
* Returns true if oldColumn was present and thus replaced.
* oldColumn and newColumn should have the same name.
*/
public boolean replace(IColumn oldColumn, IColumn newColumn);
public boolean replace(Column oldColumn, Column newColumn);
/**
* Remove if present a column by name.
@ -103,7 +103,7 @@ public interface ISortedColumns extends IIterableColumns
* Get a column given its name, returning null if the column is not
* present.
*/
public IColumn getColumn(ByteBuffer name);
public Column getColumn(ByteBuffer name);
/**
* Returns a set with the names of columns in this column map.
@ -117,14 +117,14 @@ public interface ISortedColumns extends IIterableColumns
* The columns in the returned collection should be sorted as the columns
* in this map.
*/
public Collection<IColumn> getSortedColumns();
public Collection<Column> getSortedColumns();
/**
* Returns the columns of this column map as a collection.
* The columns in the returned collection should be sorted in reverse
* order of the columns in this map.
*/
public Collection<IColumn> getReverseSortedColumns();
public Collection<Column> getReverseSortedColumns();
/**
* Returns the number of columns in this map.
@ -140,13 +140,13 @@ public interface ISortedColumns extends IIterableColumns
* Returns an iterator over the columns of this map that returns only the matching @param slices.
* The provided slices must be in order and must be non-overlapping.
*/
public Iterator<IColumn> iterator(ColumnSlice[] slices);
public Iterator<Column> iterator(ColumnSlice[] slices);
/**
* Returns a reversed iterator over the columns of this map that returns only the matching @param slices.
* The provided slices must be in reversed order and must be non-overlapping.
*/
public Iterator<IColumn> reverseIterator(ColumnSlice[] slices);
public Iterator<Column> reverseIterator(ColumnSlice[] slices);
/**
* Returns if this map only support inserts in reverse order.
@ -171,6 +171,6 @@ public interface ISortedColumns extends IIterableColumns
* columns in the provided sorted map.
* See {@code create} for the description of {@code insertReversed}
*/
public ISortedColumns fromSorted(SortedMap<ByteBuffer, IColumn> sm, boolean insertReversed);
public ISortedColumns fromSorted(SortedMap<ByteBuffer, Column> sm, boolean insertReversed);
}
}

View File

@ -93,9 +93,9 @@ public class Memtable
private final SlabAllocator allocator = new SlabAllocator();
// We really only need one column by allocator but one by memtable is not a big waste and avoids needing allocators to know about CFS
private final Function<IColumn, IColumn> localCopyFunction = new Function<IColumn, IColumn>()
private final Function<Column, Column> localCopyFunction = new Function<Column, Column>()
{
public IColumn apply(IColumn c)
public Column apply(Column c)
{
return c.localCopy(cfs, allocator);
};
@ -226,7 +226,7 @@ public class Memtable
if (previous == null)
{
// AtomicSortedColumns doesn't work for super columns (see #3821)
ColumnFamily empty = cf.cloneMeShallow(cf.isSuper() ? ThreadSafeSortedColumns.factory() : AtomicSortedColumns.factory(), false);
ColumnFamily empty = cf.cloneMeShallow(AtomicSortedColumns.factory(), false);
// We'll add the columns later. This avoids wasting works if we get beaten in the putIfAbsent
previous = columnFamilies.putIfAbsent(new DecoratedKey(key.token, allocator.clone(key.key)), empty);
if (previous == null)
@ -316,7 +316,7 @@ public class Memtable
public static OnDiskAtomIterator getSliceIterator(final DecoratedKey key, final ColumnFamily cf, SliceQueryFilter filter)
{
assert cf != null;
final Iterator<IColumn> filteredIter = filter.reversed ? cf.reverseIterator(filter.slices) : cf.iterator(filter.slices);
final Iterator<Column> filteredIter = filter.reversed ? cf.reverseIterator(filter.slices) : cf.iterator(filter.slices);
return new AbstractColumnIterator()
{
@ -345,7 +345,6 @@ public class Memtable
public static OnDiskAtomIterator getNamesIterator(final DecoratedKey key, final ColumnFamily cf, final NamesQueryFilter filter)
{
assert cf != null;
final boolean isStandard = !cf.isSuper();
return new SimpleAbstractColumnIterator()
{
@ -366,10 +365,9 @@ public class Memtable
while (iter.hasNext())
{
ByteBuffer current = iter.next();
IColumn column = cf.getColumn(current);
Column column = cf.getColumn(current);
if (column != null)
// clone supercolumns so caller can freely removeDeleted or otherwise mutate it
return isStandard ? column : ((SuperColumn)column).cloneMe();
return column;
}
return endOfData();
}

View File

@ -23,7 +23,6 @@ import java.security.MessageDigest;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.marshal.MarshalException;
import org.apache.cassandra.io.IColumnSerializer;
import org.apache.cassandra.io.ISSTableSerializer;
import org.apache.cassandra.io.sstable.Descriptor;
import org.apache.cassandra.utils.ByteBufferUtil;
@ -48,18 +47,15 @@ public interface OnDiskAtom
public static class Serializer implements ISSTableSerializer<OnDiskAtom>
{
private final IColumnSerializer columnSerializer;
public static Serializer instance = new Serializer();
public Serializer(IColumnSerializer columnSerializer)
{
this.columnSerializer = columnSerializer;
}
private Serializer() {}
public void serializeForSSTable(OnDiskAtom atom, DataOutput dos) throws IOException
{
if (atom instanceof IColumn)
if (atom instanceof Column)
{
columnSerializer.serialize((IColumn)atom, dos);
Column.serializer().serialize((Column)atom, dos);
}
else
{
@ -70,27 +66,20 @@ public interface OnDiskAtom
public OnDiskAtom deserializeFromSSTable(DataInput dis, Descriptor.Version version) throws IOException
{
return deserializeFromSSTable(dis, IColumnSerializer.Flag.LOCAL, (int)(System.currentTimeMillis() / 1000), version);
return deserializeFromSSTable(dis, ColumnSerializer.Flag.LOCAL, (int)(System.currentTimeMillis() / 1000), version);
}
public OnDiskAtom deserializeFromSSTable(DataInput dis, IColumnSerializer.Flag flag, int expireBefore, Descriptor.Version version) throws IOException
public OnDiskAtom deserializeFromSSTable(DataInput dis, ColumnSerializer.Flag flag, int expireBefore, Descriptor.Version version) throws IOException
{
if (columnSerializer instanceof SuperColumnSerializer)
{
return columnSerializer.deserialize(dis, flag, expireBefore);
}
else
{
ByteBuffer name = ByteBufferUtil.readWithShortLength(dis);
if (name.remaining() <= 0)
throw ColumnSerializer.CorruptColumnException.create(dis, name);
ByteBuffer name = ByteBufferUtil.readWithShortLength(dis);
if (name.remaining() <= 0)
throw ColumnSerializer.CorruptColumnException.create(dis, name);
int b = dis.readUnsignedByte();
if ((b & ColumnSerializer.RANGE_TOMBSTONE_MASK) != 0)
return RangeTombstone.serializer.deserializeBody(dis, name, version);
else
return ((ColumnSerializer)columnSerializer).deserializeColumnBody(dis, name, b, flag, expireBefore);
}
int b = dis.readUnsignedByte();
if ((b & ColumnSerializer.RANGE_TOMBSTONE_MASK) != 0)
return RangeTombstone.serializer.deserializeBody(dis, name, version);
else
return Column.serializer().deserializeColumnBody(dis, name, b, flag, expireBefore);
}
}
}

View File

@ -49,13 +49,13 @@ import org.apache.cassandra.db.filter.IDiskAtomFilter;
import org.apache.cassandra.db.filter.NamesQueryFilter;
import org.apache.cassandra.db.filter.SliceQueryFilter;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.CompositeType;
import org.apache.cassandra.dht.AbstractBounds;
import org.apache.cassandra.exceptions.*;
import org.apache.cassandra.io.IVersionedSerializer;
import org.apache.cassandra.net.MessageOut;
import org.apache.cassandra.net.MessagingService;
import org.apache.cassandra.service.IReadCommand;
import org.apache.cassandra.thrift.ColumnParent;
import org.apache.cassandra.thrift.IndexClause;
import org.apache.cassandra.thrift.IndexExpression;
import org.apache.cassandra.thrift.IndexOperator;
@ -76,7 +76,6 @@ public class RangeSliceCommand implements IReadCommand
public final String keyspace;
public final String column_family;
public final ByteBuffer super_column;
public final IDiskAtomFilter predicate;
public final List<IndexExpression> row_filter;
@ -86,26 +85,20 @@ public class RangeSliceCommand implements IReadCommand
public final boolean countCQL3Rows;
public final boolean isPaging;
public RangeSliceCommand(String keyspace, String column_family, ByteBuffer super_column, IDiskAtomFilter predicate, AbstractBounds<RowPosition> range, int maxResults)
public RangeSliceCommand(String keyspace, String column_family, IDiskAtomFilter predicate, AbstractBounds<RowPosition> range, int maxResults)
{
this(keyspace, column_family, super_column, predicate, range, null, maxResults, false, false);
this(keyspace, column_family, predicate, range, null, maxResults, false, false);
}
public RangeSliceCommand(String keyspace, ColumnParent column_parent, IDiskAtomFilter predicate, AbstractBounds<RowPosition> range, List<IndexExpression> row_filter, int maxResults)
public RangeSliceCommand(String keyspace, String column_family, IDiskAtomFilter predicate, AbstractBounds<RowPosition> range, List<IndexExpression> row_filter, int maxResults)
{
this(keyspace, column_parent.getColumn_family(), column_parent.super_column, predicate, range, row_filter, maxResults, false, false);
this(keyspace, column_family, predicate, range, row_filter, maxResults, false, false);
}
public RangeSliceCommand(String keyspace, String column_family, ByteBuffer super_column, IDiskAtomFilter predicate, AbstractBounds<RowPosition> range, List<IndexExpression> row_filter, int maxResults)
{
this(keyspace, column_family, super_column, predicate, range, row_filter, maxResults, false, false);
}
public RangeSliceCommand(String keyspace, String column_family, ByteBuffer super_column, IDiskAtomFilter predicate, AbstractBounds<RowPosition> range, List<IndexExpression> row_filter, int maxResults, boolean countCQL3Rows, boolean isPaging)
public RangeSliceCommand(String keyspace, String column_family, IDiskAtomFilter predicate, AbstractBounds<RowPosition> range, List<IndexExpression> row_filter, int maxResults, boolean countCQL3Rows, boolean isPaging)
{
this.keyspace = keyspace;
this.column_family = column_family;
this.super_column = super_column;
this.predicate = predicate;
this.range = range;
this.row_filter = row_filter;
@ -125,7 +118,6 @@ public class RangeSliceCommand implements IReadCommand
return "RangeSliceCommand{" +
"keyspace='" + keyspace + '\'' +
", column_family='" + column_family + '\'' +
", super_column=" + super_column +
", predicate=" + predicate +
", range=" + range +
", row_filter =" + row_filter +
@ -198,10 +190,26 @@ class RangeSliceCommandSerializer implements IVersionedSerializer<RangeSliceComm
{
dos.writeUTF(sliceCommand.keyspace);
dos.writeUTF(sliceCommand.column_family);
ByteBuffer sc = sliceCommand.super_column;
dos.writeInt(sc == null ? 0 : sc.remaining());
if (sc != null)
ByteBufferUtil.write(sc, dos);
IDiskAtomFilter filter = sliceCommand.predicate;
if (version < MessagingService.VERSION_20)
{
// Pre-2.0, we need to know if it's a super column. If it is, we
// must extract the super column name from the predicate (and
// modify the predicate accordingly)
ByteBuffer sc = null;
CFMetaData metadata = Schema.instance.getCFMetaData(sliceCommand.getKeyspace(), sliceCommand.column_family);
if (metadata.cfType == ColumnFamilyType.Super)
{
SuperColumns.SCFilter scFilter = SuperColumns.filterToSC((CompositeType)metadata.comparator, filter);
sc = scFilter.scName;
filter = scFilter.updatedFilter;
}
dos.writeInt(sc == null ? 0 : sc.remaining());
if (sc != null)
ByteBufferUtil.write(sc, dos);
}
if (version < MessagingService.VERSION_12)
{
@ -250,26 +258,48 @@ class RangeSliceCommandSerializer implements IVersionedSerializer<RangeSliceComm
String keyspace = dis.readUTF();
String columnFamily = dis.readUTF();
int scLength = dis.readInt();
ByteBuffer superColumn = null;
if (scLength > 0)
{
byte[] buf = new byte[scLength];
dis.readFully(buf);
superColumn = ByteBuffer.wrap(buf);
}
CFMetaData metadata = Schema.instance.getCFMetaData(keyspace, columnFamily);
IDiskAtomFilter predicate;
AbstractType<?> comparator = ColumnFamily.getComparatorFor(keyspace, columnFamily, superColumn);
if (version < MessagingService.VERSION_12)
if (version < MessagingService.VERSION_20)
{
SlicePredicate pred = new SlicePredicate();
FBUtilities.deserialize(new TDeserializer(new TBinaryProtocol.Factory()), pred, dis);
predicate = ThriftValidation.asIFilter(pred, comparator);
int scLength = dis.readInt();
ByteBuffer superColumn = null;
if (scLength > 0)
{
byte[] buf = new byte[scLength];
dis.readFully(buf);
superColumn = ByteBuffer.wrap(buf);
}
AbstractType<?> comparator;
if (metadata.cfType == ColumnFamilyType.Super)
{
CompositeType type = (CompositeType)metadata.comparator;
comparator = superColumn == null ? type.types.get(0) : type.types.get(1);
}
else
{
comparator = metadata.comparator;
}
if (version < MessagingService.VERSION_12)
{
SlicePredicate pred = new SlicePredicate();
FBUtilities.deserialize(new TDeserializer(new TBinaryProtocol.Factory()), pred, dis);
predicate = ThriftValidation.asIFilter(pred, metadata, superColumn);
}
else
{
predicate = IDiskAtomFilter.Serializer.instance.deserialize(dis, version, comparator);
}
if (metadata.cfType == ColumnFamilyType.Super)
predicate = SuperColumns.fromSCFilter((CompositeType)metadata.comparator, superColumn, predicate);
}
else
{
predicate = IDiskAtomFilter.Serializer.instance.deserialize(dis, version, comparator);
predicate = IDiskAtomFilter.Serializer.instance.deserialize(dis, version, metadata.comparator);
}
List<IndexExpression> rowFilter = null;
@ -304,7 +334,7 @@ class RangeSliceCommandSerializer implements IVersionedSerializer<RangeSliceComm
countCQL3Rows = dis.readBoolean();
isPaging = dis.readBoolean();
}
return new RangeSliceCommand(keyspace, columnFamily, superColumn, predicate, range, rowFilter, maxResults, countCQL3Rows, isPaging);
return new RangeSliceCommand(keyspace, columnFamily, predicate, range, rowFilter, maxResults, countCQL3Rows, isPaging);
}
public long serializedSize(RangeSliceCommand rsc, int version)
@ -312,15 +342,27 @@ class RangeSliceCommandSerializer implements IVersionedSerializer<RangeSliceComm
long size = TypeSizes.NATIVE.sizeof(rsc.keyspace);
size += TypeSizes.NATIVE.sizeof(rsc.column_family);
ByteBuffer sc = rsc.super_column;
if (sc != null)
IDiskAtomFilter filter = rsc.predicate;
if (version < MessagingService.VERSION_20)
{
size += TypeSizes.NATIVE.sizeof(sc.remaining());
size += sc.remaining();
}
else
{
size += TypeSizes.NATIVE.sizeof(0);
ByteBuffer sc = null;
CFMetaData metadata = Schema.instance.getCFMetaData(rsc.keyspace, rsc.column_family);
if (metadata.cfType == ColumnFamilyType.Super)
{
SuperColumns.SCFilter scFilter = SuperColumns.filterToSC((CompositeType)metadata.comparator, filter);
sc = scFilter.scName;
filter = scFilter.updatedFilter;
}
if (sc != null)
{
size += TypeSizes.NATIVE.sizeof(sc.remaining());
size += sc.remaining();
}
else
{
size += TypeSizes.NATIVE.sizeof(0);
}
}
if (version < MessagingService.VERSION_12)
@ -328,7 +370,7 @@ class RangeSliceCommandSerializer implements IVersionedSerializer<RangeSliceComm
TSerializer ser = new TSerializer(new TBinaryProtocol.Factory());
try
{
int predicateLength = ser.serialize(asSlicePredicate(rsc.predicate)).length;
int predicateLength = ser.serialize(asSlicePredicate(filter)).length;
if (version < MessagingService.VERSION_12)
size += TypeSizes.NATIVE.sizeof(predicateLength);
size += predicateLength;
@ -340,7 +382,7 @@ class RangeSliceCommandSerializer implements IVersionedSerializer<RangeSliceComm
}
else
{
size += IDiskAtomFilter.Serializer.instance.serializedSize(rsc.predicate, version);
size += IDiskAtomFilter.Serializer.instance.serializedSize(filter, version);
}
if (version >= MessagingService.VERSION_11)

View File

@ -83,9 +83,8 @@ public class RangeTombstone extends Interval<ByteBuffer, DeletionTime> implement
public void validateFields(CFMetaData metadata) throws MarshalException
{
AbstractType<?> nameValidator = metadata.cfType == ColumnFamilyType.Super ? metadata.subcolumnComparator : metadata.comparator;
nameValidator.validate(min);
nameValidator.validate(max);
metadata.comparator.validate(min);
metadata.comparator.validate(max);
}
public void updateDigest(MessageDigest digest)
@ -192,7 +191,7 @@ public class RangeTombstone extends Interval<ByteBuffer, DeletionTime> implement
/**
* Update this tracker given an {@code atom}.
* If column is a IColumn, check if any tracked range is useless and
* If column is a Column, check if any tracked range is useless and
* can be removed. If it is a RangeTombstone, add it to this tracker.
*/
public void update(OnDiskAtom atom)
@ -219,7 +218,7 @@ public class RangeTombstone extends Interval<ByteBuffer, DeletionTime> implement
}
else
{
assert atom instanceof IColumn;
assert atom instanceof Column;
Iterator<RangeTombstone> iter = maxOrderingSet.iterator();
while (iter.hasNext())
{
@ -240,7 +239,7 @@ public class RangeTombstone extends Interval<ByteBuffer, DeletionTime> implement
}
}
public boolean isDeleted(IColumn column)
public boolean isDeleted(Column column)
{
for (RangeTombstone tombstone : ranges)
{

View File

@ -24,10 +24,14 @@ import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.config.Schema;
import org.apache.cassandra.db.filter.IDiskAtomFilter;
import org.apache.cassandra.db.filter.QueryPath;
import org.apache.cassandra.db.filter.NamesQueryFilter;
import org.apache.cassandra.db.filter.SliceQueryFilter;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.CompositeType;
import org.apache.cassandra.io.IVersionedSerializer;
import org.apache.cassandra.net.MessageOut;
import org.apache.cassandra.net.MessagingService;
@ -38,8 +42,22 @@ import org.apache.cassandra.utils.IFilter;
public abstract class ReadCommand implements IReadCommand
{
public static final byte CMD_TYPE_GET_SLICE_BY_NAMES = 1;
public static final byte CMD_TYPE_GET_SLICE = 2;
public enum Type {
GET_BY_NAMES((byte)1),
GET_SLICES((byte)2);
public final byte serializedValue;
private Type(byte b)
{
this.serializedValue = b;
}
public static Type fromSerializedValue(byte b)
{
return b == 1 ? GET_BY_NAMES : GET_SLICES;
}
}
public static final ReadCommandSerializer serializer = new ReadCommandSerializer();
@ -48,20 +66,28 @@ public abstract class ReadCommand implements IReadCommand
return new MessageOut<ReadCommand>(MessagingService.Verb.READ, this, serializer);
}
public final QueryPath queryPath;
public final String table;
public final String cfName;
public final ByteBuffer key;
private boolean isDigestQuery = false;
protected final byte commandType;
protected final Type commandType;
protected ReadCommand(String table, ByteBuffer key, QueryPath queryPath, byte cmdType)
protected ReadCommand(String table, ByteBuffer key, String cfName, Type cmdType)
{
this.table = table;
this.key = key;
this.queryPath = queryPath;
this.cfName = cfName;
this.commandType = cmdType;
}
public static ReadCommand create(String table, ByteBuffer key, String cfName, IDiskAtomFilter filter)
{
if (filter instanceof SliceQueryFilter)
return new SliceFromReadCommand(table, key, cfName, (SliceQueryFilter)filter);
else
return new SliceByNamesReadCommand(table, key, cfName, (NamesQueryFilter)filter);
}
public boolean isDigestQuery()
{
return isDigestQuery;
@ -74,7 +100,7 @@ public abstract class ReadCommand implements IReadCommand
public String getColumnFamilyName()
{
return queryPath.columnFamilyName;
return cfName;
}
public abstract ReadCommand copy();
@ -83,11 +109,6 @@ public abstract class ReadCommand implements IReadCommand
public abstract IDiskAtomFilter filter();
protected AbstractType<?> getComparator()
{
return ColumnFamily.getComparatorFor(table, getColumnFamilyName(), queryPath.superColumnName);
}
public String getKeyspace()
{
return table;
@ -113,28 +134,77 @@ public abstract class ReadCommand implements IReadCommand
class ReadCommandSerializer implements IVersionedSerializer<ReadCommand>
{
private static final Map<Byte, IVersionedSerializer<ReadCommand>> CMD_SERIALIZER_MAP = new HashMap<Byte, IVersionedSerializer<ReadCommand>>();
static
{
CMD_SERIALIZER_MAP.put(ReadCommand.CMD_TYPE_GET_SLICE_BY_NAMES, new SliceByNamesReadCommandSerializer());
CMD_SERIALIZER_MAP.put(ReadCommand.CMD_TYPE_GET_SLICE, new SliceFromReadCommandSerializer());
}
public void serialize(ReadCommand command, DataOutput dos, int version) throws IOException
{
dos.writeByte(command.commandType);
CMD_SERIALIZER_MAP.get(command.commandType).serialize(command, dos, version);
// For super columns, when talking to an older node, we need to translate the filter used.
// That translation can change the filter type (names -> slice), and so change the command type.
// Hence we need to detect that early on, before we've written the command type.
ReadCommand newCommand = command;
ByteBuffer superColumn = null;
if (version < MessagingService.VERSION_20)
{
CFMetaData metadata = Schema.instance.getCFMetaData(command.table, command.cfName);
if (metadata.cfType == ColumnFamilyType.Super)
{
SuperColumns.SCFilter scFilter = SuperColumns.filterToSC((CompositeType)metadata.comparator, command.filter());
newCommand = ReadCommand.create(command.table, command.key, command.cfName, scFilter.updatedFilter);
newCommand.setDigestQuery(command.isDigestQuery());
superColumn = scFilter.scName;
}
}
dos.writeByte(newCommand.commandType.serializedValue);
switch (command.commandType)
{
case GET_BY_NAMES:
SliceByNamesReadCommand.serializer.serialize(newCommand, superColumn, dos, version);
break;
case GET_SLICES:
SliceFromReadCommand.serializer.serialize(newCommand, superColumn, dos, version);
break;
default:
throw new AssertionError();
}
}
public ReadCommand deserialize(DataInput dis, int version) throws IOException
{
byte msgType = dis.readByte();
return CMD_SERIALIZER_MAP.get(msgType).deserialize(dis, version);
ReadCommand.Type msgType = ReadCommand.Type.fromSerializedValue(dis.readByte());
switch (msgType)
{
case GET_BY_NAMES:
return SliceByNamesReadCommand.serializer.deserialize(dis, version);
case GET_SLICES:
return SliceFromReadCommand.serializer.deserialize(dis, version);
default:
throw new AssertionError();
}
}
public long serializedSize(ReadCommand command, int version)
{
return 1 + CMD_SERIALIZER_MAP.get(command.commandType).serializedSize(command, version);
ReadCommand newCommand = command;
ByteBuffer superColumn = null;
if (version < MessagingService.VERSION_20)
{
CFMetaData metadata = Schema.instance.getCFMetaData(command.table, command.cfName);
if (metadata.cfType == ColumnFamilyType.Super)
{
SuperColumns.SCFilter scFilter = SuperColumns.filterToSC((CompositeType)metadata.comparator, command.filter());
newCommand = ReadCommand.create(command.table, command.key, command.cfName, scFilter.updatedFilter);
newCommand.setDigestQuery(command.isDigestQuery());
superColumn = scFilter.scName;
}
}
switch (command.commandType)
{
case GET_BY_NAMES:
return 1 + SliceByNamesReadCommand.serializer.serializedSize(newCommand, superColumn, version);
case GET_SLICES:
return 1 + SliceFromReadCommand.serializer.serializedSize(newCommand, superColumn, version);
default:
throw new AssertionError();
}
}
}

View File

@ -20,7 +20,6 @@ package org.apache.cassandra.db;
import java.io.*;
import java.nio.ByteBuffer;
import org.apache.cassandra.io.IColumnSerializer;
import org.apache.cassandra.io.IVersionedSerializer;
import org.apache.cassandra.utils.ByteBufferUtil;
@ -94,7 +93,7 @@ class ReadResponseSerializer implements IVersionedSerializer<ReadResponse>
if (!isDigest)
{
// This is coming from a remote host
row = Row.serializer.deserialize(dis, version, IColumnSerializer.Flag.FROM_REMOTE, ArrayBackedSortedColumns.factory());
row = Row.serializer.deserialize(dis, version, ColumnSerializer.Flag.FROM_REMOTE, ArrayBackedSortedColumns.factory());
}
return isDigest ? new ReadResponse(ByteBuffer.wrap(digest)) : new ReadResponse(row);

View File

@ -29,21 +29,16 @@ public class RetriedSliceFromReadCommand extends SliceFromReadCommand
static final Logger logger = LoggerFactory.getLogger(RetriedSliceFromReadCommand.class);
public final int originalCount;
public RetriedSliceFromReadCommand(String table, ByteBuffer key, ColumnParent column_parent, SliceQueryFilter filter, int originalCount)
public RetriedSliceFromReadCommand(String table, ByteBuffer key, String cfName, SliceQueryFilter filter, int originalCount)
{
this(table, key, new QueryPath(column_parent), filter, originalCount);
}
public RetriedSliceFromReadCommand(String table, ByteBuffer key, QueryPath path, SliceQueryFilter filter, int originalCount)
{
super(table, key, path, filter);
super(table, key, cfName, filter);
this.originalCount = originalCount;
}
@Override
public ReadCommand copy()
{
ReadCommand readCommand = new RetriedSliceFromReadCommand(table, key, queryPath, filter, originalCount);
ReadCommand readCommand = new RetriedSliceFromReadCommand(table, key, cfName, filter, originalCount);
readCommand.setDigestQuery(isDigestQuery());
return readCommand;
}

View File

@ -20,7 +20,6 @@ package org.apache.cassandra.db;
import java.io.*;
import org.apache.cassandra.db.filter.IDiskAtomFilter;
import org.apache.cassandra.io.IColumnSerializer;
import org.apache.cassandra.io.IVersionedSerializer;
import org.apache.cassandra.service.StorageService;
import org.apache.cassandra.utils.ByteBufferUtil;
@ -62,7 +61,7 @@ public class Row
ColumnFamily.serializer.serialize(row.cf, dos, version);
}
public Row deserialize(DataInput dis, int version, IColumnSerializer.Flag flag, ISortedColumns.Factory factory) throws IOException
public Row deserialize(DataInput dis, int version, ColumnSerializer.Flag flag, ISortedColumns.Factory factory) throws IOException
{
return new Row(StorageService.getPartitioner().decorateKey(ByteBufferUtil.readWithShortLength(dis)),
ColumnFamily.serializer.deserialize(dis, flag, factory, version));
@ -70,7 +69,7 @@ public class Row
public Row deserialize(DataInput dis, int version) throws IOException
{
return deserialize(dis, version, IColumnSerializer.Flag.LOCAL, TreeMapBackedSortedColumns.factory());
return deserialize(dis, version, ColumnSerializer.Flag.LOCAL, TreeMapBackedSortedColumns.factory());
}
public long serializedSize(Row row, int version)

View File

@ -107,7 +107,7 @@ public class RowIteratorFactory
}
else
{
QueryFilter keyFilter = new QueryFilter(key, filter.path, filter.filter);
QueryFilter keyFilter = new QueryFilter(key, filter.cfName, filter.filter);
returnCF = cfs.filterColumnFamily(cached, keyFilter, gcBefore);
}

View File

@ -29,9 +29,7 @@ import org.apache.commons.lang.StringUtils;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.config.KSMetaData;
import org.apache.cassandra.config.Schema;
import org.apache.cassandra.db.filter.QueryPath;
import org.apache.cassandra.db.marshal.UUIDType;
import org.apache.cassandra.io.IColumnSerializer;
import org.apache.cassandra.io.IVersionedSerializer;
import org.apache.cassandra.io.util.FastByteArrayInputStream;
import org.apache.cassandra.net.MessageOut;
@ -115,8 +113,9 @@ public class RowMutation implements IMutation
ttl = Math.min(ttl, cf.metadata().getGcGraceSeconds());
// serialize the hint with id and version as a composite column name
QueryPath path = new QueryPath(SystemTable.HINTS_CF, null, HintedHandOffManager.comparator.decompose(hintId, MessagingService.current_version));
rm.add(path, ByteBuffer.wrap(mutation.getSerializedBuffer(MessagingService.current_version)), System.currentTimeMillis(), ttl);
ByteBuffer name = HintedHandOffManager.comparator.decompose(hintId, MessagingService.current_version);
ByteBuffer value = ByteBuffer.wrap(mutation.getSerializedBuffer(MessagingService.current_version));
rm.add(SystemTable.HINTS_CF, name, value, System.currentTimeMillis(), ttl);
return rm;
}
@ -156,81 +155,37 @@ public class RowMutation implements IMutation
return modifications.isEmpty();
}
/*
* Specify a column name and a corresponding value for
* the column. Column name is specified as <column family>:column.
* This will result in a ColumnFamily associated with
* <column family> as name and a Column with <column>
* as name. The column can be further broken up
* as super column name : columnname in case of super columns
*
* param @ cf - column name as <column family>:<column>
* param @ value - value associated with the column
* param @ timestamp - timestamp associated with this data.
* param @ timeToLive - ttl for the column, 0 for standard (non expiring) columns
*
* @Deprecated this tends to be low-performance; we're doing two hash lookups,
* one of which instantiates a Pair, and callers tend to instantiate new QP objects
* for each call as well. Use the add(ColumnFamily) overload instead.
*/
public void add(QueryPath path, ByteBuffer value, long timestamp, int timeToLive)
public void add(String cfName, ByteBuffer name, ByteBuffer value, long timestamp, int timeToLive)
{
UUID id = Schema.instance.getId(table, path.columnFamilyName);
ColumnFamily columnFamily = modifications.get(id);
if (columnFamily == null)
{
columnFamily = ColumnFamily.create(table, path.columnFamilyName);
modifications.put(id, columnFamily);
}
columnFamily.addColumn(path, value, timestamp, timeToLive);
addOrGet(cfName).addColumn(name, value, timestamp, timeToLive);
}
public void addCounter(QueryPath path, long value)
public void addCounter(String cfName, ByteBuffer name, long value)
{
UUID id = Schema.instance.getId(table, path.columnFamilyName);
ColumnFamily columnFamily = modifications.get(id);
if (columnFamily == null)
{
columnFamily = ColumnFamily.create(table, path.columnFamilyName);
modifications.put(id, columnFamily);
}
columnFamily.addCounter(path, value);
addOrGet(cfName).addCounter(name, value);
}
public void add(QueryPath path, ByteBuffer value, long timestamp)
public void add(String cfName, ByteBuffer name, ByteBuffer value, long timestamp)
{
add(path, value, timestamp, 0);
add(cfName, name, value, timestamp, 0);
}
public void delete(QueryPath path, long timestamp)
public void delete(String cfName, long timestamp)
{
UUID id = Schema.instance.getId(table, path.columnFamilyName);
int localDeleteTime = (int) (System.currentTimeMillis() / 1000);
addOrGet(cfName).delete(new DeletionInfo(timestamp, localDeleteTime));
}
ColumnFamily columnFamily = modifications.get(id);
if (columnFamily == null)
{
columnFamily = ColumnFamily.create(table, path.columnFamilyName);
modifications.put(id, columnFamily);
}
public void delete(String cfName, ByteBuffer name, long timestamp)
{
int localDeleteTime = (int) (System.currentTimeMillis() / 1000);
addOrGet(cfName).addTombstone(name, localDeleteTime, timestamp);
}
if (path.superColumnName == null && path.columnName == null)
{
columnFamily.delete(new DeletionInfo(timestamp, localDeleteTime));
}
else if (path.columnName == null)
{
SuperColumn sc = new SuperColumn(path.superColumnName, columnFamily.getSubComparator());
sc.delete(new DeletionInfo(timestamp, localDeleteTime));
columnFamily.addColumn(sc);
}
else
{
columnFamily.addTombstone(path, localDeleteTime, timestamp);
}
public void deleteRange(String cfName, ByteBuffer start, ByteBuffer end, long timestamp)
{
int localDeleteTime = (int) (System.currentTimeMillis() / 1000);
addOrGet(cfName).addAtom(new RangeTombstone(start, end, timestamp, localDeleteTime));
}
public void addAll(IMutation m)
@ -314,49 +269,6 @@ public class RowMutation implements IMutation
return buff.append("])").toString();
}
public void addColumnOrSuperColumn(String cfName, ColumnOrSuperColumn cosc)
{
if (cosc.super_column != null)
{
for (org.apache.cassandra.thrift.Column column : cosc.super_column.columns)
{
add(new QueryPath(cfName, cosc.super_column.name, column.name), column.value, column.timestamp, column.ttl);
}
}
else if (cosc.column != null)
{
add(new QueryPath(cfName, null, cosc.column.name), cosc.column.value, cosc.column.timestamp, cosc.column.ttl);
}
else if (cosc.counter_super_column != null)
{
for (org.apache.cassandra.thrift.CounterColumn column : cosc.counter_super_column.columns)
{
addCounter(new QueryPath(cfName, cosc.counter_super_column.name, column.name), column.value);
}
}
else // cosc.counter_column != null
{
addCounter(new QueryPath(cfName, null, cosc.counter_column.name), cosc.counter_column.value);
}
}
public void deleteColumnOrSuperColumn(String cfName, Deletion del)
{
if (del.predicate != null && del.predicate.column_names != null)
{
for(ByteBuffer c : del.predicate.column_names)
{
if (del.super_column == null && Schema.instance.getColumnFamilyType(table, cfName) == ColumnFamilyType.Super)
delete(new QueryPath(cfName, c), del.timestamp);
else
delete(new QueryPath(cfName, del.super_column, c), del.timestamp);
}
}
else
{
delete(new QueryPath(cfName, del.super_column), del.timestamp);
}
}
public static RowMutation fromBytes(byte[] raw, int version) throws IOException
{
@ -396,7 +308,7 @@ public class RowMutation implements IMutation
}
}
public RowMutation deserialize(DataInput dis, int version, IColumnSerializer.Flag flag) throws IOException
public RowMutation deserialize(DataInput dis, int version, ColumnSerializer.Flag flag) throws IOException
{
String table = dis.readUTF();
ByteBuffer key = ByteBufferUtil.readWithShortLength(dis);
@ -417,7 +329,7 @@ public class RowMutation implements IMutation
public RowMutation deserialize(DataInput dis, int version) throws IOException
{
return deserialize(dis, version, IColumnSerializer.Flag.FROM_REMOTE);
return deserialize(dis, version, ColumnSerializer.Flag.FROM_REMOTE);
}
public long serializedSize(RowMutation rm, int version)

View File

@ -21,39 +21,31 @@ import java.io.*;
import java.nio.ByteBuffer;
import java.util.*;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.config.Schema;
import org.apache.cassandra.db.filter.*;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.CompositeType;
import org.apache.cassandra.io.IVersionedSerializer;
import org.apache.cassandra.net.MessagingService;
import org.apache.cassandra.service.StorageService;
import org.apache.cassandra.thrift.ColumnParent;
import org.apache.cassandra.utils.ByteBufferUtil;
public class SliceByNamesReadCommand extends ReadCommand
{
static final SliceByNamesReadCommandSerializer serializer = new SliceByNamesReadCommandSerializer();
public final NamesQueryFilter filter;
public SliceByNamesReadCommand(String table, ByteBuffer key, ColumnParent column_parent, Collection<ByteBuffer> columnNames)
public SliceByNamesReadCommand(String table, ByteBuffer key, String cfName, NamesQueryFilter filter)
{
this(table, key, new QueryPath(column_parent), columnNames);
}
public SliceByNamesReadCommand(String table, ByteBuffer key, QueryPath path, Collection<ByteBuffer> columnNames)
{
super(table, key, path, CMD_TYPE_GET_SLICE_BY_NAMES);
SortedSet s = new TreeSet<ByteBuffer>(getComparator());
s.addAll(columnNames);
this.filter = new NamesQueryFilter(s);
}
public SliceByNamesReadCommand(String table, ByteBuffer key, QueryPath path, NamesQueryFilter filter)
{
super(table, key, path, CMD_TYPE_GET_SLICE_BY_NAMES);
super(table, key, cfName, Type.GET_BY_NAMES);
this.filter = filter;
}
public ReadCommand copy()
{
ReadCommand readCommand= new SliceByNamesReadCommand(table, key, queryPath, filter);
ReadCommand readCommand= new SliceByNamesReadCommand(table, key, cfName, filter);
readCommand.setDigestQuery(isDigestQuery());
return readCommand;
}
@ -61,7 +53,7 @@ public class SliceByNamesReadCommand extends ReadCommand
public Row getRow(Table table) throws IOException
{
DecoratedKey dk = StorageService.getPartitioner().decorateKey(key);
return table.getRow(new QueryFilter(dk, queryPath, filter));
return table.getRow(new QueryFilter(dk, cfName, filter));
}
@Override
@ -70,7 +62,7 @@ public class SliceByNamesReadCommand extends ReadCommand
return "SliceByNamesReadCommand(" +
"table='" + table + '\'' +
", key=" + ByteBufferUtil.bytesToHex(key) +
", columnParent='" + queryPath + '\'' +
", cfName='" + cfName + '\'' +
", filter=" + filter +
')';
}
@ -84,30 +76,86 @@ public class SliceByNamesReadCommand extends ReadCommand
class SliceByNamesReadCommandSerializer implements IVersionedSerializer<ReadCommand>
{
public void serialize(ReadCommand cmd, DataOutput dos, int version) throws IOException
{
serialize(cmd, null, dos, version);
}
public void serialize(ReadCommand cmd, ByteBuffer superColumn, DataOutput dos, int version) throws IOException
{
SliceByNamesReadCommand command = (SliceByNamesReadCommand) cmd;
dos.writeBoolean(command.isDigestQuery());
dos.writeUTF(command.table);
ByteBufferUtil.writeWithShortLength(command.key, dos);
command.queryPath.serialize(dos);
if (version < MessagingService.VERSION_20)
new QueryPath(command.cfName, superColumn).serialize(dos);
else
dos.writeUTF(command.cfName);
NamesQueryFilter.serializer.serialize(command.filter, dos, version);
}
public SliceByNamesReadCommand deserialize(DataInput dis, int version) throws IOException
public ReadCommand deserialize(DataInput dis, int version) throws IOException
{
boolean isDigest = dis.readBoolean();
String table = dis.readUTF();
ByteBuffer key = ByteBufferUtil.readWithShortLength(dis);
QueryPath columnParent = QueryPath.deserialize(dis);
AbstractType<?> comparator = ColumnFamily.getComparatorFor(table, columnParent.columnFamilyName, columnParent.superColumnName);
NamesQueryFilter filter = NamesQueryFilter.serializer.deserialize(dis, version, comparator);
SliceByNamesReadCommand command = new SliceByNamesReadCommand(table, key, columnParent, filter);
String cfName;
ByteBuffer sc = null;
if (version < MessagingService.VERSION_20)
{
QueryPath path = QueryPath.deserialize(dis);
cfName = path.columnFamilyName;
sc = path.superColumnName;
}
else
{
cfName = dis.readUTF();
}
CFMetaData metadata = Schema.instance.getCFMetaData(table, cfName);
ReadCommand command;
if (version < MessagingService.VERSION_20)
{
AbstractType<?> comparator;
if (metadata.cfType == ColumnFamilyType.Super)
{
CompositeType type = (CompositeType)metadata.comparator;
comparator = sc == null ? type.types.get(0) : type.types.get(1);
}
else
{
comparator = metadata.comparator;
}
IDiskAtomFilter filter = NamesQueryFilter.serializer.deserialize(dis, version, comparator);
if (metadata.cfType == ColumnFamilyType.Super)
filter = SuperColumns.fromSCFilter((CompositeType)metadata.comparator, sc, filter);
// Due to SC compat, it's possible we get back a slice filter at this point
if (filter instanceof NamesQueryFilter)
command = new SliceByNamesReadCommand(table, key, cfName, (NamesQueryFilter)filter);
else
command = new SliceFromReadCommand(table, key, cfName, (SliceQueryFilter)filter);
}
else
{
NamesQueryFilter filter = NamesQueryFilter.serializer.deserialize(dis, version, metadata.comparator);
command = new SliceByNamesReadCommand(table, key, cfName, filter);
}
command.setDigestQuery(isDigest);
return command;
}
public long serializedSize(ReadCommand cmd, int version)
{
return serializedSize(cmd, null, version);
}
public long serializedSize(ReadCommand cmd, ByteBuffer superColumn, int version)
{
TypeSizes sizes = TypeSizes.NATIVE;
SliceByNamesReadCommand command = (SliceByNamesReadCommand) cmd;
@ -116,7 +164,16 @@ class SliceByNamesReadCommandSerializer implements IVersionedSerializer<ReadComm
size += sizes.sizeof(command.table);
size += sizes.sizeof((short)keySize) + keySize;
size += command.queryPath.serializedSize(sizes);
if (version < MessagingService.VERSION_20)
{
size += new QueryPath(command.cfName, superColumn).serializedSize(sizes);
}
else
{
size += sizes.sizeof(command.cfName);
}
size += NamesQueryFilter.serializer.serializedSize(command.filter, version);
return size;
}

View File

@ -25,41 +25,37 @@ import java.nio.ByteBuffer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.config.Schema;
import org.apache.cassandra.db.filter.IDiskAtomFilter;
import org.apache.cassandra.db.filter.QueryFilter;
import org.apache.cassandra.db.filter.QueryPath;
import org.apache.cassandra.db.filter.SliceQueryFilter;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.CompositeType;
import org.apache.cassandra.io.IVersionedSerializer;
import org.apache.cassandra.net.MessagingService;
import org.apache.cassandra.service.RepairCallback;
import org.apache.cassandra.service.StorageService;
import org.apache.cassandra.thrift.ColumnParent;
import org.apache.cassandra.utils.ByteBufferUtil;
public class SliceFromReadCommand extends ReadCommand
{
static final Logger logger = LoggerFactory.getLogger(SliceFromReadCommand.class);
static final SliceFromReadCommandSerializer serializer = new SliceFromReadCommandSerializer();
public final SliceQueryFilter filter;
public SliceFromReadCommand(String table, ByteBuffer key, ColumnParent column_parent, ByteBuffer start, ByteBuffer finish, boolean reversed, int count)
public SliceFromReadCommand(String table, ByteBuffer key, String cfName, SliceQueryFilter filter)
{
this(table, key, new QueryPath(column_parent), start, finish, reversed, count);
}
public SliceFromReadCommand(String table, ByteBuffer key, QueryPath path, ByteBuffer start, ByteBuffer finish, boolean reversed, int count)
{
this(table, key, path, new SliceQueryFilter(start, finish, reversed, count));
}
public SliceFromReadCommand(String table, ByteBuffer key, QueryPath path, SliceQueryFilter filter)
{
super(table, key, path, CMD_TYPE_GET_SLICE);
super(table, key, cfName, Type.GET_SLICES);
this.filter = filter;
}
public ReadCommand copy()
{
ReadCommand readCommand = new SliceFromReadCommand(table, key, queryPath, filter);
ReadCommand readCommand = new SliceFromReadCommand(table, key, cfName, filter);
readCommand.setDigestQuery(isDigestQuery());
return readCommand;
}
@ -67,7 +63,7 @@ public class SliceFromReadCommand extends ReadCommand
public Row getRow(Table table)
{
DecoratedKey dk = StorageService.getPartitioner().decorateKey(key);
return table.getRow(new QueryFilter(dk, queryPath, filter));
return table.getRow(new QueryFilter(dk, cfName, filter));
}
@Override
@ -91,7 +87,7 @@ public class SliceFromReadCommand extends ReadCommand
// round we want to ask x column so that x * (l/t) == t, i.e. x = t^2/l.
int retryCount = liveCountInRow == 0 ? count + 1 : ((count * count) / liveCountInRow) + 1;
SliceQueryFilter newFilter = filter.withUpdatedCount(retryCount);
return new RetriedSliceFromReadCommand(table, key, queryPath, newFilter, getOriginalRequestedCount());
return new RetriedSliceFromReadCommand(table, key, cfName, newFilter, getOriginalRequestedCount());
}
return null;
@ -127,7 +123,7 @@ public class SliceFromReadCommand extends ReadCommand
return "SliceFromReadCommand(" +
"table='" + table + '\'' +
", key='" + ByteBufferUtil.bytesToHex(key) + '\'' +
", column_parent='" + queryPath + '\'' +
", cfName='" + cfName + '\'' +
", filter='" + filter + '\'' +
')';
}
@ -136,12 +132,22 @@ public class SliceFromReadCommand extends ReadCommand
class SliceFromReadCommandSerializer implements IVersionedSerializer<ReadCommand>
{
public void serialize(ReadCommand rm, DataOutput dos, int version) throws IOException
{
serialize(rm, null, dos, version);
}
public void serialize(ReadCommand rm, ByteBuffer superColumn, DataOutput dos, int version) throws IOException
{
SliceFromReadCommand realRM = (SliceFromReadCommand)rm;
dos.writeBoolean(realRM.isDigestQuery());
dos.writeUTF(realRM.table);
ByteBufferUtil.writeWithShortLength(realRM.key, dos);
realRM.queryPath.serialize(dos);
if (version < MessagingService.VERSION_20)
new QueryPath(realRM.cfName, superColumn).serialize(dos);
else
dos.writeUTF(realRM.cfName);
SliceQueryFilter.serializer.serialize(realRM.filter, dos, version);
}
@ -150,14 +156,45 @@ class SliceFromReadCommandSerializer implements IVersionedSerializer<ReadCommand
boolean isDigest = dis.readBoolean();
String table = dis.readUTF();
ByteBuffer key = ByteBufferUtil.readWithShortLength(dis);
QueryPath path = QueryPath.deserialize(dis);
SliceQueryFilter filter = SliceQueryFilter.serializer.deserialize(dis, version);
SliceFromReadCommand rm = new SliceFromReadCommand(table, key, path, filter);
rm.setDigestQuery(isDigest);
return rm;
String cfName;
ByteBuffer sc = null;
if (version < MessagingService.VERSION_20)
{
QueryPath path = QueryPath.deserialize(dis);
cfName = path.columnFamilyName;
sc = path.superColumnName;
}
else
{
cfName = dis.readUTF();
}
CFMetaData metadata = Schema.instance.getCFMetaData(table, cfName);
SliceQueryFilter filter;
if (version < MessagingService.VERSION_20)
{
filter = SliceQueryFilter.serializer.deserialize(dis, version);
if (metadata.cfType == ColumnFamilyType.Super)
filter = SuperColumns.fromSCSliceFilter((CompositeType)metadata.comparator, sc, filter);
}
else
{
filter = SliceQueryFilter.serializer.deserialize(dis, version);
}
ReadCommand command = new SliceFromReadCommand(table, key, cfName, filter);
command.setDigestQuery(isDigest);
return command;
}
public long serializedSize(ReadCommand cmd, int version)
{
return serializedSize(cmd, null, version);
}
public long serializedSize(ReadCommand cmd, ByteBuffer superColumn, int version)
{
TypeSizes sizes = TypeSizes.NATIVE;
SliceFromReadCommand command = (SliceFromReadCommand) cmd;
@ -166,7 +203,16 @@ class SliceFromReadCommandSerializer implements IVersionedSerializer<ReadCommand
int size = sizes.sizeof(cmd.isDigestQuery()); // boolean
size += sizes.sizeof(command.table);
size += sizes.sizeof((short) keySize) + keySize;
size += command.queryPath.serializedSize(sizes);
if (version < MessagingService.VERSION_20)
{
size += new QueryPath(command.cfName, superColumn).serializedSize(sizes);
}
else
{
size += sizes.sizeof(command.cfName);
}
size += SliceQueryFilter.serializer.serializedSize(command.filter, version);
return size;
}

View File

@ -51,9 +51,8 @@ public class SliceQueryPager implements Iterator<ColumnFamily>
if (exhausted)
return null;
QueryPath path = new QueryPath(cfs.name);
SliceQueryFilter sliceFilter = new SliceQueryFilter(slices, false, DEFAULT_PAGE_SIZE);
QueryFilter filter = new QueryFilter(key, path, sliceFilter);
QueryFilter filter = new QueryFilter(key, cfs.name, sliceFilter);
ColumnFamily cf = cfs.getColumnFamily(filter);
if (cf == null || sliceFilter.getLiveCount(cf) < DEFAULT_PAGE_SIZE)
{
@ -61,8 +60,8 @@ public class SliceQueryPager implements Iterator<ColumnFamily>
}
else
{
Iterator<IColumn> iter = cf.getReverseSortedColumns().iterator();
IColumn lastColumn = iter.next();
Iterator<Column> iter = cf.getReverseSortedColumns().iterator();
Column lastColumn = iter.next();
while (lastColumn.isMarkedForDelete())
lastColumn = iter.next();

View File

@ -1,432 +0,0 @@
/*
* 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.DataOutput;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.util.Collection;
import java.util.Comparator;
import com.google.common.base.Objects;
import com.google.common.collect.Iterables;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.MarshalException;
import org.apache.cassandra.io.IColumnSerializer;
import org.apache.cassandra.io.util.ColumnSortedMap;
import org.apache.cassandra.io.util.DataOutputBuffer;
import org.apache.cassandra.net.MessagingService;
import org.apache.cassandra.utils.Allocator;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.HeapAllocator;
import org.cliffc.high_scale_lib.NonBlockingHashMap;
public class SuperColumn extends AbstractColumnContainer implements IColumn
{
private static final NonBlockingHashMap<Comparator, SuperColumnSerializer> serializers = new NonBlockingHashMap<Comparator, SuperColumnSerializer>();
public static SuperColumnSerializer serializer(AbstractType<?> comparator)
{
SuperColumnSerializer serializer = serializers.get(comparator);
if (serializer == null)
{
serializer = new SuperColumnSerializer(comparator);
serializers.put(comparator, serializer);
}
return serializer;
}
public static OnDiskAtom.Serializer onDiskSerializer(AbstractType<?> comparator)
{
return new OnDiskAtom.Serializer(serializer(comparator));
}
private final ByteBuffer name;
public SuperColumn(ByteBuffer name, AbstractType<?> comparator)
{
this(name, AtomicSortedColumns.factory().create(comparator, false));
}
SuperColumn(ByteBuffer name, ISortedColumns columns)
{
super(columns);
assert name != null;
assert name.remaining() <= IColumn.MAX_NAME_LENGTH;
this.name = name;
}
public SuperColumn cloneMeShallow()
{
SuperColumn sc = new SuperColumn(name, getComparator());
sc.delete(this);
return sc;
}
public IColumn cloneMe()
{
SuperColumn sc = new SuperColumn(name, columns.cloneMe());
sc.delete(this);
return sc;
}
public ByteBuffer name()
{
return name;
}
public Collection<IColumn> getSubColumns()
{
return getSortedColumns();
}
public IColumn getSubColumn(ByteBuffer columnName)
{
IColumn column = columns.getColumn(columnName);
assert column == null || column instanceof Column;
return column;
}
/**
* This calculates the exact size of the sub columns on the fly
*/
public int dataSize()
{
int size = TypeSizes.NATIVE.sizeof(getMarkedForDeleteAt());
for (IColumn subColumn : getSubColumns())
size += subColumn.dataSize();
return size;
}
/**
* This returns the size of the super-column when serialized.
* @see org.apache.cassandra.db.IColumn#serializedSize(TypeSizes)
*/
public int serializedSize(TypeSizes typeSizes)
{
/*
* We need to keep the way we are calculating the column size in sync with the
* way we are calculating the size for the column family serializer.
*
* 2 bytes for name size
* n bytes for the name
* 4 bytes for getLocalDeletionTime
* 8 bytes for getMarkedForDeleteAt
* 4 bytes for the subcolumns size
* size(constantSize) of subcolumns.
*/
int nameSize = name.remaining();
int subColumnsSize = 0;
for (IColumn subColumn : getSubColumns())
subColumnsSize += subColumn.serializedSize(typeSizes);
int size = typeSizes.sizeof((short) nameSize) + nameSize
+ typeSizes.sizeof(getLocalDeletionTime())
+ typeSizes.sizeof(getMarkedForDeleteAt())
+ typeSizes.sizeof(subColumnsSize) + subColumnsSize;
return size;
}
public long serializedSizeForSSTable()
{
return serializedSize(TypeSizes.NATIVE);
}
public long timestamp()
{
throw new UnsupportedOperationException("This operation is not supported for Super Columns.");
}
public long minTimestamp()
{
long minTimestamp = getMarkedForDeleteAt();
for (IColumn subColumn : getSubColumns())
minTimestamp = Math.min(minTimestamp, subColumn.minTimestamp());
return minTimestamp;
}
public long maxTimestamp()
{
long maxTimestamp = getMarkedForDeleteAt();
for (IColumn subColumn : getSubColumns())
maxTimestamp = Math.max(maxTimestamp, subColumn.maxTimestamp());
return maxTimestamp;
}
public long mostRecentLiveChangeAt()
{
long max = Long.MIN_VALUE;
for (IColumn column : getSubColumns())
{
if (!column.isMarkedForDelete() && column.timestamp() > max)
{
max = column.timestamp();
}
}
return max;
}
public long getMarkedForDeleteAt()
{
return deletionInfo().getTopLevelDeletion().markedForDeleteAt;
}
public int getLocalDeletionTime()
{
return deletionInfo().getTopLevelDeletion().localDeletionTime;
}
public long mostRecentNonGCableChangeAt(int gcbefore)
{
long max = Long.MIN_VALUE;
for (IColumn column : getSubColumns())
{
if (column.getLocalDeletionTime() >= gcbefore && column.timestamp() > max)
{
max = column.timestamp();
}
}
return max;
}
public ByteBuffer value()
{
throw new UnsupportedOperationException("This operation is not supported for Super Columns.");
}
@Override
public void addColumn(IColumn column, Allocator allocator)
{
assert column instanceof Column : "A super column can only contain simple columns";
super.addColumn(column, allocator);
}
/*
* Go through each sub column if it exists then as it to resolve itself
* if the column does not exist then create it.
*/
void putColumn(SuperColumn column, Allocator allocator)
{
for (IColumn subColumn : column.getSubColumns())
{
addColumn(subColumn, allocator);
}
delete(column);
}
public IColumn diff(IColumn columnNew)
{
IColumn columnDiff = new SuperColumn(columnNew.name(), ((SuperColumn)columnNew).getComparator());
((SuperColumn)columnDiff).delete(((SuperColumn)columnNew).deletionInfo());
// (don't need to worry about columnNew containing subColumns that are shadowed by
// the delete tombstone, since columnNew was generated by CF.resolve, which
// takes care of those for us.)
for (IColumn subColumn : columnNew.getSubColumns())
{
IColumn columnInternal = columns.getColumn(subColumn.name());
if(columnInternal == null )
{
columnDiff.addColumn(subColumn);
}
else
{
IColumn subColumnDiff = columnInternal.diff(subColumn);
if(subColumnDiff != null)
{
columnDiff.addColumn(subColumnDiff);
}
}
}
if (!columnDiff.getSubColumns().isEmpty() || columnNew.isMarkedForDelete())
return columnDiff;
else
return null;
}
public void updateDigest(MessageDigest digest)
{
assert name != null;
digest.update(name.duplicate());
DataOutputBuffer buffer = new DataOutputBuffer();
try
{
buffer.writeLong(getMarkedForDeleteAt());
}
catch (IOException e)
{
throw new RuntimeException(e);
}
digest.update(buffer.getData(), 0, buffer.getLength());
for (IColumn column : getSubColumns())
{
column.updateDigest(digest);
}
}
public String getString(AbstractType<?> comparator)
{
StringBuilder sb = new StringBuilder();
sb.append("SuperColumn(");
sb.append(comparator.getString(name));
if (isMarkedForDelete()) {
sb.append(" -delete at ").append(getMarkedForDeleteAt()).append("-");
}
sb.append(" [");
sb.append(getComparator().getColumnsString(getSubColumns()));
sb.append("])");
return sb.toString();
}
public boolean isLive()
{
return mostRecentLiveChangeAt() > getMarkedForDeleteAt();
}
public IColumn localCopy(ColumnFamilyStore cfs)
{
return localCopy(cfs, HeapAllocator.instance);
}
public IColumn localCopy(ColumnFamilyStore cfs, Allocator allocator)
{
// we don't try to intern supercolumn names, because if we're using Cassandra correctly it's almost
// certainly just going to pollute our interning map with unique, dynamic values
SuperColumn sc = new SuperColumn(allocator.clone(name), this.getComparator());
sc.delete(this);
for(IColumn c : columns)
{
sc.addColumn(c.localCopy(cfs, allocator));
}
return sc;
}
public IColumn reconcile(IColumn c)
{
return reconcile(null, null);
}
public IColumn reconcile(IColumn c, Allocator allocator)
{
throw new UnsupportedOperationException("This operation is unsupported on super columns.");
}
public int serializationFlags()
{
throw new UnsupportedOperationException("Super columns don't have a serialization mask");
}
public void validateFields(CFMetaData metadata) throws MarshalException
{
metadata.comparator.validate(name());
for (IColumn column : getSubColumns())
{
column.validateFields(metadata);
}
}
@Override
public boolean equals(Object o)
{
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
SuperColumn sc = (SuperColumn)o;
if (!name.equals(sc.name))
return false;
if (getMarkedForDeleteAt() != sc.getMarkedForDeleteAt())
return false;
if (getLocalDeletionTime() != sc.getLocalDeletionTime())
return false;
return Iterables.elementsEqual(columns, sc.columns);
}
@Override
public int hashCode()
{
return Objects.hashCode(name, getMarkedForDeleteAt(), getLocalDeletionTime(), columns);
}
}
class SuperColumnSerializer implements IColumnSerializer
{
private final AbstractType<?> comparator;
public SuperColumnSerializer(AbstractType<?> comparator)
{
this.comparator = comparator;
}
public AbstractType<?> getComparator()
{
return comparator;
}
public void serialize(IColumn column, DataOutput dos) throws IOException
{
SuperColumn superColumn = (SuperColumn)column;
ByteBufferUtil.writeWithShortLength(superColumn.name(), dos);
DeletionInfo.serializer().serialize(superColumn.deletionInfo(), dos, MessagingService.VERSION_10);
Collection<IColumn> columns = superColumn.getSubColumns();
dos.writeInt(columns.size());
for (IColumn subColumn : columns)
{
Column.serializer().serialize(subColumn, dos);
}
}
public IColumn deserialize(DataInput dis) throws IOException
{
return deserialize(dis, IColumnSerializer.Flag.LOCAL);
}
public IColumn deserialize(DataInput dis, IColumnSerializer.Flag flag) throws IOException
{
return deserialize(dis, flag, (int)(System.currentTimeMillis() / 1000));
}
public IColumn deserialize(DataInput dis, IColumnSerializer.Flag flag, int expireBefore) throws IOException
{
ByteBuffer name = ByteBufferUtil.readWithShortLength(dis);
DeletionInfo delInfo = DeletionInfo.serializer().deserialize(dis, MessagingService.VERSION_10, comparator);
/* read the number of columns */
int size = dis.readInt();
ColumnSerializer serializer = Column.serializer();
ColumnSortedMap preSortedMap = new ColumnSortedMap(comparator, serializer, dis, size, flag, expireBefore);
SuperColumn superColumn = new SuperColumn(name, AtomicSortedColumns.factory().fromSorted(preSortedMap, false));
superColumn.delete(delInfo);
return superColumn;
}
public long serializedSize(IColumn object, TypeSizes typeSizes)
{
return object.serializedSize(typeSizes);
}
}

View File

@ -0,0 +1,442 @@
/*
* 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.DataOutput;
import java.io.IOError;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.filter.*;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.CompositeType;
import org.apache.cassandra.io.sstable.Descriptor;
import org.apache.cassandra.net.MessagingService;
import org.apache.cassandra.utils.ByteBufferUtil;
public class SuperColumns
{
public static Iterator<OnDiskAtom> onDiskIterator(DataInput dis, int superColumnCount, ColumnSerializer.Flag flag, int expireBefore)
{
return new SCIterator(dis, superColumnCount, flag, expireBefore);
}
public static void serializeSuperColumnFamily(ColumnFamily scf, DataOutput dos, int version) throws IOException
{
/*
* There is 2 complications:
* 1) We need to know the number of super columns in the column
* family to write in the header (so we do a first pass to group
* columns before serializing).
* 2) For deletion infos, we need to figure out which are top-level
* deletions and which are super columns deletions (i.e. the
* subcolumns range deletions).
*/
DeletionInfo delInfo = scf.deletionInfo();
Map<ByteBuffer, List<Column>> scMap = groupSuperColumns(scf);
// Actually Serialize
DeletionInfo.serializer().serialize(new DeletionInfo(delInfo.getTopLevelDeletion()), dos, version);
dos.writeInt(scMap.size());
for (Map.Entry<ByteBuffer, List<Column>> entry : scMap.entrySet())
{
ByteBufferUtil.writeWithShortLength(entry.getKey(), dos);
List<DeletionTime> delTimes = delInfo.rangeCovering(entry.getKey());
assert delTimes.size() <= 1; // We're supposed to have either no deletion, or a full SC deletion.
DeletionInfo scDelInfo = delTimes.isEmpty() ? DeletionInfo.LIVE : new DeletionInfo(delTimes.get(0));
DeletionInfo.serializer().serialize(scDelInfo, dos, MessagingService.VERSION_10);
dos.writeInt(entry.getValue().size());
for (Column subColumn : entry.getValue())
Column.serializer().serialize(subColumn, dos);
}
}
private static Map<ByteBuffer, List<Column>> groupSuperColumns(ColumnFamily scf)
{
CompositeType type = (CompositeType)scf.getComparator();
// The order of insertion matters!
Map<ByteBuffer, List<Column>> scMap = new LinkedHashMap<ByteBuffer, List<Column>>();
ByteBuffer scName = null;
List<Column> subColumns = null;
for (Column column : scf)
{
ByteBuffer newScName = scName(column.name());
ByteBuffer newSubName = subName(column.name());
if (scName == null || type.types.get(0).compare(scName, newScName) != 0)
{
// new super column
scName = newScName;
subColumns = new ArrayList<Column>();
scMap.put(scName, subColumns);
}
subColumns.add(((Column)column).withUpdatedName(newSubName));
}
return scMap;
}
public static void deserializerSuperColumnFamily(DataInput dis, ColumnFamily cf, ColumnSerializer.Flag flag, int expireBefore, int version) throws IOException
{
// Note that there was no way to insert a range tombstone in a SCF in 1.2
cf.delete(DeletionInfo.serializer().deserialize(dis, version, cf.getComparator()));
assert !cf.deletionInfo().rangeIterator().hasNext();
Iterator<OnDiskAtom> iter = onDiskIterator(dis, dis.readInt(), flag, expireBefore);
while (iter.hasNext())
cf.addAtom(iter.next());
}
public static long serializedSize(ColumnFamily scf, TypeSizes typeSizes, int version)
{
Map<ByteBuffer, List<Column>> scMap = groupSuperColumns(scf);
DeletionInfo delInfo = scf.deletionInfo();
// Actually Serialize
long size = DeletionInfo.serializer().serializedSize(new DeletionInfo(delInfo.getTopLevelDeletion()), version);
for (Map.Entry<ByteBuffer, List<Column>> entry : scMap.entrySet())
{
int nameSize = entry.getKey().remaining();
size += typeSizes.sizeof((short) nameSize) + nameSize;
List<DeletionTime> delTimes = delInfo.rangeCovering(entry.getKey());
assert delTimes.size() <= 1; // We're supposed to have either no deletion, or a full SC deletion.
DeletionInfo scDelInfo = delTimes.isEmpty() ? DeletionInfo.LIVE : new DeletionInfo(delTimes.get(0));
size += DeletionInfo.serializer().serializedSize(scDelInfo, MessagingService.VERSION_10);
size += typeSizes.sizeof(entry.getValue().size());
for (Column subColumn : entry.getValue())
size += Column.serializer().serializedSize(subColumn, typeSizes);
}
return size;
}
private static class SCIterator implements Iterator<OnDiskAtom>
{
private final DataInput dis;
private final int scCount;
private final ColumnSerializer.Flag flag;
private final int expireBefore;
private int read;
private ByteBuffer scName;
private Iterator<Column> subColumnsIterator;
private SCIterator(DataInput dis, int superColumnCount, ColumnSerializer.Flag flag, int expireBefore)
{
this.dis = dis;
this.scCount = superColumnCount;
this.flag = flag;
this.expireBefore = expireBefore;
}
public boolean hasNext()
{
return (subColumnsIterator != null && subColumnsIterator.hasNext()) || read < scCount;
}
public OnDiskAtom next()
{
try
{
if (subColumnsIterator != null && subColumnsIterator.hasNext())
{
Column c = subColumnsIterator.next();
return c.withUpdatedName(CompositeType.build(scName, c.name()));
}
// Read one more super column
++read;
scName = ByteBufferUtil.readWithShortLength(dis);
DeletionInfo delInfo = DeletionInfo.serializer().deserialize(dis, MessagingService.VERSION_10, null);
assert !delInfo.rangeIterator().hasNext(); // We assume no range tombstone (there was no way to insert some in a SCF in 1.2)
/* read the number of columns */
int size = dis.readInt();
List<Column> subColumns = new ArrayList<Column>(size);
for (int i = 0; i < size; ++i)
subColumns.add(Column.serializer().deserialize(dis, flag, expireBefore));
subColumnsIterator = subColumns.iterator();
// If the SC was deleted, return that first, otherwise return the first subcolumn
DeletionTime dtime = delInfo.getTopLevelDeletion();
if (!dtime.equals(DeletionTime.LIVE))
return new RangeTombstone(startOf(scName), endOf(scName), dtime);
return next();
}
catch (IOException e)
{
throw new IOError(e);
}
}
public void remove()
{
throw new UnsupportedOperationException();
}
}
public static AbstractType<?> getComparatorFor(CFMetaData metadata, ByteBuffer superColumn)
{
return getComparatorFor(metadata, superColumn != null);
}
public static AbstractType<?> getComparatorFor(CFMetaData metadata, boolean subColumn)
{
return metadata.isSuper()
? ((CompositeType)metadata.comparator).types.get(subColumn ? 1 : 0)
: metadata.comparator;
}
// Extract the first component of a columnName, i.e. the super column name
public static ByteBuffer scName(ByteBuffer columnName)
{
return CompositeType.extractComponent(columnName, 0);
}
// Extract the 2nd component of a columnName, i.e. the sub-column name
public static ByteBuffer subName(ByteBuffer columnName)
{
return CompositeType.extractComponent(columnName, 1);
}
// We don't use CompositeType.Builder mostly because we want to avoid having to provide the comparator.
public static ByteBuffer startOf(ByteBuffer scName)
{
int length = scName.remaining();
ByteBuffer bb = ByteBuffer.allocate(2 + length + 1);
bb.put((byte) ((length >> 8) & 0xFF));
bb.put((byte) (length & 0xFF));
bb.put(scName.duplicate());
bb.put((byte) 0);
bb.flip();
return bb;
}
public static ByteBuffer endOf(ByteBuffer scName)
{
ByteBuffer bb = startOf(scName);
bb.put(bb.remaining() - 1, (byte)1);
return bb;
}
public static SCFilter filterToSC(CompositeType type, IDiskAtomFilter filter)
{
if (filter instanceof NamesQueryFilter)
return namesFilterToSC(type, (NamesQueryFilter)filter);
else
return sliceFilterToSC(type, (SliceQueryFilter)filter);
}
public static SCFilter namesFilterToSC(CompositeType type, NamesQueryFilter filter)
{
ByteBuffer scName = null;
SortedSet<ByteBuffer> newColumns = new TreeSet<ByteBuffer>(filter.columns.comparator());
for (ByteBuffer name : filter.columns)
{
ByteBuffer newScName = scName(name);
if (scName == null)
{
scName = newScName;
}
else if (type.types.get(0).compare(scName, newScName) != 0)
{
// If we're selecting column across multiple SC, it's not something we can translate for an old node
throw new RuntimeException("Cannot convert filter to old super column format. Update all nodes to Cassandra 2.0 first.");
}
newColumns.add(subName(name));
}
return new SCFilter(scName, new NamesQueryFilter(newColumns));
}
public static SCFilter sliceFilterToSC(CompositeType type, SliceQueryFilter filter)
{
/*
* There is 3 main cases that we can translate back into super column
* queries:
* 1) We have only one slice where the first component of start and
* finish is the same, we translate as a slice query on one SC.
* 2) We have only one slice, neither the start and finish have a 2nd
* component, and end has the 'end of component' set, we translate
* as a slice of SCs.
* 3) Each slice has the same first component for start and finish, no
* 2nd component and each finish has the 'end of component' set, we
* translate as a names query of SCs (the filter must then not be reversed).
* Otherwise, we can't do much.
*/
boolean reversed = filter.reversed;
if (filter.slices.length == 1)
{
ByteBuffer start = filter.slices[0].start;
ByteBuffer finish = filter.slices[0].start;
if (filter.compositesToGroup == 1)
{
// Note: all the resulting filter must have compositeToGroup == 0 because this
// make no sense for super column on the destination node otherwise
if (start.remaining() == 0)
{
if (finish.remaining() == 0)
// An 'IdentityFilter', keep as is (except for the compositeToGroup)
return new SCFilter(null, new SliceQueryFilter(filter.start(), filter.finish(), reversed, filter.count));
if (subName(finish) == null
&& ((!reversed && !firstEndOfComponent(finish)) || (reversed && firstEndOfComponent(finish))))
return new SCFilter(null, new SliceQueryFilter(ByteBufferUtil.EMPTY_BYTE_BUFFER, scName(finish), reversed, filter.count));
}
else if (finish.remaining() == 0)
{
if (subName(start) == null
&& ((!reversed && firstEndOfComponent(start)) || (reversed && !firstEndOfComponent(start))))
return new SCFilter(null, new SliceQueryFilter(scName(start), ByteBufferUtil.EMPTY_BYTE_BUFFER, reversed, filter.count));
}
else if (subName(start) == null && subName(finish) == null
&& (( reversed && !firstEndOfComponent(start) && firstEndOfComponent(finish))
|| (!reversed && firstEndOfComponent(start) && !firstEndOfComponent(finish))))
{
// A slice of supercolumns
return new SCFilter(null, new SliceQueryFilter(scName(start), scName(finish), reversed, filter.count));
}
}
else if (filter.compositesToGroup == 0 && type.types.get(0).compare(scName(start), scName(finish)) == 0)
{
// A slice of subcolumns
return new SCFilter(scName(start), filter.withUpdatedSlice(subName(start), subName(finish)));
}
}
else if (!reversed)
{
SortedSet<ByteBuffer> columns = new TreeSet<ByteBuffer>(type.types.get(0));
for (int i = 0; i < filter.slices.length; ++i)
{
ByteBuffer start = filter.slices[i].start;
ByteBuffer finish = filter.slices[i].finish;
if (subName(start) != null || subName(finish) != null
|| type.types.get(0).compare(scName(start), scName(finish)) != 0
|| firstEndOfComponent(start) || !firstEndOfComponent(finish))
throw new RuntimeException("Cannot convert filter to old super column format. Update all nodes to Cassandra 2.0 first.");
columns.add(scName(start));
}
return new SCFilter(null, new NamesQueryFilter(columns));
}
throw new RuntimeException("Cannot convert filter to old super column format. Update all nodes to Cassandra 2.0 first.");
}
public static IDiskAtomFilter fromSCFilter(CompositeType type, ByteBuffer scName, IDiskAtomFilter filter)
{
if (filter instanceof NamesQueryFilter)
return fromSCNamesFilter(type, scName, (NamesQueryFilter)filter);
else
return fromSCSliceFilter(type, scName, (SliceQueryFilter)filter);
}
public static IDiskAtomFilter fromSCNamesFilter(CompositeType type, ByteBuffer scName, NamesQueryFilter filter)
{
if (scName == null)
{
ColumnSlice[] slices = new ColumnSlice[filter.columns.size()];
int i = 0;
for (ByteBuffer bb : filter.columns)
{
CompositeType.Builder builder = type.builder().add(bb);
slices[i++] = new ColumnSlice(builder.build(), builder.buildAsEndOfRange());
}
return new SliceQueryFilter(slices, false, slices.length, 1, 1);
}
else
{
SortedSet<ByteBuffer> newColumns = new TreeSet<ByteBuffer>(type);
for (ByteBuffer c : filter.columns)
newColumns.add(CompositeType.build(scName, c));
return filter.withUpdatedColumns(newColumns);
}
}
public static SliceQueryFilter fromSCSliceFilter(CompositeType type, ByteBuffer scName, SliceQueryFilter filter)
{
assert filter.slices.length == 1;
if (scName == null)
{
ByteBuffer start = filter.start().remaining() == 0
? filter.start()
: (filter.reversed ? type.builder().add(filter.start()).buildAsEndOfRange()
: type.builder().add(filter.start()).build());
ByteBuffer finish = filter.finish().remaining() == 0
? filter.finish()
: (filter.reversed ? type.builder().add(filter.finish()).build()
: type.builder().add(filter.finish()).buildAsEndOfRange());
return new SliceQueryFilter(start, finish, filter.reversed, filter.count, 1);
}
else
{
CompositeType.Builder builder = type.builder().add(scName);
ByteBuffer start = filter.start().remaining() == 0
? filter.reversed ? builder.buildAsEndOfRange() : builder.build()
: builder.copy().add(filter.start()).build();
ByteBuffer end = filter.finish().remaining() == 0
? filter.reversed ? builder.build() : builder.buildAsEndOfRange()
: builder.add(filter.finish()).build();
return new SliceQueryFilter(start, end, filter.reversed, filter.count);
}
}
private static boolean firstEndOfComponent(ByteBuffer bb)
{
bb = bb.duplicate();
int length = (bb.get() & 0xFF) << 8;
length |= (bb.get() & 0xFF);
return bb.get(length + 2) == 1;
}
public static class SCFilter
{
public final ByteBuffer scName;
public final IDiskAtomFilter updatedFilter;
public SCFilter(ByteBuffer scName, IDiskAtomFilter updatedFilter)
{
this.scName = scName;
this.updatedFilter = updatedFilter;
}
}
}

View File

@ -43,7 +43,6 @@ import org.apache.cassandra.cql3.QueryProcessor;
import org.apache.cassandra.cql3.UntypedResultSet;
import org.apache.cassandra.db.columniterator.IdentityQueryFilter;
import org.apache.cassandra.db.filter.QueryFilter;
import org.apache.cassandra.db.filter.QueryPath;
import org.apache.cassandra.db.marshal.AsciiType;
import org.apache.cassandra.db.marshal.BytesType;
import org.apache.cassandra.db.marshal.UTF8Type;
@ -156,9 +155,9 @@ public class SystemTable
SortedSet<ByteBuffer> cols = new TreeSet<ByteBuffer>(BytesType.instance);
cols.add(ByteBufferUtil.bytes("ClusterName"));
cols.add(ByteBufferUtil.bytes("Token"));
QueryFilter filter = QueryFilter.getNamesFilter(decorate(ByteBufferUtil.bytes("L")), new QueryPath(OLD_STATUS_CF), cols);
QueryFilter filter = QueryFilter.getNamesFilter(decorate(ByteBufferUtil.bytes("L")), OLD_STATUS_CF, cols);
ColumnFamily oldCf = oldStatusCfs.getColumnFamily(filter);
Iterator<IColumn> oldColumns = oldCf.columns.iterator();
Iterator<Column> oldColumns = oldCf.columns.iterator();
String clusterName = null;
try
@ -514,7 +513,7 @@ public class SystemTable
{
ColumnFamilyStore cfs = Table.open(Table.SYSTEM_KS).getColumnFamilyStore(INDEX_CF);
QueryFilter filter = QueryFilter.getNamesFilter(decorate(ByteBufferUtil.bytes(table)),
new QueryPath(INDEX_CF),
INDEX_CF,
ByteBufferUtil.bytes(indexName));
return ColumnFamilyStore.removeDeleted(cfs.getColumnFamily(filter), Integer.MAX_VALUE) != null;
}
@ -532,7 +531,7 @@ public class SystemTable
public static void setIndexRemoved(String table, String indexName)
{
RowMutation rm = new RowMutation(Table.SYSTEM_KS, ByteBufferUtil.bytes(table));
rm.delete(new QueryPath(INDEX_CF, null, ByteBufferUtil.bytes(indexName)), FBUtilities.timestampMicros());
rm.delete(INDEX_CF, ByteBufferUtil.bytes(indexName), FBUtilities.timestampMicros());
rm.apply();
forceBlockingFlush(INDEX_CF);
}
@ -573,7 +572,7 @@ public class SystemTable
// Get the last CounterId (since CounterId are timeuuid is thus ordered from the older to the newer one)
QueryFilter filter = QueryFilter.getSliceFilter(decorate(ALL_LOCAL_NODE_ID_KEY),
new QueryPath(COUNTER_ID_CF),
COUNTER_ID_CF,
ByteBufferUtil.EMPTY_BYTE_BUFFER,
ByteBufferUtil.EMPTY_BYTE_BUFFER,
true,
@ -611,11 +610,11 @@ public class SystemTable
List<CounterId.CounterIdRecord> l = new ArrayList<CounterId.CounterIdRecord>();
Table table = Table.open(Table.SYSTEM_KS);
QueryFilter filter = QueryFilter.getIdentityFilter(decorate(ALL_LOCAL_NODE_ID_KEY), new QueryPath(COUNTER_ID_CF));
QueryFilter filter = QueryFilter.getIdentityFilter(decorate(ALL_LOCAL_NODE_ID_KEY), COUNTER_ID_CF);
ColumnFamily cf = table.getColumnFamilyStore(COUNTER_ID_CF).getColumnFamily(filter);
CounterId previous = null;
for (IColumn c : cf)
for (Column c : cf)
{
if (previous != null)
l.add(new CounterId.CounterIdRecord(previous, c.timestamp()));
@ -655,8 +654,7 @@ public class SystemTable
{
Token minToken = StorageService.getPartitioner().getMinimumToken();
return schemaCFS(schemaCfName).getRangeSlice(null,
new Range<RowPosition>(minToken.minKeyBound(),
return schemaCFS(schemaCfName).getRangeSlice(new Range<RowPosition>(minToken.minKeyBound(),
minToken.maxKeyBound()),
Integer.MAX_VALUE,
new IdentityQueryFilter(),
@ -713,7 +711,7 @@ public class SystemTable
DecoratedKey key = StorageService.getPartitioner().decorateKey(getSchemaKSKey(ksName));
ColumnFamilyStore schemaCFS = SystemTable.schemaCFS(SCHEMA_KEYSPACES_CF);
ColumnFamily result = schemaCFS.getColumnFamily(QueryFilter.getIdentityFilter(key, new QueryPath(SCHEMA_KEYSPACES_CF)));
ColumnFamily result = schemaCFS.getColumnFamily(QueryFilter.getIdentityFilter(key, SCHEMA_KEYSPACES_CF));
return new Row(key, result);
}
@ -724,7 +722,6 @@ public class SystemTable
ColumnFamilyStore schemaCFS = SystemTable.schemaCFS(SCHEMA_COLUMNFAMILIES_CF);
ColumnFamily result = schemaCFS.getColumnFamily(key,
new QueryPath(SCHEMA_COLUMNFAMILIES_CF),
DefsTable.searchComposite(cfName, true),
DefsTable.searchComposite(cfName, false),
false,

View File

@ -425,7 +425,7 @@ public class Table
{
ColumnFamily cf = pager.next();
ColumnFamily cf2 = cf.cloneMeShallow();
for (IColumn column : cf)
for (Column column : cf)
{
if (cfs.indexManager.indexes(column.name(), indexes))
cf2.addColumn(column);

View File

@ -33,7 +33,7 @@ import org.apache.cassandra.utils.Allocator;
public class ThreadSafeSortedColumns extends AbstractThreadUnsafeSortedColumns implements ISortedColumns
{
private final ConcurrentSkipListMap<ByteBuffer, IColumn> map;
private final ConcurrentSkipListMap<ByteBuffer, Column> map;
public static final ISortedColumns.Factory factory = new Factory()
{
@ -42,7 +42,7 @@ public class ThreadSafeSortedColumns extends AbstractThreadUnsafeSortedColumns i
return new ThreadSafeSortedColumns(comparator);
}
public ISortedColumns fromSorted(SortedMap<ByteBuffer, IColumn> sortedMap, boolean insertReversed)
public ISortedColumns fromSorted(SortedMap<ByteBuffer, Column> sortedMap, boolean insertReversed)
{
return new ThreadSafeSortedColumns(sortedMap);
}
@ -60,12 +60,12 @@ public class ThreadSafeSortedColumns extends AbstractThreadUnsafeSortedColumns i
private ThreadSafeSortedColumns(AbstractType<?> comparator)
{
this.map = new ConcurrentSkipListMap<ByteBuffer, IColumn>(comparator);
this.map = new ConcurrentSkipListMap<ByteBuffer, Column>(comparator);
}
private ThreadSafeSortedColumns(SortedMap<ByteBuffer, IColumn> columns)
private ThreadSafeSortedColumns(SortedMap<ByteBuffer, Column> columns)
{
this.map = new ConcurrentSkipListMap<ByteBuffer, IColumn>(columns);
this.map = new ConcurrentSkipListMap<ByteBuffer, Column>(columns);
}
public ISortedColumns.Factory getFactory()
@ -87,59 +87,49 @@ public class ThreadSafeSortedColumns extends AbstractThreadUnsafeSortedColumns i
* If we find an old column that has the same name
* the ask it to resolve itself else add the new column
*/
public void addColumn(IColumn column, Allocator allocator)
public void addColumn(Column column, Allocator allocator)
{
addColumnInternal(column, allocator);
}
private long addColumnInternal(IColumn column, Allocator allocator)
private long addColumnInternal(Column column, Allocator allocator)
{
ByteBuffer name = column.name();
while (true)
{
IColumn oldColumn = map.putIfAbsent(name, column);
Column oldColumn = map.putIfAbsent(name, column);
if (oldColumn == null)
return column.dataSize();
if (oldColumn instanceof SuperColumn)
{
assert column instanceof SuperColumn;
long previousSize = oldColumn.dataSize();
((SuperColumn) oldColumn).putColumn((SuperColumn)column, allocator);
return oldColumn.dataSize() - previousSize;
}
else
{
// calculate reconciled col from old (existing) col and new col
IColumn reconciledColumn = column.reconcile(oldColumn, allocator);
if (map.replace(name, oldColumn, reconciledColumn))
return reconciledColumn.dataSize() - oldColumn.dataSize();
// calculate reconciled col from old (existing) col and new col
Column reconciledColumn = column.reconcile(oldColumn, allocator);
if (map.replace(name, oldColumn, reconciledColumn))
return reconciledColumn.dataSize() - oldColumn.dataSize();
// We failed to replace column due to a concurrent update or a concurrent removal. Keep trying.
// (Currently, concurrent removal should not happen (only updates), but let us support that anyway.)
}
// We failed to replace column due to a concurrent update or a concurrent removal. Keep trying.
// (Currently, concurrent removal should not happen (only updates), but let us support that anyway.)
}
}
/**
* We need to go through each column in the column container and resolve it before adding
*/
public void addAll(ISortedColumns cm, Allocator allocator, Function<IColumn, IColumn> transformation)
public void addAll(ISortedColumns cm, Allocator allocator, Function<Column, Column> transformation)
{
addAllWithSizeDelta(cm, allocator, transformation, null);
}
@Override
public long addAllWithSizeDelta(ISortedColumns cm, Allocator allocator, Function<IColumn, IColumn> transformation, SecondaryIndexManager.Updater indexer)
public long addAllWithSizeDelta(ISortedColumns cm, Allocator allocator, Function<Column, Column> transformation, SecondaryIndexManager.Updater indexer)
{
delete(cm.getDeletionInfo());
long sizeDelta = 0;
for (IColumn column : cm.getSortedColumns())
for (Column column : cm.getSortedColumns())
sizeDelta += addColumnInternal(transformation.apply(column), allocator);
return sizeDelta;
}
public boolean replace(IColumn oldColumn, IColumn newColumn)
public boolean replace(Column oldColumn, Column newColumn)
{
if (!oldColumn.name().equals(newColumn.name()))
throw new IllegalArgumentException();
@ -147,7 +137,7 @@ public class ThreadSafeSortedColumns extends AbstractThreadUnsafeSortedColumns i
return map.replace(oldColumn.name(), oldColumn, newColumn);
}
public IColumn getColumn(ByteBuffer name)
public Column getColumn(ByteBuffer name)
{
return map.get(name);
}
@ -167,12 +157,12 @@ public class ThreadSafeSortedColumns extends AbstractThreadUnsafeSortedColumns i
return map.size();
}
public Collection<IColumn> getSortedColumns()
public Collection<Column> getSortedColumns()
{
return map.values();
}
public Collection<IColumn> getReverseSortedColumns()
public Collection<Column> getReverseSortedColumns()
{
return map.descendingMap().values();
}
@ -182,17 +172,17 @@ public class ThreadSafeSortedColumns extends AbstractThreadUnsafeSortedColumns i
return map.navigableKeySet();
}
public Iterator<IColumn> iterator()
public Iterator<Column> iterator()
{
return map.values().iterator();
}
public Iterator<IColumn> iterator(ColumnSlice[] slices)
public Iterator<Column> iterator(ColumnSlice[] slices)
{
return new ColumnSlice.NavigableMapIterator(map, slices);
}
public Iterator<IColumn> reverseIterator(ColumnSlice[] slices)
public Iterator<Column> reverseIterator(ColumnSlice[] slices)
{
return new ColumnSlice.NavigableMapIterator(map.descendingMap(), slices);
}

View File

@ -33,7 +33,7 @@ import org.apache.cassandra.utils.Allocator;
public class TreeMapBackedSortedColumns extends AbstractThreadUnsafeSortedColumns implements ISortedColumns
{
private final TreeMap<ByteBuffer, IColumn> map;
private final TreeMap<ByteBuffer, Column> map;
public static final ISortedColumns.Factory factory = new Factory()
{
@ -42,7 +42,7 @@ public class TreeMapBackedSortedColumns extends AbstractThreadUnsafeSortedColumn
return new TreeMapBackedSortedColumns(comparator);
}
public ISortedColumns fromSorted(SortedMap<ByteBuffer, IColumn> sortedMap, boolean insertReversed)
public ISortedColumns fromSorted(SortedMap<ByteBuffer, Column> sortedMap, boolean insertReversed)
{
return new TreeMapBackedSortedColumns(sortedMap);
}
@ -60,12 +60,12 @@ public class TreeMapBackedSortedColumns extends AbstractThreadUnsafeSortedColumn
private TreeMapBackedSortedColumns(AbstractType<?> comparator)
{
this.map = new TreeMap<ByteBuffer, IColumn>(comparator);
this.map = new TreeMap<ByteBuffer, Column>(comparator);
}
private TreeMapBackedSortedColumns(SortedMap<ByteBuffer, IColumn> columns)
private TreeMapBackedSortedColumns(SortedMap<ByteBuffer, Column> columns)
{
this.map = new TreeMap<ByteBuffer, IColumn>(columns);
this.map = new TreeMap<ByteBuffer, Column>(columns);
}
public ISortedColumns.Factory getFactory()
@ -83,7 +83,7 @@ public class TreeMapBackedSortedColumns extends AbstractThreadUnsafeSortedColumn
return false;
}
public void addColumn(IColumn column, Allocator allocator)
public void addColumn(Column column, Allocator allocator)
{
addColumn(column, allocator, SecondaryIndexManager.nullUpdater);
}
@ -92,47 +92,33 @@ public class TreeMapBackedSortedColumns extends AbstractThreadUnsafeSortedColumn
* If we find an old column that has the same name
* the ask it to resolve itself else add the new column
*/
public long addColumn(IColumn column, Allocator allocator, SecondaryIndexManager.Updater indexer)
public long addColumn(Column column, Allocator allocator, SecondaryIndexManager.Updater indexer)
{
ByteBuffer name = column.name();
// this is a slightly unusual way to structure this; a more natural way is shown in ThreadSafeSortedColumns,
// but TreeMap lacks putAbsent. Rather than split it into a "get, then put" check, we do it as follows,
// which saves the extra "get" in the no-conflict case [for both normal and super columns],
// in exchange for a re-put in the SuperColumn case.
IColumn oldColumn = map.put(name, column);
Column oldColumn = map.put(name, column);
if (oldColumn == null)
return column.dataSize();
if (oldColumn instanceof SuperColumn)
{
assert column instanceof SuperColumn;
long previousSize = oldColumn.dataSize();
// since oldColumn is where we've been accumulating results, it's usually going to be faster to
// add the new one to the old, then place old back in the Map, rather than copy the old contents
// into the new Map entry.
((SuperColumn) oldColumn).putColumn((SuperColumn)column, allocator);
map.put(name, oldColumn);
return oldColumn.dataSize() - previousSize;
}
// calculate reconciled col from old (existing) col and new col
Column reconciledColumn = column.reconcile(oldColumn, allocator);
map.put(name, reconciledColumn);
// for memtable updates we only care about oldcolumn, reconciledcolumn, but when compacting
// we need to make sure we update indexes no matter the order we merge
if (reconciledColumn == column)
indexer.update(oldColumn, reconciledColumn);
else
{
// calculate reconciled col from old (existing) col and new col
IColumn reconciledColumn = column.reconcile(oldColumn, allocator);
map.put(name, reconciledColumn);
// for memtable updates we only care about oldcolumn, reconciledcolumn, but when compacting
// we need to make sure we update indexes no matter the order we merge
if (reconciledColumn == column)
indexer.update(oldColumn, reconciledColumn);
else
indexer.update(column, reconciledColumn);
return reconciledColumn.dataSize() - oldColumn.dataSize();
}
indexer.update(column, reconciledColumn);
return reconciledColumn.dataSize() - oldColumn.dataSize();
}
public long addAllWithSizeDelta(ISortedColumns cm, Allocator allocator, Function<IColumn, IColumn> transformation, SecondaryIndexManager.Updater indexer)
public long addAllWithSizeDelta(ISortedColumns cm, Allocator allocator, Function<Column, Column> transformation, SecondaryIndexManager.Updater indexer)
{
delete(cm.getDeletionInfo());
for (IColumn column : cm.getSortedColumns())
for (Column column : cm.getSortedColumns())
addColumn(transformation.apply(column), allocator, indexer);
// we don't use this for memtables, so we don't bother computing size
@ -142,12 +128,12 @@ public class TreeMapBackedSortedColumns extends AbstractThreadUnsafeSortedColumn
/**
* We need to go through each column in the column container and resolve it before adding
*/
public void addAll(ISortedColumns cm, Allocator allocator, Function<IColumn, IColumn> transformation)
public void addAll(ISortedColumns cm, Allocator allocator, Function<Column, Column> transformation)
{
addAllWithSizeDelta(cm, allocator, transformation, SecondaryIndexManager.nullUpdater);
}
public boolean replace(IColumn oldColumn, IColumn newColumn)
public boolean replace(Column oldColumn, Column newColumn)
{
if (!oldColumn.name().equals(newColumn.name()))
throw new IllegalArgumentException();
@ -156,7 +142,7 @@ public class TreeMapBackedSortedColumns extends AbstractThreadUnsafeSortedColumn
// column or the column was not equal to oldColumn (to be coherent
// with other implementation). We optimize for the common case where
// oldColumn do is present though.
IColumn previous = map.put(oldColumn.name(), newColumn);
Column previous = map.put(oldColumn.name(), newColumn);
if (previous == null)
{
map.remove(oldColumn.name());
@ -170,7 +156,7 @@ public class TreeMapBackedSortedColumns extends AbstractThreadUnsafeSortedColumn
return true;
}
public IColumn getColumn(ByteBuffer name)
public Column getColumn(ByteBuffer name)
{
return map.get(name);
}
@ -190,12 +176,12 @@ public class TreeMapBackedSortedColumns extends AbstractThreadUnsafeSortedColumn
return map.size();
}
public Collection<IColumn> getSortedColumns()
public Collection<Column> getSortedColumns()
{
return map.values();
}
public Collection<IColumn> getReverseSortedColumns()
public Collection<Column> getReverseSortedColumns()
{
return map.descendingMap().values();
}
@ -205,17 +191,17 @@ public class TreeMapBackedSortedColumns extends AbstractThreadUnsafeSortedColumn
return map.navigableKeySet();
}
public Iterator<IColumn> iterator()
public Iterator<Column> iterator()
{
return map.values().iterator();
}
public Iterator<IColumn> iterator(ColumnSlice[] slices)
public Iterator<Column> iterator(ColumnSlice[] slices)
{
return new ColumnSlice.NavigableMapIterator(map, slices);
}
public Iterator<IColumn> reverseIterator(ColumnSlice[] slices)
public Iterator<Column> reverseIterator(ColumnSlice[] slices)
{
return new ColumnSlice.NavigableMapIterator(map.descendingMap(), slices);
}

View File

@ -17,7 +17,6 @@
*/
package org.apache.cassandra.db.columniterator;
import org.apache.cassandra.db.SuperColumn;
import org.apache.cassandra.db.filter.SliceQueryFilter;
import org.apache.cassandra.utils.ByteBufferUtil;
@ -30,10 +29,4 @@ public class IdentityQueryFilter extends SliceQueryFilter
{
super(ByteBufferUtil.EMPTY_BYTE_BUFFER, ByteBufferUtil.EMPTY_BYTE_BUFFER, false, Integer.MAX_VALUE);
}
public SuperColumn filterSuperColumn(SuperColumn superColumn, int gcBefore)
{
// no filtering done, deliberately
return superColumn;
}
}

View File

@ -21,6 +21,7 @@ import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import com.google.common.collect.AbstractIterator;
@ -352,7 +353,9 @@ class IndexedSliceReader extends AbstractIterator<OnDiskAtom> implements OnDiskA
if (file == null)
file = originalInput == null ? sstable.getFileDataInput(positionToSeek) : originalInput;
OnDiskAtom.Serializer atomSerializer = emptyColumnFamily.getOnDiskSerializer();
// Give a bogus atom count since we'll deserialize as long as we're
// within the index block but we don't know how much atom is there
Iterator<OnDiskAtom> atomIterator = emptyColumnFamily.metadata().getOnDiskIterator(file, Integer.MAX_VALUE, sstable.descriptor.version);
file.seek(positionToSeek);
FileMark mark = file.mark();
@ -365,7 +368,7 @@ class IndexedSliceReader extends AbstractIterator<OnDiskAtom> implements OnDiskA
{
// Only fetch a new column if we haven't dealt with the previous one.
if (column == null)
column = atomSerializer.deserializeFromSSTable(file, sstable.descriptor.version);
column = atomIterator.next();
// col is before slice
// (If in slice, don't bother checking that until we change slice)
@ -434,12 +437,10 @@ class IndexedSliceReader extends AbstractIterator<OnDiskAtom> implements OnDiskA
// We remenber when we are whithin a slice to avoid some comparison
boolean inSlice = false;
OnDiskAtom.Serializer atomSerializer = emptyColumnFamily.getOnDiskSerializer();
int columns = file.readInt();
for (int i = 0; i < columns; i++)
Iterator<OnDiskAtom> atomIterator = emptyColumnFamily.metadata().getOnDiskIterator(file, file.readInt(), sstable.descriptor.version);
while (atomIterator.hasNext())
{
OnDiskAtom column = atomSerializer.deserializeFromSSTable(file, sstable.descriptor.version);
OnDiskAtom column = atomIterator.next();
// col is before slice
// (If in slice, don't bother checking that until we change slice)

View File

@ -26,7 +26,7 @@ import org.apache.cassandra.db.ColumnFamily;
import org.apache.cassandra.db.ColumnFamilySerializer;
import org.apache.cassandra.db.DecoratedKey;
import org.apache.cassandra.db.DeletionInfo;
import org.apache.cassandra.db.IColumn;
import org.apache.cassandra.db.Column;
import org.apache.cassandra.db.RowIndexEntry;
import org.apache.cassandra.db.OnDiskAtom;
import org.apache.cassandra.db.marshal.AbstractType;
@ -196,13 +196,12 @@ public class SSTableNamesIterator extends SimpleAbstractColumnIterator implement
private void readSimpleColumns(FileDataInput file, SortedSet<ByteBuffer> columnNames, List<ByteBuffer> filteredColumnNames, List<OnDiskAtom> result) throws IOException
{
OnDiskAtom.Serializer atomSerializer = cf.getOnDiskSerializer();
int columns = file.readInt();
Iterator<OnDiskAtom> atomIterator = cf.metadata().getOnDiskIterator(file, file.readInt(), sstable.descriptor.version);
int n = 0;
for (int i = 0; i < columns; i++)
while (atomIterator.hasNext())
{
OnDiskAtom column = atomSerializer.deserializeFromSSTable(file, sstable.descriptor.version);
if (column instanceof IColumn)
OnDiskAtom column = atomIterator.next();
if (column instanceof Column)
{
if (columnNames.contains(column.name()))
{
@ -255,15 +254,16 @@ public class SSTableNamesIterator extends SimpleAbstractColumnIterator implement
if (file == null)
file = createFileDataInput(positionToSeek);
OnDiskAtom.Serializer atomSerializer = cf.getOnDiskSerializer();
// We'll read as much atom as there is in the index block, so provide a bogus atom count
Iterator<OnDiskAtom> atomIterator = cf.metadata().getOnDiskIterator(file, Integer.MAX_VALUE, sstable.descriptor.version);
file.seek(positionToSeek);
FileMark mark = file.mark();
// TODO only completely deserialize columns we are interested in
while (file.bytesPastMark(mark) < indexInfo.width)
{
OnDiskAtom column = atomSerializer.deserializeFromSSTable(file, sstable.descriptor.version);
OnDiskAtom column = atomIterator.next();
// we check vs the original Set, not the filtered List, for efficiency
if (!(column instanceof IColumn) || columnNames.contains(column.name()))
if (!(column instanceof Column) || columnNames.contains(column.name()))
result.add(column);
}
}

View File

@ -19,6 +19,7 @@ package org.apache.cassandra.db.columniterator;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Iterator;
import com.google.common.collect.AbstractIterator;
@ -43,10 +44,9 @@ class SimpleSliceReader extends AbstractIterator<OnDiskAtom> implements OnDiskAt
private final ByteBuffer finishColumn;
private final AbstractType<?> comparator;
private final ColumnFamily emptyColumnFamily;
private final int columns;
private int i;
private FileMark mark;
private final OnDiskAtom.Serializer atomSerializer;
private final Iterator<OnDiskAtom> atomIterator;
public SimpleSliceReader(SSTableReader sstable, RowIndexEntry indexEntry, FileDataInput input, ByteBuffer finishColumn)
{
@ -79,8 +79,7 @@ class SimpleSliceReader extends AbstractIterator<OnDiskAtom> implements OnDiskAt
emptyColumnFamily = ColumnFamily.create(sstable.metadata);
emptyColumnFamily.delete(DeletionInfo.serializer().deserializeFromSSTable(file, sstable.descriptor.version));
atomSerializer = emptyColumnFamily.getOnDiskSerializer();
columns = file.readInt();
atomIterator = emptyColumnFamily.metadata().getOnDiskIterator(file, file.readInt(), sstable.descriptor.version);
mark = file.mark();
}
catch (IOException e)
@ -92,14 +91,14 @@ class SimpleSliceReader extends AbstractIterator<OnDiskAtom> implements OnDiskAt
protected OnDiskAtom computeNext()
{
if (i++ >= columns)
if (!atomIterator.hasNext())
return endOfData();
OnDiskAtom column;
try
{
file.reset(mark);
column = atomSerializer.deserializeFromSSTable(file, sstable.descriptor.version);
column = atomIterator.next();
}
catch (IOException e)
{

View File

@ -35,11 +35,12 @@ public class CommitLogDescriptor
public static final int LEGACY_VERSION = 1;
public static final int VERSION_12 = 2;
public static final int VERSION_20 = 3;
/**
* Increment this number if there is a changes in the commit log disc layout or MessagingVersion changes.
* Note: make sure to handle {@link #getMessagingVersion()}
*/
public static final int current_version = VERSION_12;
public static final int current_version = VERSION_20;
private final int version;
public final long id;
@ -75,13 +76,15 @@ public class CommitLogDescriptor
public int getMessagingVersion()
{
assert MessagingService.current_version == MessagingService.VERSION_12;
assert MessagingService.current_version == MessagingService.VERSION_20;
switch (version)
{
case LEGACY_VERSION:
return MessagingService.VERSION_11;
case VERSION_12:
return MessagingService.VERSION_12;
case VERSION_20:
return MessagingService.VERSION_20;
default:
throw new IllegalStateException("Unknown commitlog version " + version);
}

View File

@ -36,7 +36,6 @@ import org.apache.cassandra.concurrent.Stage;
import org.apache.cassandra.concurrent.StageManager;
import org.apache.cassandra.config.Schema;
import org.apache.cassandra.db.*;
import org.apache.cassandra.io.IColumnSerializer;
import org.apache.cassandra.io.util.FastByteArrayInputStream;
import org.apache.cassandra.io.util.FileUtils;
import org.apache.cassandra.io.util.RandomAccessReader;
@ -201,7 +200,7 @@ public class CommitLogReplayer
{
// assuming version here. We've gone to lengths to make sure what gets written to the CL is in
// the current version. so do make sure the CL is drained prior to upgrading a node.
rm = RowMutation.serializer.deserialize(new DataInputStream(bufIn), version, IColumnSerializer.Flag.LOCAL);
rm = RowMutation.serializer.deserialize(new DataInputStream(bufIn), version, ColumnSerializer.Flag.LOCAL);
}
catch (UnknownColumnFamilyException ex)
{

View File

@ -603,7 +603,7 @@ public class CompactionManager implements CompactionManagerMBean
SSTableScanner scanner = sstable.getDirectScanner();
long rowsRead = 0;
List<IColumn> indexedColumnsInRow = null;
List<Column> indexedColumnsInRow = null;
CleanupInfo ci = new CleanupInfo(sstable, scanner);
metrics.beginCompaction(ci);
@ -637,12 +637,12 @@ public class CompactionManager implements CompactionManagerMBean
OnDiskAtom column = row.next();
if (column instanceof CounterColumn)
renewer.maybeRenew((CounterColumn) column);
if (column instanceof IColumn && cfs.indexManager.indexes((IColumn)column))
if (column instanceof Column && cfs.indexManager.indexes((Column)column))
{
if (indexedColumnsInRow == null)
indexedColumnsInRow = new ArrayList<IColumn>();
indexedColumnsInRow = new ArrayList<Column>();
indexedColumnsInRow.add((IColumn)column);
indexedColumnsInRow.add((Column)column);
}
}

View File

@ -252,7 +252,7 @@ public class LazilyCompactedRow extends AbstractCompactedRow implements Iterable
}
else
{
IColumn column = (IColumn) current;
Column column = (Column) current;
container.addColumn(column);
if (container.getColumn(column.name()) != column)
indexer.remove(column);
@ -284,7 +284,7 @@ public class LazilyCompactedRow extends AbstractCompactedRow implements Iterable
container.clear();
return null;
}
IColumn reduced = purged.iterator().next();
Column reduced = purged.iterator().next();
container.clear();
// PrecompactedRow.removeDeletedAndOldShards have only checked the top-level CF deletion times,

View File

@ -207,7 +207,7 @@ public class ParallelCompactionIterable extends AbstractCompactionIterable
{
// addAll is ok even if cf is an ArrayBackedSortedColumns
SecondaryIndexManager.Updater indexer = controller.cfs.indexManager.updaterFor(row.key, false);
cf.addAllWithSizeDelta(thisCF, HeapAllocator.instance, Functions.<IColumn>identity(), indexer);
cf.addAllWithSizeDelta(thisCF, HeapAllocator.instance, Functions.<Column>identity(), indexer);
}
}
@ -218,7 +218,7 @@ public class ParallelCompactionIterable extends AbstractCompactionIterable
private class DeserializedColumnIterator implements ICountableColumnIterator
{
private final Row row;
private Iterator<IColumn> iter;
private Iterator<Column> iter;
public DeserializedColumnIterator(Row row)
{

View File

@ -121,7 +121,7 @@ public class PrecompactedRow extends AbstractCompactedRow
else
{
// addAll is ok even if cf is an ArrayBackedSortedColumns
cf.addAllWithSizeDelta(thisCF, HeapAllocator.instance, Functions.<IColumn>identity(), indexer);
cf.addAllWithSizeDelta(thisCF, HeapAllocator.instance, Functions.<Column>identity(), indexer);
}
}
return cf;

View File

@ -22,8 +22,8 @@ package org.apache.cassandra.db.filter;
import java.nio.ByteBuffer;
import org.apache.cassandra.db.IColumn;
import org.apache.cassandra.db.IColumnContainer;
import org.apache.cassandra.db.Column;
import org.apache.cassandra.db.ColumnFamily;
import org.apache.cassandra.db.marshal.CompositeType;
import org.apache.cassandra.utils.ByteBufferUtil;
@ -32,7 +32,7 @@ public class ColumnCounter
protected int live;
protected int ignored;
public void count(IColumn column, IColumnContainer container)
public void count(Column column, ColumnFamily container)
{
if (!isLive(column, container))
ignored++;
@ -40,7 +40,7 @@ public class ColumnCounter
live++;
}
protected static boolean isLive(IColumn column, IColumnContainer container)
protected static boolean isLive(Column column, ColumnFamily container)
{
return column.isLive() && (!container.deletionInfo().isDeleted(column));
}
@ -79,7 +79,7 @@ public class ColumnCounter
assert toGroup == 0 || type != null;
}
public void count(IColumn column, IColumnContainer container)
public void count(Column column, ColumnFamily container)
{
if (!isLive(column, container))
{

View File

@ -140,21 +140,21 @@ public class ColumnSlice
}
}
public static class NavigableMapIterator extends AbstractIterator<IColumn>
public static class NavigableMapIterator extends AbstractIterator<Column>
{
private final NavigableMap<ByteBuffer, IColumn> map;
private final NavigableMap<ByteBuffer, Column> map;
private final ColumnSlice[] slices;
private int idx = 0;
private Iterator<IColumn> currentSlice;
private Iterator<Column> currentSlice;
public NavigableMapIterator(NavigableMap<ByteBuffer, IColumn> map, ColumnSlice[] slices)
public NavigableMapIterator(NavigableMap<ByteBuffer, Column> map, ColumnSlice[] slices)
{
this.map = map;
this.slices = slices;
}
protected IColumn computeNext()
protected Column computeNext()
{
if (currentSlice == null)
{

View File

@ -281,7 +281,7 @@ public abstract class ExtendedFilter
{
// check column data vs expression
ByteBuffer colName = builder == null ? expression.column_name : builder.copy().add(expression.column_name).build();
IColumn column = data.getColumn(colName);
Column column = data.getColumn(colName);
if (column == null)
return false;
int v = data.metadata().getValueValidator(expression.column_name).compare(column.value(), expression.value);

View File

@ -66,15 +66,9 @@ public interface IDiskAtomFilter
* by the filter code, which should have some limit on the number of columns
* to avoid running out of memory on large rows.
*/
public void collectReducedColumns(IColumnContainer container, Iterator<IColumn> reducedColumns, int gcBefore);
public void collectReducedColumns(ColumnFamily container, Iterator<Column> reducedColumns, int gcBefore);
/**
* subcolumns of a supercolumn are unindexed, so to pick out parts of those we operate in-memory.
* @param superColumn may be modified by filtering op.
*/
public SuperColumn filterSuperColumn(SuperColumn superColumn, int gcBefore);
public Comparator<IColumn> getColumnComparator(AbstractType<?> comparator);
public Comparator<Column> getColumnComparator(AbstractType<?> comparator);
public boolean isReversed();
public void updateColumnsLimit(int newLimit);

View File

@ -86,29 +86,17 @@ public class NamesQueryFilter implements IDiskAtomFilter
return new SSTableNamesIterator(sstable, file, key, columns, indexEntry);
}
public SuperColumn filterSuperColumn(SuperColumn superColumn, int gcBefore)
{
for (IColumn column : superColumn.getSubColumns())
{
if (!columns.contains(column.name()) || !QueryFilter.isRelevant(column, superColumn, gcBefore))
{
superColumn.remove(column.name());
}
}
return superColumn;
}
public void collectReducedColumns(IColumnContainer container, Iterator<IColumn> reducedColumns, int gcBefore)
public void collectReducedColumns(ColumnFamily container, Iterator<Column> reducedColumns, int gcBefore)
{
while (reducedColumns.hasNext())
{
IColumn column = reducedColumns.next();
Column column = reducedColumns.next();
if (QueryFilter.isRelevant(column, container, gcBefore))
container.addColumn(column);
}
}
public Comparator<IColumn> getColumnComparator(AbstractType<?> comparator)
public Comparator<Column> getColumnComparator(AbstractType<?> comparator)
{
return comparator.columnComparator;
}
@ -136,7 +124,7 @@ public class NamesQueryFilter implements IDiskAtomFilter
return cf.hasOnlyTombstones() ? 0 : 1;
int count = 0;
for (IColumn column : cf)
for (Column column : cf)
{
if (column.isLive())
count++;

View File

@ -33,16 +33,14 @@ import org.apache.cassandra.utils.MergeIterator;
public class QueryFilter
{
public final DecoratedKey key;
public final QueryPath path;
public final String cfName;
public final IDiskAtomFilter filter;
private final IDiskAtomFilter superFilter;
public QueryFilter(DecoratedKey key, QueryPath path, IDiskAtomFilter filter)
public QueryFilter(DecoratedKey key, String cfName, IDiskAtomFilter filter)
{
this.key = key;
this.path = path;
this.cfName = cfName;
this.filter = filter;
superFilter = path.superColumnName == null ? null : new NamesQueryFilter(path.superColumnName);
}
public OnDiskAtomIterator getMemtableColumnIterator(Memtable memtable)
@ -56,95 +54,62 @@ public class QueryFilter
public OnDiskAtomIterator getMemtableColumnIterator(ColumnFamily cf, DecoratedKey key)
{
assert cf != null;
if (path.superColumnName == null)
return filter.getMemtableColumnIterator(cf, key);
return superFilter.getMemtableColumnIterator(cf, key);
return filter.getMemtableColumnIterator(cf, key);
}
// TODO move gcBefore into a field
public ISSTableColumnIterator getSSTableColumnIterator(SSTableReader sstable)
{
if (path.superColumnName == null)
return filter.getSSTableColumnIterator(sstable, key);
return superFilter.getSSTableColumnIterator(sstable, key);
return filter.getSSTableColumnIterator(sstable, key);
}
public ISSTableColumnIterator getSSTableColumnIterator(SSTableReader sstable, FileDataInput file, DecoratedKey key, RowIndexEntry indexEntry)
{
if (path.superColumnName == null)
return filter.getSSTableColumnIterator(sstable, file, key, indexEntry);
return superFilter.getSSTableColumnIterator(sstable, file, key, indexEntry);
return filter.getSSTableColumnIterator(sstable, file, key, indexEntry);
}
public void collateOnDiskAtom(final ColumnFamily returnCF, List<? extends CloseableIterator<OnDiskAtom>> toCollate, final int gcBefore)
{
List<CloseableIterator<IColumn>> filteredIterators = new ArrayList<CloseableIterator<IColumn>>(toCollate.size());
List<CloseableIterator<Column>> filteredIterators = new ArrayList<CloseableIterator<Column>>(toCollate.size());
for (CloseableIterator<OnDiskAtom> iter : toCollate)
filteredIterators.add(gatherTombstones(returnCF, iter));
collateColumns(returnCF, filteredIterators, gcBefore);
}
// TODO move gcBefore into a field
public void collateColumns(final ColumnFamily returnCF, List<? extends CloseableIterator<IColumn>> toCollate, final int gcBefore)
public void collateColumns(final ColumnFamily returnCF, List<? extends CloseableIterator<Column>> toCollate, final int gcBefore)
{
IDiskAtomFilter topLevelFilter = (superFilter == null ? filter : superFilter);
Comparator<IColumn> fcomp = topLevelFilter.getColumnComparator(returnCF.getComparator());
Comparator<Column> fcomp = filter.getColumnComparator(returnCF.getComparator());
// define a 'reduced' iterator that merges columns w/ the same name, which
// greatly simplifies computing liveColumns in the presence of tombstones.
MergeIterator.Reducer<IColumn, IColumn> reducer = new MergeIterator.Reducer<IColumn, IColumn>()
MergeIterator.Reducer<Column, Column> reducer = new MergeIterator.Reducer<Column, Column>()
{
ColumnFamily curCF = returnCF.cloneMeShallow();
public void reduce(IColumn current)
public void reduce(Column current)
{
if (curCF.isSuper() && curCF.isEmpty())
{
// If it is the first super column we add, we must clone it since other super column may modify
// it otherwise and it could be aliased in a memtable somewhere. We'll also don't have to care about what
// consumers make of the result (for instance CFS.getColumnFamily() call removeDeleted() on the
// result which removes column; which shouldn't be done on the original super column).
assert current instanceof SuperColumn;
curCF.addColumn(((SuperColumn) current).cloneMe());
}
else
{
curCF.addColumn(current);
}
curCF.addColumn(current);
}
protected IColumn getReduced()
protected Column getReduced()
{
IColumn c = curCF.iterator().next();
if (superFilter != null)
{
// filterSuperColumn only looks at immediate parent (the supercolumn) when determining if a subcolumn
// is still live, i.e., not shadowed by the parent's tombstone. so, bump it up temporarily to the tombstone
// time of the cf, if that is greater.
DeletionInfo delInfo = ((SuperColumn) c).deletionInfo();
((SuperColumn) c).delete(returnCF.deletionInfo());
c = filter.filterSuperColumn((SuperColumn) c, gcBefore);
((SuperColumn) c).setDeletionInfo(delInfo); // reset sc tombstone time to what it should be
}
Column c = curCF.iterator().next();
curCF.clear();
return c;
}
};
Iterator<IColumn> reduced = MergeIterator.get(toCollate, fcomp, reducer);
Iterator<Column> reduced = MergeIterator.get(toCollate, fcomp, reducer);
topLevelFilter.collectReducedColumns(returnCF, reduced, gcBefore);
filter.collectReducedColumns(returnCF, reduced, gcBefore);
}
/**
* Given an iterator of on disk atom, returns an iterator that filters the tombstone range
* markers adding them to {@code returnCF} and returns the normal column.
*/
public static CloseableIterator<IColumn> gatherTombstones(final ColumnFamily returnCF, final CloseableIterator<OnDiskAtom> iter)
public static CloseableIterator<Column> gatherTombstones(final ColumnFamily returnCF, final CloseableIterator<OnDiskAtom> iter)
{
return new CloseableIterator<IColumn>()
return new CloseableIterator<Column>()
{
private IColumn next;
private Column next;
public boolean hasNext()
{
@ -155,13 +120,13 @@ public class QueryFilter
return next != null;
}
public IColumn next()
public Column next()
{
if (next == null)
getNext();
assert next != null;
IColumn toReturn = next;
Column toReturn = next;
next = null;
return toReturn;
}
@ -172,9 +137,9 @@ public class QueryFilter
{
OnDiskAtom atom = iter.next();
if (atom instanceof IColumn)
if (atom instanceof Column)
{
next = (IColumn)atom;
next = (Column)atom;
break;
}
else
@ -198,10 +163,10 @@ public class QueryFilter
public String getColumnFamilyName()
{
return path.columnFamilyName;
return cfName;
}
public static boolean isRelevant(IColumn column, IColumnContainer container, int gcBefore)
public static boolean isRelevant(Column column, ColumnFamily container, int gcBefore)
{
// the column itself must be not gc-able (it is live, or a still relevant tombstone, or has live subcolumns), (1)
// and if its container is deleted, the column must be changed more recently than the container tombstone (2)
@ -214,51 +179,48 @@ public class QueryFilter
/**
* @return a QueryFilter object to satisfy the given slice criteria:
* @param key the row to slice
* @param path path to the level to slice at (CF or SuperColumn)
* @param cfName column family to query
* @param start column to start slice at, inclusive; empty for "the first column"
* @param finish column to stop slice at, inclusive; empty for "the last column"
* @param reversed true to start with the largest column (as determined by configured sort order) instead of smallest
* @param limit maximum number of non-deleted columns to return
*/
public static QueryFilter getSliceFilter(DecoratedKey key, QueryPath path, ByteBuffer start, ByteBuffer finish, boolean reversed, int limit)
public static QueryFilter getSliceFilter(DecoratedKey key, String cfName, ByteBuffer start, ByteBuffer finish, boolean reversed, int limit)
{
return new QueryFilter(key, path, new SliceQueryFilter(start, finish, reversed, limit));
return new QueryFilter(key, cfName, new SliceQueryFilter(start, finish, reversed, limit));
}
/**
* return a QueryFilter object that includes every column in the row.
* This is dangerous on large rows; avoid except for test code.
*/
public static QueryFilter getIdentityFilter(DecoratedKey key, QueryPath path)
public static QueryFilter getIdentityFilter(DecoratedKey key, String cfName)
{
return new QueryFilter(key, path, new IdentityQueryFilter());
return new QueryFilter(key, cfName, new IdentityQueryFilter());
}
/**
* @return a QueryFilter object that will return columns matching the given names
* @param key the row to slice
* @param path path to the level to slice at (CF or SuperColumn)
* @param cfName column family to query
* @param columns the column names to restrict the results to, sorted in comparator order
*/
public static QueryFilter getNamesFilter(DecoratedKey key, QueryPath path, SortedSet<ByteBuffer> columns)
public static QueryFilter getNamesFilter(DecoratedKey key, String cfName, SortedSet<ByteBuffer> columns)
{
return new QueryFilter(key, path, new NamesQueryFilter(columns));
return new QueryFilter(key, cfName, new NamesQueryFilter(columns));
}
/**
* convenience method for creating a name filter matching a single column
*/
public static QueryFilter getNamesFilter(DecoratedKey key, QueryPath path, ByteBuffer column)
public static QueryFilter getNamesFilter(DecoratedKey key, String cfName, ByteBuffer column)
{
return new QueryFilter(key, path, new NamesQueryFilter(column));
return new QueryFilter(key, cfName, new NamesQueryFilter(column));
}
@Override
public String toString() {
return getClass().getSimpleName() + "(key=" + key +
", path=" + path +
(filter == null ? "" : ", filter=" + filter) +
(superFilter == null ? "" : ", superFilter=" + superFilter) +
")";
public String toString()
{
return getClass().getSimpleName() + "(key=" + key + ", cfName=" + cfName + (filter == null ? "" : ", filter=" + filter) + ")";
}
}

View File

@ -21,10 +21,12 @@ import java.io.*;
import java.nio.ByteBuffer;
import org.apache.cassandra.db.TypeSizes;
import org.apache.cassandra.thrift.ColumnParent;
import org.apache.cassandra.thrift.ColumnPath;
import org.apache.cassandra.utils.ByteBufferUtil;
/**
* This class is obsolete internally, but kept for wire compatibility with
* older nodes. I.e. we kept it only for the serialization part.
*/
public class QueryPath
{
public final String columnFamilyName;
@ -38,31 +40,11 @@ public class QueryPath
this.columnName = columnName;
}
public QueryPath(ColumnParent columnParent)
{
this(columnParent.column_family, columnParent.super_column, null);
}
public QueryPath(String columnFamilyName, ByteBuffer superColumnName)
{
this(columnFamilyName, superColumnName, null);
}
public QueryPath(String columnFamilyName)
{
this(columnFamilyName, null);
}
public QueryPath(ColumnPath column_path)
{
this(column_path.column_family, column_path.super_column, column_path.column);
}
public static QueryPath column(ByteBuffer columnName)
{
return new QueryPath(null, null, columnName);
}
@Override
public String toString()
{

View File

@ -46,7 +46,7 @@ public class SliceQueryFilter implements IDiskAtomFilter
public final ColumnSlice[] slices;
public final boolean reversed;
public volatile int count;
private final int compositesToGroup;
public final int compositesToGroup;
// This is a hack to allow rolling upgrade with pre-1.2 nodes
private final int countMutliplierForCompatibility;
@ -91,6 +91,11 @@ public class SliceQueryFilter implements IDiskAtomFilter
return new SliceQueryFilter(newSlices, reversed, count, compositesToGroup, countMutliplierForCompatibility);
}
public SliceQueryFilter withUpdatedSlice(ByteBuffer start, ByteBuffer finish)
{
return new SliceQueryFilter(new ColumnSlice[]{ new ColumnSlice(start, finish) }, reversed, count, compositesToGroup, countMutliplierForCompatibility);
}
public OnDiskAtomIterator getMemtableColumnIterator(ColumnFamily cf, DecoratedKey key)
{
return Memtable.getSliceIterator(key, cf, this);
@ -106,57 +111,18 @@ public class SliceQueryFilter implements IDiskAtomFilter
return new SSTableSliceIterator(sstable, file, key, slices, reversed, indexEntry);
}
public SuperColumn filterSuperColumn(SuperColumn superColumn, int gcBefore)
{
// we clone shallow, then add, under the theory that generally we're interested in a relatively small number of subcolumns.
// this may be a poor assumption.
SuperColumn scFiltered = superColumn.cloneMeShallow();
final Iterator<IColumn> subcolumns;
if (reversed)
{
List<IColumn> columnsAsList = new ArrayList<IColumn>(superColumn.getSubColumns());
subcolumns = Lists.reverse(columnsAsList).iterator();
}
else
{
subcolumns = superColumn.getSubColumns().iterator();
}
final Comparator<ByteBuffer> comparator = reversed ? superColumn.getComparator().reverseComparator : superColumn.getComparator();
Iterator<IColumn> results = new AbstractIterator<IColumn>()
{
protected IColumn computeNext()
{
while (subcolumns.hasNext())
{
IColumn subcolumn = subcolumns.next();
// iterate until we get to the "real" start column
if (comparator.compare(subcolumn.name(), start()) < 0)
continue;
// exit loop when columns are out of the range.
if (finish().remaining() > 0 && comparator.compare(subcolumn.name(), finish()) > 0)
break;
return subcolumn;
}
return endOfData();
}
};
// subcolumns is either empty now, or has been redefined in the loop above. either is ok.
collectReducedColumns(scFiltered, results, gcBefore);
return scFiltered;
}
public Comparator<IColumn> getColumnComparator(AbstractType<?> comparator)
public Comparator<Column> getColumnComparator(AbstractType<?> comparator)
{
return reversed ? comparator.columnReverseComparator : comparator.columnComparator;
}
public void collectReducedColumns(IColumnContainer container, Iterator<IColumn> reducedColumns, int gcBefore)
public void collectReducedColumns(ColumnFamily container, Iterator<Column> reducedColumns, int gcBefore)
{
columnCounter = getColumnCounter(container);
while (reducedColumns.hasNext())
{
IColumn column = reducedColumns.next();
Column column = reducedColumns.next();
if (logger.isTraceEnabled())
logger.trace(String.format("collecting %s of %s: %s",
columnCounter.live(), count, column.getString(container.getComparator())));
@ -177,12 +143,12 @@ public class SliceQueryFilter implements IDiskAtomFilter
public int getLiveCount(ColumnFamily cf)
{
ColumnCounter counter = getColumnCounter(cf);
for (IColumn column : cf)
for (Column column : cf)
counter.count(column, cf);
return counter.live();
}
private ColumnCounter getColumnCounter(IColumnContainer container)
private ColumnCounter getColumnCounter(ColumnFamily container)
{
AbstractType<?> comparator = container.getComparator();
if (compositesToGroup < 0)
@ -200,11 +166,11 @@ public class SliceQueryFilter implements IDiskAtomFilter
Collection<ByteBuffer> toRemove = null;
boolean trimRemaining = false;
Collection<IColumn> columns = reversed
? cf.getReverseSortedColumns()
: cf.getSortedColumns();
Collection<Column> columns = reversed
? cf.getReverseSortedColumns()
: cf.getSortedColumns();
for (IColumn column : columns)
for (Column column : columns)
{
if (trimRemaining)
{

View File

@ -72,7 +72,7 @@ public abstract class AbstractSimplePerColumnSecondaryIndex extends PerColumnSec
protected abstract void init(ColumnDefinition columnDef);
protected abstract ByteBuffer makeIndexColumnName(ByteBuffer rowKey, IColumn column);
protected abstract ByteBuffer makeIndexColumnName(ByteBuffer rowKey, Column column);
protected abstract AbstractType getExpressionComparator();
@ -86,7 +86,7 @@ public abstract class AbstractSimplePerColumnSecondaryIndex extends PerColumnSec
}
public void delete(ByteBuffer rowKey, IColumn column)
public void delete(ByteBuffer rowKey, Column column)
{
if (column.isMarkedForDelete())
return;
@ -100,7 +100,7 @@ public abstract class AbstractSimplePerColumnSecondaryIndex extends PerColumnSec
logger.debug("removed index entry for cleaned-up value {}:{}", valueKey, cfi);
}
public void insert(ByteBuffer rowKey, IColumn column)
public void insert(ByteBuffer rowKey, Column column)
{
DecoratedKey valueKey = getIndexKeyFor(column.value());
ColumnFamily cfi = ColumnFamily.create(indexCfs.metadata);
@ -120,7 +120,7 @@ public abstract class AbstractSimplePerColumnSecondaryIndex extends PerColumnSec
indexCfs.apply(valueKey, cfi, SecondaryIndexManager.nullUpdater);
}
public void update(ByteBuffer rowKey, IColumn col)
public void update(ByteBuffer rowKey, Column col)
{
insert(rowKey, col);
}

View File

@ -19,8 +19,7 @@ package org.apache.cassandra.db.index;
import java.nio.ByteBuffer;
import org.apache.cassandra.db.IColumn;
import org.apache.cassandra.thrift.Column;
import org.apache.cassandra.db.Column;
import org.apache.cassandra.utils.FBUtilities;
/**
@ -35,7 +34,7 @@ public abstract class PerColumnSecondaryIndex extends SecondaryIndex
* @param rowKey the underlying row key which is indexed
* @param col all the column info
*/
public abstract void delete(ByteBuffer rowKey, IColumn col);
public abstract void delete(ByteBuffer rowKey, Column col);
/**
* insert a column to the index
@ -43,7 +42,7 @@ public abstract class PerColumnSecondaryIndex extends SecondaryIndex
* @param rowKey the underlying row key which is indexed
* @param col all the column info
*/
public abstract void insert(ByteBuffer rowKey, IColumn col);
public abstract void insert(ByteBuffer rowKey, Column col);
/**
* update a column from the index
@ -51,7 +50,7 @@ public abstract class PerColumnSecondaryIndex extends SecondaryIndex
* @param rowKey the underlying row key which is indexed
* @param col all the column info
*/
public abstract void update(ByteBuffer rowKey, IColumn col);
public abstract void update(ByteBuffer rowKey, Column col);
public String getNameForSystemTable(ByteBuffer column)
{
@ -61,6 +60,6 @@ public abstract class PerColumnSecondaryIndex extends SecondaryIndex
@Override
public boolean validate(Column column)
{
return column.value.remaining() < FBUtilities.MAX_UNSIGNED_SHORT;
return column.value().remaining() < FBUtilities.MAX_UNSIGNED_SHORT;
}
}

View File

@ -20,9 +20,9 @@ package org.apache.cassandra.db.index;
import java.nio.ByteBuffer;
import java.nio.charset.CharacterCodingException;
import org.apache.cassandra.db.Column;
import org.apache.cassandra.db.ColumnFamily;
import org.apache.cassandra.db.DecoratedKey;
import org.apache.cassandra.thrift.Column;
import org.apache.cassandra.utils.ByteBufferUtil;
/**

View File

@ -28,6 +28,7 @@ import org.slf4j.LoggerFactory;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.config.ColumnDefinition;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.db.Column;
import org.apache.cassandra.db.ColumnFamilyStore;
import org.apache.cassandra.db.DecoratedKey;
import org.apache.cassandra.db.SystemTable;
@ -41,7 +42,6 @@ import org.apache.cassandra.db.marshal.LocalByPartionerType;
import org.apache.cassandra.dht.*;
import org.apache.cassandra.io.sstable.ReducingKeyIterator;
import org.apache.cassandra.io.sstable.SSTableReader;
import org.apache.cassandra.thrift.Column;
import org.apache.cassandra.service.StorageService;
/**

View File

@ -36,7 +36,6 @@ import org.apache.cassandra.db.compaction.CompactionManager;
import org.apache.cassandra.dht.AbstractBounds;
import org.apache.cassandra.io.sstable.ReducingKeyIterator;
import org.apache.cassandra.io.sstable.SSTableReader;
import org.apache.cassandra.thrift.Column;
import org.apache.cassandra.thrift.IndexExpression;
/**
@ -49,11 +48,11 @@ public class SecondaryIndexManager
public static final Updater nullUpdater = new Updater()
{
public void insert(IColumn column) { }
public void insert(Column column) { }
public void update(IColumn oldColumn, IColumn column) { }
public void update(Column oldColumn, Column column) { }
public void remove(IColumn current) { }
public void remove(Column current) { }
};
/**
@ -172,7 +171,7 @@ public class SecondaryIndexManager
return null;
}
public boolean indexes(IColumn column)
public boolean indexes(Column column)
{
return indexes(column.name());
}
@ -434,7 +433,7 @@ public class SecondaryIndexManager
}
else
{
for (IColumn column : cf)
for (Column column : cf)
{
if (index.indexes(column.name()))
((PerColumnSecondaryIndex) index).insert(key, column);
@ -449,12 +448,12 @@ public class SecondaryIndexManager
* @param key the row key
* @param indexedColumnsInRow all column names in row
*/
public void deleteFromIndexes(DecoratedKey key, List<IColumn> indexedColumnsInRow)
public void deleteFromIndexes(DecoratedKey key, List<Column> indexedColumnsInRow)
{
// Update entire row only once per row level index
Set<Class<? extends SecondaryIndex>> cleanedRowLevelIndexes = null;
for (IColumn column : indexedColumnsInRow)
for (Column column : indexedColumnsInRow)
{
SecondaryIndex index = indexesByColumn.get(column.name());
if (index == null)
@ -574,17 +573,17 @@ public class SecondaryIndexManager
public boolean validate(Column column)
{
SecondaryIndex index = getIndexForColumn(column.name);
SecondaryIndex index = getIndexForColumn(column.name());
return index != null ? index.validate(column) : true;
}
public static interface Updater
{
public void insert(IColumn column);
public void insert(Column column);
public void update(IColumn oldColumn, IColumn column);
public void update(Column oldColumn, Column column);
public void remove(IColumn current);
public void remove(Column current);
}
private class PerColumnIndexUpdater implements Updater
@ -596,7 +595,7 @@ public class SecondaryIndexManager
this.key = key;
}
public void insert(IColumn column)
public void insert(Column column)
{
if (column.isMarkedForDelete())
return;
@ -608,7 +607,7 @@ public class SecondaryIndexManager
((PerColumnSecondaryIndex) index).insert(key.key, column);
}
public void update(IColumn oldColumn, IColumn column)
public void update(Column oldColumn, Column column)
{
if (column.isMarkedForDelete())
return;
@ -621,7 +620,7 @@ public class SecondaryIndexManager
((PerColumnSecondaryIndex) index).insert(key.key, column);
}
public void remove(IColumn column)
public void remove(Column column)
{
if (column.isMarkedForDelete())
return;
@ -644,7 +643,7 @@ public class SecondaryIndexManager
this.key = key;
}
public void insert(IColumn column)
public void insert(Column column)
{
if (column.isMarkedForDelete())
return;
@ -664,7 +663,7 @@ public class SecondaryIndexManager
}
}
public void update(IColumn oldColumn, IColumn column)
public void update(Column oldColumn, Column column)
{
if (column.isMarkedForDelete())
return;
@ -685,7 +684,7 @@ public class SecondaryIndexManager
}
}
public void remove(IColumn column)
public void remove(Column column)
{
if (column.isMarkedForDelete())
return;

View File

@ -47,7 +47,7 @@ public abstract class SecondaryIndexSearcher
protected boolean isIndexValueStale(ColumnFamily liveData, ByteBuffer indexedColumnName, ByteBuffer indexedValue)
{
IColumn liveColumn = liveData.getColumn(indexedColumnName);
Column liveColumn = liveData.getColumn(indexedColumnName);
if (liveColumn == null || liveColumn.isMarkedForDelete())
return true;

View File

@ -56,7 +56,7 @@ public class CompositesIndex extends AbstractSimplePerColumnSecondaryIndex
indexComparator = (CompositeType)SecondaryIndex.getIndexComparator(baseCfs.metadata, columnDef);
}
protected ByteBuffer makeIndexColumnName(ByteBuffer rowKey, IColumn column)
protected ByteBuffer makeIndexColumnName(ByteBuffer rowKey, Column column)
{
CompositeType baseComparator = (CompositeType)baseCfs.getComparator();
ByteBuffer[] components = baseComparator.split(column.name());

View File

@ -160,8 +160,7 @@ public class CompositesSearcher extends SecondaryIndexSearcher
return new ColumnFamilyStore.AbstractScanIterator()
{
private ByteBuffer lastSeenPrefix = startPrefix;
private Deque<IColumn> indexColumns;
private final QueryPath path = new QueryPath(baseCfs.name);
private Deque<Column> indexColumns;
private int columnsRead = Integer.MAX_VALUE;
private final int meanColumns = Math.max(index.getIndexCfs().getMeanColumns(), 1);
@ -218,7 +217,7 @@ public class CompositesSearcher extends SecondaryIndexSearcher
((AbstractSimplePerColumnSecondaryIndex)index).expressionString(primary), indexComparator.getString(startPrefix));
QueryFilter indexFilter = QueryFilter.getSliceFilter(indexKey,
new QueryPath(index.getIndexCfs().name),
index.getIndexCfs().name,
lastSeenPrefix,
endPrefix,
false,
@ -227,10 +226,10 @@ public class CompositesSearcher extends SecondaryIndexSearcher
if (indexRow == null)
return makeReturn(currentKey, data);
Collection<IColumn> sortedColumns = indexRow.getSortedColumns();
Collection<Column> sortedColumns = indexRow.getSortedColumns();
columnsRead = sortedColumns.size();
indexColumns = new ArrayDeque(sortedColumns);
IColumn firstColumn = sortedColumns.iterator().next();
Column firstColumn = sortedColumns.iterator().next();
// Paging is racy, so it is possible the first column of a page is not the last seen one.
if (lastSeenPrefix != startPrefix && lastSeenPrefix.equals(firstColumn.name()))
@ -249,7 +248,7 @@ public class CompositesSearcher extends SecondaryIndexSearcher
while (!indexColumns.isEmpty() && columnsCount <= limit)
{
IColumn column = indexColumns.poll();
Column column = indexColumns.poll();
lastSeenPrefix = column.name();
if (column.isMarkedForDelete())
{
@ -302,7 +301,7 @@ public class CompositesSearcher extends SecondaryIndexSearcher
continue;
SliceQueryFilter dataFilter = new SliceQueryFilter(start, builder.copy().buildAsEndOfRange(), false, Integer.MAX_VALUE, prefixSize);
ColumnFamily newData = baseCfs.getColumnFamily(new QueryFilter(dk, path, dataFilter));
ColumnFamily newData = baseCfs.getColumnFamily(new QueryFilter(dk, baseCfs.name, dataFilter));
if (newData != null)
{
ByteBuffer baseColumnName = builder.copy().add(primary.column_name).build();
@ -311,7 +310,7 @@ public class CompositesSearcher extends SecondaryIndexSearcher
if (isIndexValueStale(newData, baseColumnName, indexedValue))
{
// delete the index entry w/ its own timestamp
IColumn dummyColumn = new Column(baseColumnName, indexedValue, column.timestamp());
Column dummyColumn = new Column(baseColumnName, indexedValue, column.timestamp());
((PerColumnSecondaryIndex) index).delete(dk.key, dummyColumn);
continue;
}

View File

@ -21,7 +21,7 @@ import java.nio.ByteBuffer;
import java.util.Set;
import org.apache.cassandra.config.ColumnDefinition;
import org.apache.cassandra.db.IColumn;
import org.apache.cassandra.db.Column;
import org.apache.cassandra.db.index.AbstractSimplePerColumnSecondaryIndex;
import org.apache.cassandra.db.index.SecondaryIndexSearcher;
import org.apache.cassandra.db.marshal.AbstractType;
@ -38,7 +38,7 @@ public class KeysIndex extends AbstractSimplePerColumnSecondaryIndex
// Nothing specific
}
protected ByteBuffer makeIndexColumnName(ByteBuffer rowKey, IColumn column)
protected ByteBuffer makeIndexColumnName(ByteBuffer rowKey, Column column)
{
return rowKey;
}

View File

@ -108,8 +108,7 @@ public class KeysSearcher extends SecondaryIndexSearcher
return new ColumnFamilyStore.AbstractScanIterator()
{
private ByteBuffer lastSeenKey = startKey;
private Iterator<IColumn> indexColumns;
private final QueryPath path = new QueryPath(baseCfs.name);
private Iterator<Column> indexColumns;
private int columnsRead = Integer.MAX_VALUE;
protected Row computeNext()
@ -132,7 +131,7 @@ public class KeysSearcher extends SecondaryIndexSearcher
((AbstractSimplePerColumnSecondaryIndex)index).expressionString(primary), index.getBaseCfs().metadata.getKeyValidator().getString(startKey));
QueryFilter indexFilter = QueryFilter.getSliceFilter(indexKey,
new QueryPath(index.getIndexCfs().name),
index.getIndexCfs().name,
lastSeenKey,
endKey,
false,
@ -145,10 +144,10 @@ public class KeysSearcher extends SecondaryIndexSearcher
return endOfData();
}
Collection<IColumn> sortedColumns = indexRow.getSortedColumns();
Collection<Column> sortedColumns = indexRow.getSortedColumns();
columnsRead = sortedColumns.size();
indexColumns = sortedColumns.iterator();
IColumn firstColumn = sortedColumns.iterator().next();
Column firstColumn = sortedColumns.iterator().next();
// Paging is racy, so it is possible the first column of a page is not the last seen one.
if (lastSeenKey != startKey && lastSeenKey.equals(firstColumn.name()))
@ -167,7 +166,7 @@ public class KeysSearcher extends SecondaryIndexSearcher
while (indexColumns.hasNext())
{
IColumn column = indexColumns.next();
Column column = indexColumns.next();
lastSeenKey = column.name();
if (column.isMarkedForDelete())
{
@ -188,7 +187,7 @@ public class KeysSearcher extends SecondaryIndexSearcher
}
logger.trace("Returning index hit for {}", dk);
ColumnFamily data = baseCfs.getColumnFamily(new QueryFilter(dk, path, filter.initialFilter()));
ColumnFamily data = baseCfs.getColumnFamily(new QueryFilter(dk, baseCfs.name, filter.initialFilter()));
// While the column family we'll get in the end should contains the primary clause column, the initialFilter may not have found it and can thus be null
if (data == null)
data = ColumnFamily.create(baseCfs.metadata);
@ -198,7 +197,7 @@ public class KeysSearcher extends SecondaryIndexSearcher
IDiskAtomFilter extraFilter = filter.getExtraFilter(data);
if (extraFilter != null)
{
ColumnFamily cf = baseCfs.getColumnFamily(new QueryFilter(dk, path, extraFilter));
ColumnFamily cf = baseCfs.getColumnFamily(new QueryFilter(dk, baseCfs.name, extraFilter));
if (cf != null)
data.addAll(cf, HeapAllocator.instance);
}
@ -206,7 +205,7 @@ public class KeysSearcher extends SecondaryIndexSearcher
if (isIndexValueStale(data, primary.column_name, indexKey.key))
{
// delete the index entry w/ its own timestamp
IColumn dummyColumn = new Column(primary.column_name, indexKey.key, column.timestamp());
Column dummyColumn = new Column(primary.column_name, indexKey.key, column.timestamp());
((PerColumnSecondaryIndex)index).delete(dk.key, dummyColumn);
continue;
}

View File

@ -23,7 +23,7 @@ import java.util.Comparator;
import java.util.Map;
import org.apache.cassandra.exceptions.SyntaxException;
import org.apache.cassandra.db.IColumn;
import org.apache.cassandra.db.Column;
import org.apache.cassandra.db.OnDiskAtom;
import org.apache.cassandra.db.RangeTombstone;
import static org.apache.cassandra.io.sstable.IndexHelper.IndexInfo;
@ -40,8 +40,8 @@ public abstract class AbstractType<T> implements Comparator<ByteBuffer>
{
public final Comparator<IndexInfo> indexComparator;
public final Comparator<IndexInfo> indexReverseComparator;
public final Comparator<IColumn> columnComparator;
public final Comparator<IColumn> columnReverseComparator;
public final Comparator<Column> columnComparator;
public final Comparator<Column> columnReverseComparator;
public final Comparator<OnDiskAtom> onDiskAtomComparator;
public final Comparator<ByteBuffer> reverseComparator;
@ -61,16 +61,16 @@ public abstract class AbstractType<T> implements Comparator<ByteBuffer>
return AbstractType.this.compare(o1.firstName, o2.firstName);
}
};
columnComparator = new Comparator<IColumn>()
columnComparator = new Comparator<Column>()
{
public int compare(IColumn c1, IColumn c2)
public int compare(Column c1, Column c2)
{
return AbstractType.this.compare(c1.name(), c2.name());
}
};
columnReverseComparator = new Comparator<IColumn>()
columnReverseComparator = new Comparator<Column>()
{
public int compare(IColumn c1, IColumn c2)
public int compare(Column c1, Column c2)
{
return AbstractType.this.compare(c2.name(), c1.name());
}
@ -159,10 +159,10 @@ public abstract class AbstractType<T> implements Comparator<ByteBuffer>
}
/* convenience method */
public String getColumnsString(Collection<IColumn> columns)
public String getColumnsString(Collection<Column> columns)
{
StringBuilder builder = new StringBuilder();
for (IColumn column : columns)
for (Column column : columns)
{
builder.append(column.getString(this)).append(",");
}

View File

@ -20,7 +20,7 @@ package org.apache.cassandra.db.marshal;
import java.nio.ByteBuffer;
import java.util.List;
import org.apache.cassandra.db.IColumn;
import org.apache.cassandra.db.Column;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.Pair;
@ -49,7 +49,7 @@ public abstract class CollectionType<T> extends AbstractType<T>
protected abstract void appendToStringBuilder(StringBuilder sb);
public abstract ByteBuffer serialize(List<Pair<ByteBuffer, IColumn>> columns);
public abstract ByteBuffer serialize(List<Pair<ByteBuffer, Column>> columns);
@Override
public String toString()

View File

@ -68,6 +68,11 @@ public class CompositeType extends AbstractCompositeType
return getInstance(parser.getTypeParameters());
}
public static CompositeType getInstance(AbstractType... types)
{
return getInstance(Arrays.<AbstractType<?>>asList(types));
}
public static synchronized CompositeType getInstance(List<AbstractType<?>> types)
{
assert types != null && !types.isEmpty();
@ -126,6 +131,23 @@ public class CompositeType extends AbstractCompositeType
return build(serialized);
}
// Extract component idx from bb. Return null if there is not enough component.
public static ByteBuffer extractComponent(ByteBuffer bb, int idx)
{
bb = bb.duplicate();
int i = 0;
while (bb.remaining() > 0)
{
ByteBuffer c = getWithShortLength(bb);
if (i == idx)
return c;
bb.get(); // skip end-of-component
++i;
}
return null;
}
@Override
public boolean isCompatibleWith(AbstractType<?> previous)
{
@ -190,7 +212,7 @@ public class CompositeType extends AbstractCompositeType
return new Builder(this);
}
public ByteBuffer build(ByteBuffer... buffers)
public static ByteBuffer build(ByteBuffer... buffers)
{
int totalLength = 0;
for (ByteBuffer bb : buffers)
@ -200,7 +222,7 @@ public class CompositeType extends AbstractCompositeType
for (ByteBuffer bb : buffers)
{
putShortLength(out, bb.remaining());
out.put(bb);
out.put(bb.duplicate());
out.put((byte) 0);
}
out.flip();

View File

@ -21,7 +21,7 @@ import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.util.*;
import org.apache.cassandra.db.IColumn;
import org.apache.cassandra.db.Column;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.exceptions.SyntaxException;
import org.apache.cassandra.utils.Pair;
@ -118,11 +118,11 @@ public class ListType<T> extends CollectionType<List<T>>
sb.append(getClass().getName()).append(TypeParser.stringifyTypeParameters(Collections.<AbstractType<?>>singletonList(elements)));
}
public ByteBuffer serialize(List<Pair<ByteBuffer, IColumn>> columns)
public ByteBuffer serialize(List<Pair<ByteBuffer, Column>> columns)
{
List<ByteBuffer> bbs = new ArrayList<ByteBuffer>(columns.size());
int size = 0;
for (Pair<ByteBuffer, IColumn> p : columns)
for (Pair<ByteBuffer, Column> p : columns)
{
bbs.add(p.right.value());
size += 2 + p.right.value().remaining();

View File

@ -21,7 +21,7 @@ import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.util.*;
import org.apache.cassandra.db.IColumn;
import org.apache.cassandra.db.Column;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.exceptions.SyntaxException;
import org.apache.cassandra.utils.Pair;
@ -135,11 +135,11 @@ public class MapType<K, V> extends CollectionType<Map<K, V>>
/**
* Creates the same output than decompose, but from the internal representation.
*/
public ByteBuffer serialize(List<Pair<ByteBuffer, IColumn>> columns)
public ByteBuffer serialize(List<Pair<ByteBuffer, Column>> columns)
{
List<ByteBuffer> bbs = new ArrayList<ByteBuffer>(2 * columns.size());
int size = 0;
for (Pair<ByteBuffer, IColumn> p : columns)
for (Pair<ByteBuffer, Column> p : columns)
{
bbs.add(p.left);
bbs.add(p.right.value());

View File

@ -21,7 +21,7 @@ import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.util.*;
import org.apache.cassandra.db.IColumn;
import org.apache.cassandra.db.Column;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.exceptions.SyntaxException;
import org.apache.cassandra.utils.Pair;
@ -118,11 +118,11 @@ public class SetType<T> extends CollectionType<Set<T>>
sb.append(getClass().getName()).append(TypeParser.stringifyTypeParameters(Collections.<AbstractType<?>>singletonList(elements)));
}
public ByteBuffer serialize(List<Pair<ByteBuffer, IColumn>> columns)
public ByteBuffer serialize(List<Pair<ByteBuffer, Column>> columns)
{
List<ByteBuffer> bbs = new ArrayList<ByteBuffer>(columns.size());
int size = 0;
for (Pair<ByteBuffer, IColumn> p : columns)
for (Pair<ByteBuffer, Column> p : columns)
{
bbs.add(p.left);
size += 2 + p.left.remaining();

View File

@ -37,7 +37,7 @@ import org.apache.thrift.TApplicationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.cassandra.db.IColumn;
import org.apache.cassandra.db.Column;
import org.apache.cassandra.dht.IPartitioner;
import org.apache.cassandra.dht.Range;
import org.apache.cassandra.dht.Token;
@ -65,8 +65,8 @@ import org.apache.thrift.TException;
*
* The default split size is 64k rows.
*/
public class ColumnFamilyInputFormat extends InputFormat<ByteBuffer, SortedMap<ByteBuffer, IColumn>>
implements org.apache.hadoop.mapred.InputFormat<ByteBuffer, SortedMap<ByteBuffer, IColumn>>
public class ColumnFamilyInputFormat extends InputFormat<ByteBuffer, SortedMap<ByteBuffer, Column>>
implements org.apache.hadoop.mapred.InputFormat<ByteBuffer, SortedMap<ByteBuffer, Column>>
{
private static final Logger logger = LoggerFactory.getLogger(ColumnFamilyInputFormat.class);
@ -313,7 +313,7 @@ public class ColumnFamilyInputFormat extends InputFormat<ByteBuffer, SortedMap<B
return map;
}
public RecordReader<ByteBuffer, SortedMap<ByteBuffer, IColumn>> createRecordReader(InputSplit inputSplit, TaskAttemptContext taskAttemptContext) throws IOException, InterruptedException
public RecordReader<ByteBuffer, SortedMap<ByteBuffer, Column>> createRecordReader(InputSplit inputSplit, TaskAttemptContext taskAttemptContext) throws IOException, InterruptedException
{
return new ColumnFamilyRecordReader();
}
@ -332,7 +332,7 @@ public class ColumnFamilyInputFormat extends InputFormat<ByteBuffer, SortedMap<B
return oldInputSplits;
}
public org.apache.hadoop.mapred.RecordReader<ByteBuffer, SortedMap<ByteBuffer, IColumn>> getRecordReader(org.apache.hadoop.mapred.InputSplit split, JobConf jobConf, final Reporter reporter) throws IOException
public org.apache.hadoop.mapred.RecordReader<ByteBuffer, SortedMap<ByteBuffer, Column>> getRecordReader(org.apache.hadoop.mapred.InputSplit split, JobConf jobConf, final Reporter reporter) throws IOException
{
TaskAttemptContext tac = new TaskAttemptContext(jobConf, TaskAttemptID.forName(jobConf.get(MAPRED_TASK_ID)))
{

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