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]

Reply via email to