Make disabling auto snapshot on selected tables possible

patch by Tommy Stendahl; reviewed by Stefan Miklosovic and Aleksey Yeschenko for CASSANDRA-10383

Co-authored-by: Tommy Stendahl <tommy.stendahl@ericsson.com>
Co-authored-by: Stefan Miklosovic <smiklosovic@apache.org>
This commit is contained in:
Stefan Miklosovic 2022-09-07 16:23:01 +02:00
parent 97a5ff9925
commit b6d8e2ce6b
14 changed files with 281 additions and 28 deletions

View File

@ -1,4 +1,5 @@
4.2
* Make disabling auto snapshot on selected tables possible (CASSANDRA-10383)
* Introduce compaction priorities to prevent upgrade compaction inability to finish (CASSANDRA-17851)
* Prevent a user from manually removing ephemeral snapshots (CASSANDRA-17757)
* Remove dependency on Maven Ant Tasks (CASSANDRA-17750)

View File

@ -85,6 +85,9 @@ New features
isEmptyWithoutStatus() our usage of hbState() + applicationState), however there are other failure cases which
block host replacements and require intrusive workarounds and human intervention to recover from when you
have something in hbState() you don't expect. See CASSANDRA-17842 for further details.
- Added new CQL table property 'allow_auto_snapshot' which is by default true. When set to false and 'auto_snapshot: true'
in cassandra.yaml, there will be no snapshot taken when a table is truncated or dropped. When auto_snapshot in
casandra.yaml is set to false, the newly added table property does not have any effect.
Upgrading
---------
@ -92,6 +95,8 @@ Upgrading
there is a dedicated flag in snapshot manifest instead. On upgrade of a node to version 4.2, on node's start, in case there
are such ephemeral snapshots on disk, they will be deleted (same behaviour as before) and any new ephemeral snapshots
will stop to create ephemeral marker files as flag in a snapshot manifest was introduced instead.
- There was new table property introduced called 'allow_auto_snapshot' (see section 'New features'). Hence, upgraded
node will be on a new schema version. Please do a rolling upgrade of nodes of a cluster to converge to one schema version.
Deprecation
-----------

View File

@ -43,6 +43,7 @@ NONALTERBALE_KEYSPACES = ('system', 'system_schema', 'system_views', 'system_vir
class Cql3ParsingRuleSet(CqlParsingRuleSet):
columnfamily_layout_options = (
('allow_auto_snapshot', None),
('bloom_filter_fp_chance', None),
('comment', None),
('gc_grace_seconds', None),
@ -514,6 +515,8 @@ def cf_prop_val_completer(ctxt, cass):
return [Hint('<true|false>')]
if this_opt in ('read_repair'):
return [Hint('<\'none\'|\'blocking\'>')]
if this_opt == 'allow_auto_snapshot':
return [Hint('<boolean>')]
return [Hint('<option_value>')]

View File

@ -616,7 +616,8 @@ class TestCqlshCompletion(CqlshCompletionCase):
self.trycompletions(prefix + ' new_table (col_a int PRIMARY KEY) W',
immediate='ITH ')
self.trycompletions(prefix + ' new_table (col_a int PRIMARY KEY) WITH ',
choices=['bloom_filter_fp_chance', 'compaction',
choices=['allow_auto_snapshot',
'bloom_filter_fp_chance', 'compaction',
'compression',
'default_time_to_live', 'gc_grace_seconds',
'max_index_interval',
@ -625,7 +626,8 @@ class TestCqlshCompletion(CqlshCompletionCase):
'COMPACT', 'caching', 'comment',
'min_index_interval', 'speculative_retry', 'additional_write_policy', 'cdc', 'read_repair'])
self.trycompletions(prefix + ' new_table (col_a int PRIMARY KEY) WITH ',
choices=['bloom_filter_fp_chance', 'compaction',
choices=['allow_auto_snapshot',
'bloom_filter_fp_chance', 'compaction',
'compression',
'default_time_to_live', 'gc_grace_seconds',
'max_index_interval',
@ -673,7 +675,7 @@ class TestCqlshCompletion(CqlshCompletionCase):
choices=[';', 'AND'])
self.trycompletions(prefix + " new_table (col_a int PRIMARY KEY) WITH compaction = "
+ "{'class': 'SizeTieredCompactionStrategy'} AND ",
choices=['bloom_filter_fp_chance', 'compaction',
choices=['allow_auto_snapshot', 'bloom_filter_fp_chance', 'compaction',
'compression',
'default_time_to_live', 'gc_grace_seconds',
'max_index_interval',

View File

@ -652,6 +652,7 @@ class TestCqlshOutput(BaseTestCase):
varcharcol text,
varintcol varint
) WITH additional_write_policy = '99p'
AND allow_auto_snapshot = true
AND bloom_filter_fp_chance = 0.01
AND caching = {'keys': 'ALL', 'rows_per_partition': 'NONE'}
AND cdc = false

View File

@ -98,6 +98,9 @@ public final class TableAttributes extends PropertyDefinitions
private TableParams build(TableParams.Builder builder)
{
if (hasOption(Option.ALLOW_AUTO_SNAPSHOT))
builder.allowAutoSnapshot(getBoolean(Option.ALLOW_AUTO_SNAPSHOT.toString(), true));
if (hasOption(Option.BLOOM_FILTER_FP_CHANCE))
builder.bloomFilterFpChance(getDouble(Option.BLOOM_FILTER_FP_CHANCE));

View File

@ -2581,7 +2581,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean, Memtable.Owner
if (!noSnapshot &&
((keyspace.getMetadata().params.durableWrites && !memtableWritesAreDurable()) // need to clear dirty regions
|| DatabaseDescriptor.isAutoSnapshot())) // need sstable for snapshot
|| isAutoSnapshotEnabled()))
{
replayAfter = forceBlockingFlush(FlushReason.TRUNCATE);
viewManager.forceBlockingFlush(FlushReason.TRUNCATE);
@ -2614,7 +2614,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean, Memtable.Owner
"Stopping parent sessions {} due to truncation of tableId="+metadata.id);
data.notifyTruncated(truncatedAt);
if (!noSnapshot && DatabaseDescriptor.isAutoSnapshot())
if (!noSnapshot && isAutoSnapshotEnabled())
snapshot(Keyspace.getTimestampedSnapshotNameWithPrefix(name, SNAPSHOT_TRUNCATE_PREFIX), DatabaseDescriptor.getAutoSnapshotTtl());
discardSSTables(truncatedAt);
@ -3073,6 +3073,11 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean, Memtable.Owner
return metadata().params.caching.cacheKeys() && CacheService.instance.keyCache.getCapacity() > 0;
}
public boolean isAutoSnapshotEnabled()
{
return metadata().params.allowAutoSnapshot && DatabaseDescriptor.isAutoSnapshot();
}
/**
* Discard all SSTables that were created before given timestamp.
*
@ -3207,7 +3212,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean, Memtable.Owner
CompactionManager.instance.interruptCompactionForCFs(concatWithIndexes(), (sstable) -> true, true);
if (DatabaseDescriptor.isAutoSnapshot())
if (isAutoSnapshotEnabled())
snapshot(Keyspace.getTimestampedSnapshotNameWithPrefix(name, ColumnFamilyStore.SNAPSHOT_DROP_PREFIX), DatabaseDescriptor.getAutoSnapshotTtl());
CommitLog.instance.forceRecycleAllSegments(Collections.singleton(metadata.id));

View File

@ -100,6 +100,7 @@ public final class SchemaKeyspace
"CREATE TABLE %s ("
+ "keyspace_name text,"
+ "table_name text,"
+ "allow_auto_snapshot boolean,"
+ "bloom_filter_fp_chance double,"
+ "caching frozen<map<text, text>>,"
+ "comment text,"
@ -168,6 +169,7 @@ public final class SchemaKeyspace
+ "base_table_id uuid,"
+ "base_table_name text,"
+ "where_clause text,"
+ "allow_auto_snapshot boolean,"
+ "bloom_filter_fp_chance double,"
+ "caching frozen<map<text, text>>,"
+ "comment text,"
@ -563,6 +565,11 @@ public final class SchemaKeyspace
// in mixed operation with pre-4.1 versioned node during upgrades.
if (params.memtable != MemtableParams.DEFAULT)
builder.add("memtable", params.memtable.configurationKey());
// As above, only add the allow_auto_snapshot column if the value is not default (true) and
// auto-snapshotting is enabled, to avoid RTE in pre-4.2 versioned node during upgrades
if (!params.allowAutoSnapshot)
builder.add("allow_auto_snapshot", false);
}
private static void addAlterTableToSchemaMutation(TableMetadata oldTable, TableMetadata newTable, Mutation.SimpleBuilder builder)
@ -954,27 +961,32 @@ public final class SchemaKeyspace
@VisibleForTesting
static TableParams createTableParamsFromRow(UntypedResultSet.Row row)
{
return TableParams.builder()
.bloomFilterFpChance(row.getDouble("bloom_filter_fp_chance"))
.caching(CachingParams.fromMap(row.getFrozenTextMap("caching")))
.comment(row.getString("comment"))
.compaction(CompactionParams.fromMap(row.getFrozenTextMap("compaction")))
.compression(CompressionParams.fromMap(row.getFrozenTextMap("compression")))
.memtable(MemtableParams.get(row.has("memtable") ? row.getString("memtable") : null)) // memtable column was introduced in 4.1
.defaultTimeToLive(row.getInt("default_time_to_live"))
.extensions(row.getFrozenMap("extensions", UTF8Type.instance, BytesType.instance))
.gcGraceSeconds(row.getInt("gc_grace_seconds"))
.maxIndexInterval(row.getInt("max_index_interval"))
.memtableFlushPeriodInMs(row.getInt("memtable_flush_period_in_ms"))
.minIndexInterval(row.getInt("min_index_interval"))
.crcCheckChance(row.getDouble("crc_check_chance"))
.speculativeRetry(SpeculativeRetryPolicy.fromString(row.getString("speculative_retry")))
.additionalWritePolicy(row.has("additional_write_policy") ?
SpeculativeRetryPolicy.fromString(row.getString("additional_write_policy")) :
SpeculativeRetryPolicy.fromString("99PERCENTILE"))
.cdc(row.has("cdc") && row.getBoolean("cdc"))
.readRepair(getReadRepairStrategy(row))
.build();
TableParams.Builder builder = TableParams.builder()
.bloomFilterFpChance(row.getDouble("bloom_filter_fp_chance"))
.caching(CachingParams.fromMap(row.getFrozenTextMap("caching")))
.comment(row.getString("comment"))
.compaction(CompactionParams.fromMap(row.getFrozenTextMap("compaction")))
.compression(CompressionParams.fromMap(row.getFrozenTextMap("compression")))
.memtable(MemtableParams.get(row.has("memtable") ? row.getString("memtable") : null)) // memtable column was introduced in 4.1
.defaultTimeToLive(row.getInt("default_time_to_live"))
.extensions(row.getFrozenMap("extensions", UTF8Type.instance, BytesType.instance))
.gcGraceSeconds(row.getInt("gc_grace_seconds"))
.maxIndexInterval(row.getInt("max_index_interval"))
.memtableFlushPeriodInMs(row.getInt("memtable_flush_period_in_ms"))
.minIndexInterval(row.getInt("min_index_interval"))
.crcCheckChance(row.getDouble("crc_check_chance"))
.speculativeRetry(SpeculativeRetryPolicy.fromString(row.getString("speculative_retry")))
.additionalWritePolicy(row.has("additional_write_policy") ?
SpeculativeRetryPolicy.fromString(row.getString("additional_write_policy")) :
SpeculativeRetryPolicy.fromString("99PERCENTILE"))
.cdc(row.has("cdc") && row.getBoolean("cdc"))
.readRepair(getReadRepairStrategy(row));
// allow_auto_snapshot column was introduced in 4.2
if (row.has("allow_auto_snapshot"))
builder.allowAutoSnapshot(row.getBoolean("allow_auto_snapshot"));
return builder.build();
}
private static List<ColumnMetadata> fetchColumns(String keyspace, String table, Types types)

View File

@ -777,6 +777,12 @@ public class TableMetadata implements SchemaElement
return this;
}
public Builder allowAutoSnapshot(boolean val)
{
params.allowAutoSnapshot(val);
return this;
}
public Builder bloomFilterFpChance(double val)
{
params.bloomFilterFpChance(val);

View File

@ -41,6 +41,7 @@ public final class TableParams
{
public enum Option
{
ALLOW_AUTO_SNAPSHOT,
BLOOM_FILTER_FP_CHANCE,
CACHING,
COMMENT,
@ -67,6 +68,7 @@ public final class TableParams
}
public final String comment;
public final boolean allowAutoSnapshot;
public final double bloomFilterFpChance;
public final double crcCheckChance;
public final int gcGraceSeconds;
@ -87,6 +89,7 @@ public final class TableParams
private TableParams(Builder builder)
{
comment = builder.comment;
allowAutoSnapshot = builder.allowAutoSnapshot;
bloomFilterFpChance = builder.bloomFilterFpChance == null
? builder.compaction.defaultBloomFilterFbChance()
: builder.bloomFilterFpChance;
@ -114,7 +117,8 @@ public final class TableParams
public static Builder builder(TableParams params)
{
return new Builder().bloomFilterFpChance(params.bloomFilterFpChance)
return new Builder().allowAutoSnapshot(params.allowAutoSnapshot)
.bloomFilterFpChance(params.bloomFilterFpChance)
.caching(params.caching)
.comment(params.comment)
.compaction(params.compaction)
@ -204,6 +208,7 @@ public final class TableParams
TableParams p = (TableParams) o;
return comment.equals(p.comment)
&& allowAutoSnapshot == p.allowAutoSnapshot
&& bloomFilterFpChance == p.bloomFilterFpChance
&& crcCheckChance == p.crcCheckChance
&& gcGraceSeconds == p.gcGraceSeconds
@ -225,6 +230,7 @@ public final class TableParams
public int hashCode()
{
return Objects.hashCode(comment,
allowAutoSnapshot,
bloomFilterFpChance,
crcCheckChance,
gcGraceSeconds,
@ -247,6 +253,7 @@ public final class TableParams
{
return MoreObjects.toStringHelper(this)
.add(Option.COMMENT.toString(), comment)
.add(Option.ALLOW_AUTO_SNAPSHOT.toString(), allowAutoSnapshot)
.add(Option.BLOOM_FILTER_FP_CHANCE.toString(), bloomFilterFpChance)
.add(Option.CRC_CHECK_CHANCE.toString(), crcCheckChance)
.add(Option.GC_GRACE_SECONDS.toString(), gcGraceSeconds)
@ -269,6 +276,8 @@ public final class TableParams
{
// option names should be in alphabetical order
builder.append("additional_write_policy = ").appendWithSingleQuotes(additionalWritePolicy.toString())
.newLine()
.append("AND allow_auto_snapshot = ").append(allowAutoSnapshot)
.newLine()
.append("AND bloom_filter_fp_chance = ").append(bloomFilterFpChance)
.newLine()
@ -315,6 +324,7 @@ public final class TableParams
public static final class Builder
{
private String comment = "";
private boolean allowAutoSnapshot = true;
private Double bloomFilterFpChance;
private double crcCheckChance = 1.0;
private int gcGraceSeconds = 864000; // 10 days
@ -347,6 +357,12 @@ public final class TableParams
return this;
}
public Builder allowAutoSnapshot(boolean val)
{
allowAutoSnapshot = val;
return this;
}
public Builder bloomFilterFpChance(double val)
{
bloomFilterFpChance = val;

View File

@ -0,0 +1,156 @@
/*
* 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.distributed.test;
import java.io.IOException;
import java.util.Collections;
import java.util.function.Predicate;
import java.util.stream.Stream;
import org.junit.Test;
import org.apache.cassandra.distributed.Cluster;
import org.apache.cassandra.distributed.api.IIsolatedExecutor;
import org.apache.cassandra.service.StorageService;
import static org.apache.cassandra.distributed.Cluster.build;
import static org.apache.cassandra.distributed.api.ConsistencyLevel.ALL;
import static org.apache.cassandra.distributed.api.Feature.GOSSIP;
import static org.awaitility.Awaitility.await;
public class AllowAutoSnapshotTest extends TestBaseImpl
{
@Test
public void testAllowAutoSnapshotOnAutoSnapshotEnabled() throws Exception
{
try (Cluster c = getCluster(true))
{
c.schemaChange(withKeyspace("CREATE TABLE %s.test_table (a text primary key, b int) WITH allow_auto_snapshot = true"));
c.schemaChange(withKeyspace("DROP TABLE %s.test_table;"));
checkSnapshots(c, true, "test_table", "dropped");
c.schemaChange(withKeyspace("CREATE TABLE %s.test_table2 (a text primary key, b int) WITH allow_auto_snapshot = false"));
c.schemaChange(withKeyspace("DROP TABLE %s.test_table2;"));
checkSnapshots(c, false, "test_table2", "dropped");
}
}
@Test
public void testAllowAutoSnapshotOnAutoSnapshotDisabled() throws Exception
{
try (Cluster c = getCluster(false))
{
c.schemaChange(withKeyspace("CREATE TABLE %s.test_table (a text primary key, b int) WITH allow_auto_snapshot = true"));
c.schemaChange(withKeyspace("DROP TABLE %s.test_table;"));
checkSnapshots(c, false, "test_table", "dropped");
c.schemaChange(withKeyspace("CREATE TABLE %s.test_table2 (a text primary key, b int) WITH allow_auto_snapshot = false"));
c.schemaChange(withKeyspace("DROP TABLE %s.test_table2;"));
checkSnapshots(c, false, "test_table2", "dropped");
}
}
@Test
public void testDisableAndEnableAllowAutoSnapshot() throws Exception
{
try (Cluster c = getCluster(true))
{
c.schemaChange(withKeyspace("CREATE TABLE %s.test_table (a text primary key, b int) WITH allow_auto_snapshot = true"));
c.schemaChange(withKeyspace("ALTER TABLE %s.test_table WITH allow_auto_snapshot = false"));
c.schemaChange(withKeyspace("ALTER TABLE %s.test_table WITH allow_auto_snapshot = true"));
c.schemaChange(withKeyspace("DROP TABLE %s.test_table;"));
checkSnapshots(c, true, "test_table", "dropped");
}
}
@Test
public void testTruncateAllowAutoSnapshot() throws Exception
{
try (Cluster c = getCluster(true))
{
// allow_auto_snapshot = true
c.schemaChange(withKeyspace("CREATE TABLE %s.test_table (a text primary key, b int) WITH allow_auto_snapshot = true"));
c.coordinator(1).execute(withKeyspace("INSERT INTO %s.test_table (a, b) VALUES ('a', 1);"), ALL);
c.schemaChange(withKeyspace("TRUNCATE TABLE %s.test_table;"));
checkSnapshots(c, true, "test_table", "truncated");
// allow_auto_snapshot = false
c.schemaChange(withKeyspace("CREATE TABLE %s.test_table2 (a text primary key, b int) WITH allow_auto_snapshot = false"));
c.coordinator(1).execute(withKeyspace("INSERT INTO %s.test_table2 (a, b) VALUES ('a', 1);"), ALL);
c.schemaChange(withKeyspace("TRUNCATE TABLE %s.test_table2;"));
checkSnapshots(c, false, "test_table2", "truncated");
}
}
@Test
public void testMaterializedViewAllowAutoSnapshot() throws Exception
{
try (Cluster c = getCluster(true))
{
// materialized view allow_auto_snapshot = false
c.schemaChange(withKeyspace("CREATE TABLE %s.t (k int, c1 int, c2 int, v1 int, v2 int, PRIMARY KEY (k, c1, c2))"));
c.schemaChange(withKeyspace("CREATE MATERIALIZED VIEW %s.mv1 AS SELECT * FROM t WHERE k IS NOT NULL AND c1 IS NOT NULL AND c2 IS NOT NULL PRIMARY KEY (c1, k, c2) WITH allow_auto_snapshot = false"));
c.coordinator(1).execute(withKeyspace("INSERT INTO %s.t (k, c1, c2, v1, v2) VALUES (1, 2, 3, 4, 5);"), ALL);
c.schemaChange(withKeyspace("DROP MATERIALIZED VIEW %s.mv1;"));
checkSnapshots(c, false, "mv1", "dropped");
// materialized view allow_auto_snapshot = true
c.schemaChange(withKeyspace("CREATE MATERIALIZED VIEW %s.mv1 AS SELECT * FROM t WHERE k IS NOT NULL AND c1 IS NOT NULL AND c2 IS NOT NULL PRIMARY KEY (c1, k, c2) WITH allow_auto_snapshot = true"));
c.schemaChange(withKeyspace("DROP MATERIALIZED VIEW %s.mv1;"));
checkSnapshots(c, true, "mv1", "dropped");
}
}
private Cluster getCluster(boolean autoSnapshotEnabled) throws IOException
{
return init(build(2).withConfig(c -> c.with(GOSSIP)
.set("auto_snapshot", autoSnapshotEnabled)
.set("materialized_views_enabled", true)).start());
}
private void checkSnapshots(Cluster cluster, boolean shouldContain, String table, String snapshotPrefix)
{
for (int i = 1; i < cluster.size() + 1; i++)
{
final int node = i; // has to be effectively final for the usage in "until" method
await().until(() -> cluster.get(node).appliesOnInstance((IIsolatedExecutor.SerializableTriFunction<Boolean, String, String, Boolean>) (shouldContainSnapshot, tableName, prefix) -> {
Stream<String> stream = StorageService.instance.getSnapshotDetails(Collections.emptyMap()).keySet().stream();
Predicate<String> predicate = tag -> tag.startsWith(prefix + '-') && tag.endsWith('-' + tableName);
return shouldContainSnapshot ? stream.anyMatch(predicate) : stream.noneMatch(predicate);
}).apply(shouldContain, table, snapshotPrefix));
}
}
}

View File

@ -839,6 +839,7 @@ public class DescribeStatementTest extends CQLTester
private static String tableParametersCql()
{
return "additional_write_policy = '99p'\n" +
" AND allow_auto_snapshot = true\n" +
" AND bloom_filter_fp_chance = 0.01\n" +
" AND caching = {'keys': 'ALL', 'rows_per_partition': 'NONE'}\n" +
" AND cdc = false\n" +
@ -860,6 +861,7 @@ public class DescribeStatementTest extends CQLTester
private static String mvParametersCql()
{
return "additional_write_policy = '99p'\n" +
" AND allow_auto_snapshot = true\n" +
" AND bloom_filter_fp_chance = 0.01\n" +
" AND caching = {'keys': 'ALL', 'rows_per_partition': 'NONE'}\n" +
" AND cdc = false\n" +

View File

@ -297,6 +297,7 @@ public class SchemaCQLHelperTest extends CQLTester
assertThat(SchemaCQLHelper.getTableMetadataAsCQL(cfs.metadata(), cfs.keyspace.getMetadata()),
containsString("CLUSTERING ORDER BY (cl1 ASC)\n" +
" AND additional_write_policy = 'ALWAYS'\n" +
" AND allow_auto_snapshot = true\n" +
" AND bloom_filter_fp_chance = 1.0\n" +
" AND caching = {'keys': 'ALL', 'rows_per_partition': 'NONE'}\n" +
" AND cdc = false\n" +

View File

@ -24,6 +24,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@ -33,11 +34,13 @@ import java.util.stream.Stream;
import com.google.common.collect.ImmutableMap;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.apache.cassandra.SchemaLoader;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.cql3.QueryProcessor;
import org.apache.cassandra.cql3.UntypedResultSet;
import org.apache.cassandra.cql3.statements.schema.CreateTableStatement;
@ -61,6 +64,7 @@ import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import static org.apache.cassandra.cql3.QueryProcessor.executeOnceInternal;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
@RunWith(BMUnitRunner.class)
public class SchemaKeyspaceTest
@ -181,6 +185,42 @@ public class SchemaKeyspaceTest
}
@Test
public void testAutoSnapshotEnabledOnTable()
{
Assume.assumeTrue(DatabaseDescriptor.isAutoSnapshot());
String keyspaceName = "AutoSnapshot";
String tableName = "table1";
createTable(keyspaceName, "CREATE TABLE " + tableName + " (a text primary key, b int) WITH allow_auto_snapshot = true");
ColumnFamilyStore cfs = Keyspace.open(keyspaceName).getColumnFamilyStore(tableName);
assertTrue(cfs.isAutoSnapshotEnabled());
SchemaTestUtil.announceTableDrop(keyspaceName, tableName);
assertFalse(cfs.listSnapshots().isEmpty());
}
@Test
public void testAutoSnapshotDisabledOnTable()
{
Assume.assumeTrue(DatabaseDescriptor.isAutoSnapshot());
String keyspaceName = "AutoSnapshot";
String tableName = "table2";
createTable(keyspaceName, "CREATE TABLE " + tableName + " (a text primary key, b int) WITH allow_auto_snapshot = false");
ColumnFamilyStore cfs = Keyspace.open(keyspaceName).getColumnFamilyStore(tableName);
assertFalse(cfs.isAutoSnapshotEnabled());
SchemaTestUtil.announceTableDrop(keyspaceName, tableName);
assertTrue(cfs.listSnapshots().isEmpty());
}
private static void updateTable(String keyspace, TableMetadata oldTable, TableMetadata newTable)
{
KeyspaceMetadata ksm = Schema.instance.getKeyspaceInstance(keyspace).getMetadata();