Search in sources :

Example 26 with CFMetaData

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);
}
Also used : StatsMetadata(org.apache.cassandra.io.sstable.metadata.StatsMetadata) SSTableWriter(org.apache.cassandra.io.sstable.format.SSTableWriter) SSTableReader(org.apache.cassandra.io.sstable.format.SSTableReader) CFMetaData(org.apache.cassandra.config.CFMetaData) Test(org.junit.Test)

Example 27 with CFMetaData

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;
}
Also used : ArrayList(java.util.ArrayList) ColumnDefinition(org.apache.cassandra.config.ColumnDefinition) CFMetaData(org.apache.cassandra.config.CFMetaData) Map(java.util.Map)

Example 28 with CFMetaData

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;
}
Also used : CFMetaData(org.apache.cassandra.config.CFMetaData)

Example 29 with CFMetaData

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;
}
Also used : CFMetaData(org.apache.cassandra.config.CFMetaData) ByteBuffer(java.nio.ByteBuffer) ColumnDefinition(org.apache.cassandra.config.ColumnDefinition)

Example 30 with CFMetaData

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;
}
Also used : CFMetaData(org.apache.cassandra.config.CFMetaData) ByteBuffer(java.nio.ByteBuffer) Test(org.junit.Test)

Aggregations

CFMetaData (org.apache.cassandra.config.CFMetaData)126 Test (org.junit.Test)51 ByteBuffer (java.nio.ByteBuffer)36 Composite (org.apache.cassandra.db.composites.Composite)23 ColumnDefinition (org.apache.cassandra.config.ColumnDefinition)14 KSMetaData (org.apache.cassandra.config.KSMetaData)8 File (java.io.File)6 Map (java.util.Map)6 DatabaseDescriptor (org.apache.cassandra.config.DatabaseDescriptor)5 TriggerDefinition (org.apache.cassandra.config.TriggerDefinition)5 AbstractType (org.apache.cassandra.db.marshal.AbstractType)5 ConfigurationException (org.apache.cassandra.exceptions.ConfigurationException)5 IDiskAtomFilter (org.apache.cassandra.db.filter.IDiskAtomFilter)4 SSTableReader (org.apache.cassandra.io.sstable.format.SSTableReader)4 InetAddress (java.net.InetAddress)3 ArrayList (java.util.ArrayList)3 UUID (java.util.UUID)3 ConfigurationException (org.apache.cassandra.config.ConfigurationException)3 BufferCell (org.apache.cassandra.db.BufferCell)3 Cell (org.apache.cassandra.db.Cell)3