From ca42cfe68dbf1772a878dd0912d73cfc10ce5324 Mon Sep 17 00:00:00 2001 From: Stefan Miklosovic Date: Fri, 27 May 2022 12:24:42 +0200 Subject: [PATCH] Add nodetool getreplicas nodetool getendpoints is deprecated. Also, all StorageServiceMBean.getNaturalEndpoints* methods are deprecated and they call their replica counterparts. The deprecated methods are also not used directly anywhere in the code (nor tests). patch by Stefan Miklosovic; reviewed by Brandon Williams for CASSANDRA-17665 --- CHANGES.txt | 1 + .../cassandra/service/StorageService.java | 12 ++- .../service/StorageServiceMBean.java | 20 ++++- .../org/apache/cassandra/tools/NodeProbe.java | 8 +- .../tools/nodetool/GetEndpoints.java | 58 +------------- .../cassandra/tools/nodetool/GetReplicas.java | 79 +++++++++++++++++++ .../tools/nodetool/NodetoolCommand.java | 1 + .../distributed/test/GetEndpointsTest.java | 6 +- .../distributed/test/GossipSettlesTest.java | 25 ++++-- test/resources/nodetool/help/getendpoints | 5 +- test/resources/nodetool/help/getreplicas | 37 +++++++++ test/resources/nodetool/help/nodetool | 3 +- 12 files changed, 179 insertions(+), 76 deletions(-) create mode 100644 src/java/org/apache/cassandra/tools/nodetool/GetReplicas.java create mode 100644 test/resources/nodetool/help/getreplicas diff --git a/CHANGES.txt b/CHANGES.txt index 2449f51844..b35ff548b2 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 7.0 + * Add nodetool getreplicas (CASSANDRA-17665) * Implementation of CEP-49: Hardware-accelerated compression (CASSANDRA-20975) * Avoid using ObjectUtils.getFirstNonNull in Schema (CASSANDRA-21394) * Allow nodetool garbagecollect to take a user defined list of SSTables (CASSANDRA-16767) diff --git a/src/java/org/apache/cassandra/service/StorageService.java b/src/java/org/apache/cassandra/service/StorageService.java index 397e50fa0d..b4c8343558 100644 --- a/src/java/org/apache/cassandra/service/StorageService.java +++ b/src/java/org/apache/cassandra/service/StorageService.java @@ -3403,6 +3403,11 @@ public class StorageService extends NotificationBroadcasterSupport implements IE */ @Deprecated(since = "4.0") public List getNaturalEndpoints(String keyspaceName, String cf, String key) + { + return getNaturalReplicas(keyspaceName, cf, key); + } + + public List getNaturalReplicas(String keyspaceName, String cf, String key) { EndpointsForToken replicas = getNaturalReplicasForToken(keyspaceName, cf, key); List inetList = new ArrayList<>(replicas.size()); @@ -3410,11 +3415,16 @@ public class StorageService extends NotificationBroadcasterSupport implements IE return inetList; } - public List getNaturalEndpointsWithPort(String keyspaceName, String cf, String key) + public List getNaturalReplicasWithPort(String keyspaceName, String cf, String key) { return Replicas.stringify(getNaturalReplicasForToken(keyspaceName, cf, key), true); } + public List getNaturalEndpointsWithPort(String keyspaceName, String cf, String key) + { + return getNaturalReplicasWithPort(keyspaceName, cf, key); + } + /** @deprecated See CASSANDRA-7544 */ @Deprecated(since = "4.0") public List getNaturalEndpoints(String keyspaceName, ByteBuffer key) diff --git a/src/java/org/apache/cassandra/service/StorageServiceMBean.java b/src/java/org/apache/cassandra/service/StorageServiceMBean.java index e6f7a18c8e..abc8689031 100644 --- a/src/java/org/apache/cassandra/service/StorageServiceMBean.java +++ b/src/java/org/apache/cassandra/service/StorageServiceMBean.java @@ -262,12 +262,28 @@ public interface StorageServiceMBean extends NotificationEmitter * @param key - key for which we need to find the endpoint return value - * the endpoint responsible for this key * @deprecated See CASSANDRA-7544 + * @link getNaturalReplicas + * @link getNaturalReplicasWithPort */ @Deprecated(since = "4.0") public List getNaturalEndpoints(String keyspaceName, String cf, String key); - public List getNaturalEndpointsWithPort(String keyspaceName, String cf, String key); + /** @deprecated See CASSANDRA-17665 */ + @Deprecated(since = "7.0") public List getNaturalEndpointsWithPort(String keyspaceName, String cf, String key); /** @deprecated See CASSANDRA-7544 */ @Deprecated(since = "4.0") public List getNaturalEndpoints(String keyspaceName, ByteBuffer key); - public List getNaturalEndpointsWithPort(String keysapceName, ByteBuffer key); + /** @deprecated See CASSANDRA-17665 */ + @Deprecated(since = "7.0") public List getNaturalEndpointsWithPort(String keysapceName, ByteBuffer key); + + /** + * This method returns the N replicas that are responsible for storing the + * specified key i.e for replication. + * + * @param keyspaceName keyspace name + * @param cf Column family name + * @param key - key for which we need to find the replica return value - + * the replica responsible for this key + */ + public List getNaturalReplicas(String keyspaceName, String cf, String key); + public List getNaturalReplicasWithPort(String keyspaceName, String cf, String key); /** * @deprecated use {@link #takeSnapshot(String tag, Map options, String... entities)} instead. See CASSANDRA-10907 diff --git a/src/java/org/apache/cassandra/tools/NodeProbe.java b/src/java/org/apache/cassandra/tools/NodeProbe.java index 353324e0ea..c60e0427e5 100644 --- a/src/java/org/apache/cassandra/tools/NodeProbe.java +++ b/src/java/org/apache/cassandra/tools/NodeProbe.java @@ -1200,14 +1200,14 @@ public class NodeProbe implements AutoCloseable ssProxy.setHintedHandoffThrottleInKB(throttleInKB); } - public List getEndpointsWithPort(String keyspace, String cf, String key) + public List getReplicasWithPort(String keyspace, String cf, String key) { - return ssProxy.getNaturalEndpointsWithPort(keyspace, cf, key); + return ssProxy.getNaturalReplicasWithPort(keyspace, cf, key); } - public List getEndpoints(String keyspace, String cf, String key) + public List getReplicas(String keyspace, String cf, String key) { - return ssProxy.getNaturalEndpoints(keyspace, cf, key); + return ssProxy.getNaturalReplicas(keyspace, cf, key); } public List getSSTables(String keyspace, String cf, String key, boolean hexFormat) diff --git a/src/java/org/apache/cassandra/tools/nodetool/GetEndpoints.java b/src/java/org/apache/cassandra/tools/nodetool/GetEndpoints.java index 3f30680951..6f0b6ea972 100644 --- a/src/java/org/apache/cassandra/tools/nodetool/GetEndpoints.java +++ b/src/java/org/apache/cassandra/tools/nodetool/GetEndpoints.java @@ -17,62 +17,10 @@ */ package org.apache.cassandra.tools.nodetool; -import java.net.InetAddress; -import java.util.ArrayList; -import java.util.List; - -import org.apache.cassandra.tools.NodeProbe; -import org.apache.cassandra.tools.nodetool.layout.CassandraUsage; - import picocli.CommandLine.Command; -import picocli.CommandLine.Mixin; -import picocli.CommandLine.Parameters; -import static com.google.common.base.Preconditions.checkArgument; -import static org.apache.cassandra.tools.nodetool.CommandUtils.concatArgs; - -@Command(name = "getendpoints", description = "Print the end points that owns the key") -public class GetEndpoints extends AbstractCommand +@Deprecated(since = "7.0") // this is alias to getreplicas +@Command(name = "getendpoints", description = "Print the end points that owns the key, deprecated, use getreplicas instead") +public class GetEndpoints extends GetReplicas { - @CassandraUsage(usage = " ", description = "The keyspace, the table, and the partition key for which we need to find the endpoint") - private List args = new ArrayList<>(); - - @Parameters(index = "0", arity = "0..1", description = "The keyspace for which we need to find the endpoint") - private String keyspace; - - @Parameters(index = "1", arity = "0..1", description = "The table for which we need to find the endpoint") - private String table; - - @Parameters(index = "2", arity = "0..1", description = "The partition key for which we need to find the endpoint") - private String key; - - @Mixin - private PrintPortMixin printPortMixin = new PrintPortMixin(); - - @Override - public void execute(NodeProbe probe) - { - args = concatArgs(keyspace, table, key); - - checkArgument(args.size() == 3, "getendpoints requires keyspace, table and partition key arguments"); - String ks = args.get(0); - String table = args.get(1); - String key = args.get(2); - - if (printPortMixin.printPort) - { - for (String endpoint : probe.getEndpointsWithPort(ks, table, key)) - { - probe.output().out.println(endpoint); - } - } - else - { - List endpoints = probe.getEndpoints(ks, table, key); - for (InetAddress endpoint : endpoints) - { - probe.output().out.println(endpoint.getHostAddress()); - } - } - } } diff --git a/src/java/org/apache/cassandra/tools/nodetool/GetReplicas.java b/src/java/org/apache/cassandra/tools/nodetool/GetReplicas.java new file mode 100644 index 0000000000..0f9e09810d --- /dev/null +++ b/src/java/org/apache/cassandra/tools/nodetool/GetReplicas.java @@ -0,0 +1,79 @@ +/* + * 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.tools.nodetool; + +import java.net.InetAddress; +import java.util.ArrayList; +import java.util.List; + +import org.apache.cassandra.tools.NodeProbe; +import org.apache.cassandra.tools.nodetool.layout.CassandraUsage; + +import picocli.CommandLine.Command; +import picocli.CommandLine.Mixin; +import picocli.CommandLine.Parameters; + +import static com.google.common.base.Preconditions.checkArgument; +import static org.apache.cassandra.tools.nodetool.CommandUtils.concatArgs; + +@Command(name = "getreplicas", description = "Print the replicas that own the key") +public class GetReplicas extends AbstractCommand +{ + @CassandraUsage(usage = "
", description = "The keyspace, the table, and the partition key for which we need to find the replica") + private List args = new ArrayList<>(); + + @Parameters(index = "0", arity = "0..1", description = "The keyspace for which we need to find the replica") + private String keyspace; + + @Parameters(index = "1", arity = "0..1", description = "The table for which we need to find the replica") + private String table; + + @Parameters(index = "2", arity = "0..1", description = "The partition key for which we need to find the replica") + private String key; + + @Mixin + private PrintPortMixin printPortMixin = new PrintPortMixin(); + + @Override + public void execute(NodeProbe probe) + { + args = concatArgs(keyspace, table, key); + + checkArgument(args.size() == 3, "requires keyspace, table and partition key arguments"); + String ks = args.get(0); + String table = args.get(1); + String key = args.get(2); + + if (printPortMixin.printPort) + { + for (String replica : probe.getReplicasWithPort(ks, table, key)) + { + probe.output().out.println(replica); + } + } + else + { + List replicas = probe.getReplicas(ks, table, key); + for (InetAddress replica : replicas) + { + probe.output().out.println(replica.getHostAddress()); + } + } + } +} diff --git a/src/java/org/apache/cassandra/tools/nodetool/NodetoolCommand.java b/src/java/org/apache/cassandra/tools/nodetool/NodetoolCommand.java index af1e835d91..fd2ccde672 100644 --- a/src/java/org/apache/cassandra/tools/nodetool/NodetoolCommand.java +++ b/src/java/org/apache/cassandra/tools/nodetool/NodetoolCommand.java @@ -120,6 +120,7 @@ import static org.apache.cassandra.tools.nodetool.Help.printTopCommandUsage; GetInterDCStreamThroughput.class, GetLoggingLevels.class, GetMaxHintWindow.class, + GetReplicas.class, GetSSTables.class, GetSeeds.class, GetSnapshotThrottle.class, diff --git a/test/distributed/org/apache/cassandra/distributed/test/GetEndpointsTest.java b/test/distributed/org/apache/cassandra/distributed/test/GetEndpointsTest.java index 214d6f698f..aa89d12417 100644 --- a/test/distributed/org/apache/cassandra/distributed/test/GetEndpointsTest.java +++ b/test/distributed/org/apache/cassandra/distributed/test/GetEndpointsTest.java @@ -81,9 +81,9 @@ public class GetEndpointsTest extends TestBaseImpl for (IInvokableInstance i : cluster) { i.runOnInstance(() -> { - List endpoints = StorageService.instance.getNaturalEndpointsWithPort("system_cluster_metadata", "distributed_metadata_log", "1"); - assertEquals(endpoints.toString(), 3, endpoints.size()); - assertEquals(Replicas.stringify(ClusterMetadata.current().fullCMSMembersAsReplicas(), true), endpoints); + List replicas = StorageService.instance.getNaturalReplicasWithPort("system_cluster_metadata", "distributed_metadata_log", "1"); + assertEquals(replicas.toString(), 3, replicas.size()); + assertEquals(Replicas.stringify(ClusterMetadata.current().fullCMSMembersAsReplicas(), true), replicas); }); } diff --git a/test/distributed/org/apache/cassandra/distributed/test/GossipSettlesTest.java b/test/distributed/org/apache/cassandra/distributed/test/GossipSettlesTest.java index e86dcdf383..b67bbe5ed4 100644 --- a/test/distributed/org/apache/cassandra/distributed/test/GossipSettlesTest.java +++ b/test/distributed/org/apache/cassandra/distributed/test/GossipSettlesTest.java @@ -19,6 +19,7 @@ package org.apache.cassandra.distributed.test; import java.net.InetAddress; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -32,6 +33,8 @@ import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.distributed.Cluster; import org.apache.cassandra.gms.FailureDetector; import org.apache.cassandra.gms.Gossiper; +import org.apache.cassandra.locator.EndpointsForToken; +import org.apache.cassandra.locator.Replicas; import org.apache.cassandra.net.MessagingService; import org.apache.cassandra.schema.SchemaConstants; import org.apache.cassandra.schema.SystemDistributedKeyspace; @@ -78,16 +81,22 @@ public class GossipSettlesTest extends TestBaseImpl Assert.assertEquals(addPortToValues(ss.getHostIdToEndpoint()), ss.getHostIdToEndpointWithPort()); Assert.assertEquals(addPortToKeys(ss.getLoadMap()), ss.getLoadMapWithPort()); Assert.assertEquals(addPortToList(ss.getLiveNodes()), ss.getLiveNodesWithPort()); - List naturalEndpointsAddedPort = ss.getNaturalEndpoints(SchemaConstants.DISTRIBUTED_KEYSPACE_NAME, + List naturalReplicasAddedPort = ss.getNaturalReplicas(SchemaConstants.DISTRIBUTED_KEYSPACE_NAME, SystemDistributedKeyspace.VIEW_BUILD_STATUS, "dummy").stream() .map(e -> addStoragePortToIP(e.getHostAddress())).collect(Collectors.toList()); - Assert.assertEquals(naturalEndpointsAddedPort, - ss.getNaturalEndpointsWithPort(SchemaConstants.DISTRIBUTED_KEYSPACE_NAME, - SystemDistributedKeyspace.VIEW_BUILD_STATUS, "dummy")); - naturalEndpointsAddedPort = ss.getNaturalEndpoints(SchemaConstants.DISTRIBUTED_KEYSPACE_NAME, ByteBufferUtil.EMPTY_BYTE_BUFFER).stream() - .map(e -> addStoragePortToIP(e.getHostAddress())).collect(Collectors.toList()); - Assert.assertEquals(naturalEndpointsAddedPort, - ss.getNaturalEndpointsWithPort(SchemaConstants.DISTRIBUTED_KEYSPACE_NAME, ByteBufferUtil.EMPTY_BYTE_BUFFER)); + Assert.assertEquals(naturalReplicasAddedPort, + ss.getNaturalReplicasWithPort(SchemaConstants.DISTRIBUTED_KEYSPACE_NAME, + SystemDistributedKeyspace.VIEW_BUILD_STATUS, "dummy")); + + EndpointsForToken replicas = ss.getNaturalReplicasForToken(SchemaConstants.DISTRIBUTED_KEYSPACE_NAME, ByteBufferUtil.EMPTY_BYTE_BUFFER); + List inetList = new ArrayList<>(replicas.size()); + replicas.forEach(r -> inetList.add(r.endpoint().getAddress())); + + naturalReplicasAddedPort = inetList.stream().map(e -> addStoragePortToIP(e.getHostAddress())).collect(Collectors.toList()); + + List replicas2 = Replicas.stringify(ss.getNaturalReplicasForToken(SchemaConstants.DISTRIBUTED_KEYSPACE_NAME, ByteBufferUtil.EMPTY_BYTE_BUFFER), true); + + Assert.assertEquals(naturalReplicasAddedPort, replicas2); // Difference in key type... convert to String and add the port to the older format diff --git a/test/resources/nodetool/help/getendpoints b/test/resources/nodetool/help/getendpoints index 7eb9aef60d..6daeb4c0c4 100644 --- a/test/resources/nodetool/help/getendpoints +++ b/test/resources/nodetool/help/getendpoints @@ -1,5 +1,6 @@ NAME - nodetool getendpoints - Print the end points that owns the key + nodetool getendpoints - Print the end points that owns the key, + deprecated, use getreplicas instead SYNOPSIS nodetool [(-h | --host )] [(-p | --port )] @@ -34,4 +35,4 @@ OPTIONS
The keyspace, the table, and the partition key for which we need to - find the endpoint + find the replica diff --git a/test/resources/nodetool/help/getreplicas b/test/resources/nodetool/help/getreplicas new file mode 100644 index 0000000000..259aebc748 --- /dev/null +++ b/test/resources/nodetool/help/getreplicas @@ -0,0 +1,37 @@ +NAME + nodetool getreplicas - Print the replicas that own the key + +SYNOPSIS + nodetool [(-h | --host )] [(-p | --port )] + [(-pw | --password )] + [(-pwf | --password-file )] + [(-u | --username )] getreplicas + [(-pp | --print-port)] [--]
+ +OPTIONS + -h , --host + Node hostname or ip address + + -p , --port + Remote jmx agent port number + + -pp, --print-port + Operate in 4.0 mode with hosts disambiguated by port number + + -pw , --password + Remote jmx agent password + + -pwf , --password-file + Path to the JMX password file + + -u , --username + Remote jmx agent username + + -- + This option can be used to separate command-line options from the + list of argument, (useful when arguments might be mistaken for + command-line options + +
+ The keyspace, the table, and the partition key for which we need to + find the replica diff --git a/test/resources/nodetool/help/nodetool b/test/resources/nodetool/help/nodetool index a3fe2c520e..3c8172f96b 100644 --- a/test/resources/nodetool/help/nodetool +++ b/test/resources/nodetool/help/nodetool @@ -64,12 +64,13 @@ The most commonly used nodetool commands are: getconcurrentcompactors Get the number of concurrent compactors in the system. getconcurrentviewbuilders Get the number of concurrent view builders in the system getdefaultrf Gets default keyspace replication factor. - getendpoints Print the end points that owns the key + getendpoints Print the end points that owns the key, deprecated, use getreplicas instead getfullquerylog Print configuration of fql if enabled, otherwise the configuration reflected in cassandra.yaml getguardrailsconfig Print runtime configuration of guardrails. getinterdcstreamthroughput Print the throughput cap for inter-datacenter streaming and entire SSTable inter-datacenter streaming in the systemin rounded megabits. For precise number, please, use option -d getlogginglevels Get the runtime logging levels getmaxhintwindow Print the max hint window in ms + getreplicas Print the replicas that own the key getseeds Get the currently in use seed node IP list excluding the node IP getsnapshotthrottle Print the snapshot_links_per_second throttle for snapshot/clearsnapshot getsstables Print the sstable filenames that own the key