HDFS-4850. Merging change r1490080 from trunk

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/branch-2@1490084 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Jing Zhao 2013-06-05 23:42:11 +00:00
parent d77a2579f2
commit 5826b0c186
9 changed files with 125 additions and 50 deletions

View File

@ -829,6 +829,9 @@ Release 2.1.0-beta - UNRELEASED
HDFS-4826. TestNestedSnapshots times out due to repeated slow edit log HDFS-4826. TestNestedSnapshots times out due to repeated slow edit log
flushes when running on virtualized disk. (Chris Nauroth via szetszwo) flushes when running on virtualized disk. (Chris Nauroth via szetszwo)
HDFS-4850. Fix OfflineImageViewer to work on fsimages with empty files or
snapshots. (jing9)
Release 2.0.5-alpha - UNRELEASED Release 2.0.5-alpha - UNRELEASED
INCOMPATIBLE CHANGES INCOMPATIBLE CHANGES

View File

@ -186,7 +186,7 @@ public class INodesInPath {
// check if the next byte[] in components is for ".snapshot" // check if the next byte[] in components is for ".snapshot"
if (isDotSnapshotDir(childName) if (isDotSnapshotDir(childName)
&& isDir && dir instanceof INodeDirectoryWithSnapshot) { && isDir && dir instanceof INodeDirectorySnapshottable) {
// skip the ".snapshot" in components // skip the ".snapshot" in components
count++; count++;
index++; index++;

View File

@ -177,7 +177,11 @@ class ImageLoaderCurrent implements ImageLoader {
imageVersion); imageVersion);
if (supportSnapshot) { if (supportSnapshot) {
v.visit(ImageElement.SNAPSHOT_COUNTER, in.readInt()); v.visit(ImageElement.SNAPSHOT_COUNTER, in.readInt());
v.visit(ImageElement.NUM_SNAPSHOTS_TOTAL, in.readInt()); int numSnapshots = in.readInt();
v.visit(ImageElement.NUM_SNAPSHOTS_TOTAL, numSnapshots);
for (int i = 0; i < numSnapshots; i++) {
processSnapshot(in, v);
}
} }
if (LayoutVersion.supports(Feature.FSIMAGE_COMPRESSION, imageVersion)) { if (LayoutVersion.supports(Feature.FSIMAGE_COMPRESSION, imageVersion)) {
@ -335,8 +339,8 @@ class ImageLoaderCurrent implements ImageLoader {
v.visitEnclosingElement(ImageElement.BLOCKS, v.visitEnclosingElement(ImageElement.BLOCKS,
ImageElement.NUM_BLOCKS, numBlocks); ImageElement.NUM_BLOCKS, numBlocks);
// directory or symlink, no blocks to process // directory or symlink or reference node, no blocks to process
if(numBlocks == -1 || numBlocks == -2) { if(numBlocks < 0) {
v.leaveEnclosingElement(); // Blocks v.leaveEnclosingElement(); // Blocks
return; return;
} }
@ -484,10 +488,6 @@ class ImageLoaderCurrent implements ImageLoader {
// process snapshot // process snapshot
v.visitEnclosingElement(ImageElement.SNAPSHOT); v.visitEnclosingElement(ImageElement.SNAPSHOT);
v.visit(ImageElement.SNAPSHOT_ID, in.readInt()); v.visit(ImageElement.SNAPSHOT_ID, in.readInt());
// process root of snapshot
v.visitEnclosingElement(ImageElement.SNAPSHOT_ROOT);
processINode(in, v, true, rootName, false);
v.leaveEnclosingElement();
v.leaveEnclosingElement(); v.leaveEnclosingElement();
} }
v.visit(ImageElement.SNAPSHOT_QUOTA, in.readInt()); v.visit(ImageElement.SNAPSHOT_QUOTA, in.readInt());
@ -495,6 +495,17 @@ class ImageLoaderCurrent implements ImageLoader {
} }
} }
private void processSnapshot(DataInputStream in, ImageVisitor v)
throws IOException {
v.visitEnclosingElement(ImageElement.SNAPSHOT);
v.visit(ImageElement.SNAPSHOT_ID, in.readInt());
// process root of snapshot
v.visitEnclosingElement(ImageElement.SNAPSHOT_ROOT);
processINode(in, v, true, "", false);
v.leaveEnclosingElement();
v.leaveEnclosingElement();
}
private void processDirectoryDiffList(DataInputStream in, ImageVisitor v, private void processDirectoryDiffList(DataInputStream in, ImageVisitor v,
String currentINodeName) throws IOException { String currentINodeName) throws IOException {
final int numDirDiff = in.readInt(); final int numDirDiff = in.readInt();
@ -512,8 +523,8 @@ class ImageLoaderCurrent implements ImageLoader {
private void processDirectoryDiff(DataInputStream in, ImageVisitor v, private void processDirectoryDiff(DataInputStream in, ImageVisitor v,
String currentINodeName) throws IOException { String currentINodeName) throws IOException {
v.visitEnclosingElement(ImageElement.SNAPSHOT_DIR_DIFF); v.visitEnclosingElement(ImageElement.SNAPSHOT_DIR_DIFF);
String snapshot = FSImageSerialization.readString(in); int snapshotId = in.readInt();
v.visit(ImageElement.SNAPSHOT_DIFF_SNAPSHOTROOT, snapshot); v.visit(ImageElement.SNAPSHOT_DIFF_SNAPSHOTID, snapshotId);
v.visit(ImageElement.SNAPSHOT_DIR_DIFF_CHILDREN_SIZE, in.readInt()); v.visit(ImageElement.SNAPSHOT_DIR_DIFF_CHILDREN_SIZE, in.readInt());
// process snapshotINode // process snapshotINode
@ -617,7 +628,7 @@ class ImageLoaderCurrent implements ImageLoader {
processBlocks(in, v, numBlocks, skipBlocks); processBlocks(in, v, numBlocks, skipBlocks);
if (numBlocks > 0) { // File if (numBlocks >= 0) { // File
if (supportSnapshot) { if (supportSnapshot) {
// process file diffs // process file diffs
processFileDiffList(in, v, parentName); processFileDiffList(in, v, parentName);
@ -631,6 +642,7 @@ class ImageLoaderCurrent implements ImageLoader {
} }
} }
} }
processPermission(in, v);
} else if (numBlocks == -1) { // Directory } else if (numBlocks == -1) { // Directory
if (supportSnapshot && supportInodeId) { if (supportSnapshot && supportInodeId) {
dirNodeMap.put(inodeId, pathName); dirNodeMap.put(inodeId, pathName);
@ -647,6 +659,7 @@ class ImageLoaderCurrent implements ImageLoader {
v.visit(ImageElement.IS_SNAPSHOTTABLE_DIR, Boolean.toString(snapshottable)); v.visit(ImageElement.IS_SNAPSHOTTABLE_DIR, Boolean.toString(snapshottable));
} }
} }
processPermission(in, v);
} else if (numBlocks == -2) { } else if (numBlocks == -2) {
v.visit(ImageElement.SYMLINK, Text.readString(in)); v.visit(ImageElement.SYMLINK, Text.readString(in));
} else if (numBlocks == -3) { // reference node } else if (numBlocks == -3) { // reference node
@ -668,7 +681,6 @@ class ImageLoaderCurrent implements ImageLoader {
} }
} }
processPermission(in, v);
v.leaveEnclosingElement(); // INode v.leaveEnclosingElement(); // INode
} }
@ -678,8 +690,18 @@ class ImageLoaderCurrent implements ImageLoader {
if (size >= 0) { if (size >= 0) {
v.visitEnclosingElement(ImageElement.SNAPSHOT_FILE_DIFFS, v.visitEnclosingElement(ImageElement.SNAPSHOT_FILE_DIFFS,
ImageElement.NUM_SNAPSHOT_FILE_DIFF, size); ImageElement.NUM_SNAPSHOT_FILE_DIFF, size);
String snapshot = FSImageSerialization.readString(in); for (int i = 0; i < size; i++) {
v.visit(ImageElement.SNAPSHOT_DIFF_SNAPSHOTROOT, snapshot); processFileDiff(in, v, currentINodeName);
}
v.leaveEnclosingElement();
}
}
private void processFileDiff(DataInputStream in, ImageVisitor v,
String currentINodeName) throws IOException {
int snapshotId = in.readInt();
v.visitEnclosingElement(ImageElement.SNAPSHOT_FILE_DIFF,
ImageElement.SNAPSHOT_DIFF_SNAPSHOTID, snapshotId);
v.visit(ImageElement.SNAPSHOT_FILE_SIZE, in.readLong()); v.visit(ImageElement.SNAPSHOT_FILE_SIZE, in.readLong());
if (in.readBoolean()) { if (in.readBoolean()) {
v.visitEnclosingElement(ImageElement.SNAPSHOT_DIFF_SNAPSHOTINODE); v.visitEnclosingElement(ImageElement.SNAPSHOT_DIFF_SNAPSHOTINODE);
@ -688,7 +710,6 @@ class ImageLoaderCurrent implements ImageLoader {
} }
v.leaveEnclosingElement(); v.leaveEnclosingElement();
} }
}
/** /**
* Helper method to format dates during processing. * Helper method to format dates during processing.

View File

@ -95,7 +95,7 @@ abstract class ImageVisitor {
NUM_SNAPSHOT_DIR_DIFF, NUM_SNAPSHOT_DIR_DIFF,
SNAPSHOT_DIR_DIFFS, SNAPSHOT_DIR_DIFFS,
SNAPSHOT_DIR_DIFF, SNAPSHOT_DIR_DIFF,
SNAPSHOT_DIFF_SNAPSHOTROOT, SNAPSHOT_DIFF_SNAPSHOTID,
SNAPSHOT_DIR_DIFF_CHILDREN_SIZE, SNAPSHOT_DIR_DIFF_CHILDREN_SIZE,
SNAPSHOT_DIFF_SNAPSHOTINODE, SNAPSHOT_DIFF_SNAPSHOTINODE,
SNAPSHOT_DIR_DIFF_CREATEDLIST, SNAPSHOT_DIR_DIFF_CREATEDLIST,

View File

@ -18,7 +18,6 @@
package org.apache.hadoop.hdfs.tools.offlineImageViewer; package org.apache.hadoop.hdfs.tools.offlineImageViewer;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;

View File

@ -24,7 +24,7 @@ import java.util.LinkedList;
* An XmlImageVisitor walks over an fsimage structure and writes out * An XmlImageVisitor walks over an fsimage structure and writes out
* an equivalent XML document that contains the fsimage's components. * an equivalent XML document that contains the fsimage's components.
*/ */
class XmlImageVisitor extends TextWriterImageVisitor { public class XmlImageVisitor extends TextWriterImageVisitor {
final private LinkedList<ImageElement> tagQ = final private LinkedList<ImageElement> tagQ =
new LinkedList<ImageElement>(); new LinkedList<ImageElement>();

View File

@ -30,9 +30,11 @@ import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.Socket; import java.net.Socket;
@ -845,6 +847,25 @@ public class DFSTestUtil {
new StorageInfo(), new ExportedBlockKeys(), VersionInfo.getVersion()); new StorageInfo(), new ExportedBlockKeys(), VersionInfo.getVersion());
} }
/** Copy one file's contents into the other **/
public static void copyFile(File src, File dest) throws IOException {
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(src);
out = new FileOutputStream(dest);
byte [] b = new byte[1024];
while( in.read(b) > 0 ) {
out.write(b);
}
} finally {
if(in != null) in.close();
if(out != null) out.close();
}
}
public static class Builder { public static class Builder {
private int maxLevels = 3; private int maxLevels = 3;
private int maxSize = 8*1024; private int maxSize = 8*1024;

View File

@ -18,6 +18,7 @@
package org.apache.hadoop.hdfs.server.namenode.snapshot; package org.apache.hadoop.hdfs.server.namenode.snapshot;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
@ -44,10 +45,13 @@ import org.apache.hadoop.hdfs.MiniDFSCluster;
import org.apache.hadoop.hdfs.client.HdfsDataOutputStream; import org.apache.hadoop.hdfs.client.HdfsDataOutputStream;
import org.apache.hadoop.hdfs.protocol.HdfsConstants.SafeModeAction; import org.apache.hadoop.hdfs.protocol.HdfsConstants.SafeModeAction;
import org.apache.hadoop.hdfs.server.namenode.FSDirectory; import org.apache.hadoop.hdfs.server.namenode.FSDirectory;
import org.apache.hadoop.hdfs.server.namenode.FSImageTestUtil;
import org.apache.hadoop.hdfs.server.namenode.FSNamesystem; import org.apache.hadoop.hdfs.server.namenode.FSNamesystem;
import org.apache.hadoop.hdfs.server.namenode.INode; import org.apache.hadoop.hdfs.server.namenode.INode;
import org.apache.hadoop.hdfs.server.namenode.snapshot.SnapshotTestHelper.TestDirectoryTree; import org.apache.hadoop.hdfs.server.namenode.snapshot.SnapshotTestHelper.TestDirectoryTree;
import org.apache.hadoop.hdfs.server.namenode.snapshot.SnapshotTestHelper.TestDirectoryTree.Node; import org.apache.hadoop.hdfs.server.namenode.snapshot.SnapshotTestHelper.TestDirectoryTree.Node;
import org.apache.hadoop.hdfs.tools.offlineImageViewer.OfflineImageViewer;
import org.apache.hadoop.hdfs.tools.offlineImageViewer.XmlImageVisitor;
import org.apache.hadoop.test.GenericTestUtils; import org.apache.hadoop.test.GenericTestUtils;
import org.apache.hadoop.util.Time; import org.apache.hadoop.util.Time;
import org.apache.log4j.Level; import org.apache.log4j.Level;
@ -68,7 +72,13 @@ public class TestSnapshot {
SnapshotTestHelper.disableLogs(); SnapshotTestHelper.disableLogs();
} }
private static final long seed = Time.now(); private static final long seed;
private static final Random random;
static {
seed = Time.now();
random = new Random(seed);
System.out.println("Random seed: " + seed);
}
protected static final short REPLICATION = 3; protected static final short REPLICATION = 3;
protected static final int BLOCKSIZE = 1024; protected static final int BLOCKSIZE = 1024;
/** The number of times snapshots are created for a snapshottable directory */ /** The number of times snapshots are created for a snapshottable directory */
@ -82,8 +92,6 @@ public class TestSnapshot {
protected static FSDirectory fsdir; protected static FSDirectory fsdir;
protected DistributedFileSystem hdfs; protected DistributedFileSystem hdfs;
private static Random random = new Random(seed);
private static String testDir = private static String testDir =
System.getProperty("test.build.data", "build/test/data"); System.getProperty("test.build.data", "build/test/data");
@ -220,7 +228,7 @@ public class TestSnapshot {
@Test @Test
public void testSnapshot() throws Throwable { public void testSnapshot() throws Throwable {
try { try {
runTestSnapshot(); runTestSnapshot(SNAPSHOT_ITERATION_NUMBER);
} catch(Throwable t) { } catch(Throwable t) {
SnapshotTestHelper.LOG.info("FAILED", t); SnapshotTestHelper.LOG.info("FAILED", t);
SnapshotTestHelper.dumpTree("FAILED", cluster); SnapshotTestHelper.dumpTree("FAILED", cluster);
@ -228,8 +236,49 @@ public class TestSnapshot {
} }
} }
private void runTestSnapshot() throws Exception { /**
for (int i = 0; i < SNAPSHOT_ITERATION_NUMBER; i++) { * Test if the OfflineImageViewer can correctly parse a fsimage containing
* snapshots
*/
@Test
public void testOfflineImageViewer() throws Throwable {
runTestSnapshot(SNAPSHOT_ITERATION_NUMBER);
// retrieve the fsimage. Note that we already save namespace to fsimage at
// the end of each iteration of runTestSnapshot.
File originalFsimage = FSImageTestUtil.findLatestImageFile(
FSImageTestUtil.getFSImage(
cluster.getNameNode()).getStorage().getStorageDir(0));
assertNotNull("Didn't generate or can't find fsimage", originalFsimage);
String ROOT = System.getProperty("test.build.data", "build/test/data");
File testFile = new File(ROOT, "/image");
String xmlImage = ROOT + "/image_xml";
boolean success = false;
try {
DFSTestUtil.copyFile(originalFsimage, testFile);
XmlImageVisitor v = new XmlImageVisitor(xmlImage, true);
OfflineImageViewer oiv = new OfflineImageViewer(testFile.getPath(), v,
true);
oiv.go();
success = true;
} finally {
if (testFile.exists()) {
testFile.delete();
}
// delete the xml file if the parsing is successful
if (success) {
File xmlImageFile = new File(xmlImage);
if (xmlImageFile.exists()) {
xmlImageFile.delete();
}
}
}
}
private void runTestSnapshot(int iteration) throws Exception {
for (int i = 0; i < iteration; i++) {
// create snapshot and check the creation // create snapshot and check the creation
cluster.getNamesystem().getSnapshotManager().setAllowNestedSnapshots(true); cluster.getNamesystem().getSnapshotManager().setAllowNestedSnapshots(true);
TestDirectoryTree.Node[] ssNodes = createSnapshots(); TestDirectoryTree.Node[] ssNodes = createSnapshots();

View File

@ -47,6 +47,7 @@ import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hdfs.DFSConfigKeys; import org.apache.hadoop.hdfs.DFSConfigKeys;
import org.apache.hadoop.hdfs.DFSTestUtil;
import org.apache.hadoop.hdfs.HdfsConfiguration; import org.apache.hadoop.hdfs.HdfsConfiguration;
import org.apache.hadoop.hdfs.MiniDFSCluster; import org.apache.hadoop.hdfs.MiniDFSCluster;
import org.apache.hadoop.hdfs.protocol.HdfsConstants.SafeModeAction; import org.apache.hadoop.hdfs.protocol.HdfsConstants.SafeModeAction;
@ -173,7 +174,7 @@ public class TestOfflineImageViewer {
File outputFile = new File(ROOT, "/basicCheckOutput"); File outputFile = new File(ROOT, "/basicCheckOutput");
try { try {
copyFile(originalFsimage, testFile); DFSTestUtil.copyFile(originalFsimage, testFile);
ImageVisitor v = new LsImageVisitor(outputFile.getPath(), true); ImageVisitor v = new LsImageVisitor(outputFile.getPath(), true);
OfflineImageViewer oiv = new OfflineImageViewer(testFile.getPath(), v, false); OfflineImageViewer oiv = new OfflineImageViewer(testFile.getPath(), v, false);
@ -367,25 +368,6 @@ public class TestOfflineImageViewer {
} }
} }
// Copy one file's contents into the other
private void copyFile(File src, File dest) throws IOException {
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(src);
out = new FileOutputStream(dest);
byte [] b = new byte[1024];
while( in.read(b) > 0 ) {
out.write(b);
}
} finally {
if(in != null) in.close();
if(out != null) out.close();
}
}
@Test @Test
public void outputOfFileDistributionVisitor() throws IOException { public void outputOfFileDistributionVisitor() throws IOException {
File testFile = new File(ROOT, "/basicCheck"); File testFile = new File(ROOT, "/basicCheck");
@ -394,7 +376,7 @@ public class TestOfflineImageViewer {
int totalFiles = 0; int totalFiles = 0;
BufferedReader reader = null; BufferedReader reader = null;
try { try {
copyFile(originalFsimage, testFile); DFSTestUtil.copyFile(originalFsimage, testFile);
ImageVisitor v = new FileDistributionVisitor(outputFile.getPath(), 0, 0); ImageVisitor v = new FileDistributionVisitor(outputFile.getPath(), 0, 0);
OfflineImageViewer oiv = OfflineImageViewer oiv =
new OfflineImageViewer(testFile.getPath(), v, false); new OfflineImageViewer(testFile.getPath(), v, false);
@ -466,7 +448,7 @@ public class TestOfflineImageViewer {
File testFile = new File(ROOT, "/basicCheck"); File testFile = new File(ROOT, "/basicCheck");
try { try {
copyFile(originalFsimage, testFile); DFSTestUtil.copyFile(originalFsimage, testFile);
TestImageVisitor v = new TestImageVisitor(); TestImageVisitor v = new TestImageVisitor();
OfflineImageViewer oiv = new OfflineImageViewer(testFile.getPath(), v, true); OfflineImageViewer oiv = new OfflineImageViewer(testFile.getPath(), v, true);
oiv.go(); oiv.go();