Author: xedin Date: Mon Aug 29 12:53:02 2011 New Revision: 1162775 URL: http://svn.apache.org/viewvc?rev=1162775&view=rev Log: Improvements of the CLI `describe` command patch by satishbabu; reviewed by xedin for CASSANDRA-2630
Modified: cassandra/trunk/CHANGES.txt cassandra/trunk/src/java/org/apache/cassandra/cli/Cli.g cassandra/trunk/src/java/org/apache/cassandra/cli/CliClient.java cassandra/trunk/src/java/org/apache/cassandra/cli/CliUtils.java cassandra/trunk/src/resources/org/apache/cassandra/cli/CliHelp.yaml cassandra/trunk/test/unit/org/apache/cassandra/cli/CliTest.java Modified: cassandra/trunk/CHANGES.txt URL: http://svn.apache.org/viewvc/cassandra/trunk/CHANGES.txt?rev=1162775&r1=1162774&r2=1162775&view=diff ============================================================================== --- cassandra/trunk/CHANGES.txt (original) +++ cassandra/trunk/CHANGES.txt Mon Aug 29 12:53:02 2011 @@ -45,7 +45,7 @@ * Add timeouts to client request schedulers (CASSANDRA-3079) * Cli to use hashes rather than array of hashes for strategy options (CASSANDRA-3081) * LeveledCompactionStrategy (CASSANDRA-1608) - + * Improvements of the CLI `describe` command (CASSANDRA-2630) 0.8.5 * fix NPE when encryption_options is unspecified (CASSANDRA-3007) Modified: cassandra/trunk/src/java/org/apache/cassandra/cli/Cli.g URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/cli/Cli.g?rev=1162775&r1=1162774&r2=1162775&view=diff ============================================================================== --- cassandra/trunk/src/java/org/apache/cassandra/cli/Cli.g (original) +++ cassandra/trunk/src/java/org/apache/cassandra/cli/Cli.g Mon Aug 29 12:53:02 2011 @@ -35,7 +35,7 @@ tokens { // various top-level CLI statements. // NODE_CONNECT; - NODE_DESCRIBE_TABLE; + NODE_DESCRIBE; NODE_DESCRIBE_CLUSTER; NODE_USE_TABLE; NODE_EXIT; @@ -180,8 +180,8 @@ helpStatement -> ^(NODE_HELP NODE_CONNECT) | HELP USE -> ^(NODE_HELP NODE_USE_TABLE) - | HELP DESCRIBE KEYSPACE - -> ^(NODE_HELP NODE_DESCRIBE_TABLE) + | HELP DESCRIBE + -> ^(NODE_HELP NODE_DESCRIBE) | HELP DESCRIBE 'CLUSTER' -> ^(NODE_HELP NODE_DESCRIBE_CLUSTER) | HELP EXIT @@ -366,8 +366,8 @@ showSchema ; describeTable - : DESCRIBE KEYSPACE (keyspace)? - -> ^(NODE_DESCRIBE_TABLE (keyspace)?) + : DESCRIBE (keyspace)? + -> ^(NODE_DESCRIBE (keyspace)?) ; describeCluster Modified: cassandra/trunk/src/java/org/apache/cassandra/cli/CliClient.java URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/cli/CliClient.java?rev=1162775&r1=1162774&r2=1162775&view=diff ============================================================================== --- cassandra/trunk/src/java/org/apache/cassandra/cli/CliClient.java (original) +++ cassandra/trunk/src/java/org/apache/cassandra/cli/CliClient.java Mon Aug 29 12:53:02 2011 @@ -250,8 +250,8 @@ public class CliClient case CliParser.NODE_SHOW_SCHEMA: executeShowSchema(tree); break; - case CliParser.NODE_DESCRIBE_TABLE: - executeDescribeKeySpace(tree); + case CliParser.NODE_DESCRIBE: + executeDescribe(tree); break; case CliParser.NODE_DESCRIBE_CLUSTER: executeDescribeCluster(); @@ -1857,92 +1857,10 @@ public class CliClient sessionState.out.println(" Column Families:"); - boolean isSuper; - Collections.sort(ks_def.cf_defs, new CfDefNamesComparator()); - for (CfDef cf_def : ks_def.cf_defs) - { - // fetching bean for current column family store - ColumnFamilyStoreMBean cfMBean = (probe == null) ? null : probe.getCfsProxy(ks_def.getName(), cf_def.getName()); - isSuper = cf_def.column_type.equals("Super"); - sessionState.out.printf(" ColumnFamily: %s%s%n", cf_def.name, isSuper ? " (Super)" : ""); - - if (cf_def.comment != null && !cf_def.comment.isEmpty()) - { - sessionState.out.printf(" \"%s\"%n", cf_def.comment); - } - if (cf_def.key_validation_class != null) - sessionState.out.printf(" Key Validation Class: %s%n", cf_def.key_validation_class); - if (cf_def.default_validation_class != null) - sessionState.out.printf(" Default column value validator: %s%n", cf_def.default_validation_class); - sessionState.out.printf(" Columns sorted by: %s%s%n", cf_def.comparator_type, cf_def.column_type.equals("Super") ? "/" + cf_def.subcomparator_type : ""); - sessionState.out.printf(" Row cache size / save period in seconds / keys to save : %s/%s/%s%n", - cf_def.row_cache_size, cf_def.row_cache_save_period_in_seconds, - cf_def.row_cache_keys_to_save == Integer.MAX_VALUE ? "all" : cf_def.row_cache_keys_to_save); - sessionState.out.printf(" Key cache size / save period in seconds: %s/%s%n", cf_def.key_cache_size, cf_def.key_cache_save_period_in_seconds); - sessionState.out.printf(" Memtable thresholds: %s/%s (millions of ops/MB)%n", - cf_def.memtable_operations_in_millions, cf_def.memtable_throughput_in_mb); - sessionState.out.printf(" GC grace seconds: %s%n", cf_def.gc_grace_seconds); - sessionState.out.printf(" Compaction min/max thresholds: %s/%s%n", cf_def.min_compaction_threshold, cf_def.max_compaction_threshold); - sessionState.out.printf(" Read repair chance: %s%n", cf_def.read_repair_chance); - sessionState.out.printf(" Replicate on write: %s%n", cf_def.replicate_on_write); - sessionState.out.printf(" Compression enabled: %s%n", cf_def.compression); - - // if we have connection to the cfMBean established - if (cfMBean != null) - { - sessionState.out.printf(" Built indexes: %s%n", cfMBean.getBuiltIndexes()); - } - - if (cf_def.getColumn_metadataSize() != 0) - { - String leftSpace = " "; - String columnLeftSpace = leftSpace + " "; - - String compareWith = isSuper ? cf_def.subcomparator_type - : cf_def.comparator_type; - AbstractType columnNameValidator = getFormatType(compareWith); - - sessionState.out.println(leftSpace + "Column Metadata:"); - for (ColumnDef columnDef : cf_def.getColumn_metadata()) - { - String columnName = columnNameValidator.getString(columnDef.name); - if (columnNameValidator instanceof BytesType) - { - try - { - String columnString = UTF8Type.instance.getString(columnDef.name); - columnName = columnString + " (" + columnName + ")"; - } - catch (MarshalException e) - { - // guess it wasn't a utf8 column name after all - } - } - - sessionState.out.println(leftSpace + " Column Name: " + columnName); - sessionState.out.println(columnLeftSpace + "Validation Class: " + columnDef.getValidation_class()); - - if (columnDef.isSetIndex_name()) - { - sessionState.out.println(columnLeftSpace + "Index Name: " + columnDef.getIndex_name()); - } - - if (columnDef.isSetIndex_type()) - { - sessionState.out.println(columnLeftSpace + "Index Type: " + columnDef.getIndex_type().name()); - } - } - } - sessionState.out.printf(" Compaction Strategy: %s%n", cf_def.compaction_strategy); - if (!cf_def.compaction_strategy_options.isEmpty()) - { - sessionState.out.println(" Compaction Strategy Options:"); - for (Map.Entry<String, String> e : cf_def.compaction_strategy_options.entrySet()) - sessionState.out.printf(" %s: %s%n", e.getKey(), e.getValue()); - } - } + for (CfDef cf_def : ks_def.cf_defs) + describeColumnFamily(ks_def, cf_def, probe); // compaction manager information if (compactionManagerMBean != null) @@ -1977,34 +1895,151 @@ public class CliClient } } - // DESCRIBE KEYSPACE (<keyspace_name>)? - private void executeDescribeKeySpace(Tree statement) throws TException, InvalidRequestException + private void describeColumnFamily(KsDef ks_def, CfDef cf_def, NodeProbe probe) throws TException { - if (!CliMain.isConnected()) - return; + // fetching bean for current column family store + ColumnFamilyStoreMBean cfMBean = (probe == null) ? null : probe.getCfsProxy(ks_def.getName(), cf_def.getName()); + boolean isSuper = cf_def.column_type.equals("Super"); + sessionState.out.printf(" ColumnFamily: %s%s%n", cf_def.name, isSuper ? " (Super)" : ""); - String keySpaceName; + if (cf_def.comment != null && !cf_def.comment.isEmpty()) + sessionState.out.printf(" \"%s\"%n", cf_def.comment); - // Get keyspace name - if (statement.getChildCount() == 0) + if (cf_def.key_validation_class != null) + sessionState.out.printf(" Key Validation Class: %s%n", cf_def.key_validation_class); + + if (cf_def.default_validation_class != null) + sessionState.out.printf(" Default column value validator: %s%n", cf_def.default_validation_class); + + sessionState.out.printf(" Columns sorted by: %s%s%n", cf_def.comparator_type, cf_def.column_type.equals("Super") ? "/" + cf_def.subcomparator_type : ""); + sessionState.out.printf(" Row cache size / save period in seconds / keys to save : %s/%s/%s%n", + cf_def.row_cache_size, cf_def.row_cache_save_period_in_seconds, + cf_def.row_cache_keys_to_save == Integer.MAX_VALUE ? "all" : cf_def.row_cache_keys_to_save); + sessionState.out.printf(" Key cache size / save period in seconds: %s/%s%n", cf_def.key_cache_size, cf_def.key_cache_save_period_in_seconds); + sessionState.out.printf(" Memtable thresholds: %s/%s (millions of ops/MB)%n", + cf_def.memtable_operations_in_millions, cf_def.memtable_throughput_in_mb); + sessionState.out.printf(" GC grace seconds: %s%n", cf_def.gc_grace_seconds); + sessionState.out.printf(" Compaction min/max thresholds: %s/%s%n", cf_def.min_compaction_threshold, cf_def.max_compaction_threshold); + sessionState.out.printf(" Read repair chance: %s%n", cf_def.read_repair_chance); + sessionState.out.printf(" Replicate on write: %s%n", cf_def.replicate_on_write); + sessionState.out.printf(" Compression enabled: %s%n", cf_def.compression); + + // if we have connection to the cfMBean established + if (cfMBean != null) + sessionState.out.printf(" Built indexes: %s%n", cfMBean.getBuiltIndexes()); + + if (cf_def.getColumn_metadataSize() != 0) { - // trying to use current keyspace if keyspace name was not given - keySpaceName = keySpace; + String leftSpace = " "; + String columnLeftSpace = leftSpace + " "; + + String compareWith = isSuper ? cf_def.subcomparator_type + : cf_def.comparator_type; + AbstractType columnNameValidator = getFormatType(compareWith); + + sessionState.out.println(leftSpace + "Column Metadata:"); + for (ColumnDef columnDef : cf_def.getColumn_metadata()) + { + String columnName = columnNameValidator.getString(columnDef.name); + if (columnNameValidator instanceof BytesType) + { + try + { + String columnString = UTF8Type.instance.getString(columnDef.name); + columnName = columnString + " (" + columnName + ")"; + } + catch (MarshalException e) + { + // guess it wasn't a utf8 column name after all + } + } + + sessionState.out.println(leftSpace + " Column Name: " + columnName); + sessionState.out.println(columnLeftSpace + "Validation Class: " + columnDef.getValidation_class()); + + if (columnDef.isSetIndex_name()) + sessionState.out.println(columnLeftSpace + "Index Name: " + columnDef.getIndex_name()); + + if (columnDef.isSetIndex_type()) + sessionState.out.println(columnLeftSpace + "Index Type: " + columnDef.getIndex_type().name()); + } } - else + + sessionState.out.printf(" Compaction Strategy: %s%n", cf_def.compaction_strategy); + + if (!cf_def.compaction_strategy_options.isEmpty()) { - // we have keyspace name as an argument - keySpaceName = CliCompiler.getKeySpace(statement, thriftClient.describe_keyspaces()); + sessionState.out.println(" Compaction Strategy Options:"); + for (Map.Entry<String, String> e : cf_def.compaction_strategy_options.entrySet()) + sessionState.out.printf(" %s: %s%n", e.getKey(), e.getValue()); } + } - if (keySpaceName == null) - { - sessionState.out.println("Keyspace argument required if you are not authorized in any keyspace."); + // DESCRIBE KEYSPACE (<keyspace> | <column_family>)? + private void executeDescribe(Tree statement) throws TException, InvalidRequestException + { + if (!CliMain.isConnected()) return; + + int argCount = statement.getChildCount(); + + KsDef currentKeySpace = keyspacesMap.get(keySpace); + + if (argCount > 1) // in case somebody changes Cli grammar + throw new RuntimeException("`describe` command take maximum one argument. See `help describe;`"); + + if (argCount == 0) + { + if (currentKeySpace != null) + { + describeKeySpace(currentKeySpace.name, null); + return; + } + + sessionState.out.println("Authenticate to a Keyspace, before using `describe` or `describe <column_family>`"); + } + else if (argCount == 1) + { + // name of the keyspace or ColumnFamily + String entityName = statement.getChild(0).getText(); + + KsDef inputKsDef = CliUtils.getKeySpaceDef(entityName, thriftClient.describe_keyspaces()); + + if (inputKsDef == null && currentKeySpace == null) + throw new RuntimeException(String.format("Keyspace with name '%s' wasn't found, " + + "to lookup ColumnFamily with that name, please, authorize to one " + + "of the keyspaces first.", entityName)); + + CfDef inputCfDef = (inputKsDef == null) + ? getCfDef(currentKeySpace, entityName) + : null; // no need to lookup CfDef if we know that it was keyspace + + if (inputKsDef != null) + { + describeKeySpace(inputKsDef.name, inputKsDef); + } + else if (inputCfDef != null) + { + NodeProbe probe = sessionState.getNodeProbe(); + + try + { + describeColumnFamily(currentKeySpace, inputCfDef, probe); + + if (probe != null) + probe.close(); + } + catch (IOException e) + { + sessionState.out.println("Error while closing JMX connection: " + e.getMessage()); + } + } + else + { + sessionState.out.println("Sorry, no Keyspace nor ColumnFamily was found with name: " + entityName); + } } - - describeKeySpace(keySpaceName, null); } // ^(NODE_DESCRIBE_CLUSTER) or describe: schema_versions, partitioner, snitch Modified: cassandra/trunk/src/java/org/apache/cassandra/cli/CliUtils.java URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/cli/CliUtils.java?rev=1162775&r1=1162774&r2=1162775&view=diff ============================================================================== --- cassandra/trunk/src/java/org/apache/cassandra/cli/CliUtils.java (original) +++ cassandra/trunk/src/java/org/apache/cassandra/cli/CliUtils.java Mon Aug 29 12:53:02 2011 @@ -1,6 +1,7 @@ package org.apache.cassandra.cli; import java.util.LinkedHashSet; +import java.util.List; import java.util.Set; import org.apache.cassandra.thrift.CfDef; @@ -96,4 +97,25 @@ public class CliUtils return names; } + + /** + * Parse the statement from cli and return KsDef + * + * @param keyspaceName - name of the keyspace to lookup + * @param keyspaces - List of known keyspaces + * + * @return metadata about keyspace or null + */ + public static KsDef getKeySpaceDef(String keyspaceName, List<KsDef> keyspaces) + { + keyspaceName = keyspaceName.toUpperCase(); + + for (KsDef ksDef : keyspaces) + { + if (ksDef.name.toUpperCase().equals(keyspaceName)) + return ksDef; + } + + return null; + } } Modified: cassandra/trunk/src/resources/org/apache/cassandra/cli/CliHelp.yaml URL: http://svn.apache.org/viewvc/cassandra/trunk/src/resources/org/apache/cassandra/cli/CliHelp.yaml?rev=1162775&r1=1162774&r2=1162775&view=diff ============================================================================== --- cassandra/trunk/src/resources/org/apache/cassandra/cli/CliHelp.yaml (original) +++ cassandra/trunk/src/resources/org/apache/cassandra/cli/CliHelp.yaml Mon Aug 29 12:53:02 2011 @@ -41,7 +41,7 @@ help: | del Delete a column, super column or row. decr Decrements a counter column. describe cluster Describe the cluster configuration. - describe keyspace Describe a keyspace and it's column families. + describe Describe a keyspace and it's column families or column family in current keyspace. drop column family Remove a column family and it's data. drop keyspace Remove a keyspace and it's data. drop index Remove an existing index from specific column. @@ -115,21 +115,24 @@ commands: Examples: use Keyspace1; use Keyspace1 user 'badpasswd'; - - name: NODE_DESCRIBE_TABLE + - name: NODE_DESCRIBE help: | - describe keyspace; - describe keyspace <keyspace>; + describe; + describe <keyspace>; + describe <column_family>; - Describes the settings for the current or named keyspace, and the settings - for all column families in the keyspace. + Describes the settings for the current or named keyspace, or the settings + of the column family in the current authenticated keyspace. Optional Parameters: - keyspace: Name of the keyspace to describe. + - column_family: Name of the column family to describe. Examples: - describe keyspace; - describe keyspace Keyspace1; - - name: NODE_DESCRIBE_CLUSTER + describe; - Describes current authenticated keyspace + describe <keyspace>; - Describe this keyspace + describe <column_family>; - Describe the colum family in the current authenticated keyspace + - name: help: | describe cluster; Modified: cassandra/trunk/test/unit/org/apache/cassandra/cli/CliTest.java URL: http://svn.apache.org/viewvc/cassandra/trunk/test/unit/org/apache/cassandra/cli/CliTest.java?rev=1162775&r1=1162774&r2=1162775&view=diff ============================================================================== --- cassandra/trunk/test/unit/org/apache/cassandra/cli/CliTest.java (original) +++ cassandra/trunk/test/unit/org/apache/cassandra/cli/CliTest.java Mon Aug 29 12:53:02 2011 @@ -170,7 +170,7 @@ public class CliTest extends CleanupHelp "help help", "help connect", "help use", - "help describe KEYSPACE", + "help describe", "HELP exit", "help QUIT", "help show cluster name",