    private void describeKeySpace(String keySpaceName, KsDef metadata) throws TException
    {
        NodeProbe probe = sessionState.getNodeProbe();
        CompactionManagerMBean compactionManagerMBean = (probe == null) ? null : probe.getCompactionManagerProxy();
        sessionState.out.println("Keyspace: " + keySpaceName + ":");
        try
        {
            KsDef ks_def;
            ks_def = metadata == null ? thriftClient.describe_keyspace(keySpaceName) : metadata;
            sessionState.out.println("  Replication Strategy: " + ks_def.strategy_class);
            if (ks_def.strategy_class.endsWith(".NetworkTopologyStrategy"))
            {
                Map<String, String> options = ks_def.strategy_options;
                sessionState.out.println("    Options: [" + ((options == null) ? "" : FBUtilities.toString(options)) + "]");
            }
            else
            {
                sessionState.out.println("    Replication Factor: " + ks_def.replication_factor);
            }
            sessionState.out.println("  Column Families:");
            boolean isSuper;
            Collections.sort(ks_def.cf_defs, new CfDefNamesComparator());
            for (CfDef cf_def : ks_def.cf_defs)
            {
                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.default_validation_class != null)
                    sessionState.out.printf("      default_validation_class: %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: %s/%s%n", cf_def.row_cache_size, cf_def.row_cache_save_period_in_seconds);
                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/%s (millions of ops/minutes/MB)%n",
                                cf_def.memtable_operations_in_millions, cf_def.memtable_throughput_in_mb, cf_def.memtable_flush_after_mins);
                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);
                if (cfMBean != null)
                {
                    sessionState.out.printf("      Built indexes: %s%n", cfMBean.getBuiltIndexes());
                }
                if (cf_def.getColumn_metadataSize() != 0)
                {
                    String leftSpace = "      ";
                    String columnLeftSpace = leftSpace + "    ";
                    AbstractType columnNameValidator = getFormatTypeForColumn(isSuper ? cf_def.subcomparator_type
                                                                                      : cf_def.comparator_type);
                    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)
                            {
                            }
                        }
                        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());
                        }
                    }
                }
            }
            if (compactionManagerMBean != null)
            {
                String compactionType = compactionManagerMBean.getCompactionType();
                if (compactionType != null && compactionType.contains("index build"))
                {
                    String indexName         = compactionManagerMBean.getColumnFamilyInProgress();
                    long bytesCompacted      = compactionManagerMBean.getBytesCompacted();
                    long totalBytesToProcess = compactionManagerMBean.getBytesTotalInProgress();
                    sessionState.out.printf("%nCurrently building index %s, completed %d of %d bytes.%n", indexName, bytesCompacted, totalBytesToProcess);
                }
            }
            if (probe != null)
                probe.close();
        }
        catch (InvalidRequestException e)
        {
            sessionState.out.println("Invalid request: " + e);
        }
        catch (NotFoundException e)
        {
            sessionState.out.println("Keyspace " + keySpaceName + " could not be found.");
        }
        catch (IOException e)
        {
            sessionState.out.println("Error while closing JMX connection: " + e.getMessage());
        }
    }

    private void describeKeySpace(String keySpaceName, KsDef metadata) throws TException
    {
        NodeProbe probe = sessionState.getNodeProbe();
        CompactionManagerMBean compactionManagerMBean = (probe == null) ? null : probe.getCompactionManagerProxy();
        sessionState.out.println("Keyspace: " + keySpaceName + ":");
        try
        {
            KsDef ks_def;
            ks_def = metadata == null ? thriftClient.describe_keyspace(keySpaceName) : metadata;
            sessionState.out.println("  Replication Strategy: " + ks_def.strategy_class);
            if (ks_def.strategy_class.endsWith(".NetworkTopologyStrategy"))
            {
                Map<String, String> options = ks_def.strategy_options;
                sessionState.out.println("    Options: [" + ((options == null) ? "" : FBUtilities.toString(options)) + "]");
            }
            else
            {
                sessionState.out.println("    Replication Factor: " + ks_def.replication_factor);
            }
            sessionState.out.println("  Column Families:");
            boolean isSuper;
            Collections.sort(ks_def.cf_defs, new CfDefNamesComparator());
            for (CfDef cf_def : ks_def.cf_defs)
            {
                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.default_validation_class != null)
                    sessionState.out.printf("      default_validation_class: %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: %s/%s%n", cf_def.row_cache_size, cf_def.row_cache_save_period_in_seconds);
                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/%s (millions of ops/minutes/MB)%n",
                                cf_def.memtable_operations_in_millions, cf_def.memtable_flush_after_mins, 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);
                if (cfMBean != null)
                {
                    sessionState.out.printf("      Built indexes: %s%n", cfMBean.getBuiltIndexes());
                }
                if (cf_def.getColumn_metadataSize() != 0)
                {
                    String leftSpace = "      ";
                    String columnLeftSpace = leftSpace + "    ";
                    AbstractType columnNameValidator = getFormatTypeForColumn(isSuper ? cf_def.subcomparator_type
                                                                                      : cf_def.comparator_type);
                    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)
                            {
                            }
                        }
                        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());
                        }
                    }
                }
            }
            if (compactionManagerMBean != null)
            {
                String compactionType = compactionManagerMBean.getCompactionType();
                if (compactionType != null && compactionType.contains("index build"))
                {
                    String indexName         = compactionManagerMBean.getColumnFamilyInProgress();
                    long bytesCompacted      = compactionManagerMBean.getBytesCompacted();
                    long totalBytesToProcess = compactionManagerMBean.getBytesTotalInProgress();
                    sessionState.out.printf("%nCurrently building index %s, completed %d of %d bytes.%n", indexName, bytesCompacted, totalBytesToProcess);
                }
            }
            if (probe != null)
                probe.close();
        }
        catch (InvalidRequestException e)
        {
            sessionState.out.println("Invalid request: " + e);
        }
        catch (NotFoundException e)
        {
            sessionState.out.println("Keyspace " + keySpaceName + " could not be found.");
        }
        catch (IOException e)
        {
            sessionState.out.println("Error while closing JMX connection: " + e.getMessage());
        }
    }
