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. */