Skip to content

Commit

Permalink
ZOOKEEPER-2579: ZooKeeper server should verify that dataDir and snapD…
Browse files Browse the repository at this point in the history
…ir are writeable before starting (Abraham Fine via phunt)

Change-Id: I2cf47cfa304057423650c0a30eab47e7acd10223
  • Loading branch information
phunt committed Sep 18, 2016
1 parent b2a484c commit ec20c54
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 9 deletions.
3 changes: 3 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ public FileTxnSnapLog(File dataDir, File snapDir) throws IOException {
+ 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
Expand All @@ -122,6 +126,10 @@ public FileTxnSnapLog(File dataDir, File snapDir) throws IOException {
+ 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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,18 @@ public static class MainThread extends Thread {
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);
Expand All @@ -74,20 +81,21 @@ public MainThread(int clientPort, boolean preCreateDirs, String configs)
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();
Expand Down Expand Up @@ -194,6 +202,74 @@ public void commit() throws IOException {
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.
*/
Expand Down

0 comments on commit ec20c54

Please sign in to comment.