This is an automated email from the ASF dual-hosted git repository.
smiklosovic 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 fc9efd6357 Add virtual table system_views.snapshots
fc9efd6357 is described below
commit fc9efd6357fb4255174689b3c107b897254a7d2f
Author: maxwellguo <[email protected]>
AuthorDate: Thu Mar 9 11:18:14 2023 +0800
Add virtual table system_views.snapshots
patch by Maxwell Guo; reviewed by Stefan Miklosovic and Paulo Motta for
CASSANDRA-18102
Co-authored-by: Stefan Miklosovic <[email protected]>
---
CHANGES.txt | 1 +
NEWS.txt | 1 +
.../cassandra/db/virtual/SnapshotsTable.java | 82 ++++++++++++++++
.../cassandra/db/virtual/SystemViewsKeyspace.java | 1 +
.../apache/cassandra/service/StorageService.java | 2 +-
.../cassandra/db/virtual/SnapshotsTableTest.java | 105 +++++++++++++++++++++
6 files changed, 191 insertions(+), 1 deletion(-)
diff --git a/CHANGES.txt b/CHANGES.txt
index 1b6dcf3c5e..6d234a7055 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
5.0
+ * Add system_views.snapshots virtual table (CASSANDRA-18102)
* Update OpenHFT dependencies (chronicle-queue, chronicle-core,
chronicle-bytes, chronicle-wire, chronicle-threads) (CASSANDRA-18049)
* Remove org.apache.cassandra.hadoop code (CASSANDRA-18323)
* Remove deprecated CQL functions dateOf and unixTimestampOf (CASSANDRA-18328)
diff --git a/NEWS.txt b/NEWS.txt
index c1fe5427f2..48789e4bbe 100644
--- a/NEWS.txt
+++ b/NEWS.txt
@@ -131,6 +131,7 @@ New features
`maxTimestamp - minTimestamp`, effectively non-zero for SSTables
produced by TimeWindowCompactionStrategy.
- Added local read/write ratio to tablestats.
- Added system_views.max_sstable_size and
system_views.max_sstable_duration tables.
+ - Added virtual table system_views.snapshots to see all snapshots from CQL
shell.
Upgrading
---------
diff --git a/src/java/org/apache/cassandra/db/virtual/SnapshotsTable.java
b/src/java/org/apache/cassandra/db/virtual/SnapshotsTable.java
new file mode 100644
index 0000000000..d3df293903
--- /dev/null
+++ b/src/java/org/apache/cassandra/db/virtual/SnapshotsTable.java
@@ -0,0 +1,82 @@
+/*
+ * 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.db.virtual;
+
+import java.util.Date;
+
+import org.apache.cassandra.db.marshal.BooleanType;
+import org.apache.cassandra.db.marshal.LongType;
+import org.apache.cassandra.db.marshal.TimestampType;
+import org.apache.cassandra.db.marshal.UTF8Type;
+import org.apache.cassandra.dht.LocalPartitioner;
+import org.apache.cassandra.schema.TableMetadata;
+import org.apache.cassandra.service.StorageService;
+import org.apache.cassandra.service.snapshot.TableSnapshot;
+
+public class SnapshotsTable extends AbstractVirtualTable
+{
+ private static final String NAME = "name";
+ private static final String KEYSPACE_NAME = "keyspace_name";
+ private static final String TABLE_NAME = "table_name";
+ private static final String TRUE_SIZE = "true_size";
+ private static final String SIZE_ON_DISK = "size_on_disk";
+ private static final String CREATED_AT = "created_at";
+ private static final String EXPIRES_AT = "expires_at";
+ private static final String EPHEMERAL = "ephemeral";
+
+ SnapshotsTable(String keyspace)
+ {
+ super(TableMetadata.builder(keyspace, "snapshots")
+ .comment("available snapshots")
+ .kind(TableMetadata.Kind.VIRTUAL)
+ .partitioner(new
LocalPartitioner(UTF8Type.instance))
+ .addPartitionKeyColumn(NAME, UTF8Type.instance)
+ .addClusteringColumn(KEYSPACE_NAME,
UTF8Type.instance)
+ .addClusteringColumn(TABLE_NAME, UTF8Type.instance)
+ .addRegularColumn(TRUE_SIZE, LongType.instance)
+ .addRegularColumn(SIZE_ON_DISK, LongType.instance)
+ .addRegularColumn(CREATED_AT,
TimestampType.instance)
+ .addRegularColumn(EXPIRES_AT,
TimestampType.instance)
+ .addRegularColumn(EPHEMERAL, BooleanType.instance)
+ .build());
+ }
+
+ @Override
+ public DataSet data()
+ {
+ SimpleDataSet result = new SimpleDataSet(metadata());
+
+ for (TableSnapshot tableSnapshot :
StorageService.instance.snapshotManager.loadSnapshots())
+ {
+ SimpleDataSet row = result.row(tableSnapshot.getTag(),
+ tableSnapshot.getKeyspaceName(),
+ tableSnapshot.getTableName())
+ .column(TRUE_SIZE,
tableSnapshot.computeTrueSizeBytes())
+ .column(SIZE_ON_DISK,
tableSnapshot.computeSizeOnDiskBytes())
+ .column(CREATED_AT, new
Date(tableSnapshot.getCreatedAt().toEpochMilli()));
+
+ if (tableSnapshot.isExpiring())
+ row.column(EXPIRES_AT, new
Date(tableSnapshot.getExpiresAt().toEpochMilli()));
+
+ row.column(EPHEMERAL, tableSnapshot.isEphemeral());
+ }
+
+ return result;
+ }
+}
diff --git a/src/java/org/apache/cassandra/db/virtual/SystemViewsKeyspace.java
b/src/java/org/apache/cassandra/db/virtual/SystemViewsKeyspace.java
index d2aac53764..12df6c7790 100644
--- a/src/java/org/apache/cassandra/db/virtual/SystemViewsKeyspace.java
+++ b/src/java/org/apache/cassandra/db/virtual/SystemViewsKeyspace.java
@@ -49,6 +49,7 @@ public final class SystemViewsKeyspace extends VirtualKeyspace
.add(new GossipInfoTable(VIRTUAL_VIEWS))
.add(new QueriesTable(VIRTUAL_VIEWS))
.add(new LogMessagesTable(VIRTUAL_VIEWS))
+ .add(new SnapshotsTable(VIRTUAL_VIEWS))
.addAll(LocalRepairTables.getAll(VIRTUAL_VIEWS))
.build());
}
diff --git a/src/java/org/apache/cassandra/service/StorageService.java
b/src/java/org/apache/cassandra/service/StorageService.java
index a7c743fd71..d2e3da95c7 100644
--- a/src/java/org/apache/cassandra/service/StorageService.java
+++ b/src/java/org/apache/cassandra/service/StorageService.java
@@ -311,7 +311,7 @@ public class StorageService extends
NotificationBroadcasterSupport implements IE
private final List<Runnable> preShutdownHooks = new ArrayList<>();
private final List<Runnable> postShutdownHooks = new ArrayList<>();
- private final SnapshotManager snapshotManager = new SnapshotManager();
+ public final SnapshotManager snapshotManager = new SnapshotManager();
public static final StorageService instance = new StorageService();
diff --git a/test/unit/org/apache/cassandra/db/virtual/SnapshotsTableTest.java
b/test/unit/org/apache/cassandra/db/virtual/SnapshotsTableTest.java
new file mode 100644
index 0000000000..09832309c1
--- /dev/null
+++ b/test/unit/org/apache/cassandra/db/virtual/SnapshotsTableTest.java
@@ -0,0 +1,105 @@
+/*
+ * 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.db.virtual;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import java.util.Collections;
+import java.util.Date;
+
+import com.google.common.collect.ImmutableList;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.cassandra.config.DurationSpec;
+import org.apache.cassandra.cql3.CQLTester;
+import org.apache.cassandra.cql3.UntypedResultSet;
+import org.apache.cassandra.service.StorageService;
+import org.apache.cassandra.utils.Clock;
+
+public class SnapshotsTableTest extends CQLTester
+{
+ private static final String KS_NAME = "vts";
+ private static final String SNAPSHOT_TTL = "snapshotTtl";
+ private static final String SNAPSHOT_NO_TTL = "snapshotNoTtl";
+ private static final DurationSpec.IntSecondsBound ttl = new
DurationSpec.IntSecondsBound("4h");
+
+ @Before
+ public void before() throws Throwable
+ {
+ SnapshotsTable vtable = new SnapshotsTable(KS_NAME);
+ VirtualKeyspaceRegistry.instance.register(new VirtualKeyspace(KS_NAME,
ImmutableList.of(vtable)));
+
+ createTable("CREATE TABLE %s (pk int, ck int, PRIMARY KEY (pk, ck))");
+
+ for (int i = 0; i != 10; ++i)
+ execute("INSERT INTO %s (pk, ck) VALUES (?, ?)", i, i);
+
+ flush();
+ }
+
+ @After
+ public void after()
+ {
+ StorageService.instance.clearSnapshot(Collections.emptyMap(),
SNAPSHOT_NO_TTL, KEYSPACE);
+ StorageService.instance.clearSnapshot(Collections.emptyMap(),
SNAPSHOT_TTL, KEYSPACE);
+
+ schemaChange(String.format("DROP TABLE %s", KEYSPACE + "." +
currentTable()));
+ }
+
+ @Test
+ public void testSnapshots() throws Throwable
+ {
+ Instant now =
Instant.ofEpochMilli(Clock.Global.currentTimeMillis()).truncatedTo(ChronoUnit.MILLIS);
+ Date createdAt = new Date(now.toEpochMilli());
+ Date expiresAt = new
Date(now.plusSeconds(ttl.toSeconds()).toEpochMilli());
+
+ getCurrentColumnFamilyStore(KEYSPACE).snapshot(SNAPSHOT_NO_TTL, null,
false, false, null, null, now);
+ getCurrentColumnFamilyStore(KEYSPACE).snapshot(SNAPSHOT_TTL, null,
false, false, ttl, null, now);
+
+ // query all from snapshots virtual table
+ UntypedResultSet result = execute("SELECT name, keyspace_name,
table_name, created_at, expires_at, ephemeral FROM vts.snapshots");
+ assertRowsIgnoringOrder(result,
+ row(SNAPSHOT_NO_TTL, KEYSPACE, currentTable(),
createdAt, null, false),
+ row(SNAPSHOT_TTL, KEYSPACE, currentTable(),
createdAt, expiresAt, false));
+
+ // query with conditions
+ result = execute("SELECT name, keyspace_name, table_name, created_at,
expires_at, ephemeral FROM vts.snapshots where ephemeral = false");
+ assertRows(result,
+ row(SNAPSHOT_NO_TTL, KEYSPACE, currentTable(), createdAt,
null, false),
+ row(SNAPSHOT_TTL, KEYSPACE, currentTable(), createdAt,
expiresAt, false));
+
+ result = execute("SELECT name, keyspace_name, table_name, created_at,
expires_at, ephemeral FROM vts.snapshots where size_on_disk > 1000");
+ assertRows(result,
+ row(SNAPSHOT_NO_TTL, KEYSPACE, currentTable(), createdAt,
null, false),
+ row(SNAPSHOT_TTL, KEYSPACE, currentTable(), createdAt,
expiresAt, false));
+
+ result = execute("SELECT name, keyspace_name, table_name, created_at,
expires_at, ephemeral FROM vts.snapshots where name = ?", SNAPSHOT_TTL);
+ assertRows(result,
+ row(SNAPSHOT_TTL, KEYSPACE, currentTable(), createdAt,
expiresAt, false));
+
+ // clear some snapshots
+ StorageService.instance.clearSnapshot(Collections.emptyMap(),
SNAPSHOT_NO_TTL, KEYSPACE);
+
+ result = execute("SELECT name, keyspace_name, table_name, created_at,
expires_at, ephemeral FROM vts.snapshots");
+ assertRowsIgnoringOrder(result,
+ row(SNAPSHOT_TTL, KEYSPACE, currentTable(),
createdAt, expiresAt, false));
+ }
+}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]