Repository: zookeeper
Updated Branches:
  refs/heads/master b2a484cfe -> ec20c5434


ZOOKEEPER-2579: ZooKeeper server should verify that dataDir and snapDir are 
writeable before starting (Abraham Fine via phunt)

Change-Id: I2cf47cfa304057423650c0a30eab47e7acd10223


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

Branch: refs/heads/master
Commit: ec20c5434cc8a334b3fd25e27d26dccf4793c8f3
Parents: b2a484c
Author: Patrick Hunt <ph...@apache.org>
Authored: Sun Sep 18 14:21:51 2016 -0700
Committer: Patrick Hunt <ph...@apache.org>
Committed: Sun Sep 18 14:21:51 2016 -0700

----------------------------------------------------------------------
 CHANGES.txt                                     |  3 +
 .../server/persistence/FileTxnSnapLog.java      |  8 ++
 .../server/ZooKeeperServerMainTest.java         | 94 ++++++++++++++++++--
 3 files changed, 96 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/zookeeper/blob/ec20c543/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 977ce11..3e75f01 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -389,6 +389,9 @@ BUGFIXES:
   ZOOKEEPER-2576: Missing changes (cleanup build.xml)
   (Patrick Hunt via rgs)
 
+  ZOOKEEPER-2579: ZooKeeper server should verify that dataDir and
+  snapDir are writeable before starting (Abraham Fine via phunt)
+
 IMPROVEMENTS:
   ZOOKEEPER-2024 Major throughput improvement with mixed workloads (Kfir 
Lev-Ari via shralex)
 

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/ec20c543/src/java/main/org/apache/zookeeper/server/persistence/FileTxnSnapLog.java
----------------------------------------------------------------------
diff --git 
a/src/java/main/org/apache/zookeeper/server/persistence/FileTxnSnapLog.java 
b/src/java/main/org/apache/zookeeper/server/persistence/FileTxnSnapLog.java
index c9a06d7..9a34bd1 100644
--- a/src/java/main/org/apache/zookeeper/server/persistence/FileTxnSnapLog.java
+++ b/src/java/main/org/apache/zookeeper/server/persistence/FileTxnSnapLog.java
@@ -106,6 +106,10 @@ public class FileTxnSnapLog {
                         + this.dataDir);
             }
         }
+        if (!this.dataDir.canWrite()) {
+            throw new DatadirException("Cannot write to data directory " + 
this.dataDir);
+        }
+
         if (!this.snapDir.exists()) {
             // by default create this directory, but otherwise complain instead
             // See ZOOKEEPER-1161 for more details
@@ -122,6 +126,10 @@ public class FileTxnSnapLog {
                         + this.snapDir);
             }
         }
+        if (!this.snapDir.canWrite()) {
+            throw new DatadirException("Cannot write to snap directory " + 
this.snapDir);
+        }
+
         txnLog = new FileTxnLog(this.dataDir);
         snapLog = new FileSnap(this.snapDir);
     }

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/ec20c543/src/java/test/org/apache/zookeeper/server/ZooKeeperServerMainTest.java
----------------------------------------------------------------------
diff --git 
a/src/java/test/org/apache/zookeeper/server/ZooKeeperServerMainTest.java 
b/src/java/test/org/apache/zookeeper/server/ZooKeeperServerMainTest.java
index 1fcd865..1030209 100644
--- a/src/java/test/org/apache/zookeeper/server/ZooKeeperServerMainTest.java
+++ b/src/java/test/org/apache/zookeeper/server/ZooKeeperServerMainTest.java
@@ -59,11 +59,18 @@ public class ZooKeeperServerMainTest extends ZKTestCase 
implements Watcher {
         final File confFile;
         final TestZKSMain main;
         final File tmpDir;
+        final File dataDir;
+        final File logDir;
 
         public MainThread(int clientPort, boolean preCreateDirs, String 
configs)
                 throws IOException {
+            this(clientPort, preCreateDirs, ClientBase.createTmpDir(), 
configs);
+        }
+
+        public MainThread(int clientPort, boolean preCreateDirs, File tmpDir, 
String configs)
+                throws IOException {
             super("Standalone server with clientPort:" + clientPort);
-            tmpDir = ClientBase.createTmpDir();
+            this.tmpDir = tmpDir;
             confFile = new File(tmpDir, "zoo.cfg");
 
             FileWriter fwriter = new FileWriter(confFile);
@@ -74,20 +81,21 @@ public class ZooKeeperServerMainTest extends ZKTestCase 
implements Watcher {
                 fwriter.write(configs);
             }
 
-            File dataDir = new File(tmpDir, "data");
-            String dir = dataDir.toString();
-            String dirLog = dataDir.toString() + "_txnlog";
+            dataDir = new File(this.tmpDir, "data");
+            logDir = new File(dataDir.toString() + "_txnlog");
             if (preCreateDirs) {
                 if (!dataDir.mkdir()) {
                     throw new IOException("unable to mkdir " + dataDir);
                 }
-                dirLog = dataDir.toString();
+                if (!logDir.mkdir()) {
+                    throw new IOException("unable to mkdir " + logDir);
+                }
             }
             
-            dir = PathUtils.normalizeFileSystemPath(dir);
-            dirLog = PathUtils.normalizeFileSystemPath(dirLog);
-            fwriter.write("dataDir=" + dir + "\n");
-            fwriter.write("dataLogDir=" + dirLog + "\n");
+            String normalizedDataDir = 
PathUtils.normalizeFileSystemPath(dataDir.toString());
+            String normalizedLogDir = 
PathUtils.normalizeFileSystemPath(logDir.toString());
+            fwriter.write("dataDir=" + normalizedDataDir + "\n");
+            fwriter.write("dataLogDir=" + normalizedLogDir + "\n");
             fwriter.write("clientPort=" + clientPort + "\n");
             fwriter.flush();
             fwriter.close();
@@ -194,6 +202,74 @@ public class ZooKeeperServerMainTest extends ZKTestCase 
implements Watcher {
         main.deleteDirs();
     }
 
+    @Test(timeout = 30000)
+    public void testReadOnlySnapshotDir() throws Exception {
+        ClientBase.setupTestEnv();
+        final int CLIENT_PORT = PortAssignment.unique();
+
+        // Start up the ZK server to automatically create the necessary 
directories
+        // and capture the directory where data is stored
+        MainThread main = new MainThread(CLIENT_PORT, true, null);
+        File tmpDir = main.tmpDir;
+        main.start();
+        Assert.assertTrue("waiting for server being up", ClientBase
+                .waitForServerUp("127.0.0.1:" + CLIENT_PORT,
+                        CONNECTION_TIMEOUT / 2));
+        main.shutdown();
+
+        // Make the snapshot directory read only
+        File snapDir = new File(main.dataDir, FileTxnSnapLog.version + 
FileTxnSnapLog.VERSION);
+        snapDir.setWritable(false);
+
+        // Restart ZK and observe a failure
+        main = new MainThread(CLIENT_PORT, false, tmpDir, null);
+        main.start();
+
+        Assert.assertFalse("waiting for server being up", ClientBase
+                .waitForServerUp("127.0.0.1:" + CLIENT_PORT,
+                        CONNECTION_TIMEOUT / 2));
+
+        main.shutdown();
+
+        snapDir.setWritable(true);
+
+        main.deleteDirs();
+    }
+
+    @Test(timeout = 30000)
+    public void testReadOnlyTxnLogDir() throws Exception {
+        ClientBase.setupTestEnv();
+        final int CLIENT_PORT = PortAssignment.unique();
+
+        // Start up the ZK server to automatically create the necessary 
directories
+        // and capture the directory where data is stored
+        MainThread main = new MainThread(CLIENT_PORT, true, null);
+        File tmpDir = main.tmpDir;
+        main.start();
+        Assert.assertTrue("waiting for server being up", ClientBase
+                .waitForServerUp("127.0.0.1:" + CLIENT_PORT,
+                        CONNECTION_TIMEOUT / 2));
+        main.shutdown();
+
+        // Make the transaction log directory read only
+        File logDir = new File(main.logDir, FileTxnSnapLog.version + 
FileTxnSnapLog.VERSION);
+        logDir.setWritable(false);
+
+        // Restart ZK and observe a failure
+        main = new MainThread(CLIENT_PORT, false, tmpDir, null);
+        main.start();
+
+        Assert.assertFalse("waiting for server being up", ClientBase
+                .waitForServerUp("127.0.0.1:" + CLIENT_PORT,
+                        CONNECTION_TIMEOUT / 2));
+
+        main.shutdown();
+
+        logDir.setWritable(true);
+
+        main.deleteDirs();
+    }
+
     /**
      * Verify the ability to start a standalone server instance.
      */

Reply via email to