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 2011/04/11 05:08:30 UTC

svn commit: r1090925 - in /cassandra/trunk: ./ src/java/org/apache/cassandra/db/ src/java/org/apache/cassandra/service/ src/java/org/apache/cassandra/tools/ test/unit/org/apache/cassandra/service/

Author: jbellis
Date: Mon Apr 11 03:08:29 2011
New Revision: 1090925

URL: http://svn.apache.org/viewvc?rev=1090925&view=rev
Log:
give snapshots the same name on each node
patch by Nick Bailey; reviewed by jbellis for CASSANDRA-1791

Modified:
    cassandra/trunk/CHANGES.txt
    cassandra/trunk/src/java/org/apache/cassandra/db/Table.java
    cassandra/trunk/src/java/org/apache/cassandra/service/StorageService.java
    cassandra/trunk/src/java/org/apache/cassandra/service/StorageServiceMBean.java
    cassandra/trunk/src/java/org/apache/cassandra/tools/ClusterCmd.java
    cassandra/trunk/src/java/org/apache/cassandra/tools/NodeCmd.java
    cassandra/trunk/src/java/org/apache/cassandra/tools/NodeProbe.java
    cassandra/trunk/test/unit/org/apache/cassandra/service/StorageServiceServerTest.java

Modified: cassandra/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/cassandra/trunk/CHANGES.txt?rev=1090925&r1=1090924&r2=1090925&view=diff
==============================================================================
--- cassandra/trunk/CHANGES.txt (original)
+++ cassandra/trunk/CHANGES.txt Mon Apr 11 03:08:29 2011
@@ -18,6 +18,7 @@
  * repair works on a token range instead of full ring (CASSANDRA-2324)
  * purge tombstones from row cache (CASSANDRA-2305)
  * push replication_factor into strategy_options (CASSANDRA-1263)
+ * give snapshots the same name on each node (CASSANDRA-1791)
 
 
 0.7.5

Modified: cassandra/trunk/src/java/org/apache/cassandra/db/Table.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/Table.java?rev=1090925&r1=1090924&r2=1090925&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/db/Table.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/db/Table.java Mon Apr 11 03:08:29 2011
@@ -190,10 +190,8 @@ public class Table
      * @param clientSuppliedName the tag associated with the name of the snapshot.  This
      *                           value can be null.
      */
-    public void snapshot(String clientSuppliedName)
+    public void snapshot(String snapshotName)
     {
-        String snapshotName = getTimestampedSnapshotName(clientSuppliedName);
-
         for (ColumnFamilyStore cfStore : columnFamilyStores.values())
         {
             cfStore.snapshot(snapshotName);
@@ -214,15 +212,36 @@ public class Table
         return snapshotName;
     }
 
+    /**
+     * Clear snapshots for this table. If no tag is given we will clear all
+     * snapshots
+     *
+     * @param snapshotName the user supplied snapshot name
+     * @return true if the snapshot exists
+     */
+    public boolean snapshotExists(String snapshotName)
+    {
+        for (String dataDirPath : DatabaseDescriptor.getAllDataFileLocations())
+        {
+            String snapshotPath = dataDirPath + File.separator + name + File.separator + SNAPSHOT_SUBDIR_NAME + File.separator + snapshotName;
+            File snapshot = new File(snapshotPath);
+            if (snapshot.exists())
+            {
+                return true;
+            }
+        }
+        return false;
+    }
 
     /**
      * Clear all the snapshots for a given table.
      */
-    public void clearSnapshot() throws IOException
+    public void clearSnapshot(String tag) throws IOException
     {
         for (String dataDirPath : DatabaseDescriptor.getAllDataFileLocations())
         {
-            String snapshotPath = dataDirPath + File.separator + name + File.separator + SNAPSHOT_SUBDIR_NAME;
+            // If tag is empty we will delete the entire snapshot directory
+            String snapshotPath = dataDirPath + File.separator + name + File.separator + SNAPSHOT_SUBDIR_NAME + File.separator + tag;
             File snapshotDir = new File(snapshotPath);
             if (snapshotDir.exists())
             {

Modified: cassandra/trunk/src/java/org/apache/cassandra/service/StorageService.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/service/StorageService.java?rev=1090925&r1=1090924&r2=1090925&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/service/StorageService.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/service/StorageService.java Mon Apr 11 03:08:29 2011
@@ -1348,15 +1348,37 @@ public class StorageService implements I
     }
 
     /**
-     * Takes the snapshot for a given table.
+     * Takes the snapshot for the given tables. A snapshot name must be specified.
      *
-     * @param tableName the name of the table.
-     * @param tag   the tag given to the snapshot (null is permissible)
+     * @param tag the tag given to the snapshot; may not be null or empty
+     * @param tableNames the name of the tables to snapshot; empty means "all."
      */
-    public void takeSnapshot(String tableName, String tag) throws IOException
+    public void takeSnapshot(String tag, String... tableNames) throws IOException
     {
-        Table tableInstance = getValidTable(tableName);
-        tableInstance.snapshot(tag);
+        if (tag == null || tag.equals(""))
+            throw new IOException("You must supply a snapshot name.");
+
+        Iterable<Table> tables;
+        if (tableNames.length == 0)
+        {
+            tables = Table.all();
+        }
+        else
+        {
+            ArrayList<Table> t = new ArrayList<Table>();
+            for (String table : tableNames)
+                t.add(getValidTable(table));
+            tables = t;
+        }
+
+        // Do a check to see if this snapshot exists before we actually snapshot
+        for (Table table : tables)
+            if (table.snapshotExists(tag))
+                throw new IOException("Snapshot " + tag + " already exists.");
+
+
+        for (Table table : tables)
+            table.snapshot(tag);
     }
 
     private Table getValidTable(String tableName) throws IOException
@@ -1369,26 +1391,32 @@ public class StorageService implements I
     }
 
     /**
-     * Takes a snapshot for every table.
-     *
-     * @param tag the tag given to the snapshot (null is permissible)
+     * Remove the snapshot with the given name from the given tables.
+     * If no tag is specified we will remove all snapshots.
      */
-    public void takeAllSnapshot(String tag) throws IOException
+    public void clearSnapshot(String tag, String... tableNames) throws IOException
     {
-        for (Table table : Table.all())
-            table.snapshot(tag);
-    }
+        if(tag == null)
+            tag = "";
 
-    /**
-     * Remove all the existing snapshots.
-     */
-    public void clearSnapshot() throws IOException
-    {
-        for (Table table : Table.all())
-            table.clearSnapshot();
+        Iterable<Table> tables;
+        if (tableNames.length == 0)
+        {
+            tables = Table.all();
+        }
+        else
+        {
+            ArrayList<Table> tempTables = new ArrayList<Table>();
+            for(String table : tableNames)
+                tempTables.add(getValidTable(table));
+            tables = tempTables;
+        }
+
+        for (Table table : tables)
+            table.clearSnapshot(tag);
 
         if (logger_.isDebugEnabled())
-            logger_.debug("Cleared out all snapshot directories");
+            logger_.debug("Cleared out snapshot directories");
     }
 
     public Iterable<ColumnFamilyStore> getValidColumnFamilies(String tableName, String... cfNames) throws IOException

Modified: cassandra/trunk/src/java/org/apache/cassandra/service/StorageServiceMBean.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/service/StorageServiceMBean.java?rev=1090925&r1=1090924&r2=1090925&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/service/StorageServiceMBean.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/service/StorageServiceMBean.java Mon Apr 11 03:08:29 2011
@@ -137,24 +137,18 @@ public interface StorageServiceMBean
     public List<InetAddress> getNaturalEndpoints(String table, ByteBuffer key);
 
     /**
-     * Takes the snapshot for a given table.
-     * 
-     * @param tableName the name of the table.
-     * @param tag       the tag given to the snapshot (null is permissible)
-     */
-    public void takeSnapshot(String tableName, String tag) throws IOException;
-
-    /**
-     * Takes a snapshot for every table.
-     * 
-     * @param tag the tag given to the snapshot (null is permissible)
+     * Takes the snapshot for the given tables. A snapshot name must be specified.
+     *
+     * @param tag the tag given to the snapshot; may not be null or empty
+     * @param tableNames the name of the tables to snapshot; empty means "all."
      */
-    public void takeAllSnapshot(String tag) throws IOException;
+    public void takeSnapshot(String tag, String... tableNames) throws IOException;
 
     /**
-     * Remove all the existing snapshots.
+     * Remove the snapshot with the given name from the given tables.
+     * If no tag is specified we will remove all snapshots.
      */
-    public void clearSnapshot() throws IOException;
+    public void clearSnapshot(String tag, String... tableNames) throws IOException;
 
     /**
      * Forces major compaction of a single keyspace

Modified: cassandra/trunk/src/java/org/apache/cassandra/tools/ClusterCmd.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/tools/ClusterCmd.java?rev=1090925&r1=1090924&r2=1090925&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/tools/ClusterCmd.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/tools/ClusterCmd.java Mon Apr 11 03:08:29 2011
@@ -162,7 +162,7 @@ public class ClusterCmd {
             {
                 NodeProbe hostProbe = new NodeProbe(liveNode, probe.port);
                 hostProbe.takeSnapshot(snapshotName);
-                System.out.println(liveNode + " snapshot taken");
+                System.out.println(liveNode + " snapshot taken in directory: " + snapshotName);
             }
             catch (IOException e)
             {
@@ -174,14 +174,14 @@ public class ClusterCmd {
     /**
      * Remove all the existing snapshots from all (live) nodes in the cluster
      */
-    public void clearGlobalSnapshot() throws IOException, InterruptedException
+    public void clearGlobalSnapshot(String tag) throws IOException, InterruptedException
     {
         for (String liveNode : probe.getLiveNodes())
         {
             try
             {
                 NodeProbe hostProbe = new NodeProbe(liveNode, probe.port);
-                hostProbe.clearSnapshot();
+                hostProbe.clearSnapshot(tag);
                 System.out.println(liveNode + " snapshot cleared");
             }
             catch (IOException e)
@@ -241,16 +241,13 @@ public class ClusterCmd {
         }
         else if (cmdName.equals("global_snapshot"))
         {
-            String snapshotName = "";
-            if (arguments.length > 1)
-            {
-                snapshotName = arguments[1];
-            }
+            String snapshotName = arguments.length > 1 ? arguments[1] : new Long(System.currentTimeMillis()).toString();
             clusterCmd.takeGlobalSnapshot(snapshotName);
         }
         else if (cmdName.equals("clear_global_snapshot"))
         {
-            clusterCmd.clearGlobalSnapshot();
+            String snapshotName = arguments.length > 1 ? arguments[1] : "";
+            clusterCmd.clearGlobalSnapshot(snapshotName);
         }
         else if (cmdName.equals("truncate"))
         {

Modified: cassandra/trunk/src/java/org/apache/cassandra/tools/NodeCmd.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/tools/NodeCmd.java?rev=1090925&r1=1090924&r2=1090925&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/tools/NodeCmd.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/tools/NodeCmd.java Mon Apr 11 03:08:29 2011
@@ -49,6 +49,7 @@ public class NodeCmd
     private static final Pair<String, String> PORT_OPT = new Pair<String, String>("p", "port");
     private static final Pair<String, String> USERNAME_OPT = new Pair<String, String>("u",  "username");
     private static final Pair<String, String> PASSWORD_OPT = new Pair<String, String>("pw", "password");
+    private static final Pair<String, String> TAG_OPT = new Pair<String, String>("t", "tag");
     private static final int DEFAULT_PORT = 7199;
 
     private static ToolOptions options = null;
@@ -63,6 +64,7 @@ public class NodeCmd
         options.addOption(PORT_OPT,     true, "remote jmx agent port number");
         options.addOption(USERNAME_OPT, true, "remote jmx agent username");
         options.addOption(PASSWORD_OPT, true, "remote jmx agent password");
+        options.addOption(TAG_OPT,      true, "optional name to give a snapshot");
     }
     
     public NodeCmd(NodeProbe probe)
@@ -93,7 +95,6 @@ public class NodeCmd
         addCmdHelp(header, "join", "Join the ring");
         addCmdHelp(header, "info", "Print node informations (uptime, load, ...)");
         addCmdHelp(header, "cfstats", "Print statistics on column families");
-        addCmdHelp(header, "clearsnapshot", "Remove all existing snapshots");
         addCmdHelp(header, "version", "Print cassandra version");
         addCmdHelp(header, "tpstats", "Print usage statistics of thread pools");
         addCmdHelp(header, "drain", "Drain the node (stop accepting writes and flush all column families)");
@@ -106,12 +107,13 @@ public class NodeCmd
         addCmdHelp(header, "enablethrift", "Reenable thrift server");
 
         // One arg
-        addCmdHelp(header, "snapshot [snapshotname]", "Take a snapshot using optional name snapshotname");
         addCmdHelp(header, "netstats [host]", "Print network information on provided host (connecting node by default)");
         addCmdHelp(header, "move <new token>", "Move node on the token ring to a new token");
         addCmdHelp(header, "removetoken status|force|<token>", "Show status of current token removal, force completion of pending removal or remove providen token");
 
         // Two args
+        addCmdHelp(header, "snapshot [keyspaces...] -t [snapshotName]", "Take a snapshot of the specified keyspaces using optional name snapshotName");
+        addCmdHelp(header, "clearsnapshot [keyspaces...] -t [snapshotName]", "Remove snapshots for the specified keyspaces. Either remove all snapshots or remove the snapshots with the given name.");
         addCmdHelp(header, "flush [keyspace] [cfnames]", "Flush one or more column family");
         addCmdHelp(header, "repair [keyspace] [cfnames]", "Repair one or more column family");
         addCmdHelp(header, "cleanup [keyspace] [cfnames]", "Run cleanup on one or more column family");
@@ -545,7 +547,6 @@ public class NodeCmd
             case CFSTATS         : nodeCmd.printColumnFamilyStats(System.out); break;
             case DECOMMISSION    : probe.decommission(); break;
             case LOADBALANCE     : probe.loadBalance(); break;
-            case CLEARSNAPSHOT   : probe.clearSnapshot(); break;
             case TPSTATS         : nodeCmd.printThreadPoolStats(System.out); break;
             case VERSION         : nodeCmd.printReleaseVersion(System.out); break;
             case COMPACTIONSTATS : nodeCmd.printCompactionStats(System.out); break;
@@ -565,8 +566,9 @@ public class NodeCmd
                 break;
 
             case SNAPSHOT :
-                if (arguments.length > 0) { probe.takeSnapshot(arguments[0]); }
-                else                      { probe.takeSnapshot(""); }
+            case CLEARSNAPSHOT :
+                String tag = cmd.getOptionValue(TAG_OPT.left);
+                handleSnapshots(command, tag, arguments, probe);
                 break;
 
             case MOVE :
@@ -648,6 +650,27 @@ public class NodeCmd
         System.exit(3);
     }
 
+    private static void handleSnapshots(NodeCommand nc, String tag, String[] cmdArgs, NodeProbe probe) throws InterruptedException, IOException
+    {
+        int length = cmdArgs.length > 1 ? cmdArgs.length - 1 : 0;
+        String[] keyspaces = new String[length];
+        for (int i = 0; i < keyspaces.length; i++)
+            keyspaces[i] = cmdArgs[i + 1];
+
+        switch (nc)
+        {
+            case SNAPSHOT :
+                if (tag == null || tag.equals(""))
+                    tag = new Long(System.currentTimeMillis()).toString();
+                probe.takeSnapshot(tag, keyspaces);
+                System.out.println("Snapshot directory: " + tag);
+                break;
+            case CLEARSNAPSHOT :
+                probe.clearSnapshot(tag, keyspaces);
+                break;
+        }
+    }
+
     private static void optionalKSandCFs(NodeCommand nc, String[] cmdArgs, NodeProbe probe) throws InterruptedException, IOException
     {
         // if there is one additional arg, it's the keyspace; more are columnfamilies

Modified: cassandra/trunk/src/java/org/apache/cassandra/tools/NodeProbe.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/tools/NodeProbe.java?rev=1090925&r1=1090924&r2=1090925&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/tools/NodeProbe.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/tools/NodeProbe.java Mon Apr 11 03:08:29 2011
@@ -326,17 +326,17 @@ public class NodeProbe
      * 
      * @param snapshotName the name of the snapshot.
      */
-    public void takeSnapshot(String snapshotName) throws IOException
+    public void takeSnapshot(String snapshotName, String... keyspaces) throws IOException
     {
-        ssProxy.takeAllSnapshot(snapshotName);
+        ssProxy.takeSnapshot(snapshotName, keyspaces);
     }
 
     /**
      * Remove all the existing snapshots.
      */
-    public void clearSnapshot() throws IOException
+    public void clearSnapshot(String tag, String... keyspaces) throws IOException
     {
-        ssProxy.clearSnapshot();
+        ssProxy.clearSnapshot(tag, keyspaces);
     }
 
     public boolean isJoined()

Modified: cassandra/trunk/test/unit/org/apache/cassandra/service/StorageServiceServerTest.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/test/unit/org/apache/cassandra/service/StorageServiceServerTest.java?rev=1090925&r1=1090924&r2=1090925&view=diff
==============================================================================
--- cassandra/trunk/test/unit/org/apache/cassandra/service/StorageServiceServerTest.java (original)
+++ cassandra/trunk/test/unit/org/apache/cassandra/service/StorageServiceServerTest.java Mon Apr 11 03:08:29 2011
@@ -66,6 +66,6 @@ public class StorageServiceServerTest
     public void testSnapshot() throws IOException
     {
         // no need to insert extra data, even an "empty" database will have a little information in the system keyspace
-        StorageService.instance.takeAllSnapshot(null);
+        StorageService.instance.takeSnapshot("snapshot", new String[0]);
     }
 }