|
@@ -22,11 +22,14 @@ import java.io.FileOutputStream;
|
|
|
import java.io.IOException;
|
|
|
import java.io.File;
|
|
|
import java.nio.ByteBuffer;
|
|
|
+import java.nio.channels.FileChannel;
|
|
|
import java.util.Map;
|
|
|
import java.util.HashMap;
|
|
|
|
|
|
import org.junit.Test;
|
|
|
import org.junit.Before;
|
|
|
+
|
|
|
+import static org.junit.Assert.assertEquals;
|
|
|
import static org.junit.Assert.assertTrue;
|
|
|
|
|
|
import org.apache.commons.logging.Log;
|
|
@@ -34,12 +37,12 @@ import org.apache.commons.logging.LogFactory;
|
|
|
|
|
|
import org.apache.hadoop.hdfs.server.namenode.FSEditLogOpCodes;
|
|
|
import org.apache.hadoop.hdfs.tools.offlineEditsViewer.OfflineEditsViewer;
|
|
|
+import org.apache.hadoop.hdfs.tools.offlineEditsViewer.OfflineEditsViewer.Flags;
|
|
|
import org.apache.hadoop.hdfs.DFSTestUtil;
|
|
|
|
|
|
import org.apache.hadoop.hdfs.server.namenode.OfflineEditsViewerHelper;
|
|
|
|
|
|
public class TestOfflineEditsViewer {
|
|
|
-
|
|
|
private static final Log LOG = LogFactory.getLog(TestOfflineEditsViewer.class);
|
|
|
|
|
|
private static final Map<FSEditLogOpCodes, Boolean> obsoleteOpCodes =
|
|
@@ -97,8 +100,8 @@ public class TestOfflineEditsViewer {
|
|
|
String editsReparsed = cacheDir + "/editsReparsed";
|
|
|
|
|
|
// parse to XML then back to binary
|
|
|
- runOev(edits, editsParsedXml, "xml");
|
|
|
- runOev(editsParsedXml, editsReparsed, "binary");
|
|
|
+ assertEquals(0, runOev(edits, editsParsedXml, "xml", false));
|
|
|
+ assertEquals(0, runOev(editsParsedXml, editsReparsed, "binary", false));
|
|
|
|
|
|
// judgment time
|
|
|
assertTrue(
|
|
@@ -114,6 +117,42 @@ public class TestOfflineEditsViewer {
|
|
|
LOG.info("END");
|
|
|
}
|
|
|
|
|
|
+ @Test
|
|
|
+ public void testRecoveryMode() throws IOException {
|
|
|
+ LOG.info("START - testing with generated edits");
|
|
|
+
|
|
|
+ nnHelper.startCluster(buildDir + "/dfs/");
|
|
|
+
|
|
|
+ // edits generated by nnHelper (MiniDFSCluster), should have all op codes
|
|
|
+ // binary, XML, reparsed binary
|
|
|
+ String edits = nnHelper.generateEdits();
|
|
|
+
|
|
|
+ // Corrupt the file by truncating the end
|
|
|
+ FileChannel editsFile = new FileOutputStream(edits, true).getChannel();
|
|
|
+ editsFile.truncate(editsFile.size() - 5);
|
|
|
+
|
|
|
+ String editsParsedXml = cacheDir + "/editsRecoveredParsed.xml";
|
|
|
+ String editsReparsed = cacheDir + "/editsRecoveredReparsed";
|
|
|
+ String editsParsedXml2 = cacheDir + "/editsRecoveredParsed2.xml";
|
|
|
+
|
|
|
+ // Can't read the corrupted file without recovery mode
|
|
|
+ assertEquals(-1, runOev(edits, editsParsedXml, "xml", false));
|
|
|
+
|
|
|
+ // parse to XML then back to binary
|
|
|
+ assertEquals(0, runOev(edits, editsParsedXml, "xml", true));
|
|
|
+ assertEquals(0, runOev(editsParsedXml, editsReparsed, "binary", false));
|
|
|
+ assertEquals(0, runOev(editsReparsed, editsParsedXml2, "xml", false));
|
|
|
+
|
|
|
+ // judgment time
|
|
|
+ assertTrue("Test round trip",
|
|
|
+ filesEqualIgnoreTrailingZeros(editsParsedXml, editsParsedXml2));
|
|
|
+
|
|
|
+ // removes edits so do this at the end
|
|
|
+ nnHelper.shutdownCluster();
|
|
|
+
|
|
|
+ LOG.info("END");
|
|
|
+ }
|
|
|
+
|
|
|
@Test
|
|
|
public void testStored() throws IOException {
|
|
|
|
|
@@ -128,8 +167,9 @@ public class TestOfflineEditsViewer {
|
|
|
String editsStoredXml = cacheDir + "/editsStored.xml";
|
|
|
|
|
|
// parse to XML then back to binary
|
|
|
- runOev(editsStored, editsStoredParsedXml, "xml");
|
|
|
- runOev(editsStoredParsedXml, editsStoredReparsed, "binary");
|
|
|
+ assertEquals(0, runOev(editsStored, editsStoredParsedXml, "xml", false));
|
|
|
+ assertEquals(0, runOev(editsStoredParsedXml, editsStoredReparsed,
|
|
|
+ "binary", false));
|
|
|
|
|
|
// judgement time
|
|
|
assertTrue(
|
|
@@ -151,14 +191,18 @@ public class TestOfflineEditsViewer {
|
|
|
* @param inFilename input edits filename
|
|
|
* @param outFilename oputput edits filename
|
|
|
*/
|
|
|
- private void runOev(String inFilename, String outFilename, String processor)
|
|
|
- throws IOException {
|
|
|
+ private int runOev(String inFilename, String outFilename, String processor,
|
|
|
+ boolean recovery) throws IOException {
|
|
|
|
|
|
LOG.info("Running oev [" + inFilename + "] [" + outFilename + "]");
|
|
|
|
|
|
OfflineEditsViewer oev = new OfflineEditsViewer();
|
|
|
- if (oev.go(inFilename, outFilename, processor, true, false, null) != 0)
|
|
|
- throw new RuntimeException("oev failed");
|
|
|
+ Flags flags = new Flags();
|
|
|
+ flags.setPrintToScreen();
|
|
|
+ if (recovery) {
|
|
|
+ flags.setRecoveryMode();
|
|
|
+ }
|
|
|
+ return oev.go(inFilename, outFilename, processor, flags, null);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -172,7 +216,7 @@ public class TestOfflineEditsViewer {
|
|
|
FileOutputStream fout = new FileOutputStream(outFilename);
|
|
|
StatisticsEditsVisitor visitor = new StatisticsEditsVisitor(fout);
|
|
|
OfflineEditsViewer oev = new OfflineEditsViewer();
|
|
|
- if (oev.go(inFilename, outFilename, "stats", false, false, visitor) != 0)
|
|
|
+ if (oev.go(inFilename, outFilename, "stats", new Flags(), visitor) != 0)
|
|
|
return false;
|
|
|
LOG.info("Statistics for " + inFilename + "\n" +
|
|
|
visitor.getStatisticsString());
|