HDFS-3795. QJM: validate journal dir at startup. Contributed by Todd Lipcon.

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/HDFS-3077@1373178 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Todd Lipcon 2012-08-15 00:52:24 +00:00
parent f765fdb657
commit 160bfcd6c2
5 changed files with 63 additions and 2 deletions

View File

@ -16,3 +16,5 @@ HDFS-3741. Exhaustive failure injection test for skipped RPCs (todd)
HDFS-3773. TestNNWithQJM fails after HDFS-3741. (atm) HDFS-3773. TestNNWithQJM fails after HDFS-3741. (atm)
HDFS-3793. Implement genericized format() in QJM (todd) HDFS-3793. Implement genericized format() in QJM (todd)
HDFS-3795. QJM: validate journal dir at startup (todd)

View File

@ -55,6 +55,8 @@ public class JournalNode implements Tool, Configurable {
private JournalNodeHttpServer httpServer; private JournalNodeHttpServer httpServer;
private Map<String, Journal> journalsById = Maps.newHashMap(); private Map<String, Journal> journalsById = Maps.newHashMap();
private File localDir;
static { static {
HdfsConfiguration.init(); HdfsConfiguration.init();
} }
@ -82,8 +84,32 @@ public class JournalNode implements Tool, Configurable {
@Override @Override
public void setConf(Configuration conf) { public void setConf(Configuration conf) {
this.conf = conf; this.conf = conf;
this.localDir = new File(
conf.get(DFSConfigKeys.DFS_JOURNALNODE_EDITS_DIR_KEY,
DFSConfigKeys.DFS_JOURNALNODE_EDITS_DIR_DEFAULT).trim());
} }
private static void validateAndCreateJournalDir(File dir) throws IOException {
if (!dir.isAbsolute()) {
throw new IllegalArgumentException(
"Journal dir '" + dir + "' should be an absolute path");
}
if (!dir.exists() && !dir.mkdirs()) {
throw new IOException("Could not create journal dir '" +
dir + "'");
} else if (!dir.isDirectory()) {
throw new IOException("Journal directory '" + dir + "' is not " +
"a directory");
}
if (!dir.canWrite()) {
throw new IOException("Unable to write to journal dir '" +
dir + "'");
}
}
@Override @Override
public Configuration getConf() { public Configuration getConf() {
return conf; return conf;
@ -101,6 +127,8 @@ public class JournalNode implements Tool, Configurable {
public void start() throws IOException { public void start() throws IOException {
Preconditions.checkState(!isStarted(), "JN already running"); Preconditions.checkState(!isStarted(), "JN already running");
validateAndCreateJournalDir(localDir);
DefaultMetricsSystem.initialize("JournalNode"); DefaultMetricsSystem.initialize("JournalNode");
JvmMetrics.create("JournalNode", JvmMetrics.create("JournalNode",
conf.get(DFSConfigKeys.DFS_METRICS_SESSION_ID_KEY), conf.get(DFSConfigKeys.DFS_METRICS_SESSION_ID_KEY),

View File

@ -156,7 +156,7 @@ public class MiniJournalCluster {
} }
public File getStorageDir(int idx) { public File getStorageDir(int idx) {
return new File(baseDir, "journalnode-" + idx); return new File(baseDir, "journalnode-" + idx).getAbsoluteFile();
} }
public File getCurrentDir(int idx, String jid) { public File getCurrentDir(int idx, String jid) {

View File

@ -19,6 +19,7 @@ package org.apache.hadoop.hdfs.qjournal;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;
@ -42,7 +43,9 @@ public class TestMiniJournalCluster {
JournalNode node = c.getJournalNode(0); JournalNode node = c.getJournalNode(0);
String dir = node.getConf().get(DFSConfigKeys.DFS_JOURNALNODE_EDITS_DIR_KEY); String dir = node.getConf().get(DFSConfigKeys.DFS_JOURNALNODE_EDITS_DIR_KEY);
assertEquals(MiniDFSCluster.getBaseDirectory() + "journalnode-0", assertEquals(
new File(MiniDFSCluster.getBaseDirectory() + "journalnode-0")
.getAbsolutePath(),
dir); dir);
} finally { } finally {
c.shutdown(); c.shutdown();

View File

@ -23,6 +23,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import java.io.IOException;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.URL; import java.net.URL;
@ -234,6 +235,33 @@ public class TestJournalNode {
} }
} }
@Test
public void testFailToStartWithBadConfig() throws Exception {
Configuration conf = new Configuration();
conf.set(DFSConfigKeys.DFS_JOURNALNODE_EDITS_DIR_KEY, "non-absolute-path");
assertJNFailsToStart(conf, "should be an absolute path");
// Existing file which is not a directory
conf.set(DFSConfigKeys.DFS_JOURNALNODE_EDITS_DIR_KEY, "/dev/null");
assertJNFailsToStart(conf, "is not a directory");
// Directory which cannot be created
conf.set(DFSConfigKeys.DFS_JOURNALNODE_EDITS_DIR_KEY, "/proc/does-not-exist");
assertJNFailsToStart(conf, "Could not create");
}
private static void assertJNFailsToStart(Configuration conf,
String errString) {
try {
JournalNode jn = new JournalNode();
jn.setConf(conf);
jn.start();
} catch (Exception e) {
GenericTestUtils.assertExceptionContains(errString, e);
}
}
// TODO: // TODO:
// - add test that checks formatting behavior // - add test that checks formatting behavior
// - add test that checks rejects newEpoch if nsinfo doesn't match // - add test that checks rejects newEpoch if nsinfo doesn't match