You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by jb...@apache.org on 2014/01/22 07:27:48 UTC

git commit: add listsnapshots command to nodetool patch by Sankalp Kohli and Lyuben Todorov for CASSANDRA-5742

Updated Branches:
  refs/heads/trunk 0b6f03f12 -> 719103b64


add listsnapshots command to nodetool
patch by Sankalp Kohli and Lyuben Todorov for CASSANDRA-5742


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

Branch: refs/heads/trunk
Commit: 719103b649c1c5459683a8ffd1c013664f1ffbb6
Parents: 0b6f03f
Author: Jonathan Ellis <jb...@apache.org>
Authored: Tue Jan 21 22:27:24 2014 -0800
Committer: Jonathan Ellis <jb...@apache.org>
Committed: Tue Jan 21 22:27:24 2014 -0800

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 .../apache/cassandra/db/ColumnFamilyStore.java  |  9 ++++
 .../org/apache/cassandra/db/Directories.java    | 36 ++++++++++++++++
 .../org/apache/cassandra/io/util/FileUtils.java | 18 ++++++++
 .../cassandra/service/StorageService.java       | 45 ++++++++++++++++++++
 .../cassandra/service/StorageServiceMBean.java  | 13 ++++++
 .../org/apache/cassandra/tools/NodeProbe.java   | 10 +++++
 .../org/apache/cassandra/tools/NodeTool.java    | 44 +++++++++++++++++++
 8 files changed, 176 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/719103b6/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 6eeb819..5c9b64f 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 2.1
+ * add listsnapshots command to nodetool (CASSANDRA-5742)
  * Introduce AtomicBTreeColumns (CASSANDRA-6271)
  * Multithreaded commitlog (CASSANDRA-3578)
  * allocate fixed index summary memory pool and resample cold index summaries 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/719103b6/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/ColumnFamilyStore.java b/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
index 892e881..fe77d09 100644
--- a/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
+++ b/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
@@ -1839,6 +1839,15 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
         List<File> snapshotDirs = directories.getCFDirectories();
         Directories.clearSnapshot(snapshotName, snapshotDirs);
     }
+    /**
+     *
+     * @return  Return a map of all snapshots to space being used
+     * The pair for a snapshot has true size and size on disk.
+     */
+    public Map<String, Pair<Long,Long>> getSnapshotDetails()
+    {
+        return directories.getSnapshotDetails();
+    }
 
     public boolean hasUnreclaimedSpace()
     {

http://git-wip-us.apache.org/repos/asf/cassandra/blob/719103b6/src/java/org/apache/cassandra/db/Directories.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/Directories.java b/src/java/org/apache/cassandra/db/Directories.java
index a124d67..b3723b3 100644
--- a/src/java/org/apache/cassandra/db/Directories.java
+++ b/src/java/org/apache/cassandra/db/Directories.java
@@ -485,6 +485,42 @@ public class Directories
         }
     }
 
+    /**
+     *
+     * @return  Return a map of all snapshots to space being used
+     * The pair for a snapshot has size on disk and true size.
+     */
+    public Map<String, Pair<Long, Long>> getSnapshotDetails()
+    {
+        final Map<String, Pair<Long, Long>> snapshotSpaceMap = new HashMap<>();
+        for (final File dir : sstableDirectories)
+        {
+            final File snapshotDir = new File(dir,SNAPSHOT_SUBDIR);
+            if (snapshotDir.exists() && snapshotDir.isDirectory())
+            {
+                final File[] snapshots  = snapshotDir.listFiles();
+                if (snapshots != null)
+                {
+                    for (final File snapshot : snapshots)
+                    {
+                        if (snapshot.isDirectory())
+                        {
+                            final long sizeOnDisk = FileUtils.folderSize(snapshot);
+                            final long trueSize = getTrueAllocatedSizeIn(snapshot);
+                            Pair<Long,Long> spaceUsed = snapshotSpaceMap.get(snapshot.getName());
+                            if (spaceUsed == null)
+                                spaceUsed =  Pair.create(sizeOnDisk,trueSize);
+                            else
+                                spaceUsed = Pair.create(spaceUsed.left + sizeOnDisk, spaceUsed.right + trueSize);
+                            snapshotSpaceMap.put(snapshot.getName(), spaceUsed);
+                        }
+                    }
+                }
+            }
+        }
+
+        return snapshotSpaceMap;
+    }
     public boolean snapshotExists(String snapshotName)
     {
         for (File dir : sstableDirectories)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/719103b6/src/java/org/apache/cassandra/io/util/FileUtils.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/io/util/FileUtils.java b/src/java/org/apache/cassandra/io/util/FileUtils.java
index 3c84cc3..cbed4f8 100644
--- a/src/java/org/apache/cassandra/io/util/FileUtils.java
+++ b/src/java/org/apache/cassandra/io/util/FileUtils.java
@@ -447,4 +447,22 @@ public class FileUtils
                 throw new IllegalStateException();
         }
     }
+
+    /**
+     * Get the size of a directory in bytes
+     * @param The directory for which we need size.
+     * @return The size of the directory
+     */
+    public static long folderSize(File directory)
+    {
+        long length = 0;
+        for (File file : directory.listFiles())
+        {
+            if (file.isFile())
+                length += file.length();
+            else
+                length += folderSize(file);
+        }
+        return length;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/719103b6/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 6f4788f..43fead0 100644
--- a/src/java/org/apache/cassandra/service/StorageService.java
+++ b/src/java/org/apache/cassandra/service/StorageService.java
@@ -34,6 +34,8 @@ import javax.management.MBeanServer;
 import javax.management.Notification;
 import javax.management.NotificationBroadcasterSupport;
 import javax.management.ObjectName;
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.TabularDataSupport;
 
 import static java.nio.charset.StandardCharsets.ISO_8859_1;
 
@@ -2229,6 +2231,49 @@ public class StorageService extends NotificationBroadcasterSupport implements IE
             logger.debug("Cleared out snapshot directories");
     }
 
+    public Map<String, TabularData> getSnapshotDetails()
+    {
+        final Map<String, TabularData> snapshotMap = new HashMap<>();
+        for (final Keyspace keyspace : Keyspace.all())
+        {
+            if (Keyspace.SYSTEM_KS.equals(keyspace.getName()))
+                continue;
+
+            for (final ColumnFamilyStore cfStore : keyspace.getColumnFamilyStores())
+            {
+                for (final Map.Entry<String, Pair<Long,Long>> snapshotDetail : cfStore.getSnapshotDetails().entrySet())
+                {
+                    TabularDataSupport data = (TabularDataSupport)snapshotMap.get(snapshotDetail.getKey());
+                    if (data == null)
+                    {
+                        data = new TabularDataSupport(SnapshotDetailsTabularData.TABULAR_TYPE);
+                        snapshotMap.put(snapshotDetail.getKey(), data);
+                    }
+
+                    SnapshotDetailsTabularData.from(snapshotDetail.getKey(), keyspace.getName(), cfStore.getColumnFamilyName(), snapshotDetail, data);
+                }
+            }
+        }
+        return snapshotMap;
+    }
+
+    public long trueSnapshotsSize()
+    {
+        long total = 0;
+        for (final Keyspace keyspace : Keyspace.all())
+        {
+            if (Keyspace.SYSTEM_KS.equals(keyspace.getName()))
+                continue;
+
+            for (final ColumnFamilyStore cfStore : keyspace.getColumnFamilyStores())
+            {
+                total += cfStore.trueSnapshotsSize();
+            }
+        }
+
+        return total;
+    }
+
     /**
      * @param allowIndexes Allow index CF names to be passed in
      * @param autoAddIndexes Automatically add secondary indexes if a CF has them

http://git-wip-us.apache.org/repos/asf/cassandra/blob/719103b6/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 e0bca26..390795e 100644
--- a/src/java/org/apache/cassandra/service/StorageServiceMBean.java
+++ b/src/java/org/apache/cassandra/service/StorageServiceMBean.java
@@ -28,6 +28,7 @@ import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeoutException;
 
 import javax.management.NotificationEmitter;
+import javax.management.openmbean.TabularData;
 
 public interface StorageServiceMBean extends NotificationEmitter
 {
@@ -216,6 +217,18 @@ public interface StorageServiceMBean extends NotificationEmitter
     public void clearSnapshot(String tag, String... keyspaceNames) throws IOException;
 
     /**
+     *  Get the details of all the snapshot
+     * @return A map of snapshotName to all its details in Tabular form.
+     */
+    public Map<String, TabularData> getSnapshotDetails();
+
+    /**
+     * Get the true size taken by all snapshots across all keyspaces.
+     * @return True size taken by all the snapshots.
+     */
+    public long trueSnapshotsSize();
+
+    /**
      * Forces major compaction of a single keyspace
      */
     public void forceKeyspaceCompaction(String keyspaceName, String... columnFamilies) throws IOException, ExecutionException, InterruptedException;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/719103b6/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 7727401..cbd43e9 100644
--- a/src/java/org/apache/cassandra/tools/NodeProbe.java
+++ b/src/java/org/apache/cassandra/tools/NodeProbe.java
@@ -452,6 +452,16 @@ public class NodeProbe implements AutoCloseable
         ssProxy.clearSnapshot(tag, keyspaces);
     }
 
+    public Map<String, TabularData> getSnapshotDetails()
+    {
+        return ssProxy.getSnapshotDetails();
+    }
+
+    public long trueSnapshotsSize()
+    {
+        return ssProxy.trueSnapshotsSize();
+    }
+
     public boolean isJoined()
     {
         return ssProxy.isJoined();

http://git-wip-us.apache.org/repos/asf/cassandra/blob/719103b6/src/java/org/apache/cassandra/tools/NodeTool.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/tools/NodeTool.java b/src/java/org/apache/cassandra/tools/NodeTool.java
index c9ddf4f..70580f2 100644
--- a/src/java/org/apache/cassandra/tools/NodeTool.java
+++ b/src/java/org/apache/cassandra/tools/NodeTool.java
@@ -42,6 +42,7 @@ import org.apache.cassandra.db.ColumnFamilyStoreMBean;
 import org.apache.cassandra.db.Keyspace;
 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.locator.EndpointSnitchInfoMBean;
 import org.apache.cassandra.net.MessagingServiceMBean;
 import org.apache.cassandra.service.CacheServiceMBean;
@@ -117,6 +118,7 @@ public class NodeTool
                 SetStreamThroughput.class,
                 SetTraceProbability.class,
                 Snapshot.class,
+                ListSnapshots.class,
                 Status.class,
                 StatusBinary.class,
                 StatusThrift.class,
@@ -1645,6 +1647,48 @@ public class NodeTool
         }
     }
 
+    @Command(name = "listsnapshots", description = "Lists all the snapshots along with the size on disk and true size.")
+    public static class ListSnapshots extends NodeToolCmd
+    {
+        @Override
+        public void execute(NodeProbe probe)
+        {
+            try
+            {
+                System.out.println("Snapshot Details: ");
+
+                final Map<String,TabularData> snapshotDetails = probe.getSnapshotDetails();
+                if (snapshotDetails.isEmpty())
+                {
+                    System.out.printf("There are no snapshots");
+                    return;
+                }
+
+                final long trueSnapshotsSize = probe.trueSnapshotsSize();
+                final String format = "%-20s%-29s%-29s%-19s%-19s%n";
+                // 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()]));
+
+                for (final Map.Entry<String, TabularData> snapshotDetail : snapshotDetails.entrySet())
+                {
+                    Set<?> values = snapshotDetail.getValue().keySet();
+                    for (Object eachValue : values)
+                    {
+                        final List<?> value = (List<?>) eachValue;
+                        System.out.printf(format, value.toArray(new Object[value.size()]));
+                    }
+                }
+
+                System.out.println("\nTotal TrueDiskSpaceUsed: " + FileUtils.stringifyFileSize(trueSnapshotsSize) + "\n");
+            }
+            catch (Exception e)
+            {
+                throw new RuntimeException("Error during list snapshot", e);
+            }
+        }
+    }
+
     @Command(name = "status", description = "Print cluster information (state, load, IDs, ...)")
     public static class Status extends NodeToolCmd
     {