You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by dc...@apache.org on 2020/09/16 20:42:51 UTC
[cassandra] branch trunk updated: NPE thrown while updating
speculative execution time if keyspace is removed during task execution
This is an automated email from the ASF dual-hosted git repository.
dcapwell pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/cassandra.git
The following commit(s) were added to refs/heads/trunk by this push:
new f670db4 NPE thrown while updating speculative execution time if keyspace is removed during task execution
f670db4 is described below
commit f670db4a0ec6c2d76b52fa1510f585c49b4f731e
Author: Caleb Rackliffe <ca...@gmail.com>
AuthorDate: Wed Sep 16 09:52:42 2020 -0700
NPE thrown while updating speculative execution time if keyspace is removed during task execution
patch by Caleb Rackliffe; reviewed by Aleksey Yeschenko, David Capwell for CASSANDRA-15949
---
CHANGES.txt | 1 +
src/java/org/apache/cassandra/db/Keyspace.java | 76 ++++++++++-------
src/java/org/apache/cassandra/db/ReadCommand.java | 6 +-
src/java/org/apache/cassandra/schema/Schema.java | 11 ++-
...leMetadataProvider.java => SchemaProvider.java} | 27 ++++++-
.../apache/cassandra/service/CassandraDaemon.java | 25 ++++--
.../unit/org/apache/cassandra/db/KeyspaceTest.java | 22 ++++-
.../net/MessageSerializationPropertyTest.java | 6 +-
.../cassandra/service/OptionalTasksTest.java | 94 ++++++++++++++++++++++
9 files changed, 220 insertions(+), 48 deletions(-)
diff --git a/CHANGES.txt b/CHANGES.txt
index 7761d87..90f5995 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -10,6 +10,7 @@
* When compaction gets interrupted, the exception should include the compactionId (CASSANDRA-15954)
* Make Table/Keyspace Metric Names Consistent With Each Other (CASSANDRA-15909)
* Mutating sstable component may race with entire-sstable-streaming(ZCS) causing checksum validation failure (CASSANDRA-15861)
+ * NPE thrown while updating speculative execution time if keyspace is removed during task execution (CASSANDRA-15949)
Merged from 3.11:
* Use IF NOT EXISTS for index and UDT create statements in snapshot schema files (CASSANDRA-13935)
* Make sure LCS handles duplicate sstable added/removed notifications correctly (CASSANDRA-14103)
diff --git a/src/java/org/apache/cassandra/db/Keyspace.java b/src/java/org/apache/cassandra/db/Keyspace.java
index fc4f56f..1b05a36 100644
--- a/src/java/org/apache/cassandra/db/Keyspace.java
+++ b/src/java/org/apache/cassandra/db/Keyspace.java
@@ -19,18 +19,29 @@ package org.apache.cassandra.db;
import java.io.File;
import java.io.IOException;
-import java.util.*;
-import java.util.concurrent.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
+import java.util.stream.Stream;
-import com.google.common.base.Function;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Iterables;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.cassandra.concurrent.Stage;
-import org.apache.cassandra.config.*;
+import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.db.compaction.CompactionManager;
import org.apache.cassandra.db.lifecycle.SSTableSet;
import org.apache.cassandra.db.partitions.PartitionUpdate;
@@ -48,14 +59,18 @@ import org.apache.cassandra.schema.KeyspaceMetadata;
import org.apache.cassandra.schema.ReplicationParams;
import org.apache.cassandra.schema.Schema;
import org.apache.cassandra.schema.SchemaConstants;
+import org.apache.cassandra.schema.SchemaProvider;
import org.apache.cassandra.schema.TableId;
import org.apache.cassandra.schema.TableMetadata;
import org.apache.cassandra.schema.TableMetadataRef;
import org.apache.cassandra.tracing.Tracing;
-import org.apache.cassandra.utils.*;
+import org.apache.cassandra.utils.ByteBufferUtil;
+import org.apache.cassandra.utils.FBUtilities;
+import org.apache.cassandra.utils.JVMStabilityInspector;
import org.apache.cassandra.utils.concurrent.OpOrder;
-import static java.util.concurrent.TimeUnit.*;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static org.apache.cassandra.utils.MonotonicClock.approxTime;
/**
@@ -93,14 +108,7 @@ public class Keyspace
private final KeyspaceWriteHandler writeHandler;
private volatile ReplicationParams replicationParams;
private final KeyspaceRepairManager repairManager;
-
- public static final Function<String,Keyspace> keyspaceTransformer = new Function<String, Keyspace>()
- {
- public Keyspace apply(String keyspaceName)
- {
- return Keyspace.open(keyspaceName);
- }
- };
+ private final SchemaProvider schema;
private static volatile boolean initialized = false;
@@ -121,21 +129,22 @@ public class Keyspace
return open(keyspaceName, Schema.instance, false);
}
- private static Keyspace open(String keyspaceName, Schema schema, boolean loadSSTables)
+ @VisibleForTesting
+ static Keyspace open(String keyspaceName, SchemaProvider schema, boolean loadSSTables)
{
Keyspace keyspaceInstance = schema.getKeyspaceInstance(keyspaceName);
if (keyspaceInstance == null)
{
- // instantiate the Keyspace. we could use putIfAbsent but it's important to making sure it is only done once
- // per keyspace, so we synchronize and re-check before doing it.
- synchronized (Keyspace.class)
+ // Instantiate the Keyspace while holding the Schema lock. This both ensures we only do it once per
+ // keyspace, and also ensures that Keyspace construction sees a consistent view of the schema.
+ synchronized (schema)
{
keyspaceInstance = schema.getKeyspaceInstance(keyspaceName);
if (keyspaceInstance == null)
{
// open and store the keyspace
- keyspaceInstance = new Keyspace(keyspaceName, loadSSTables);
+ keyspaceInstance = new Keyspace(keyspaceName, schema, loadSSTables);
schema.storeKeyspaceInstance(keyspaceInstance);
}
}
@@ -150,7 +159,7 @@ public class Keyspace
public static Keyspace clear(String keyspaceName, Schema schema)
{
- synchronized (Keyspace.class)
+ synchronized (schema)
{
Keyspace t = schema.removeKeyspaceInstance(keyspaceName);
if (t != null)
@@ -207,7 +216,7 @@ public class Keyspace
public ColumnFamilyStore getColumnFamilyStore(String cfName)
{
- TableMetadata table = Schema.instance.getTableMetadata(getName(), cfName);
+ TableMetadata table = schema.getTableMetadata(getName(), cfName);
if (table == null)
throw new IllegalArgumentException(String.format("Unknown keyspace/cf pair (%s.%s)", getName(), cfName));
return getColumnFamilyStore(table.id);
@@ -324,10 +333,12 @@ public class Keyspace
return list;
}
- private Keyspace(String keyspaceName, boolean loadSSTables)
+ private Keyspace(String keyspaceName, SchemaProvider schema, boolean loadSSTables)
{
- metadata = Schema.instance.getKeyspaceMetadata(keyspaceName);
+ this.schema = schema;
+ metadata = schema.getKeyspaceMetadata(keyspaceName);
assert metadata != null : "Unknown keyspace " + keyspaceName;
+
if (metadata.isVirtual())
throw new IllegalStateException("Cannot initialize Keyspace with virtual metadata " + keyspaceName);
createReplicationStrategy(metadata);
@@ -337,7 +348,7 @@ public class Keyspace
for (TableMetadata cfm : metadata.tablesAndViews())
{
logger.trace("Initializing {}.{}", getName(), cfm.name);
- initCf(Schema.instance.getTableMetadataRef(cfm.id), loadSSTables);
+ initCf(schema.getTableMetadataRef(cfm.id), loadSSTables);
}
this.viewManager.reload(false);
@@ -347,6 +358,7 @@ public class Keyspace
private Keyspace(KeyspaceMetadata metadata)
{
+ this.schema = Schema.instance;
this.metadata = metadata;
createReplicationStrategy(metadata);
this.metric = new KeyspaceMetrics(this);
@@ -743,22 +755,30 @@ public class Keyspace
public static Iterable<Keyspace> all()
{
- return Iterables.transform(Schema.instance.getKeyspaces(), keyspaceTransformer);
+ return Iterables.transform(Schema.instance.getKeyspaces(), Keyspace::open);
+ }
+
+ /**
+ * @return a {@link Stream} of all existing/open {@link Keyspace} instances
+ */
+ public static Stream<Keyspace> allExisting()
+ {
+ return Schema.instance.getKeyspaces().stream().map(Schema.instance::getKeyspaceInstance).filter(Objects::nonNull);
}
public static Iterable<Keyspace> nonSystem()
{
- return Iterables.transform(Schema.instance.getNonSystemKeyspaces(), keyspaceTransformer);
+ return Iterables.transform(Schema.instance.getNonSystemKeyspaces(), Keyspace::open);
}
public static Iterable<Keyspace> nonLocalStrategy()
{
- return Iterables.transform(Schema.instance.getNonLocalStrategyKeyspaces(), keyspaceTransformer);
+ return Iterables.transform(Schema.instance.getNonLocalStrategyKeyspaces(), Keyspace::open);
}
public static Iterable<Keyspace> system()
{
- return Iterables.transform(SchemaConstants.LOCAL_SYSTEM_KEYSPACE_NAMES, keyspaceTransformer);
+ return Iterables.transform(SchemaConstants.LOCAL_SYSTEM_KEYSPACE_NAMES, Keyspace::open);
}
@Override
diff --git a/src/java/org/apache/cassandra/db/ReadCommand.java b/src/java/org/apache/cassandra/db/ReadCommand.java
index 6b19ed9..884dbe0 100644
--- a/src/java/org/apache/cassandra/db/ReadCommand.java
+++ b/src/java/org/apache/cassandra/db/ReadCommand.java
@@ -61,7 +61,7 @@ import org.apache.cassandra.schema.Schema;
import org.apache.cassandra.schema.SchemaConstants;
import org.apache.cassandra.schema.TableId;
import org.apache.cassandra.schema.TableMetadata;
-import org.apache.cassandra.schema.TableMetadataProvider;
+import org.apache.cassandra.schema.SchemaProvider;
import org.apache.cassandra.service.ActiveRepairService;
import org.apache.cassandra.service.ClientWarn;
import org.apache.cassandra.tracing.Tracing;
@@ -909,7 +909,7 @@ public abstract class ReadCommand extends AbstractReadQuery
@VisibleForTesting
public static class Serializer implements IVersionedSerializer<ReadCommand>
{
- private final TableMetadataProvider schema;
+ private final SchemaProvider schema;
public Serializer()
{
@@ -917,7 +917,7 @@ public abstract class ReadCommand extends AbstractReadQuery
}
@VisibleForTesting
- public Serializer(TableMetadataProvider schema)
+ public Serializer(SchemaProvider schema)
{
this.schema = Objects.requireNonNull(schema, "schema");
}
diff --git a/src/java/org/apache/cassandra/schema/Schema.java b/src/java/org/apache/cassandra/schema/Schema.java
index 0498993..4b70f67 100644
--- a/src/java/org/apache/cassandra/schema/Schema.java
+++ b/src/java/org/apache/cassandra/schema/Schema.java
@@ -20,7 +20,6 @@ package org.apache.cassandra.schema;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;
-import javax.annotation.Nullable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.MapDifference;
@@ -36,7 +35,6 @@ import org.apache.cassandra.db.marshal.UserType;
import org.apache.cassandra.db.virtual.VirtualKeyspaceRegistry;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.exceptions.InvalidRequestException;
-import org.apache.cassandra.exceptions.UnknownTableException;
import org.apache.cassandra.gms.ApplicationState;
import org.apache.cassandra.gms.Gossiper;
import org.apache.cassandra.io.sstable.Descriptor;
@@ -51,7 +49,7 @@ import static java.lang.String.format;
import static com.google.common.collect.Iterables.size;
-public final class Schema implements TableMetadataProvider
+public final class Schema implements SchemaProvider
{
public static final Schema instance = new Schema();
@@ -192,6 +190,7 @@ public final class Schema implements TableMetadataProvider
*
* @return Keyspace object or null if keyspace was not found
*/
+ @Override
public Keyspace getKeyspaceInstance(String keyspaceName)
{
return keyspaceInstances.get(keyspaceName);
@@ -219,6 +218,7 @@ public final class Schema implements TableMetadataProvider
*
* @throws IllegalArgumentException if Keyspace is already stored
*/
+ @Override
public void storeKeyspaceInstance(Keyspace keyspace)
{
if (keyspaceInstances.containsKey(keyspace.getName()))
@@ -283,6 +283,7 @@ public final class Schema implements TableMetadataProvider
*
* @return The keyspace metadata or null if it wasn't found
*/
+ @Override
public KeyspaceMetadata getKeyspaceMetadata(String keyspaceName)
{
assert keyspaceName != null;
@@ -356,6 +357,7 @@ public final class Schema implements TableMetadataProvider
*
* @return TableMetadataRef object or null if it wasn't found
*/
+ @Override
public TableMetadataRef getTableMetadataRef(String keyspace, String table)
{
TableMetadata tm = getTableMetadata(keyspace, table);
@@ -381,11 +383,13 @@ public final class Schema implements TableMetadataProvider
*
* @return metadata about Table or View
*/
+ @Override
public TableMetadataRef getTableMetadataRef(TableId id)
{
return metadataRefs.get(id);
}
+ @Override
public TableMetadataRef getTableMetadataRef(Descriptor descriptor)
{
return getTableMetadataRef(descriptor.ksname, descriptor.cfname);
@@ -418,7 +422,6 @@ public final class Schema implements TableMetadataProvider
}
@Override
- @Nullable
public TableMetadata getTableMetadata(TableId id)
{
TableMetadata table = keyspaces.getTableOrViewNullable(id);
diff --git a/src/java/org/apache/cassandra/schema/TableMetadataProvider.java b/src/java/org/apache/cassandra/schema/SchemaProvider.java
similarity index 50%
rename from src/java/org/apache/cassandra/schema/TableMetadataProvider.java
rename to src/java/org/apache/cassandra/schema/SchemaProvider.java
index 7c5ae8a..51c4e6b 100644
--- a/src/java/org/apache/cassandra/schema/TableMetadataProvider.java
+++ b/src/java/org/apache/cassandra/schema/SchemaProvider.java
@@ -2,13 +2,26 @@ package org.apache.cassandra.schema;
import javax.annotation.Nullable;
+import org.apache.cassandra.db.Keyspace;
import org.apache.cassandra.exceptions.UnknownTableException;
+import org.apache.cassandra.io.sstable.Descriptor;
-public interface TableMetadataProvider
+public interface SchemaProvider
{
@Nullable
+ Keyspace getKeyspaceInstance(String keyspaceName);
+
+ void storeKeyspaceInstance(Keyspace keyspace);
+
+ @Nullable
+ KeyspaceMetadata getKeyspaceMetadata(String keyspaceName);
+
+ @Nullable
TableMetadata getTableMetadata(TableId id);
+ @Nullable
+ TableMetadata getTableMetadata(String keyspace, String table);
+
default TableMetadata getExistingTableMetadata(TableId id) throws UnknownTableException
{
TableMetadata metadata = getTableMetadata(id);
@@ -21,4 +34,16 @@ public interface TableMetadataProvider
id);
throw new UnknownTableException(message, id);
}
+
+ @Nullable
+ TableMetadataRef getTableMetadataRef(String keyspace, String table);
+
+ @Nullable
+ TableMetadataRef getTableMetadataRef(TableId id);
+
+ @Nullable
+ default TableMetadataRef getTableMetadataRef(Descriptor descriptor)
+ {
+ return getTableMetadataRef(descriptor.ksname, descriptor.cfname);
+ }
}
diff --git a/src/java/org/apache/cassandra/service/CassandraDaemon.java b/src/java/org/apache/cassandra/service/CassandraDaemon.java
index e1a254a..4b92d69 100644
--- a/src/java/org/apache/cassandra/service/CassandraDaemon.java
+++ b/src/java/org/apache/cassandra/service/CassandraDaemon.java
@@ -167,6 +167,21 @@ public class CassandraDaemon
}
}
+ @VisibleForTesting
+ public static Runnable SPECULATION_THRESHOLD_UPDATER =
+ () ->
+ {
+ try
+ {
+ Keyspace.allExisting().forEach(k -> k.getColumnFamilyStores().forEach(ColumnFamilyStore::updateSpeculationThreshold));
+ }
+ catch (Throwable t)
+ {
+ logger.warn("Failed to update speculative retry thresholds.", t);
+ JVMStabilityInspector.inspectThrowable(t);
+ }
+ };
+
static final CassandraDaemon instance = new CassandraDaemon();
private NativeTransportService nativeTransportService;
@@ -431,12 +446,10 @@ public class CassandraDaemon
ScheduledExecutors.optionalTasks.scheduleWithFixedDelay(ColumnFamilyStore.getBackgroundCompactionTaskSubmitter(), 5, 1, TimeUnit.MINUTES);
// schedule periodic recomputation of speculative retry thresholds
- ScheduledExecutors.optionalTasks.scheduleWithFixedDelay(
- () -> Keyspace.all().forEach(k -> k.getColumnFamilyStores().forEach(ColumnFamilyStore::updateSpeculationThreshold)),
- DatabaseDescriptor.getReadRpcTimeout(NANOSECONDS),
- DatabaseDescriptor.getReadRpcTimeout(NANOSECONDS),
- NANOSECONDS
- );
+ ScheduledExecutors.optionalTasks.scheduleWithFixedDelay(SPECULATION_THRESHOLD_UPDATER,
+ DatabaseDescriptor.getReadRpcTimeout(NANOSECONDS),
+ DatabaseDescriptor.getReadRpcTimeout(NANOSECONDS),
+ NANOSECONDS);
initializeNativeTransport();
diff --git a/test/unit/org/apache/cassandra/db/KeyspaceTest.java b/test/unit/org/apache/cassandra/db/KeyspaceTest.java
index c549b85..fd15366 100644
--- a/test/unit/org/apache/cassandra/db/KeyspaceTest.java
+++ b/test/unit/org/apache/cassandra/db/KeyspaceTest.java
@@ -1,4 +1,4 @@
-/**
+/*
* 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
@@ -21,6 +21,10 @@ package org.apache.cassandra.db;
import java.nio.ByteBuffer;
import java.util.*;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.mockito.Mockito;
+
import org.apache.cassandra.Util;
import org.apache.cassandra.cql3.CQLTester;
import org.apache.cassandra.cql3.ColumnIdentifier;
@@ -33,13 +37,12 @@ import org.apache.cassandra.db.filter.*;
import org.apache.cassandra.db.partitions.PartitionIterator;
import org.apache.cassandra.io.sstable.format.SSTableReader;
import org.apache.cassandra.metrics.ClearableHistogram;
+import org.apache.cassandra.schema.SchemaProvider;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.FBUtilities;
-import org.junit.Test;
import static org.junit.Assert.*;
-
public class KeyspaceTest extends CQLTester
{
// Test needs synchronous table drop to avoid flushes causing flaky failures of testLimitSSTables
@@ -492,4 +495,17 @@ public class KeyspaceTest extends CQLTester
cfs.metadata(), FBUtilities.nowInSeconds(), ColumnFilter.all(cfs.metadata()), RowFilter.NONE, DataLimits.cqlLimits(3), Util.dk("0"), filter);
assertRowsInResult(cfs, command);
}
+
+ @Test
+ public void shouldThrowOnMissingKeyspace()
+ {
+ SchemaProvider schema = Mockito.mock(SchemaProvider.class);
+ String ksName = "MissingKeyspace";
+
+ Mockito.when(schema.getKeyspaceMetadata(ksName)).thenReturn(null);
+
+ Assertions.assertThatThrownBy(() -> Keyspace.open(ksName, schema, false))
+ .isInstanceOf(AssertionError.class)
+ .hasMessage("Unknown keyspace " + ksName);
+ }
}
diff --git a/test/unit/org/apache/cassandra/net/MessageSerializationPropertyTest.java b/test/unit/org/apache/cassandra/net/MessageSerializationPropertyTest.java
index 7750f15..3cde6f9 100644
--- a/test/unit/org/apache/cassandra/net/MessageSerializationPropertyTest.java
+++ b/test/unit/org/apache/cassandra/net/MessageSerializationPropertyTest.java
@@ -32,7 +32,7 @@ import org.apache.cassandra.io.util.DataInputBuffer;
import org.apache.cassandra.io.util.DataOutputBuffer;
import org.apache.cassandra.io.util.DataOutputPlus;
import org.apache.cassandra.schema.TableMetadata;
-import org.apache.cassandra.schema.TableMetadataProvider;
+import org.apache.cassandra.schema.SchemaProvider;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.CassandraGenerators;
import org.apache.cassandra.utils.FBUtilities;
@@ -88,7 +88,7 @@ public class MessageSerializationPropertyTest implements Serializable
@Test
public void testMessageSerialization() throws Exception
{
- TableMetadataProvider schema = Mockito.mock(TableMetadataProvider.class, Mockito.CALLS_REAL_METHODS);
+ SchemaProvider schema = Mockito.mock(SchemaProvider.class, Mockito.CALLS_REAL_METHODS);
ReadCommand.Serializer readCommandSerializer = new ReadCommand.Serializer(schema);
Supplier<? extends IVersionedAsymmetricSerializer<?, ?>> original = Verb.READ_REQ.unsafeSetSerializer(() -> readCommandSerializer);
try (DataOutputBuffer first = new DataOutputBuffer(1024);
@@ -127,7 +127,7 @@ public class MessageSerializationPropertyTest implements Serializable
}
}
- private static void withTable(TableMetadataProvider schema, Message<?> message, Consumer<TableMetadata> fn)
+ private static void withTable(SchemaProvider schema, Message<?> message, Consumer<TableMetadata> fn)
{
TableMetadata metadata = null;
if (message.payload instanceof ReadQuery)
diff --git a/test/unit/org/apache/cassandra/service/OptionalTasksTest.java b/test/unit/org/apache/cassandra/service/OptionalTasksTest.java
new file mode 100644
index 0000000..5d141a0
--- /dev/null
+++ b/test/unit/org/apache/cassandra/service/OptionalTasksTest.java
@@ -0,0 +1,94 @@
+/*
+ * 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.service;
+
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.cassandra.SchemaLoader;
+import org.apache.cassandra.db.ColumnFamilyStore;
+import org.apache.cassandra.db.Keyspace;
+import org.apache.cassandra.exceptions.ConfigurationException;
+import org.apache.cassandra.schema.KeyspaceParams;
+import org.apache.cassandra.schema.Schema;
+import org.apache.cassandra.schema.TableMetadata;
+
+import static org.apache.cassandra.SchemaLoader.standardCFMD;
+import static org.apache.cassandra.service.CassandraDaemon.SPECULATION_THRESHOLD_UPDATER;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+public class OptionalTasksTest
+{
+ private static final String KEYSPACE = "OpitonalTasksTest";
+ private static final String TABLE = "SpeculationThreshold";
+
+ @BeforeClass
+ public static void defineSchema() throws ConfigurationException
+ {
+ SchemaLoader.prepareServer();
+ SchemaLoader.createKeyspace(KEYSPACE, KeyspaceParams.simple(1), standardCFMD(KEYSPACE, TABLE));
+ }
+
+ @Test
+ public void shouldIgnoreDroppedKeyspace()
+ {
+ // Set the initial sampling state...
+ TableMetadata metadata = Schema.instance.getTableMetadata(KEYSPACE, TABLE);
+ ColumnFamilyStore cfs = Schema.instance.getColumnFamilyStoreInstance(Objects.requireNonNull(metadata).id);
+ Objects.requireNonNull(cfs).metric.coordinatorReadLatency.update(100, TimeUnit.NANOSECONDS);
+
+ // Remove the Keyspace name to make it invisible to the updater...
+ Keyspace removed = Schema.instance.removeKeyspaceInstance(KEYSPACE);
+
+ try
+ {
+ long originalValue = cfs.sampleReadLatencyNanos;
+
+ // ...and ensure that the speculation threshold updater doesn't run.
+ SPECULATION_THRESHOLD_UPDATER.run();
+
+ assertEquals(originalValue, cfs.sampleReadLatencyNanos);
+ }
+ finally
+ {
+ // Restore the removed Keyspace to put things back the way we found them.
+ Schema.instance.storeKeyspaceInstance(removed);
+ }
+ }
+
+ @Test
+ public void shouldUpdateSpeculationThreshold()
+ {
+ // Set the initial sampling state...
+ TableMetadata metadata = Schema.instance.getTableMetadata(KEYSPACE, TABLE);
+ ColumnFamilyStore cfs = Schema.instance.getColumnFamilyStoreInstance(Objects.requireNonNull(metadata).id);
+ Objects.requireNonNull(cfs).metric.coordinatorReadLatency.update(100, TimeUnit.NANOSECONDS);
+
+ long originalValue = cfs.sampleReadLatencyNanos;
+
+ // ...and ensure that the speculation threshold updater runs.
+ SPECULATION_THRESHOLD_UPDATER.run();
+
+ assertNotEquals(originalValue, cfs.sampleReadLatencyNanos);
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org