cassandra-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From yu...@apache.org
Subject [1/8] cassandra git commit: Support long name output from nodetool commands
Date Wed, 10 Feb 2016 23:39:52 GMT
Repository: cassandra
Updated Branches:
  refs/heads/cassandra-2.1 725b9b1f7 -> 6c6b7e40c
  refs/heads/cassandra-2.2 c08aaf69b -> d7195060c
  refs/heads/trunk 90033b921 -> c58b11bc7


Support long name output from nodetool commands

patch by yukim; reviewed by carlyeks for CASSANDRA-7950


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/b6661ac5
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/b6661ac5
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/b6661ac5

Branch: refs/heads/trunk
Commit: b6661ac52c5f8b2fe9640defbc7d86fad693fdf5
Parents: 90033b9
Author: Yuki Morishita <yukim@apache.org>
Authored: Wed Jan 20 10:51:56 2016 -0600
Committer: Yuki Morishita <yukim@apache.org>
Committed: Wed Feb 10 17:23:05 2016 -0600

----------------------------------------------------------------------
 CHANGES.txt                                     |   1 +
 .../tools/nodetool/CompactionHistory.java       |  92 +++++++--------
 .../tools/nodetool/CompactionStats.java         |  53 ++-------
 .../cassandra/tools/nodetool/ListSnapshots.java |  13 ++-
 .../tools/nodetool/formatter/TableBuilder.java  | 103 +++++++++++++++++
 .../nodetool/formatter/TableBuilderTest.java    | 114 +++++++++++++++++++
 6 files changed, 284 insertions(+), 92 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/b6661ac5/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 551d147..3825165 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 3.4
+ * Support long name output for nodetool commands (CASSANDRA-7950)
  * Encrypted hints (CASSANDRA-11040)
  * SASI index options validation (CASSANDRA-11136)
  * Optimize disk seek using min/max column name meta data when the LIMIT clause is used

http://git-wip-us.apache.org/repos/asf/cassandra/blob/b6661ac5/src/java/org/apache/cassandra/tools/nodetool/CompactionHistory.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/tools/nodetool/CompactionHistory.java b/src/java/org/apache/cassandra/tools/nodetool/CompactionHistory.java
index 1348d05..40c6887 100644
--- a/src/java/org/apache/cassandra/tools/nodetool/CompactionHistory.java
+++ b/src/java/org/apache/cassandra/tools/nodetool/CompactionHistory.java
@@ -30,6 +30,7 @@ import io.airlift.command.Command;
 
 import org.apache.cassandra.tools.NodeProbe;
 import org.apache.cassandra.tools.NodeTool.NodeToolCmd;
+import org.apache.cassandra.tools.nodetool.formatter.TableBuilder;
 
 import static com.google.common.collect.Iterables.toArray;
 
@@ -48,9 +49,9 @@ public class CompactionHistory extends NodeToolCmd
             return;
         }
 
-        String format = "%-41s%-19s%-29s%-26s%-15s%-15s%s%n";
+        TableBuilder table = new TableBuilder();
         List<String> indexNames = tabularData.getTabularType().getIndexNames();
-        System.out.printf(format, toArray(indexNames, Object.class));
+        table.add(toArray(indexNames, String.class));
 
         Set<?> values = tabularData.keySet();
         List<CompactionHistoryRow> chr = new ArrayList<>();
@@ -69,53 +70,54 @@ public class CompactionHistory extends NodeToolCmd
         Collections.sort(chr);
         for (CompactionHistoryRow eachChc : chr)
         {
-            System.out.printf(format, eachChc.getAllAsArray());
+            table.add(eachChc.getAllAsArray());
         }
+        table.printTo(System.out);
     }
-}
-
-/**
- * Allows the Compaction History output to be ordered by 'compactedAt' - that is the
- * time at which compaction finished.
- */
-class CompactionHistoryRow implements Comparable<CompactionHistoryRow>
-{
-    private final String id;
-    private final String ksName;
-    private final String cfName;
-    private final long compactedAt;
-    private final long bytesIn;
-    private final long bytesOut;
-    private final String rowMerged;
 
-    CompactionHistoryRow(String id, String ksName, String cfName, long compactedAt, long
bytesIn, long bytesOut, String rowMerged)
+    /**
+     * Allows the Compaction History output to be ordered by 'compactedAt' - that is the
+     * time at which compaction finished.
+     */
+    private static class CompactionHistoryRow implements Comparable<CompactionHistoryRow>
     {
-        this.id = id;
-        this.ksName = ksName;
-        this.cfName = cfName;
-        this.compactedAt = compactedAt;
-        this.bytesIn = bytesIn;
-        this.bytesOut = bytesOut;
-        this.rowMerged = rowMerged;
-    }
+        private final String id;
+        private final String ksName;
+        private final String cfName;
+        private final long compactedAt;
+        private final long bytesIn;
+        private final long bytesOut;
+        private final String rowMerged;
 
-    public int compareTo(CompactionHistoryRow chc)
-    {
-        return Long.signum(chc.compactedAt - this.compactedAt);
-    }
+        CompactionHistoryRow(String id, String ksName, String cfName, long compactedAt, long
bytesIn, long bytesOut, String rowMerged)
+        {
+            this.id = id;
+            this.ksName = ksName;
+            this.cfName = cfName;
+            this.compactedAt = compactedAt;
+            this.bytesIn = bytesIn;
+            this.bytesOut = bytesOut;
+            this.rowMerged = rowMerged;
+        }
 
-    public Object[] getAllAsArray()
-    {
-        Object[] obj = new Object[7];
-        obj[0] = this.id;
-        obj[1] = this.ksName;
-        obj[2] = this.cfName;
-        Instant instant = Instant.ofEpochMilli(this.compactedAt);
-        LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
-        obj[3] = ldt.toString();
-        obj[4] = this.bytesIn;
-        obj[5] = this.bytesOut;
-        obj[6] = this.rowMerged;
-        return obj;
+        public int compareTo(CompactionHistoryRow chc)
+        {
+            return Long.signum(chc.compactedAt - this.compactedAt);
+        }
+
+        public String[] getAllAsArray()
+        {
+            String[] obj = new String[7];
+            obj[0] = this.id;
+            obj[1] = this.ksName;
+            obj[2] = this.cfName;
+            Instant instant = Instant.ofEpochMilli(this.compactedAt);
+            LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
+            obj[3] = ldt.toString();
+            obj[4] = Long.toString(this.bytesIn);
+            obj[5] = Long.toString(this.bytesOut);
+            obj[6] = this.rowMerged;
+            return obj;
+        }
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/b6661ac5/src/java/org/apache/cassandra/tools/nodetool/CompactionStats.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/tools/nodetool/CompactionStats.java b/src/java/org/apache/cassandra/tools/nodetool/CompactionStats.java
index b950a1c..bc1f85c 100644
--- a/src/java/org/apache/cassandra/tools/nodetool/CompactionStats.java
+++ b/src/java/org/apache/cassandra/tools/nodetool/CompactionStats.java
@@ -17,22 +17,22 @@
  */
 package org.apache.cassandra.tools.nodetool;
 
-import static java.lang.String.format;
-import io.airlift.command.Command;
-import io.airlift.command.Option;
-
 import java.text.DecimalFormat;
-import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
+import io.airlift.command.Command;
+import io.airlift.command.Option;
+
 import org.apache.cassandra.db.compaction.CompactionManagerMBean;
 import org.apache.cassandra.db.compaction.OperationType;
 import org.apache.cassandra.io.util.FileUtils;
 import org.apache.cassandra.tools.NodeProbe;
-import org.apache.cassandra.tools.NodeTool;
 import org.apache.cassandra.tools.NodeTool.NodeToolCmd;
+import org.apache.cassandra.tools.nodetool.formatter.TableBuilder;
+
+import static java.lang.String.format;
 
 @Command(name = "compactionstats", description = "Print statistics on compactions")
 public class CompactionStats extends NodeToolCmd
@@ -54,7 +54,7 @@ public class CompactionStats extends NodeToolCmd
             for (Entry<String, Integer> tableEntry : ksEntry.getValue().entrySet())
                 numTotalPendingTask += tableEntry.getValue();
         }
-        System.out.println("pending tasks: "+numTotalPendingTask);
+        System.out.println("pending tasks: " + numTotalPendingTask);
         for (Entry<String, Map<String, Integer>> ksEntry : pendingTaskNumberByTable.entrySet())
         {
             String ksName = ksEntry.getKey();
@@ -63,26 +63,17 @@ public class CompactionStats extends NodeToolCmd
                 String tableName = tableEntry.getKey();
                 int pendingTaskCount = tableEntry.getValue();
 
-                StringBuilder builder = new StringBuilder();
-                builder.append("- ");
-                builder.append(ksName);
-                builder.append('.');
-                builder.append(tableName);
-                builder.append(": ");
-                builder.append(pendingTaskCount);
-                System.out.println(builder.toString());
+                System.out.println("- " + ksName + '.' + tableName + ": " + pendingTaskCount);
             }
         }
         System.out.println();
         long remainingBytes = 0;
+        TableBuilder table = new TableBuilder();
         List<Map<String, String>> compactions = cm.getCompactions();
         if (!compactions.isEmpty())
         {
             int compactionThroughput = probe.getCompactionThroughput();
-            List<String[]> lines = new ArrayList<>();
-            int[] columnSizes = new int[] { 0, 0, 0, 0, 0, 0, 0, 0 };
-
-            addLine(lines, columnSizes, "id", "compaction type", "keyspace", "table", "completed",
"total", "unit", "progress");
+            table.add("id", "compaction type", "keyspace", "table", "completed", "total",
"unit", "progress");
             for (Map<String, String> c : compactions)
             {
                 long total = Long.parseLong(c.get("total"));
@@ -95,24 +86,11 @@ public class CompactionStats extends NodeToolCmd
                 String unit = c.get("unit");
                 String percentComplete = total == 0 ? "n/a" : new DecimalFormat("0.00").format((double)
completed / total * 100) + "%";
                 String id = c.get("compactionId");
-                addLine(lines, columnSizes, id, taskType, keyspace, columnFamily, completedStr,
totalStr, unit, percentComplete);
+                table.add(id, taskType, keyspace, columnFamily, completedStr, totalStr, unit,
percentComplete);
                 if (taskType.equals(OperationType.COMPACTION.toString()))
                     remainingBytes += total - completed;
             }
-
-            StringBuilder buffer = new StringBuilder();
-            for (int columnSize : columnSizes) {
-                buffer.append("%");
-                buffer.append(columnSize + 3);
-                buffer.append("s");
-            }
-            buffer.append("%n");
-            String format = buffer.toString();
-
-            for (String[] line : lines)
-            {
-                System.out.printf(format, line[0], line[1], line[2], line[3], line[4], line[5],
line[6], line[7]);
-            }
+            table.printTo(System.out);
 
             String remainingTime = "n/a";
             if (compactionThroughput != 0)
@@ -123,11 +101,4 @@ public class CompactionStats extends NodeToolCmd
             System.out.printf("%25s%10s%n", "Active compaction remaining time : ", remainingTime);
         }
     }
-
-    private void addLine(List<String[]> lines, int[] columnSizes, String... columns)
{
-        lines.add(columns);
-        for (int i = 0; i < columns.length; i++) {
-            columnSizes[i] = Math.max(columnSizes[i], columns[i].length());
-        }
-    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cassandra/blob/b6661ac5/src/java/org/apache/cassandra/tools/nodetool/ListSnapshots.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/tools/nodetool/ListSnapshots.java b/src/java/org/apache/cassandra/tools/nodetool/ListSnapshots.java
index ee7bf34..1b3065b 100644
--- a/src/java/org/apache/cassandra/tools/nodetool/ListSnapshots.java
+++ b/src/java/org/apache/cassandra/tools/nodetool/ListSnapshots.java
@@ -17,17 +17,17 @@
  */
 package org.apache.cassandra.tools.nodetool;
 
-import io.airlift.command.Command;
-
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-
 import javax.management.openmbean.TabularData;
 
+import io.airlift.command.Command;
+
 import org.apache.cassandra.io.util.FileUtils;
 import org.apache.cassandra.tools.NodeProbe;
 import org.apache.cassandra.tools.NodeTool.NodeToolCmd;
+import org.apache.cassandra.tools.nodetool.formatter.TableBuilder;
 
 @Command(name = "listsnapshots", description = "Lists all the snapshots along with the size
on disk and true size.")
 public class ListSnapshots extends NodeToolCmd
@@ -47,10 +47,10 @@ public class ListSnapshots extends NodeToolCmd
             }
 
             final long trueSnapshotsSize = probe.trueSnapshotsSize();
-            final String format = "%-20s%-29s%-29s%-19s%-19s%n";
+            TableBuilder table = new TableBuilder();
             // display column names only once
             final List<String> indexNames = snapshotDetails.entrySet().iterator().next().getValue().getTabularType().getIndexNames();
-            System.out.printf(format, (Object[]) indexNames.toArray(new String[indexNames.size()]));
+            table.add(indexNames.toArray(new String[indexNames.size()]));
 
             for (final Map.Entry<String, TabularData> snapshotDetail : snapshotDetails.entrySet())
             {
@@ -58,9 +58,10 @@ public class ListSnapshots extends NodeToolCmd
                 for (Object eachValue : values)
                 {
                     final List<?> value = (List<?>) eachValue;
-                    System.out.printf(format, value.toArray(new Object[value.size()]));
+                    table.add(value.toArray(new String[value.size()]));
                 }
             }
+            table.printTo(System.out);
 
             System.out.println("\nTotal TrueDiskSpaceUsed: " + FileUtils.stringifyFileSize(trueSnapshotsSize)
+ "\n");
         }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/b6661ac5/src/java/org/apache/cassandra/tools/nodetool/formatter/TableBuilder.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/tools/nodetool/formatter/TableBuilder.java b/src/java/org/apache/cassandra/tools/nodetool/formatter/TableBuilder.java
new file mode 100644
index 0000000..a56e52e
--- /dev/null
+++ b/src/java/org/apache/cassandra/tools/nodetool/formatter/TableBuilder.java
@@ -0,0 +1,103 @@
+/*
+ * 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.formatter;
+
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import javax.annotation.Nonnull;
+
+/**
+ * Build and print table.
+ *
+ * usage:
+ * <pre>
+ * {@code
+ * TableBuilder table = new TableBuilder();
+ * for (String[] row : data)
+ * {
+ *     table.add(row);
+ * }
+ * table.print(System.out);
+ * }
+ * </pre>
+ */
+public class TableBuilder
+{
+    // column delimiter char
+    private final char columnDelimiter;
+
+    private int[] maximumColumnWidth;
+    private final List<String[]> rows = new ArrayList<>();
+
+    public TableBuilder()
+    {
+        this(' ');
+    }
+
+    public TableBuilder(char columnDelimiter)
+    {
+        this.columnDelimiter = columnDelimiter;
+    }
+
+    public void add(@Nonnull String... row)
+    {
+        Objects.requireNonNull(row);
+
+        if (rows.isEmpty())
+        {
+            maximumColumnWidth = new int[row.length];
+        }
+
+        // expand max column widths if given row has more columns
+        if (row.length > maximumColumnWidth.length)
+        {
+            int[] tmp = new int[row.length];
+            System.arraycopy(maximumColumnWidth, 0, tmp, 0, maximumColumnWidth.length);
+            maximumColumnWidth = tmp;
+        }
+        // calculate maximum column width
+        int i = 0;
+        for (String col : row)
+        {
+            maximumColumnWidth[i] = Math.max(maximumColumnWidth[i], col != null ? col.length()
: 1);
+            i++;
+        }
+        rows.add(row);
+    }
+
+    public void printTo(PrintStream out)
+    {
+        if (rows.isEmpty())
+            return;
+
+        for (String[] row : rows)
+        {
+            for (int i = 0; i < maximumColumnWidth.length; i++)
+            {
+                String col = i < row.length ? row[i] : "";
+                out.print(String.format("%-" + maximumColumnWidth[i] + 's', col != null ?
col : ""));
+                if (i < maximumColumnWidth.length - 1)
+                    out.print(columnDelimiter);
+            }
+            out.println();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/b6661ac5/test/unit/org/apache/cassandra/tools/nodetool/formatter/TableBuilderTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/tools/nodetool/formatter/TableBuilderTest.java
b/test/unit/org/apache/cassandra/tools/nodetool/formatter/TableBuilderTest.java
new file mode 100644
index 0000000..9782b5b
--- /dev/null
+++ b/test/unit/org/apache/cassandra/tools/nodetool/formatter/TableBuilderTest.java
@@ -0,0 +1,114 @@
+/*
+ * 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.formatter;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class TableBuilderTest
+{
+    @Test
+    public void testEmptyRow()
+    {
+        TableBuilder table = new TableBuilder();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        try (PrintStream out = new PrintStream(baos))
+        {
+            table.printTo(out);
+        }
+        assertEquals("", baos.toString());
+    }
+
+    @Test
+    public void testOneRow()
+    {
+        TableBuilder table = new TableBuilder();
+
+        table.add("a", "bb", "ccc");
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        try (PrintStream out = new PrintStream(baos))
+        {
+            table.printTo(out);
+        }
+        assertEquals(String.format("a bb ccc%n"), baos.toString());
+    }
+
+    @Test
+    public void testRows()
+    {
+        TableBuilder table = new TableBuilder();
+        table.add("a", "bb", "ccc");
+        table.add("aaa", "bb", "c");
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        try (PrintStream out = new PrintStream(baos))
+        {
+            table.printTo(out);
+        }
+        assertEquals(String.format("a   bb ccc%naaa bb c  %n"), baos.toString());
+    }
+
+    @Test
+    public void testNullColumn()
+    {
+        TableBuilder table = new TableBuilder();
+        table.add("a", "b", "c");
+        table.add("a", null, "c");
+        table.add("a", null, null);
+        table.add(null, "b", "c");
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        try (PrintStream out = new PrintStream(baos))
+        {
+            table.printTo(out);
+        }
+        assertEquals(String.format("a b c%na   c%na    %n  b c%n"), baos.toString());
+    }
+
+    @Test
+    public void testRowsOfDifferentSize()
+    {
+        TableBuilder table = new TableBuilder();
+        table.add("a", "b", "c");
+        table.add("a", "b", "c", "d", "e");
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        try (PrintStream out = new PrintStream(baos))
+        {
+            table.printTo(out);
+        }
+        assertEquals(baos.toString(), String.format("a b c    %na b c d e%n"), baos.toString());
+    }
+
+    @Test
+    public void testDelimiter()
+    {
+        TableBuilder table = new TableBuilder('\t');
+
+        table.add("a", "bb", "ccc");
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        try (PrintStream out = new PrintStream(baos))
+        {
+            table.printTo(out);
+        }
+        assertEquals(String.format("a\tbb\tccc%n"), baos.toString());
+    }
+}
\ No newline at end of file


Mime
View raw message