You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zookeeper.apache.org by rg...@apache.org on 2015/11/08 22:21:46 UTC

svn commit: r1713296 - in /zookeeper/trunk: CHANGES.txt src/java/main/org/apache/zookeeper/server/PurgeTxnLog.java src/java/test/org/apache/zookeeper/server/PurgeTxnTest.java

Author: rgs
Date: Sun Nov  8 21:21:38 2015
New Revision: 1713296

URL: http://svn.apache.org/viewvc?rev=1713296&view=rev
Log:
ZOOKEEPER-2211: PurgeTxnLog does not correctly purge when snapshots and
logs are at different locations (Arshad Mohammad via rgs)

Modified:
    zookeeper/trunk/CHANGES.txt
    zookeeper/trunk/src/java/main/org/apache/zookeeper/server/PurgeTxnLog.java
    zookeeper/trunk/src/java/test/org/apache/zookeeper/server/PurgeTxnTest.java

Modified: zookeeper/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/zookeeper/trunk/CHANGES.txt?rev=1713296&r1=1713295&r2=1713296&view=diff
==============================================================================
--- zookeeper/trunk/CHANGES.txt (original)
+++ zookeeper/trunk/CHANGES.txt Sun Nov  8 21:21:38 2015
@@ -199,6 +199,9 @@ BUGFIXES:
   ZOOKEEPER-1872: QuorumPeer is not shutdown in few cases
   (Rakesh R. via rgs)
 
+  ZOOKEEPER-2211: PurgeTxnLog does not correctly purge when snapshots and
+  logs are at different locations (Arshad Mohammad via rgs)
+
 IMPROVEMENTS:
   ZOOKEEPER-1660 Documentation for Dynamic Reconfiguration (Reed Wanderman-Milne via shralex)  
 

Modified: zookeeper/trunk/src/java/main/org/apache/zookeeper/server/PurgeTxnLog.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/PurgeTxnLog.java?rev=1713296&r1=1713295&r2=1713296&view=diff
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/server/PurgeTxnLog.java (original)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/server/PurgeTxnLog.java Sun Nov  8 21:21:38 2015
@@ -38,12 +38,16 @@ import org.apache.zookeeper.server.persi
  * and the corresponding logs.
  */
 public class PurgeTxnLog {
+
+    private static final String COUNT_ERR_MSG = "count should be greater than or equal to 3";
+
     static void printUsage(){
+        System.out.println("Usage:");
         System.out.println("PurgeTxnLog dataLogDir [snapDir] -n count");
         System.out.println("\tdataLogDir -- path to the txn log directory");
         System.out.println("\tsnapDir -- path to the snapshot directory");
-        System.out.println("\tcount -- the number of old snaps/logs you want to keep");
-        System.exit(1);
+        System.out.println("\tcount -- the number of old snaps/logs you want " +
+            "to keep, value should be greater than or equal to 3");
     }
 
     private static final String PREFIX_SNAPSHOT = "snapshot";
@@ -62,7 +66,7 @@ public class PurgeTxnLog {
      */
     public static void purge(File dataDir, File snapDir, int num) throws IOException {
         if (num < 3) {
-            throw new IllegalArgumentException("count should be greater than 3");
+            throw new IllegalArgumentException(COUNT_ERR_MSG);
         }
 
         FileTxnSnapLog txnLog = new FileTxnSnapLog(dataDir, snapDir);
@@ -115,22 +119,74 @@ public class PurgeTxnLog {
     }
     
     /**
-     * @param args PurgeTxnLog dataLogDir
-     *     dataLogDir -- txn log directory
-     *     -n num (number of snapshots to keep)
+     * @param args dataLogDir [snapDir] -n count
+     * dataLogDir -- path to the txn log directory
+     * snapDir -- path to the snapshot directory
+     * count -- the number of old snaps/logs you want to keep, value should be greater than or equal to 3<br>
      */
     public static void main(String[] args) throws IOException {
-        if(args.length<3 || args.length>4)
-            printUsage();
-        int i = 0;
-        File dataDir=new File(args[0]);
-        File snapDir=dataDir;
-        if(args.length==4){
-            i++;
-            snapDir=new File(args[i]);
+        if (args.length < 3 || args.length > 4) {
+            printUsageThenExit();
+        }
+        File dataDir = validateAndGetFile(args[0]);
+        File snapDir = dataDir;
+        int num = -1;
+        String countOption = "";
+        if (args.length == 3) {
+            countOption = args[1];
+            num = validateAndGetCount(args[2]);
+        } else {
+            snapDir = validateAndGetFile(args[1]);
+            countOption = args[2];
+            num = validateAndGetCount(args[3]);
+        }
+        if (!"-n".equals(countOption)) {
+            printUsageThenExit();
         }
-        i++; i++;
-        int num = Integer.parseInt(args[i]);
         purge(dataDir, snapDir, num);
     }
+
+    /**
+     * validates file existence and returns the file
+     *
+     * @param path
+     * @return File
+     */
+    private static File validateAndGetFile(String path) {
+        File file = new File(path);
+        if (!file.exists()) {
+            System.err.println("Path '" + file.getAbsolutePath()
+                    + "' does not exist. ");
+            printUsageThenExit();
+        }
+        return file;
+    }
+
+    /**
+     * Returns integer if parsed successfully and it is valid otherwise prints
+     * error and usage and then exits
+     *
+     * @param number
+     * @return
+     */
+    private static int validateAndGetCount(String number) {
+        int result = 0;
+        try {
+            result = Integer.parseInt(number);
+            if (result < 3) {
+                System.err.println(COUNT_ERR_MSG);
+                printUsageThenExit();
+            }
+        } catch (NumberFormatException e) {
+            System.err
+                    .println("'" + number + "' can not be parsed to integer.");
+            printUsageThenExit();
+        }
+        return result;
+    }
+
+    private static void printUsageThenExit() {
+        printUsage();
+        System.exit(1);
+    }
 }

Modified: zookeeper/trunk/src/java/test/org/apache/zookeeper/server/PurgeTxnTest.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/test/org/apache/zookeeper/server/PurgeTxnTest.java?rev=1713296&r1=1713295&r2=1713296&view=diff
==============================================================================
--- zookeeper/trunk/src/java/test/org/apache/zookeeper/server/PurgeTxnTest.java (original)
+++ zookeeper/trunk/src/java/test/org/apache/zookeeper/server/PurgeTxnTest.java Sun Nov  8 21:21:38 2015
@@ -18,6 +18,8 @@
 
 package org.apache.zookeeper.server;
 
+import static org.junit.Assert.assertEquals;
+
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
@@ -295,6 +297,93 @@ public class PurgeTxnTest extends ZKTest
         verifyFilesAfterPurge(logs, true);
     }
 
+    /**
+     * PurgeTxnLog is called with dataLogDir snapDir -n count This test case
+     * verify these values are parsed properly and functionality works fine
+     */
+    @Test
+    public void testPurgeTxnLogWithDataDir()
+            throws Exception {
+        tmpDir = ClientBase.createTmpDir();
+        File dataDir = new File(tmpDir, "dataDir");
+        File dataLogDir = new File(tmpDir, "dataLogDir");
+
+        File dataDirVersion2 = new File(dataDir, "version-2");
+        dataDirVersion2.mkdirs();
+        File dataLogDirVersion2 = new File(dataLogDir, "version-2");
+        dataLogDirVersion2.mkdirs();
+
+        // create dummy log and transaction file
+        int totalFiles = 20;
+
+        // create transaction and snapshot files in different-different
+        // directories
+        for (int i = 0; i < totalFiles; i++) {
+            // simulate log file
+            File logFile = new File(dataLogDirVersion2, "log."
+                    + Long.toHexString(i));
+            logFile.createNewFile();
+            // simulate snapshot file
+            File snapFile = new File(dataDirVersion2, "snapshot."
+                    + Long.toHexString(i));
+            snapFile.createNewFile();
+        }
+
+        int numberOfFilesToKeep = 10;
+        // scenario where four parameter are passed
+        String[] args = new String[] { dataLogDir.getAbsolutePath(),
+                dataDir.getAbsolutePath(), "-n",
+                Integer.toString(numberOfFilesToKeep) };
+        PurgeTxnLog.main(args);
+
+        assertEquals(numberOfFilesToKeep, dataDirVersion2.listFiles().length);
+        assertEquals(numberOfFilesToKeep, dataLogDirVersion2.listFiles().length);
+        ClientBase.recursiveDelete(tmpDir);
+
+    }
+
+    /**
+     * PurgeTxnLog is called with dataLogDir -n count This test case verify
+     * these values are parsed properly and functionality works fine
+     */
+    @Test
+    public void testPurgeTxnLogWithoutDataDir()
+            throws Exception {
+        tmpDir = ClientBase.createTmpDir();
+        File dataDir = new File(tmpDir, "dataDir");
+        File dataLogDir = new File(tmpDir, "dataLogDir");
+
+        File dataDirVersion2 = new File(dataDir, "version-2");
+        dataDirVersion2.mkdirs();
+        File dataLogDirVersion2 = new File(dataLogDir, "version-2");
+        dataLogDirVersion2.mkdirs();
+
+        // create dummy log and transaction file
+        int totalFiles = 20;
+
+        // create transaction and snapshot files in data directory
+        for (int i = 0; i < totalFiles; i++) {
+            // simulate log file
+            File logFile = new File(dataLogDirVersion2, "log."
+                    + Long.toHexString(i));
+            logFile.createNewFile();
+            // simulate snapshot file
+            File snapFile = new File(dataLogDirVersion2, "snapshot."
+                    + Long.toHexString(i));
+            snapFile.createNewFile();
+        }
+
+        int numberOfFilesToKeep = 10;
+        // scenario where only three parameter are passed
+        String[] args = new String[] { dataLogDir.getAbsolutePath(), "-n",
+                Integer.toString(numberOfFilesToKeep) };
+        PurgeTxnLog.main(args);
+        assertEquals(numberOfFilesToKeep + numberOfFilesToKeep,
+                dataLogDirVersion2.listFiles().length);
+        ClientBase.recursiveDelete(tmpDir);
+
+    }
+
     private void createDataDirFiles(AtomicInteger offset, int limit,
             File version_2, List<File> snaps, List<File> logs)
             throws IOException {