Return-Path: X-Original-To: apmail-cassandra-commits-archive@www.apache.org Delivered-To: apmail-cassandra-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id BD65C95C4 for ; Fri, 17 Feb 2012 23:29:23 +0000 (UTC) Received: (qmail 83249 invoked by uid 500); 17 Feb 2012 23:29:23 -0000 Delivered-To: apmail-cassandra-commits-archive@cassandra.apache.org Received: (qmail 83223 invoked by uid 500); 17 Feb 2012 23:29:23 -0000 Mailing-List: contact commits-help@cassandra.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cassandra.apache.org Delivered-To: mailing list commits@cassandra.apache.org Received: (qmail 83215 invoked by uid 99); 17 Feb 2012 23:29:23 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 17 Feb 2012 23:29:23 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.114] (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 17 Feb 2012 23:29:20 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 6C08E320964; Fri, 17 Feb 2012 23:28:58 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: vijay@apache.org To: commits@cassandra.apache.org X-Mailer: ASF-Git Admin Mailer Subject: git commit: Show Effective Owership patch by Vijay; reviewed by Brandon Williams for CASSANDRA-3412 Message-Id: <20120217232858.6C08E320964@tyr.zones.apache.org> Date: Fri, 17 Feb 2012 23:28:58 +0000 (UTC) X-Virus-Checked: Checked by ClamAV on apache.org Updated Branches: refs/heads/cassandra-1.1 064adba2e -> 14d57389b Show Effective Owership patch by Vijay; reviewed by Brandon Williams for CASSANDRA-3412 Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/14d57389 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/14d57389 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/14d57389 Branch: refs/heads/cassandra-1.1 Commit: 14d57389bf4bead6e52d3d0b45ac536b9ff232ed Parents: 064adba Author: Vijay Parthasarathy Authored: Fri Feb 17 15:28:19 2012 -0800 Committer: Vijay Parthasarathy Committed: Fri Feb 17 15:28:19 2012 -0800 ---------------------------------------------------------------------- CHANGES.txt | 2 +- .../apache/cassandra/service/StorageService.java | 65 +++++++++++++++ .../cassandra/service/StorageServiceMBean.java | 9 ++ src/java/org/apache/cassandra/tools/NodeCmd.java | 31 +++++-- src/java/org/apache/cassandra/tools/NodeProbe.java | 5 + 5 files changed, 103 insertions(+), 9 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/14d57389/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index 259007e..596ceeb 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,7 +2,7 @@ * avoid unproductive deserializing of cached rows during compaction (CASSANDRA-3921) * fix concurrency issues with CQL keyspace creation (CASSANDRA-3903) - + * Show Effective Owership via Nodetool ring (CASSANDRA-3412) 1.1-beta1 * add nodetool rebuild_index (CASSANDRA-3583) http://git-wip-us.apache.org/repos/asf/cassandra/blob/14d57389/src/java/org/apache/cassandra/service/StorageService.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/service/StorageService.java b/src/java/org/apache/cassandra/service/StorageService.java index d06b4a2..3635801 100644 --- a/src/java/org/apache/cassandra/service/StorageService.java +++ b/src/java/org/apache/cassandra/service/StorageService.java @@ -26,12 +26,15 @@ import java.net.InetAddress; import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.util.*; +import java.util.Map.Entry; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; import javax.management.MBeanServer; import javax.management.ObjectName; +import com.google.common.base.Supplier; import com.google.common.collect.*; + import org.apache.log4j.Level; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; @@ -935,6 +938,25 @@ public class StorageService implements IEndpointStateChangeSubscriber, StorageSe return rangeToEndpointMap; } + private Map>> constructEndpointToRangeMap(String keyspace) + { + Multimap> endpointToRangeMap = Multimaps.newListMultimap(new HashMap>>(), new Supplier>>() + { + public List> get() + { + return Lists.newArrayList(); + } + }); + + List> ranges = getAllRanges(tokenMetadata_.sortedTokens()); + for (Range range : ranges) + { + for (InetAddress endpoint : Table.open(keyspace).getReplicationStrategy().getNaturalEndpoints(range.left)) + endpointToRangeMap.put(endpoint, range); + } + return endpointToRangeMap.asMap(); + } + /* * Handle the reception of a new particular ApplicationState for a particular endpoint. Note that the value of the * ApplicationState has not necessarily "changed" since the last known value, if we already received the same update @@ -2615,6 +2637,49 @@ public class StorageService implements IEndpointStateChangeSubscriber, StorageSe return string_map; } + public Map effectiveOwnership(String keyspace) throws ConfigurationException + { + Map effective = Maps.newHashMap(); + if (Schema.instance.getNonSystemTables().size() <= 0) + throw new ConfigurationException("Couldn't find any Non System Keyspaces to infer replication topology"); + if (keyspace == null && !hasSameReplication(Schema.instance.getNonSystemTables())) + throw new ConfigurationException("Non System keyspaces doesnt have the same topology"); + + if (keyspace == null) + keyspace = Schema.instance.getNonSystemTables().get(0); + + List sortedTokens = new ArrayList(tokenMetadata_.getTokenToEndpointMapForReading().keySet()); + Collections.sort(sortedTokens); + Map ownership = getPartitioner().describeOwnership(sortedTokens); + + for (Entry>> ranges : constructEndpointToRangeMap(keyspace).entrySet()) + { + Token token = tokenMetadata_.getToken(ranges.getKey()); + for (Range range: ranges.getValue()) + { + float value = effective.get(token.toString()) == null ? 0.0F : effective.get(token.toString()); + effective.put(token.toString(), value + ownership.get(range.left)); + } + } + return effective; + } + + private boolean hasSameReplication(List list) + { + if (list.isEmpty()) + return false; + for (int i = 0; i < list.size() -1; i++) + { + KSMetaData ksm1 = Schema.instance.getKSMetaData(Schema.instance.getNonSystemTables().get(i)); + KSMetaData ksm2 = Schema.instance.getKSMetaData(Schema.instance.getNonSystemTables().get(i + 1)); + if (!ksm1.strategyClass.equals(ksm2.strategyClass) || + !Iterators.elementsEqual(ksm1.strategyOptions.entrySet().iterator(), + ksm2.strategyOptions.entrySet().iterator())) + return false; + } + return true; + } + public List getKeyspaces() { List tableslist = new ArrayList(Schema.instance.getTables()); http://git-wip-us.apache.org/repos/asf/cassandra/blob/14d57389/src/java/org/apache/cassandra/service/StorageServiceMBean.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/service/StorageServiceMBean.java b/src/java/org/apache/cassandra/service/StorageServiceMBean.java index 6af63b7..4f589d7 100644 --- a/src/java/org/apache/cassandra/service/StorageServiceMBean.java +++ b/src/java/org/apache/cassandra/service/StorageServiceMBean.java @@ -299,6 +299,15 @@ public interface StorageServiceMBean */ public Map getOwnership(); + /** + * Effective ownership is % of the data each node owns given the keyspace + * we calculate the percentage using replication factor. + * If Keyspace == null, this method will try to verify if all the keyspaces + * in the cluster have the same replication strategies and if yes then we will + * use the first else a empty Map is returned. + */ + public Map effectiveOwnership(String keyspace) throws ConfigurationException; + public List getKeyspaces(); /** http://git-wip-us.apache.org/repos/asf/cassandra/blob/14d57389/src/java/org/apache/cassandra/tools/NodeCmd.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/tools/NodeCmd.java b/src/java/org/apache/cassandra/tools/NodeCmd.java index d1648a1..198e659 100644 --- a/src/java/org/apache/cassandra/tools/NodeCmd.java +++ b/src/java/org/apache/cassandra/tools/NodeCmd.java @@ -203,7 +203,7 @@ public class NodeCmd * * @param outs the stream to write to */ - public void printRing(PrintStream outs) + public void printRing(PrintStream outs, String keyspace) { Map tokenToEndpoint = probe.getTokenToEndpointMap(); List sortedTokens = new ArrayList(tokenToEndpoint.keySet()); @@ -215,16 +215,27 @@ public class NodeCmd Collection movingNodes = probe.getMovingNodes(); Map loadMap = probe.getLoadMap(); - String format = "%-16s%-12s%-12s%-7s%-8s%-16s%-8s%-44s%n"; - outs.printf(format, "Address", "DC", "Rack", "Status", "State", "Load", "Owns", "Token"); + String format = "%-16s%-12s%-12s%-7s%-8s%-16s%-20s%-44s%n"; + + // Calculate per-token ownership of the ring + Map ownerships; + try + { + ownerships = probe.effectiveOwnership(keyspace); + outs.printf(format, "Address", "DC", "Rack", "Status", "State", "Load", "Effective-Owership", "Token"); + } + catch (ConfigurationException ex) + { + ownerships = probe.getOwnership(); + outs.printf("Note: Ownership information does not include topology, please specify a keyspace. \n"); + outs.printf(format, "Address", "DC", "Rack", "Status", "State", "Load", "Owns", "Token"); + } + // show pre-wrap token twice so you can always read a node's range as // (previous line token, current line token] if (sortedTokens.size() > 1) outs.printf(format, "", "", "", "", "", "", "", sortedTokens.get(sortedTokens.size() - 1)); - // Calculate per-token ownership of the ring - Map ownerships = probe.getOwnership(); - for (String token : sortedTokens) { String primaryEndpoint = tokenToEndpoint.get(token); @@ -264,7 +275,7 @@ public class NodeCmd String load = loadMap.containsKey(primaryEndpoint) ? loadMap.get(primaryEndpoint) : "?"; - String owns = new DecimalFormat("##0.00%").format(ownerships.get(token)); + String owns = new DecimalFormat("##0.00%").format(ownerships.get(token) == null ? 0.0F : ownerships.get(token)); outs.printf(format, primaryEndpoint, dataCenter, rack, status, state, load, owns, token); } } @@ -655,7 +666,11 @@ public class NodeCmd switch (command) { - case RING : nodeCmd.printRing(System.out); break; + case RING : + if (arguments.length > 0) { nodeCmd.printRing(System.out, arguments[0]); } + else { nodeCmd.printRing(System.out, null); }; + break; + case INFO : nodeCmd.printInfo(System.out); break; case CFSTATS : nodeCmd.printColumnFamilyStats(System.out); break; case DECOMMISSION : probe.decommission(); break; http://git-wip-us.apache.org/repos/asf/cassandra/blob/14d57389/src/java/org/apache/cassandra/tools/NodeProbe.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/tools/NodeProbe.java b/src/java/org/apache/cassandra/tools/NodeProbe.java index 46d4c63..8b0d668 100644 --- a/src/java/org/apache/cassandra/tools/NodeProbe.java +++ b/src/java/org/apache/cassandra/tools/NodeProbe.java @@ -267,6 +267,11 @@ public class NodeProbe return ssProxy.getOwnership(); } + public Map effectiveOwnership(String keyspace) throws ConfigurationException + { + return ssProxy.effectiveOwnership(keyspace); + } + public CacheServiceMBean getCacheServiceMBean() { String cachePath = "org.apache.cassandra.db:type=Caches";