mirror of https://github.com/apache/cassandra
Replace supercolumns internally by composites
patch by slebresne; reviewed by Vijay for CASSANDRA-3237
This commit is contained in:
parent
565f675b16
commit
3a005df397
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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()))
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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.");
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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.");
|
||||
|
|
|
|||
|
|
@ -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--;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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++;
|
||||
|
|
|
|||
|
|
@ -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) + ")";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(",");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in New Issue