Search in sources :

Example 36 with TableId

use of org.apache.cassandra.schema.TableId in project cassandra by apache.

the class Keyspace method applyInternal.

/**
 * This method appends a row to the global CommitLog, then updates memtables and indexes.
 *
 * @param mutation       the row to write.  Must not be modified after calling apply, since commitlog append
 *                       may happen concurrently, depending on the CL Executor type.
 * @param makeDurable    if true, don't return unless write has been made durable
 * @param updateIndexes  false to disable index updates (used by CollationController "defragmenting")
 * @param isDroppable    true if this should throw WriteTimeoutException if it does not acquire lock within write_request_timeout
 * @param isDeferrable   true if caller is not waiting for future to complete, so that future may be deferred
 */
private Future<?> applyInternal(final Mutation mutation, final boolean makeDurable, boolean updateIndexes, boolean isDroppable, boolean isDeferrable, Promise<?> future) {
    if (TEST_FAIL_WRITES && metadata.name.equals(TEST_FAIL_WRITES_KS))
        throw new RuntimeException("Testing write failures");
    Lock[] locks = null;
    boolean requiresViewUpdate = updateIndexes && viewManager.updatesAffectView(Collections.singleton(mutation), false);
    if (requiresViewUpdate) {
        mutation.viewLockAcquireStart.compareAndSet(0L, currentTimeMillis());
        // the order of lock acquisition doesn't matter (from a deadlock perspective) because we only use tryLock()
        Collection<TableId> tableIds = mutation.getTableIds();
        Iterator<TableId> idIterator = tableIds.iterator();
        locks = new Lock[tableIds.size()];
        for (int i = 0; i < tableIds.size(); i++) {
            TableId tableId = idIterator.next();
            int lockKey = Objects.hash(mutation.key().getKey(), tableId);
            while (true) {
                Lock lock = null;
                if (TEST_FAIL_MV_LOCKS_COUNT == 0)
                    lock = ViewManager.acquireLockFor(lockKey);
                else
                    TEST_FAIL_MV_LOCKS_COUNT--;
                if (lock == null) {
                    // throw WTE only if request is droppable
                    if (isDroppable && (approxTime.isAfter(mutation.approxCreatedAtNanos + DatabaseDescriptor.getWriteRpcTimeout(NANOSECONDS)))) {
                        for (int j = 0; j < i; j++) locks[j].unlock();
                        if (logger.isTraceEnabled())
                            logger.trace("Could not acquire lock for {} and table {}", ByteBufferUtil.bytesToHex(mutation.key().getKey()), columnFamilyStores.get(tableId).name);
                        Tracing.trace("Could not acquire MV lock");
                        if (future != null) {
                            future.tryFailure(new WriteTimeoutException(WriteType.VIEW, ConsistencyLevel.LOCAL_ONE, 0, 1));
                            return future;
                        } else
                            throw new WriteTimeoutException(WriteType.VIEW, ConsistencyLevel.LOCAL_ONE, 0, 1);
                    } else if (isDeferrable) {
                        for (int j = 0; j < i; j++) locks[j].unlock();
                        // This view update can't happen right now. so rather than keep this thread busy
                        // we will re-apply ourself to the queue and try again later
                        Stage.MUTATION.execute(() -> applyInternal(mutation, makeDurable, true, isDroppable, true, future));
                        return future;
                    } else {
                        // being blocked by waiting for futures which will never be processed as all workers are blocked
                        try {
                            // Wait a little bit before retrying to lock
                            Thread.sleep(10);
                        } catch (InterruptedException e) {
                            throw new UncheckedInterruptedException(e);
                        }
                        continue;
                    }
                } else {
                    locks[i] = lock;
                }
                break;
            }
        }
        long acquireTime = currentTimeMillis() - mutation.viewLockAcquireStart.get();
        // Bulk non-droppable operations (e.g. commitlog replay, hint delivery) are not measured
        if (isDroppable) {
            for (TableId tableId : tableIds) columnFamilyStores.get(tableId).metric.viewLockAcquireTime.update(acquireTime, MILLISECONDS);
        }
    }
    int nowInSec = FBUtilities.nowInSeconds();
    try (WriteContext ctx = getWriteHandler().beginWrite(mutation, makeDurable)) {
        for (PartitionUpdate upd : mutation.getPartitionUpdates()) {
            ColumnFamilyStore cfs = columnFamilyStores.get(upd.metadata().id);
            if (cfs == null) {
                logger.error("Attempting to mutate non-existant table {} ({}.{})", upd.metadata().id, upd.metadata().keyspace, upd.metadata().name);
                continue;
            }
            AtomicLong baseComplete = new AtomicLong(Long.MAX_VALUE);
            if (requiresViewUpdate) {
                try {
                    Tracing.trace("Creating materialized view mutations from base table replica");
                    viewManager.forTable(upd.metadata().id).pushViewReplicaUpdates(upd, makeDurable, baseComplete);
                } catch (Throwable t) {
                    JVMStabilityInspector.inspectThrowable(t);
                    logger.error(String.format("Unknown exception caught while attempting to update MaterializedView! %s", upd.metadata().toString()), t);
                    throw t;
                }
            }
            UpdateTransaction indexTransaction = updateIndexes ? cfs.indexManager.newUpdateTransaction(upd, ctx, nowInSec) : UpdateTransaction.NO_OP;
            cfs.getWriteHandler().write(upd, ctx, indexTransaction);
            if (requiresViewUpdate)
                baseComplete.set(currentTimeMillis());
        }
        if (future != null) {
            future.trySuccess(null);
        }
        return future;
    } finally {
        if (locks != null) {
            for (Lock lock : locks) if (lock != null)
                lock.unlock();
        }
    }
}
Also used : TableId(org.apache.cassandra.schema.TableId) UpdateTransaction(org.apache.cassandra.index.transactions.UpdateTransaction) UncheckedInterruptedException(org.apache.cassandra.utils.concurrent.UncheckedInterruptedException) Lock(java.util.concurrent.locks.Lock) WriteTimeoutException(org.apache.cassandra.exceptions.WriteTimeoutException) AtomicLong(java.util.concurrent.atomic.AtomicLong) UncheckedInterruptedException(org.apache.cassandra.utils.concurrent.UncheckedInterruptedException) PartitionUpdate(org.apache.cassandra.db.partitions.PartitionUpdate)

Example 37 with TableId

use of org.apache.cassandra.schema.TableId in project cassandra by apache.

the class Mutation method toString.

public String toString(boolean shallow) {
    StringBuilder buff = new StringBuilder("Mutation(");
    buff.append("keyspace='").append(keyspaceName).append('\'');
    buff.append(", key='").append(ByteBufferUtil.bytesToHex(key.getKey())).append('\'');
    buff.append(", modifications=[");
    if (shallow) {
        List<String> cfnames = new ArrayList<>(modifications.size());
        for (TableId tableId : modifications.keySet()) {
            TableMetadata cfm = Schema.instance.getTableMetadata(tableId);
            cfnames.add(cfm == null ? "-dropped-" : cfm.name);
        }
        buff.append(StringUtils.join(cfnames, ", "));
    } else {
        buff.append("\n  ").append(StringUtils.join(modifications.values(), "\n  ")).append('\n');
    }
    return buff.append("])").toString();
}
Also used : TableId(org.apache.cassandra.schema.TableId) TableMetadata(org.apache.cassandra.schema.TableMetadata)

Example 38 with TableId

use of org.apache.cassandra.schema.TableId in project cassandra by apache.

the class Mutation method merge.

/**
 * Creates a new mutation that merges all the provided mutations.
 *
 * @param mutations the mutations to merge together. All mutation must be
 * on the same keyspace and partition key. There should also be at least one
 * mutation.
 * @return a mutation that contains all the modifications contained in {@code mutations}.
 *
 * @throws IllegalArgumentException if not all the mutations are on the same
 * keyspace and key.
 */
public static Mutation merge(List<Mutation> mutations) {
    assert !mutations.isEmpty();
    if (mutations.size() == 1)
        return mutations.get(0);
    Set<TableId> updatedTables = new HashSet<>();
    String ks = null;
    DecoratedKey key = null;
    for (Mutation mutation : mutations) {
        updatedTables.addAll(mutation.modifications.keySet());
        if (ks != null && !ks.equals(mutation.keyspaceName))
            throw new IllegalArgumentException();
        if (key != null && !key.equals(mutation.key))
            throw new IllegalArgumentException();
        ks = mutation.keyspaceName;
        key = mutation.key;
    }
    List<PartitionUpdate> updates = new ArrayList<>(mutations.size());
    ImmutableMap.Builder<TableId, PartitionUpdate> modifications = new ImmutableMap.Builder<>();
    for (TableId table : updatedTables) {
        for (Mutation mutation : mutations) {
            PartitionUpdate upd = mutation.modifications.get(table);
            if (upd != null)
                updates.add(upd);
        }
        if (updates.isEmpty())
            continue;
        modifications.put(table, updates.size() == 1 ? updates.get(0) : PartitionUpdate.merge(updates));
        updates.clear();
    }
    return new Mutation(ks, key, modifications.build(), approxTime.now());
}
Also used : TableId(org.apache.cassandra.schema.TableId) ImmutableMap(com.google.common.collect.ImmutableMap) PartitionUpdate(org.apache.cassandra.db.partitions.PartitionUpdate)

Example 39 with TableId

use of org.apache.cassandra.schema.TableId in project cassandra by apache.

the class CommitLogTest method testDontDeleteIfDirty.

@Test
public void testDontDeleteIfDirty() throws Exception {
    Keyspace ks = Keyspace.open(KEYSPACE1);
    ColumnFamilyStore cfs1 = ks.getColumnFamilyStore(STANDARD1);
    ColumnFamilyStore cfs2 = ks.getColumnFamilyStore(STANDARD2);
    // Roughly 32 MiB mutation
    Mutation m = new RowUpdateBuilder(cfs1.metadata(), 0, "k").clustering("bytes").add("val", ByteBuffer.allocate(DatabaseDescriptor.getCommitLogSegmentSize() / 4)).build();
    // Adding it 5 times
    CommitLog.instance.add(m);
    CommitLog.instance.add(m);
    CommitLog.instance.add(m);
    CommitLog.instance.add(m);
    CommitLog.instance.add(m);
    // Adding new mutation on another CF
    Mutation m2 = new RowUpdateBuilder(cfs2.metadata(), 0, "k").clustering("bytes").add("val", ByteBuffer.allocate(4)).build();
    CommitLog.instance.add(m2);
    assertEquals(2, CommitLog.instance.segmentManager.getActiveSegments().size());
    TableId id2 = m2.getTableIds().iterator().next();
    CommitLog.instance.discardCompletedSegments(id2, CommitLogPosition.NONE, CommitLog.instance.getCurrentPosition());
    // Assert we still have both our segments
    assertEquals(2, CommitLog.instance.segmentManager.getActiveSegments().size());
}
Also used : TableId(org.apache.cassandra.schema.TableId)

Example 40 with TableId

use of org.apache.cassandra.schema.TableId in project cassandra by apache.

the class CommitlogShutdownTest method testShutdownWithPendingTasks.

@Test
@BMRule(name = "Make removing commitlog segments slow", targetClass = "CommitLogSegment", targetMethod = "discard", action = "Thread.sleep(50)")
public void testShutdownWithPendingTasks() throws Exception {
    new Random().nextBytes(entropy);
    DatabaseDescriptor.daemonInitialization();
    DatabaseDescriptor.setCommitLogCompression(new ParameterizedClass("LZ4Compressor", ImmutableMap.of()));
    DatabaseDescriptor.setCommitLogSegmentSize(1);
    DatabaseDescriptor.setCommitLogSync(Config.CommitLogSync.periodic);
    DatabaseDescriptor.setCommitLogSyncPeriod(10 * 1000);
    SchemaLoader.prepareServer();
    SchemaLoader.createKeyspace(KEYSPACE1, KeyspaceParams.simple(1), SchemaLoader.standardCFMD(KEYSPACE1, STANDARD1, 0, AsciiType.instance, BytesType.instance));
    CompactionManager.instance.disableAutoCompaction();
    ColumnFamilyStore cfs1 = Keyspace.open(KEYSPACE1).getColumnFamilyStore(STANDARD1);
    final Mutation m = new RowUpdateBuilder(cfs1.metadata.get(), 0, "k").clustering("bytes").add("val", ByteBuffer.wrap(entropy)).build();
    // force creating several commitlog files
    for (int i = 0; i < 10; i++) {
        CommitLog.instance.add(m);
    }
    // schedule discarding completed segments and immediately issue a shutdown
    TableId tableId = m.getTableIds().iterator().next();
    CommitLog.instance.discardCompletedSegments(tableId, CommitLogPosition.NONE, CommitLog.instance.getCurrentPosition());
    CommitLog.instance.shutdownBlocking();
    // the shutdown should block until all logs except the currently active one and perhaps a new, empty one are gone
    Assert.assertTrue(new File(DatabaseDescriptor.getCommitLogLocation()).tryList().length <= 2);
}
Also used : TableId(org.apache.cassandra.schema.TableId) Random(java.util.Random) RowUpdateBuilder(org.apache.cassandra.db.RowUpdateBuilder) ParameterizedClass(org.apache.cassandra.config.ParameterizedClass) ColumnFamilyStore(org.apache.cassandra.db.ColumnFamilyStore) Mutation(org.apache.cassandra.db.Mutation) File(org.apache.cassandra.io.util.File) BMRule(org.jboss.byteman.contrib.bmunit.BMRule) Test(org.junit.Test)

Aggregations

TableId (org.apache.cassandra.schema.TableId)46 ColumnFamilyStore (org.apache.cassandra.db.ColumnFamilyStore)15 Test (org.junit.Test)9 TableMetadata (org.apache.cassandra.schema.TableMetadata)6 ImmutableMap (com.google.common.collect.ImmutableMap)5 ArrayList (java.util.ArrayList)5 Map (java.util.Map)5 SSTableReader (org.apache.cassandra.io.sstable.format.SSTableReader)5 IOException (java.io.IOException)4 Collection (java.util.Collection)4 HashMap (java.util.HashMap)4 LifecycleTransaction (org.apache.cassandra.db.lifecycle.LifecycleTransaction)4 InetAddressAndPort (org.apache.cassandra.locator.InetAddressAndPort)4 ActiveRepairService (org.apache.cassandra.service.ActiveRepairService)4 VisibleForTesting (com.google.common.annotations.VisibleForTesting)3 Iterables (com.google.common.collect.Iterables)3 Sets (com.google.common.collect.Sets)3 ByteBuffer (java.nio.ByteBuffer)3 List (java.util.List)3 Set (java.util.Set)3