use of org.apache.cassandra.config.CFMetaData in project cassandra by palantir.
the class CompactionsTest method testRangeTombstones.
@Test
public void testRangeTombstones() {
Keyspace keyspace = Keyspace.open(KEYSPACE1);
ColumnFamilyStore cfs = keyspace.getColumnFamilyStore("Standard2");
cfs.clearUnsafe();
// disable compaction while flushing
cfs.disableAutoCompaction();
final CFMetaData cfmeta = cfs.metadata;
Directories dir = cfs.directories;
ArrayList<DecoratedKey> keys = new ArrayList<DecoratedKey>();
for (int i = 0; i < 4; i++) {
keys.add(Util.dk("" + i));
}
ArrayBackedSortedColumns cf = ArrayBackedSortedColumns.factory.create(cfmeta);
// this must not resurrect
cf.addColumn(Util.column("01", "a", 1));
cf.addColumn(Util.column("a", "a", 3));
cf.deletionInfo().add(new RangeTombstone(Util.cellname("0"), Util.cellname("b"), 2, (int) (System.currentTimeMillis() / 1000)), cfmeta.comparator);
try (SSTableWriter writer = SSTableWriter.create(Descriptor.fromFilename(cfs.getTempSSTablePath(dir.getDirectoryForNewSSTables())), 0, 0, 0)) {
writer.append(Util.dk("0"), cf);
writer.append(Util.dk("1"), cf);
writer.append(Util.dk("3"), cf);
cfs.addSSTable(writer.finish(true));
}
try (SSTableWriter writer = SSTableWriter.create(Descriptor.fromFilename(cfs.getTempSSTablePath(dir.getDirectoryForNewSSTables())), 0, 0, 0)) {
writer.append(Util.dk("0"), cf);
writer.append(Util.dk("1"), cf);
writer.append(Util.dk("2"), cf);
writer.append(Util.dk("3"), cf);
cfs.addSSTable(writer.finish(true));
}
Collection<SSTableReader> toCompact = cfs.getSSTables();
assert toCompact.size() == 2;
// Force compaction on first sstables. Since each row is in only one sstable, we will be using EchoedRow.
Util.compact(cfs, toCompact);
assertEquals(1, cfs.getSSTables().size());
// Now assert we do have the 4 keys
assertEquals(4, Util.getRangeSlice(cfs).size());
ArrayList<DecoratedKey> k = new ArrayList<DecoratedKey>();
for (Row r : Util.getRangeSlice(cfs)) {
k.add(r.key);
assertEquals(ByteBufferUtil.bytes("a"), r.cf.getColumn(Util.cellname("a")).value());
assertNull(r.cf.getColumn(Util.cellname("01")));
assertEquals(3, r.cf.getColumn(Util.cellname("a")).timestamp());
}
for (SSTableReader sstable : cfs.getSSTables()) {
StatsMetadata stats = sstable.getSSTableMetadata();
assertEquals(ByteBufferUtil.bytes("0"), stats.minColumnNames.get(0));
assertEquals(ByteBufferUtil.bytes("b"), stats.maxColumnNames.get(0));
}
assertEquals(keys, k);
}
use of org.apache.cassandra.config.CFMetaData in project cassandra by palantir.
the class AlterTableStatement method announceMigration.
public boolean announceMigration(boolean isLocalOnly) throws RequestValidationException {
CFMetaData meta = validateColumnFamily(keyspace(), columnFamily());
CFMetaData cfm = meta.copy();
CQL3Type validator = this.validator == null ? null : this.validator.prepare(keyspace());
ColumnIdentifier columnName = null;
ColumnDefinition def = null;
if (rawColumnName != null) {
columnName = rawColumnName.prepare(cfm);
def = cfm.getColumnDefinition(columnName);
}
if (cfProps.getId() != null)
throw new ConfigurationException("Cannot alter table id.");
switch(oType) {
case ADD:
assert columnName != null;
if (cfm.comparator.isDense())
throw new InvalidRequestException("Cannot add new column to a COMPACT STORAGE table");
if (isStatic) {
if (!cfm.comparator.isCompound())
throw new InvalidRequestException("Static columns are not allowed in COMPACT STORAGE tables");
if (cfm.clusteringColumns().isEmpty())
throw new InvalidRequestException("Static columns are only useful (and thus allowed) if the table has at least one clustering column");
}
if (def != null) {
switch(def.kind) {
case PARTITION_KEY:
case CLUSTERING_COLUMN:
throw new InvalidRequestException(String.format("Invalid column name %s because it conflicts with a PRIMARY KEY part", columnName));
default:
throw new InvalidRequestException(String.format("Invalid column name %s because it conflicts with an existing column", columnName));
}
}
// Cannot re-add a dropped counter column. See #7831.
if (meta.isCounter() && meta.getDroppedColumns().containsKey(columnName))
throw new InvalidRequestException(String.format("Cannot re-add previously dropped counter column %s", columnName));
AbstractType<?> type = validator.getType();
if (type.isCollection() && type.isMultiCell()) {
if (!cfm.comparator.supportCollections())
throw new InvalidRequestException("Cannot use non-frozen collections with a non-composite PRIMARY KEY");
if (cfm.isSuper())
throw new InvalidRequestException("Cannot use non-frozen collections with super column families");
// reason mean that we can't allow adding a new collection with that name (see the ticket for details).
if (cfm.comparator.hasCollections()) {
CollectionType previous = cfm.comparator.collectionType() == null ? null : cfm.comparator.collectionType().defined.get(columnName.bytes);
if (previous != null && !type.isCompatibleWith(previous))
throw new InvalidRequestException(String.format("Cannot add a collection with the name %s " + "because a collection with the same name and a different type has already been used in the past", columnName));
}
cfm.comparator = cfm.comparator.addOrUpdateCollection(columnName, (CollectionType) type);
}
Integer componentIndex = cfm.comparator.isCompound() ? cfm.comparator.clusteringPrefixSize() : null;
cfm.addColumnDefinition(isStatic ? ColumnDefinition.staticDef(cfm, columnName.bytes, type, componentIndex) : ColumnDefinition.regularDef(cfm, columnName.bytes, type, componentIndex));
break;
case ALTER:
assert columnName != null;
if (def == null)
throw new InvalidRequestException(String.format("Column %s was not found in table %s", columnName, columnFamily()));
AbstractType<?> validatorType = validator.getType();
switch(def.kind) {
case PARTITION_KEY:
if (validatorType instanceof CounterColumnType)
throw new InvalidRequestException(String.format("counter type is not supported for PRIMARY KEY part %s", columnName));
if (cfm.getKeyValidator() instanceof CompositeType) {
List<AbstractType<?>> oldTypes = ((CompositeType) cfm.getKeyValidator()).types;
if (!validatorType.isValueCompatibleWith(oldTypes.get(def.position())))
throw new ConfigurationException(String.format("Cannot change %s from type %s to type %s: types are incompatible.", columnName, oldTypes.get(def.position()).asCQL3Type(), validator));
List<AbstractType<?>> newTypes = new ArrayList<AbstractType<?>>(oldTypes);
newTypes.set(def.position(), validatorType);
cfm.keyValidator(CompositeType.getInstance(newTypes));
} else {
if (!validatorType.isValueCompatibleWith(cfm.getKeyValidator()))
throw new ConfigurationException(String.format("Cannot change %s from type %s to type %s: types are incompatible.", columnName, cfm.getKeyValidator().asCQL3Type(), validator));
cfm.keyValidator(validatorType);
}
break;
case CLUSTERING_COLUMN:
if (!cfm.isCQL3Table())
throw new InvalidRequestException(String.format("Cannot alter clustering column %s in a non-CQL3 table", columnName));
AbstractType<?> oldType = cfm.comparator.subtype(def.position());
// Do note that we need isCompatibleWith here, not just isValueCompatibleWith.
if (!validatorType.isCompatibleWith(oldType))
throw new ConfigurationException(String.format("Cannot change %s from type %s to type %s: types are not order-compatible.", columnName, oldType.asCQL3Type(), validator));
cfm.comparator = cfm.comparator.setSubtype(def.position(), validatorType);
break;
case COMPACT_VALUE:
// See below
if (!validatorType.isValueCompatibleWith(cfm.getDefaultValidator()))
throw new ConfigurationException(String.format("Cannot change %s from type %s to type %s: types are incompatible.", columnName, cfm.getDefaultValidator().asCQL3Type(), validator));
cfm.defaultValidator(validatorType);
break;
case REGULAR:
case STATIC:
// ColumnDefinition already).
if (!validatorType.isValueCompatibleWith(def.type))
throw new ConfigurationException(String.format("Cannot change %s from type %s to type %s: types are incompatible.", columnName, def.type.asCQL3Type(), validator));
// in the comparator and the one in the ColumnDefinition as that would be dodgy).
if (validatorType.isCollection() && validatorType.isMultiCell())
cfm.comparator = cfm.comparator.addOrUpdateCollection(def.name, (CollectionType) validatorType);
break;
}
// In any case, we update the column definition
cfm.addOrReplaceColumnDefinition(def.withNewType(validatorType));
break;
case DROP:
assert columnName != null;
if (!cfm.isCQL3Table())
throw new InvalidRequestException("Cannot drop columns from a non-CQL3 table");
if (def == null)
throw new InvalidRequestException(String.format("Column %s was not found in table %s", columnName, columnFamily()));
switch(def.kind) {
case PARTITION_KEY:
case CLUSTERING_COLUMN:
throw new InvalidRequestException(String.format("Cannot drop PRIMARY KEY part %s", columnName));
case REGULAR:
case STATIC:
ColumnDefinition toDelete = null;
for (ColumnDefinition columnDef : cfm.regularAndStaticColumns()) {
if (columnDef.name.equals(columnName)) {
toDelete = columnDef;
break;
}
}
assert toDelete != null;
cfm.removeColumnDefinition(toDelete);
cfm.recordColumnDrop(toDelete);
break;
}
break;
case OPTS:
if (cfProps == null)
throw new InvalidRequestException("ALTER TABLE WITH invoked, but no parameters found");
cfProps.validate();
if (meta.isCounter() && cfProps.getDefaultTimeToLive() > 0)
throw new InvalidRequestException("Cannot set default_time_to_live on a table with counters");
cfProps.applyToCFMetadata(cfm);
break;
case RENAME:
for (Map.Entry<ColumnIdentifier.Raw, ColumnIdentifier.Raw> entry : renames.entrySet()) {
ColumnIdentifier from = entry.getKey().prepare(cfm);
ColumnIdentifier to = entry.getValue().prepare(cfm);
cfm.renameColumn(from, to);
}
break;
}
MigrationManager.announceColumnFamilyUpdate(cfm, isLocalOnly);
return true;
}
use of org.apache.cassandra.config.CFMetaData in project cassandra by palantir.
the class UpdateParameters method getPrefetchedList.
/**
* Returns the prefetched list with the already performed modifications.
* <p>If no modification have yet been performed this method will return the fetched list.
* If some modifications (updates or deletions) have already been done the list returned
* will be the result of the merge of the fetched list and of the pending mutations.</p>
*
* @param rowKey the row key
* @param cql3ColumnName the column name
* @param cf the pending modifications
* @return the prefetched list with the already performed modifications
*/
public List<Cell> getPrefetchedList(ByteBuffer rowKey, ColumnIdentifier cql3ColumnName, ColumnFamily cf) {
if (prefetchedLists == null)
return Collections.emptyList();
CQL3Row row = prefetchedLists.get(rowKey);
List<Cell> cql3List = row == null ? Collections.<Cell>emptyList() : row.getMultiCellColumn(cql3ColumnName);
if (!cf.isEmpty()) {
ColumnFamily currentCf = cf.cloneMe();
for (Cell c : cql3List) currentCf.addColumn(c);
CFMetaData cfm = currentCf.metadata();
CQL3Row.RowIterator iterator = cfm.comparator.CQL3RowBuilder(cfm, timestamp).group(currentCf.iterator());
// We can only update one CQ3Row per partition key at a time (we don't allow IN for clustering key)
cql3List = iterator.hasNext() ? iterator.next().getMultiCellColumn(cql3ColumnName) : null;
}
return (cql3List == null) ? Collections.<Cell>emptyList() : cql3List;
}
use of org.apache.cassandra.config.CFMetaData in project cassandra by palantir.
the class CassandraStorage method getColumnMeta.
/**
* get column meta data
*/
protected List<ColumnDef> getColumnMeta(Cassandra.Client client, boolean cassandraStorage, boolean includeCompactValueColumn) throws org.apache.cassandra.thrift.InvalidRequestException, UnavailableException, TimedOutException, SchemaDisagreementException, TException, CharacterCodingException, org.apache.cassandra.exceptions.InvalidRequestException, ConfigurationException, NotFoundException {
String query = String.format("SELECT column_name, validator, index_type, type " + "FROM %s.%s " + "WHERE keyspace_name = '%s' AND columnfamily_name = '%s'", SystemKeyspace.NAME, LegacySchemaTables.COLUMNS, keyspace, column_family);
CqlResult result = client.execute_cql3_query(ByteBufferUtil.bytes(query), Compression.NONE, ConsistencyLevel.ONE);
List<CqlRow> rows = result.rows;
List<ColumnDef> columnDefs = new ArrayList<ColumnDef>();
if (rows == null || rows.isEmpty()) {
// if CassandraStorage, just return the empty list
if (cassandraStorage)
return columnDefs;
// otherwise for CqlNativeStorage, check metadata for classic thrift tables
CFMetaData cfm = getCFMetaData(keyspace, column_family, client);
for (ColumnDefinition def : cfm.regularAndStaticColumns()) {
ColumnDef cDef = new ColumnDef();
String columnName = def.name.toString();
String type = def.type.toString();
logger.trace("name: {}, type: {} ", columnName, type);
cDef.name = ByteBufferUtil.bytes(columnName);
cDef.validation_class = type;
columnDefs.add(cDef);
}
// could have already processed it as schema_columnfamilies.value_alias
if (columnDefs.size() == 0 && includeCompactValueColumn && cfm.compactValueColumn() != null) {
ColumnDefinition def = cfm.compactValueColumn();
if ("value".equals(def.name.toString())) {
ColumnDef cDef = new ColumnDef();
cDef.name = def.name.bytes;
cDef.validation_class = def.type.toString();
columnDefs.add(cDef);
}
}
return columnDefs;
}
Iterator<CqlRow> iterator = rows.iterator();
while (iterator.hasNext()) {
CqlRow row = iterator.next();
ColumnDef cDef = new ColumnDef();
String type = ByteBufferUtil.string(row.getColumns().get(3).value);
if (!type.equals("regular"))
continue;
cDef.setName(ByteBufferUtil.clone(row.getColumns().get(0).value));
cDef.validation_class = ByteBufferUtil.string(row.getColumns().get(1).value);
ByteBuffer indexType = row.getColumns().get(2).value;
if (indexType != null)
cDef.index_type = getIndexType(ByteBufferUtil.string(indexType));
columnDefs.add(cDef);
}
return columnDefs;
}
use of org.apache.cassandra.config.CFMetaData in project cassandra by palantir.
the class LongFlushMemtableTest method testFlushMemtables.
@Test
public void testFlushMemtables() throws ConfigurationException {
Keyspace keyspace = Keyspace.open(KEYSPACE1);
for (int i = 0; i < 100; i++) {
CFMetaData metadata = CFMetaData.denseCFMetaData(keyspace.getName(), "_CF" + i, UTF8Type.instance);
MigrationManager.announceNewColumnFamily(metadata);
}
for (int j = 0; j < 200; j++) {
for (int i = 0; i < 100; i++) {
Mutation rm = new Mutation(KEYSPACE1, ByteBufferUtil.bytes("key" + j));
ColumnFamily cf = ArrayBackedSortedColumns.factory.create(KEYSPACE1, "_CF" + i);
// don't cheat by allocating this outside of the loop; that defeats the purpose of deliberately using lots of memory
ByteBuffer value = ByteBuffer.allocate(100000);
cf.addColumn(new BufferCell(Util.cellname("c"), value));
rm.add(cf);
rm.applyUnsafe();
}
}
int flushes = 0;
for (ColumnFamilyStore cfs : ColumnFamilyStore.all()) {
if (cfs.name.startsWith("_CF"))
flushes += cfs.metric.memtableSwitchCount.getCount();
}
assert flushes > 0;
}
Aggregations