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

commit 407dbacb0a0fcd5eca28abe781be635476325a65
Author: Stefan Miklosovic <smikloso...@apache.org>
AuthorDate: Wed Dec 18 21:04:44 2024 +0100

    Enable filtering of snapshots on keyspace, table and snapshot name in 
nodetool listsnapshots
    
    patch by Stefan Miklosovic; reviewed by Jordan West, Bernardo Botella, 
Cheng Wang, Maxim Muzafarov for CASSANDRA-20151
---
 CHANGES.txt                                        |  3 +-
 .../service/snapshot/SnapshotManagerMBean.java     | 14 +++-
 .../cassandra/tools/nodetool/ListSnapshots.java    | 21 ++++++
 .../cassandra/distributed/test/SnapshotsTest.java  | 78 ++++++++++++++++++++--
 4 files changed, 109 insertions(+), 7 deletions(-)

diff --git a/CHANGES.txt b/CHANGES.txt
index ee4e28789e..97c6386821 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,7 +1,8 @@
 5.1
+ * Enable filtering of snapshots on keyspace, table and snapshot name in 
nodetool listsnapshots (CASSANDRA-20151)
  * Create manifest upon loading where it does not exist or enrich it 
(CASSANDRA-20150)
  * Propagate true size of snapshot in SnapshotDetailsTabularData to not call 
JMX twice in nodetool listsnapshots (CASSANDRA-20149)
- * Implementation of CEP-43 (CASSANDRA-19964)
+ * Implementation of CEP-43 - copying a table via CQL by CREATE TABLE LIKE 
(CASSANDRA-19964)
  * Periodically disconnect roles that are revoked or have LOGIN=FALSE set 
(CASSANDRA-19385)
  * AST library for CQL-based fuzz tests (CASSANDRA-20198)
  * Support audit logging for JMX operations (CASSANDRA-20128)
diff --git 
a/src/java/org/apache/cassandra/service/snapshot/SnapshotManagerMBean.java 
b/src/java/org/apache/cassandra/service/snapshot/SnapshotManagerMBean.java
index 214adcc445..332ebb4b54 100644
--- a/src/java/org/apache/cassandra/service/snapshot/SnapshotManagerMBean.java
+++ b/src/java/org/apache/cassandra/service/snapshot/SnapshotManagerMBean.java
@@ -55,7 +55,19 @@ public interface SnapshotManagerMBean
     void clearSnapshot(String tag, Map<String, Object> options, String... 
keyspaceNames) throws IOException;
 
     /**
-     * Get the details of all the snapshots
+     * Get the details of all the snapshots. Options might be:
+     *
+     * <pre>
+     * no_ttl: "true" or "false"
+     * include_ephemeral: "true" or "false"
+     * keyspace: name of keyspace to get snapshots of
+     * table: name of table to get tables of
+     * snapshot: name of snapshot to list
+     * </pre>
+     *
+     * There is no requirement as what option has to be specified.
+     * Values of 'null' for keyspace, table or snapshot do not have any effect 
/ will
+     * not be part of the filtering.
      *
      * @param options map of options used for filtering of snapshots
      * @return A map of snapshotName to all its details in Tabular form.
diff --git a/src/java/org/apache/cassandra/tools/nodetool/ListSnapshots.java 
b/src/java/org/apache/cassandra/tools/nodetool/ListSnapshots.java
index e1b61d4b51..97ea809fdd 100644
--- a/src/java/org/apache/cassandra/tools/nodetool/ListSnapshots.java
+++ b/src/java/org/apache/cassandra/tools/nodetool/ListSnapshots.java
@@ -44,6 +44,21 @@ public class ListSnapshots extends NodeToolCmd
     description = "Include ephememeral snapshots")
     private boolean includeEphemeral = false;
 
+    @Option(title = "keyspace",
+    name = { "-k", "--keyspace" },
+    description = "Include snapshots of specified keyspace name")
+    private String keyspace = null;
+
+    @Option(title = "table",
+    name = { "-t", "--table" },
+    description = "Include snapshots of specified table name")
+    private String table = null;
+
+    @Option(title = "snapshot",
+    name = { "-n", "--snapshot"},
+    description = "Include snapshots of specified name")
+    private String snapshotName = null;
+
     @Override
     public void execute(NodeProbe probe)
     {
@@ -55,6 +70,12 @@ public class ListSnapshots extends NodeToolCmd
             Map<String, String> options = new HashMap<>();
             options.put("no_ttl", Boolean.toString(noTTL));
             options.put("include_ephemeral", 
Boolean.toString(includeEphemeral));
+            if (keyspace != null)
+                options.put("keyspace", keyspace);
+            if (table != null)
+                options.put("table", table);
+            if (snapshotName != null)
+                options.put("snapshot", snapshotName);
 
             final Map<String, TabularData> snapshotDetails = 
probe.getSnapshotDetails(options);
             if (snapshotDetails.isEmpty())
diff --git 
a/test/distributed/org/apache/cassandra/distributed/test/SnapshotsTest.java 
b/test/distributed/org/apache/cassandra/distributed/test/SnapshotsTest.java
index f04a3403ca..d0b78112a8 100644
--- a/test/distributed/org/apache/cassandra/distributed/test/SnapshotsTest.java
+++ b/test/distributed/org/apache/cassandra/distributed/test/SnapshotsTest.java
@@ -512,6 +512,49 @@ public class SnapshotsTest extends TestBaseImpl
         cluster.get(1).nodetoolResult("snapshot", "-t", "somename", "-kt", 
String.format("%s.tbl2", KEYSPACE)).asserts().success();
     }
 
+    @Test
+    public void testListingOfSnapshotsByKeyspaceAndTable()
+    {
+        IInvokableInstance instance = cluster.get(1);
+        cluster.schemaChange("CREATE KEYSPACE IF NOT EXISTS ks1 WITH 
replication = {'class': 'SimpleStrategy', 'replication_factor': 1};");
+        cluster.schemaChange("CREATE KEYSPACE IF NOT EXISTS ks2 WITH 
replication = {'class': 'SimpleStrategy', 'replication_factor': 1};");
+        cluster.schemaChange("CREATE TABLE IF NOT EXISTS ks1.tbl (key int, 
value text, PRIMARY KEY (key))");
+        cluster.schemaChange("CREATE TABLE IF NOT EXISTS ks1.tbl2 (key int, 
value text, PRIMARY KEY (key))");
+        cluster.schemaChange("CREATE TABLE IF NOT EXISTS ks2.tbl (key int, 
value text, PRIMARY KEY (key))");
+        cluster.schemaChange("CREATE TABLE IF NOT EXISTS ks2.tbl2 (key int, 
value text, PRIMARY KEY (key))");
+
+        populate(cluster, "ks1", "tbl");
+        populate(cluster, "ks1", "tbl2");
+        populate(cluster, "ks2", "tbl");
+        populate(cluster, "ks2", "tbl2");
+
+        instance.nodetoolResult("snapshot", "-t", "tagks1tbl", "-kt", 
"ks1.tbl").asserts().success();
+        instance.nodetoolResult("snapshot", "-t", "tagks1tbl2", "-kt", 
"ks1.tbl2").asserts().success();
+        instance.nodetoolResult("snapshot", "-t", "tagks2tbl", "-kt", 
"ks2.tbl").asserts().success();
+        instance.nodetoolResult("snapshot", "-t", "tagks2tbl2", "-kt", 
"ks2.tbl2").asserts().success();
+
+        waitForSnapshot("ks1", null, "tagks1tbl", true, false);
+        waitForSnapshot("ks1", null, "tagks1tbl2", true, false);
+        waitForSnapshot("ks1", null, "tagks2tbl", false, false);
+        waitForSnapshot("ks1", null, "tagks2tbl2", false, false);
+
+        waitForSnapshot("ks1", "tbl", "tagks1tbl", true, false);
+        waitForSnapshot("ks1", "tbl", "tagks1tbl2", false, false);
+        waitForSnapshot("ks1", "tbl", "tagks2tbl", false, false);
+        waitForSnapshot("ks1", "tbl", "tagks2tbl2", false, false);
+
+        waitForSnapshot(null, "tbl", "tagks1tbl", true, false);
+        waitForSnapshot(null, "tbl", "tagks1tbl2", false, false);
+        waitForSnapshot(null, "tbl", "tagks2tbl", true, false);
+        waitForSnapshot(null, "tbl", "tagks2tbl2", false, false);
+
+        NodeToolResult nodeToolResult = 
instance.nodetoolResult("listsnapshots", "-n", "tagks1tbl");
+        nodeToolResult.asserts().success();
+        List<String> snapshots = extractSnapshots(nodeToolResult.getStdout());
+        assertEquals(1, snapshots.size());
+        assertTrue(snapshots.get(0).contains("tagks1tbl"));
+    }
+
     private void populate(Cluster cluster)
     {
         for (int i = 0; i < 100; i++)
@@ -555,13 +598,27 @@ public class SnapshotsTest extends TestBaseImpl
         if (noTTL)
             args.add("-nt");
 
+        if (keyspaceName != null)
+        {
+            args.add("-k");
+            args.add(keyspaceName);
+        }
+
+        if (tableName != null)
+        {
+            args.add("-t");
+            args.add(tableName);
+        }
+
+        if (snapshotName != null)
+        {
+            args.add("-n");
+            args.add(snapshotName);
+        }
+
         listsnapshots = cluster.get(1).nodetoolResult(args.toArray(new 
String[0]));
 
-        List<String> lines = 
Arrays.stream(listsnapshots.getStdout().split("\n"))
-                                   .filter(line -> !line.isEmpty())
-                                   .filter(line -> !line.startsWith("Snapshot 
Details:") && !line.startsWith("There are no snapshots"))
-                                   .filter(line -> !line.startsWith("Snapshot 
name") && !line.startsWith("Total TrueDiskSpaceUsed"))
-                                   .collect(toList());
+        List<String> lines = extractSnapshots(listsnapshots.getStdout());
 
         return expectPresent == lines.stream().anyMatch(line -> 
line.startsWith(snapshotName));
     }
@@ -632,4 +689,15 @@ public class SnapshotsTest extends TestBaseImpl
             return result.toArray(new String[0]);
         }, forSystemKeyspaces);
     }
+
+    private List<String> extractSnapshots(String listSnapshotsStdOut)
+    {
+        return Arrays.stream(listSnapshotsStdOut.split("\n"))
+                     .filter(line -> !line.isEmpty())
+                     .filter(line -> !line.startsWith("Snapshot Details:"))
+                     .filter(line -> !line.startsWith("There are no 
snapshots"))
+                     .filter(line -> !line.startsWith("Snapshot name"))
+                     .filter(line -> !line.startsWith("Total 
TrueDiskSpaceUsed"))
+                     .collect(toList());
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org
For additional commands, e-mail: commits-h...@cassandra.apache.org

Reply via email to