| /* |
| * 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 static java.lang.String.format; |
| import io.airlift.command.Arguments; |
| import io.airlift.command.Command; |
| import io.airlift.command.Option; |
| |
| import java.net.InetAddress; |
| import java.net.UnknownHostException; |
| import java.text.DecimalFormat; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| |
| import org.apache.cassandra.tools.NodeProbe; |
| import org.apache.cassandra.tools.NodeTool; |
| import org.apache.cassandra.tools.NodeTool.NodeToolCmd; |
| |
| import com.google.common.collect.LinkedHashMultimap; |
| |
| @Command(name = "ring", description = "Print information about the token ring") |
| public class Ring extends NodeToolCmd |
| { |
| @Arguments(description = "Specify a keyspace for accurate ownership information (topology awareness)") |
| private String keyspace = null; |
| |
| @Option(title = "resolve_ip", name = {"-r", "--resolve-ip"}, description = "Show node domain names instead of IPs") |
| private boolean resolveIp = false; |
| |
| @Override |
| public void execute(NodeProbe probe) |
| { |
| Map<String, String> tokensToEndpoints = probe.getTokenToEndpointMap(); |
| LinkedHashMultimap<String, String> endpointsToTokens = LinkedHashMultimap.create(); |
| boolean haveVnodes = false; |
| for (Map.Entry<String, String> entry : tokensToEndpoints.entrySet()) |
| { |
| haveVnodes |= endpointsToTokens.containsKey(entry.getValue()); |
| endpointsToTokens.put(entry.getValue(), entry.getKey()); |
| } |
| |
| int maxAddressLength = Collections.max(endpointsToTokens.keys(), new Comparator<String>() |
| { |
| @Override |
| public int compare(String first, String second) |
| { |
| return Integer.compare(first.length(), second.length()); |
| } |
| }).length(); |
| |
| String formatPlaceholder = "%%-%ds %%-12s%%-7s%%-8s%%-16s%%-20s%%-44s%%n"; |
| String format = format(formatPlaceholder, maxAddressLength); |
| |
| StringBuffer errors = new StringBuffer(); |
| boolean showEffectiveOwnership = true; |
| // Calculate per-token ownership of the ring |
| Map<InetAddress, Float> ownerships; |
| try |
| { |
| ownerships = probe.effectiveOwnership(keyspace); |
| } |
| catch (IllegalStateException ex) |
| { |
| ownerships = probe.getOwnership(); |
| errors.append("Note: " + ex.getMessage() + "%n"); |
| showEffectiveOwnership = false; |
| } |
| catch (IllegalArgumentException ex) |
| { |
| System.out.printf("%nError: " + ex.getMessage() + "%n"); |
| return; |
| } |
| |
| |
| System.out.println(); |
| for (Entry<String, SetHostStat> entry : NodeTool.getOwnershipByDc(probe, resolveIp, tokensToEndpoints, ownerships).entrySet()) |
| printDc(probe, format, entry.getKey(), endpointsToTokens, entry.getValue(),showEffectiveOwnership); |
| |
| if (haveVnodes) |
| { |
| System.out.println(" Warning: \"nodetool ring\" is used to output all the tokens of a node."); |
| System.out.println(" To view status related info of a node use \"nodetool status\" instead.\n"); |
| } |
| |
| System.out.printf("%n " + errors.toString()); |
| } |
| |
| private void printDc(NodeProbe probe, String format, |
| String dc, |
| LinkedHashMultimap<String, String> endpointsToTokens, |
| SetHostStat hoststats,boolean showEffectiveOwnership) |
| { |
| Collection<String> liveNodes = probe.getLiveNodes(); |
| Collection<String> deadNodes = probe.getUnreachableNodes(); |
| Collection<String> joiningNodes = probe.getJoiningNodes(); |
| Collection<String> leavingNodes = probe.getLeavingNodes(); |
| Collection<String> movingNodes = probe.getMovingNodes(); |
| Map<String, String> loadMap = probe.getLoadMap(); |
| |
| System.out.println("Datacenter: " + dc); |
| System.out.println("=========="); |
| |
| // get the total amount of replicas for this dc and the last token in this dc's ring |
| List<String> tokens = new ArrayList<>(); |
| String lastToken = ""; |
| |
| for (HostStat stat : hoststats) |
| { |
| tokens.addAll(endpointsToTokens.get(stat.endpoint.getHostAddress())); |
| lastToken = tokens.get(tokens.size() - 1); |
| } |
| |
| System.out.printf(format, "Address", "Rack", "Status", "State", "Load", "Owns", "Token"); |
| |
| if (hoststats.size() > 1) |
| System.out.printf(format, "", "", "", "", "", "", lastToken); |
| else |
| System.out.println(); |
| |
| for (HostStat stat : hoststats) |
| { |
| String endpoint = stat.endpoint.getHostAddress(); |
| String rack; |
| try |
| { |
| rack = probe.getEndpointSnitchInfoProxy().getRack(endpoint); |
| } |
| catch (UnknownHostException e) |
| { |
| rack = "Unknown"; |
| } |
| |
| String status = liveNodes.contains(endpoint) |
| ? "Up" |
| : deadNodes.contains(endpoint) |
| ? "Down" |
| : "?"; |
| |
| String state = "Normal"; |
| |
| if (joiningNodes.contains(endpoint)) |
| state = "Joining"; |
| else if (leavingNodes.contains(endpoint)) |
| state = "Leaving"; |
| else if (movingNodes.contains(endpoint)) |
| state = "Moving"; |
| |
| String load = loadMap.containsKey(endpoint) |
| ? loadMap.get(endpoint) |
| : "?"; |
| String owns = stat.owns != null && showEffectiveOwnership? new DecimalFormat("##0.00%").format(stat.owns) : "?"; |
| System.out.printf(format, stat.ipOrDns(), rack, status, state, load, owns, stat.token); |
| } |
| System.out.println(); |
| } |
| } |