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