HDFS-4339. Merge change r1465835 from trunk.

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/branch-2@1471596 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Suresh Srinivas 2013-04-24 18:42:14 +00:00
parent 05dc1ca3a5
commit 9d7e92100b
13 changed files with 222 additions and 23 deletions

View File

@ -11,6 +11,11 @@ Release 2.0.5-beta - UNRELEASED
HDFS-4296. Reserve layout version for release 1.2.0. (suresh) HDFS-4296. Reserve layout version for release 1.2.0. (suresh)
HDFS-4334. Add a unique id to INode. (Brandon Li via szetszwo)
HDFS-4339. Persist inode id in fsimage and editlog. (Brandon Li via
suresh)
IMPROVEMENTS IMPROVEMENTS
HDFS-4222. NN is unresponsive and loses heartbeats from DNs when HDFS-4222. NN is unresponsive and loses heartbeats from DNs when
@ -76,8 +81,6 @@ Release 2.0.5-beta - UNRELEASED
HDFS-4209. Clean up the addNode/addChild/addChildNoQuotaCheck methods in HDFS-4209. Clean up the addNode/addChild/addChildNoQuotaCheck methods in
FSDirectory and INodeDirectory. (szetszwo) FSDirectory and INodeDirectory. (szetszwo)
HDFS-4334. Add a unique id to INode. (Brandon Li via szetszwo)
OPTIMIZATIONS OPTIMIZATIONS
BUG FIXES BUG FIXES

View File

@ -96,7 +96,8 @@ public class LayoutVersion {
OPTIMIZE_PERSIST_BLOCKS(-40, OPTIMIZE_PERSIST_BLOCKS(-40,
"Serialize block lists with delta-encoded variable length ints, " + "Serialize block lists with delta-encoded variable length ints, " +
"add OP_UPDATE_BLOCKS"), "add OP_UPDATE_BLOCKS"),
RESERVED_REL1_2_0(-41, -32, "Reserved for release 1.2.0", true, CONCAT); RESERVED_REL1_2_0(-41, -32, "Reserved for release 1.2.0", true, CONCAT),
ADD_INODE_ID(-42, -40, "Assign a unique inode id for each inode", false);
final int lv; final int lv;
final int ancestorLV; final int ancestorLV;

View File

@ -636,6 +636,7 @@ public class FSEditLog implements LogsPurgeable {
*/ */
public void logOpenFile(String path, INodeFileUnderConstruction newNode) { public void logOpenFile(String path, INodeFileUnderConstruction newNode) {
AddOp op = AddOp.getInstance(cache.get()) AddOp op = AddOp.getInstance(cache.get())
.setInodeId(newNode.getId())
.setPath(path) .setPath(path)
.setReplication(newNode.getBlockReplication()) .setReplication(newNode.getBlockReplication())
.setModificationTime(newNode.getModificationTime()) .setModificationTime(newNode.getModificationTime())
@ -677,6 +678,7 @@ public class FSEditLog implements LogsPurgeable {
*/ */
public void logMkDir(String path, INode newNode) { public void logMkDir(String path, INode newNode) {
MkdirOp op = MkdirOp.getInstance(cache.get()) MkdirOp op = MkdirOp.getInstance(cache.get())
.setInodeId(newNode.getId())
.setPath(path) .setPath(path)
.setTimestamp(newNode.getModificationTime()) .setTimestamp(newNode.getModificationTime())
.setPermissionStatus(newNode.getPermissionStatus()); .setPermissionStatus(newNode.getPermissionStatus());
@ -794,6 +796,7 @@ public class FSEditLog implements LogsPurgeable {
void logSymlink(String path, String value, long mtime, void logSymlink(String path, String value, long mtime,
long atime, INodeSymlink node) { long atime, INodeSymlink node) {
SymlinkOp op = SymlinkOp.getInstance(cache.get()) SymlinkOp op = SymlinkOp.getInstance(cache.get())
.setId(node.getId())
.setPath(path) .setPath(path)
.setValue(value) .setValue(value)
.setModificationTime(mtime) .setModificationTime(mtime)

View File

@ -33,6 +33,7 @@ import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.hdfs.protocol.Block; import org.apache.hadoop.hdfs.protocol.Block;
import org.apache.hadoop.hdfs.protocol.HdfsConstants; import org.apache.hadoop.hdfs.protocol.HdfsConstants;
import org.apache.hadoop.hdfs.protocol.LayoutVersion; import org.apache.hadoop.hdfs.protocol.LayoutVersion;
import org.apache.hadoop.hdfs.protocol.LayoutVersion.Feature;
import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfo; import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfo;
import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfoUnderConstruction; import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfoUnderConstruction;
import org.apache.hadoop.hdfs.server.common.Storage; import org.apache.hadoop.hdfs.server.common.Storage;
@ -169,7 +170,7 @@ public class FSEditLogLoader {
} }
} }
try { try {
long inodeId = applyEditLogOp(op, fsDir, in.getVersion()); long inodeId = applyEditLogOp(op, fsDir, in.getVersion(), lastInodeId);
if (lastInodeId < inodeId) { if (lastInodeId < inodeId) {
lastInodeId = inodeId; lastInodeId = inodeId;
} }
@ -225,9 +226,30 @@ public class FSEditLogLoader {
return numEdits; return numEdits;
} }
// allocate and update last allocated inode id
private long getAndUpdateLastInodeId(long inodeIdFromOp, int logVersion,
long lastInodeId) throws IOException {
long inodeId = inodeIdFromOp;
if (inodeId == INodeId.GRANDFATHER_INODE_ID) {
if (LayoutVersion.supports(Feature.ADD_INODE_ID, logVersion)) {
throw new IOException("The layout version " + logVersion
+ " supports inodeId but gave bogus inodeId");
}
inodeId = fsNamesys.allocateNewInodeId();
} else {
// need to reset lastInodeId. fsnamesys gets lastInodeId firstly from
// fsimage but editlog captures more recent inodeId allocations
if (inodeId > lastInodeId) {
fsNamesys.resetLastInodeId(inodeId);
}
}
return inodeId;
}
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
private long applyEditLogOp(FSEditLogOp op, FSDirectory fsDir, private long applyEditLogOp(FSEditLogOp op, FSDirectory fsDir,
int logVersion) throws IOException { int logVersion, long lastInodeId) throws IOException {
long inodeId = INodeId.GRANDFATHER_INODE_ID; long inodeId = INodeId.GRANDFATHER_INODE_ID;
if (LOG.isTraceEnabled()) { if (LOG.isTraceEnabled()) {
LOG.trace("replaying edit log: " + op); LOG.trace("replaying edit log: " + op);
@ -258,7 +280,8 @@ public class FSEditLogLoader {
assert addCloseOp.blocks.length == 0; assert addCloseOp.blocks.length == 0;
// add to the file tree // add to the file tree
inodeId = fsNamesys.allocateNewInodeId(); inodeId = getAndUpdateLastInodeId(addCloseOp.inodeId, logVersion,
lastInodeId);
newFile = (INodeFile) fsDir.unprotectedAddFile(inodeId, newFile = (INodeFile) fsDir.unprotectedAddFile(inodeId,
addCloseOp.path, addCloseOp.permissions, replication, addCloseOp.path, addCloseOp.permissions, replication,
addCloseOp.mtime, addCloseOp.atime, addCloseOp.blockSize, true, addCloseOp.mtime, addCloseOp.atime, addCloseOp.blockSize, true,
@ -373,7 +396,8 @@ public class FSEditLogLoader {
} }
case OP_MKDIR: { case OP_MKDIR: {
MkdirOp mkdirOp = (MkdirOp)op; MkdirOp mkdirOp = (MkdirOp)op;
inodeId = fsNamesys.allocateNewInodeId(); inodeId = getAndUpdateLastInodeId(mkdirOp.inodeId, logVersion,
lastInodeId);
fsDir.unprotectedMkdir(inodeId, mkdirOp.path, mkdirOp.permissions, fsDir.unprotectedMkdir(inodeId, mkdirOp.path, mkdirOp.permissions,
mkdirOp.timestamp); mkdirOp.timestamp);
break; break;
@ -427,7 +451,8 @@ public class FSEditLogLoader {
} }
case OP_SYMLINK: { case OP_SYMLINK: {
SymlinkOp symlinkOp = (SymlinkOp)op; SymlinkOp symlinkOp = (SymlinkOp)op;
inodeId = fsNamesys.allocateNewInodeId(); inodeId = getAndUpdateLastInodeId(symlinkOp.inodeId, logVersion,
lastInodeId);
fsDir.unprotectedAddSymlink(inodeId, symlinkOp.path, fsDir.unprotectedAddSymlink(inodeId, symlinkOp.path,
symlinkOp.value, symlinkOp.mtime, symlinkOp.value, symlinkOp.mtime,
symlinkOp.atime, symlinkOp.permissionStatus); symlinkOp.atime, symlinkOp.permissionStatus);

View File

@ -158,6 +158,7 @@ public abstract class FSEditLogOp {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
static abstract class AddCloseOp extends FSEditLogOp implements BlockListUpdatingOp { static abstract class AddCloseOp extends FSEditLogOp implements BlockListUpdatingOp {
int length; int length;
long inodeId;
String path; String path;
short replication; short replication;
long mtime; long mtime;
@ -172,6 +173,11 @@ public abstract class FSEditLogOp {
super(opCode); super(opCode);
assert(opCode == OP_ADD || opCode == OP_CLOSE); assert(opCode == OP_ADD || opCode == OP_CLOSE);
} }
<T extends AddCloseOp> T setInodeId(long inodeId) {
this.inodeId = inodeId;
return (T)this;
}
<T extends AddCloseOp> T setPath(String path) { <T extends AddCloseOp> T setPath(String path) {
this.path = path; this.path = path;
@ -235,6 +241,7 @@ public abstract class FSEditLogOp {
@Override @Override
public public
void writeFields(DataOutputStream out) throws IOException { void writeFields(DataOutputStream out) throws IOException {
FSImageSerialization.writeLong(inodeId, out);
FSImageSerialization.writeString(path, out); FSImageSerialization.writeString(path, out);
FSImageSerialization.writeShort(replication, out); FSImageSerialization.writeShort(replication, out);
FSImageSerialization.writeLong(mtime, out); FSImageSerialization.writeLong(mtime, out);
@ -255,6 +262,12 @@ public abstract class FSEditLogOp {
if (!LayoutVersion.supports(Feature.EDITLOG_OP_OPTIMIZATION, logVersion)) { if (!LayoutVersion.supports(Feature.EDITLOG_OP_OPTIMIZATION, logVersion)) {
this.length = in.readInt(); this.length = in.readInt();
} }
if (LayoutVersion.supports(Feature.ADD_INODE_ID, logVersion)) {
this.inodeId = in.readLong();
} else {
// The inodeId should be updated when this editLogOp is applied
this.inodeId = INodeId.GRANDFATHER_INODE_ID;
}
if ((-17 < logVersion && length != 4) || if ((-17 < logVersion && length != 4) ||
(logVersion <= -17 && length != 5 && !LayoutVersion.supports( (logVersion <= -17 && length != 5 && !LayoutVersion.supports(
Feature.EDITLOG_OP_OPTIMIZATION, logVersion))) { Feature.EDITLOG_OP_OPTIMIZATION, logVersion))) {
@ -327,6 +340,8 @@ public abstract class FSEditLogOp {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append("[length="); builder.append("[length=");
builder.append(length); builder.append(length);
builder.append(", inodeId=");
builder.append(inodeId);
builder.append(", path="); builder.append(", path=");
builder.append(path); builder.append(path);
builder.append(", replication="); builder.append(", replication=");
@ -357,6 +372,8 @@ public abstract class FSEditLogOp {
protected void toXml(ContentHandler contentHandler) throws SAXException { protected void toXml(ContentHandler contentHandler) throws SAXException {
XMLUtils.addSaxString(contentHandler, "LENGTH", XMLUtils.addSaxString(contentHandler, "LENGTH",
Integer.valueOf(length).toString()); Integer.valueOf(length).toString());
XMLUtils.addSaxString(contentHandler, "INODEID",
Long.valueOf(inodeId).toString());
XMLUtils.addSaxString(contentHandler, "PATH", path); XMLUtils.addSaxString(contentHandler, "PATH", path);
XMLUtils.addSaxString(contentHandler, "REPLICATION", XMLUtils.addSaxString(contentHandler, "REPLICATION",
Short.valueOf(replication).toString()); Short.valueOf(replication).toString());
@ -376,6 +393,7 @@ public abstract class FSEditLogOp {
@Override void fromXml(Stanza st) throws InvalidXmlException { @Override void fromXml(Stanza st) throws InvalidXmlException {
this.length = Integer.valueOf(st.getValue("LENGTH")); this.length = Integer.valueOf(st.getValue("LENGTH"));
this.inodeId = Long.valueOf(st.getValue("INODEID"));
this.path = st.getValue("PATH"); this.path = st.getValue("PATH");
this.replication = Short.valueOf(st.getValue("REPLICATION")); this.replication = Short.valueOf(st.getValue("REPLICATION"));
this.mtime = Long.valueOf(st.getValue("MTIME")); this.mtime = Long.valueOf(st.getValue("MTIME"));
@ -907,6 +925,7 @@ public abstract class FSEditLogOp {
static class MkdirOp extends FSEditLogOp { static class MkdirOp extends FSEditLogOp {
int length; int length;
long inodeId;
String path; String path;
long timestamp; long timestamp;
PermissionStatus permissions; PermissionStatus permissions;
@ -919,6 +938,11 @@ public abstract class FSEditLogOp {
return (MkdirOp)cache.get(OP_MKDIR); return (MkdirOp)cache.get(OP_MKDIR);
} }
MkdirOp setInodeId(long inodeId) {
this.inodeId = inodeId;
return this;
}
MkdirOp setPath(String path) { MkdirOp setPath(String path) {
this.path = path; this.path = path;
return this; return this;
@ -937,6 +961,7 @@ public abstract class FSEditLogOp {
@Override @Override
public public
void writeFields(DataOutputStream out) throws IOException { void writeFields(DataOutputStream out) throws IOException {
FSImageSerialization.writeLong(inodeId, out);
FSImageSerialization.writeString(path, out); FSImageSerialization.writeString(path, out);
FSImageSerialization.writeLong(timestamp, out); // mtime FSImageSerialization.writeLong(timestamp, out); // mtime
FSImageSerialization.writeLong(timestamp, out); // atime, unused at this FSImageSerialization.writeLong(timestamp, out); // atime, unused at this
@ -953,6 +978,12 @@ public abstract class FSEditLogOp {
&& !LayoutVersion.supports(Feature.EDITLOG_OP_OPTIMIZATION, logVersion)) { && !LayoutVersion.supports(Feature.EDITLOG_OP_OPTIMIZATION, logVersion)) {
throw new IOException("Incorrect data format. Mkdir operation."); throw new IOException("Incorrect data format. Mkdir operation.");
} }
if (LayoutVersion.supports(Feature.ADD_INODE_ID, logVersion)) {
this.inodeId = FSImageSerialization.readLong(in);
} else {
// This id should be updated when this editLogOp is applied
this.inodeId = INodeId.GRANDFATHER_INODE_ID;
}
this.path = FSImageSerialization.readString(in); this.path = FSImageSerialization.readString(in);
if (LayoutVersion.supports(Feature.EDITLOG_OP_OPTIMIZATION, logVersion)) { if (LayoutVersion.supports(Feature.EDITLOG_OP_OPTIMIZATION, logVersion)) {
this.timestamp = FSImageSerialization.readLong(in); this.timestamp = FSImageSerialization.readLong(in);
@ -979,6 +1010,8 @@ public abstract class FSEditLogOp {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append("MkdirOp [length="); builder.append("MkdirOp [length=");
builder.append(length); builder.append(length);
builder.append(", inodeId=");
builder.append(inodeId);
builder.append(", path="); builder.append(", path=");
builder.append(path); builder.append(path);
builder.append(", timestamp="); builder.append(", timestamp=");
@ -997,6 +1030,8 @@ public abstract class FSEditLogOp {
protected void toXml(ContentHandler contentHandler) throws SAXException { protected void toXml(ContentHandler contentHandler) throws SAXException {
XMLUtils.addSaxString(contentHandler, "LENGTH", XMLUtils.addSaxString(contentHandler, "LENGTH",
Integer.valueOf(length).toString()); Integer.valueOf(length).toString());
XMLUtils.addSaxString(contentHandler, "INODEID",
Long.valueOf(inodeId).toString());
XMLUtils.addSaxString(contentHandler, "PATH", path); XMLUtils.addSaxString(contentHandler, "PATH", path);
XMLUtils.addSaxString(contentHandler, "TIMESTAMP", XMLUtils.addSaxString(contentHandler, "TIMESTAMP",
Long.valueOf(timestamp).toString()); Long.valueOf(timestamp).toString());
@ -1005,6 +1040,7 @@ public abstract class FSEditLogOp {
@Override void fromXml(Stanza st) throws InvalidXmlException { @Override void fromXml(Stanza st) throws InvalidXmlException {
this.length = Integer.valueOf(st.getValue("LENGTH")); this.length = Integer.valueOf(st.getValue("LENGTH"));
this.inodeId = Long.valueOf(st.getValue("INODEID"));
this.path = st.getValue("PATH"); this.path = st.getValue("PATH");
this.timestamp = Long.valueOf(st.getValue("TIMESTAMP")); this.timestamp = Long.valueOf(st.getValue("TIMESTAMP"));
this.permissions = this.permissions =
@ -1483,6 +1519,7 @@ public abstract class FSEditLogOp {
static class SymlinkOp extends FSEditLogOp { static class SymlinkOp extends FSEditLogOp {
int length; int length;
long inodeId;
String path; String path;
String value; String value;
long mtime; long mtime;
@ -1497,6 +1534,11 @@ public abstract class FSEditLogOp {
return (SymlinkOp)cache.get(OP_SYMLINK); return (SymlinkOp)cache.get(OP_SYMLINK);
} }
SymlinkOp setId(long inodeId) {
this.inodeId = inodeId;
return this;
}
SymlinkOp setPath(String path) { SymlinkOp setPath(String path) {
this.path = path; this.path = path;
return this; return this;
@ -1525,6 +1567,7 @@ public abstract class FSEditLogOp {
@Override @Override
public public
void writeFields(DataOutputStream out) throws IOException { void writeFields(DataOutputStream out) throws IOException {
FSImageSerialization.writeLong(inodeId, out);
FSImageSerialization.writeString(path, out); FSImageSerialization.writeString(path, out);
FSImageSerialization.writeString(value, out); FSImageSerialization.writeString(value, out);
FSImageSerialization.writeLong(mtime, out); FSImageSerialization.writeLong(mtime, out);
@ -1542,6 +1585,12 @@ public abstract class FSEditLogOp {
+ "symlink operation."); + "symlink operation.");
} }
} }
if (LayoutVersion.supports(Feature.ADD_INODE_ID, logVersion)) {
this.inodeId = FSImageSerialization.readLong(in);
} else {
// This id should be updated when the editLogOp is applied
this.inodeId = INodeId.GRANDFATHER_INODE_ID;
}
this.path = FSImageSerialization.readString(in); this.path = FSImageSerialization.readString(in);
this.value = FSImageSerialization.readString(in); this.value = FSImageSerialization.readString(in);
@ -1560,6 +1609,8 @@ public abstract class FSEditLogOp {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append("SymlinkOp [length="); builder.append("SymlinkOp [length=");
builder.append(length); builder.append(length);
builder.append(", inodeId=");
builder.append(inodeId);
builder.append(", path="); builder.append(", path=");
builder.append(path); builder.append(path);
builder.append(", value="); builder.append(", value=");
@ -1582,6 +1633,8 @@ public abstract class FSEditLogOp {
protected void toXml(ContentHandler contentHandler) throws SAXException { protected void toXml(ContentHandler contentHandler) throws SAXException {
XMLUtils.addSaxString(contentHandler, "LENGTH", XMLUtils.addSaxString(contentHandler, "LENGTH",
Integer.valueOf(length).toString()); Integer.valueOf(length).toString());
XMLUtils.addSaxString(contentHandler, "INODEID",
Long.valueOf(inodeId).toString());
XMLUtils.addSaxString(contentHandler, "PATH", path); XMLUtils.addSaxString(contentHandler, "PATH", path);
XMLUtils.addSaxString(contentHandler, "VALUE", value); XMLUtils.addSaxString(contentHandler, "VALUE", value);
XMLUtils.addSaxString(contentHandler, "MTIME", XMLUtils.addSaxString(contentHandler, "MTIME",
@ -1593,6 +1646,7 @@ public abstract class FSEditLogOp {
@Override void fromXml(Stanza st) throws InvalidXmlException { @Override void fromXml(Stanza st) throws InvalidXmlException {
this.length = Integer.valueOf(st.getValue("LENGTH")); this.length = Integer.valueOf(st.getValue("LENGTH"));
this.inodeId = Long.valueOf(st.getValue("INODEID"));
this.path = st.getValue("PATH"); this.path = st.getValue("PATH");
this.value = st.getValue("VALUE"); this.value = st.getValue("VALUE");
this.mtime = Long.valueOf(st.getValue("MTIME")); this.mtime = Long.valueOf(st.getValue("MTIME"));

View File

@ -206,6 +206,20 @@ class FSImageFormat {
imgTxId = 0; imgTxId = 0;
} }
// read the last allocated inode id in the fsimage
if (LayoutVersion.supports(Feature.ADD_INODE_ID, imgVersion)) {
long lastInodeId = in.readLong();
namesystem.resetLastInodeId(lastInodeId);
if (LOG.isDebugEnabled()) {
LOG.debug("load last allocated InodeId from fsimage:" + lastInodeId);
}
} else {
if (LOG.isDebugEnabled()) {
LOG.debug("Old layout version doesn't have inode id."
+ " Will assign new id for each inode.");
}
}
// read compression related info // read compression related info
FSImageCompression compression; FSImageCompression compression;
if (LayoutVersion.supports(Feature.FSIMAGE_COMPRESSION, imgVersion)) { if (LayoutVersion.supports(Feature.FSIMAGE_COMPRESSION, imgVersion)) {
@ -216,8 +230,7 @@ class FSImageFormat {
in = compression.unwrapInputStream(fin); in = compression.unwrapInputStream(fin);
LOG.info("Loading image file " + curFile + " using " + compression); LOG.info("Loading image file " + curFile + " using " + compression);
// reset INodeId. TODO: remove this after inodeId is persisted in fsimage
namesystem.resetLastInodeIdWithoutChecking(INodeId.LAST_RESERVED_ID);
// load all inodes // load all inodes
LOG.info("Number of files = " + numFiles); LOG.info("Number of files = " + numFiles);
if (LayoutVersion.supports(Feature.FSIMAGE_NAME_OPTIMIZATION, if (LayoutVersion.supports(Feature.FSIMAGE_NAME_OPTIMIZATION,
@ -264,8 +277,8 @@ class FSImageFormat {
* @param in image input stream * @param in image input stream
* @throws IOException * @throws IOException
*/ */
private void loadLocalNameINodes(long numFiles, DataInputStream in) private void loadLocalNameINodes(long numFiles, DataInputStream in)
throws IOException { throws IOException {
assert LayoutVersion.supports(Feature.FSIMAGE_NAME_OPTIMIZATION, assert LayoutVersion.supports(Feature.FSIMAGE_NAME_OPTIMIZATION,
getLayoutVersion()); getLayoutVersion());
assert numFiles > 0; assert numFiles > 0;
@ -385,7 +398,8 @@ class FSImageFormat {
long blockSize = 0; long blockSize = 0;
int imgVersion = getLayoutVersion(); int imgVersion = getLayoutVersion();
long inodeId = namesystem.allocateNewInodeId(); long inodeId = LayoutVersion.supports(Feature.ADD_INODE_ID, imgVersion) ?
in.readLong() : namesystem.allocateNewInodeId();
short replication = in.readShort(); short replication = in.readShort();
replication = namesystem.getBlockManager().adjustReplication(replication); replication = namesystem.getBlockManager().adjustReplication(replication);
@ -436,8 +450,8 @@ class FSImageFormat {
LOG.info("Number of files under construction = " + size); LOG.info("Number of files under construction = " + size);
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
INodeFileUnderConstruction cons = INodeFileUnderConstruction cons = FSImageSerialization
FSImageSerialization.readINodeUnderConstruction(in); .readINodeUnderConstruction(in, namesystem, getLayoutVersion());
// verify that file exists in namespace // verify that file exists in namespace
String path = cons.getLocalName(); String path = cons.getLocalName();
@ -566,7 +580,8 @@ class FSImageFormat {
out.writeLong(fsDir.rootDir.numItemsInTree()); out.writeLong(fsDir.rootDir.numItemsInTree());
out.writeLong(sourceNamesystem.getGenerationStamp()); out.writeLong(sourceNamesystem.getGenerationStamp());
out.writeLong(context.getTxId()); out.writeLong(context.getTxId());
out.writeLong(sourceNamesystem.getLastInodeId());
// write compression info and set up compressed stream // write compression info and set up compressed stream
out = compression.writeHeaderAndWrapStream(fos); out = compression.writeHeaderAndWrapStream(fos);
LOG.info("Saving image file " + newFile + LOG.info("Saving image file " + newFile +

View File

@ -29,6 +29,8 @@ import org.apache.hadoop.fs.permission.PermissionStatus;
import org.apache.hadoop.hdfs.DFSUtil; import org.apache.hadoop.hdfs.DFSUtil;
import org.apache.hadoop.hdfs.DeprecatedUTF8; import org.apache.hadoop.hdfs.DeprecatedUTF8;
import org.apache.hadoop.hdfs.protocol.Block; import org.apache.hadoop.hdfs.protocol.Block;
import org.apache.hadoop.hdfs.protocol.LayoutVersion;
import org.apache.hadoop.hdfs.protocol.LayoutVersion.Feature;
import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfo; import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfo;
import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfoUnderConstruction; import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfoUnderConstruction;
import org.apache.hadoop.hdfs.server.common.HdfsServerConstants.BlockUCState; import org.apache.hadoop.hdfs.server.common.HdfsServerConstants.BlockUCState;
@ -79,8 +81,11 @@ public class FSImageSerialization {
// from the input stream // from the input stream
// //
static INodeFileUnderConstruction readINodeUnderConstruction( static INodeFileUnderConstruction readINodeUnderConstruction(
DataInputStream in) throws IOException { DataInputStream in, FSNamesystem fsNamesys, int imgVersion)
throws IOException {
byte[] name = readBytes(in); byte[] name = readBytes(in);
long inodeId = LayoutVersion.supports(Feature.ADD_INODE_ID, imgVersion) ? in
.readLong() : fsNamesys.allocateNewInodeId();
short blockReplication = in.readShort(); short blockReplication = in.readShort();
long modificationTime = in.readLong(); long modificationTime = in.readLong();
long preferredBlockSize = in.readLong(); long preferredBlockSize = in.readLong();
@ -107,8 +112,7 @@ public class FSImageSerialization {
int numLocs = in.readInt(); int numLocs = in.readInt();
assert numLocs == 0 : "Unexpected block locations"; assert numLocs == 0 : "Unexpected block locations";
//TODO: get inodeId from fsimage after inodeId is persisted return new INodeFileUnderConstruction(inodeId,
return new INodeFileUnderConstruction(INodeId.GRANDFATHER_INODE_ID,
name, name,
blockReplication, blockReplication,
modificationTime, modificationTime,
@ -128,6 +132,7 @@ public class FSImageSerialization {
String path) String path)
throws IOException { throws IOException {
writeString(path, out); writeString(path, out);
out.writeLong(cons.getId());
out.writeShort(cons.getBlockReplication()); out.writeShort(cons.getBlockReplication());
out.writeLong(cons.getModificationTime()); out.writeLong(cons.getModificationTime());
out.writeLong(cons.getPreferredBlockSize()); out.writeLong(cons.getPreferredBlockSize());
@ -151,6 +156,7 @@ public class FSImageSerialization {
byte[] name = node.getLocalNameBytes(); byte[] name = node.getLocalNameBytes();
out.writeShort(name.length); out.writeShort(name.length);
out.write(name); out.write(name);
out.writeLong(node.getId());
FsPermission filePerm = TL_DATA.get().FILE_PERM; FsPermission filePerm = TL_DATA.get().FILE_PERM;
if (node.isDirectory()) { if (node.isDirectory()) {
out.writeShort(0); // replication out.writeShort(0); // replication

View File

@ -123,7 +123,7 @@ class ImageLoaderCurrent implements ImageLoader {
new SimpleDateFormat("yyyy-MM-dd HH:mm"); new SimpleDateFormat("yyyy-MM-dd HH:mm");
private static int[] versions = { -16, -17, -18, -19, -20, -21, -22, -23, private static int[] versions = { -16, -17, -18, -19, -20, -21, -22, -23,
-24, -25, -26, -27, -28, -30, -31, -32, -33, -34, -35, -36, -37, -38, -39, -24, -25, -26, -27, -28, -30, -31, -32, -33, -34, -35, -36, -37, -38, -39,
-40}; -40, -41, -42};
private int imageVersion = 0; private int imageVersion = 0;
/* (non-Javadoc) /* (non-Javadoc)
@ -163,6 +163,10 @@ class ImageLoaderCurrent implements ImageLoader {
v.visit(ImageElement.TRANSACTION_ID, in.readLong()); v.visit(ImageElement.TRANSACTION_ID, in.readLong());
} }
if (LayoutVersion.supports(Feature.ADD_INODE_ID, imageVersion)) {
v.visit(ImageElement.LAST_INODE_ID, in.readLong());
}
if (LayoutVersion.supports(Feature.FSIMAGE_COMPRESSION, imageVersion)) { if (LayoutVersion.supports(Feature.FSIMAGE_COMPRESSION, imageVersion)) {
boolean isCompressed = in.readBoolean(); boolean isCompressed = in.readBoolean();
v.visit(ImageElement.IS_COMPRESSED, String.valueOf(isCompressed)); v.visit(ImageElement.IS_COMPRESSED, String.valueOf(isCompressed));
@ -440,6 +444,9 @@ class ImageLoaderCurrent implements ImageLoader {
} }
v.visit(ImageElement.INODE_PATH, pathName); v.visit(ImageElement.INODE_PATH, pathName);
if (LayoutVersion.supports(Feature.ADD_INODE_ID, imageVersion)) {
v.visit(ImageElement.INODE_ID, in.readLong());
}
v.visit(ImageElement.REPLICATION, in.readShort()); v.visit(ImageElement.REPLICATION, in.readShort());
v.visit(ImageElement.MODIFICATION_TIME, formatDate(in.readLong())); v.visit(ImageElement.MODIFICATION_TIME, formatDate(in.readLong()));
if(LayoutVersion.supports(Feature.FILE_ACCESS_TIME, imageVersion)) if(LayoutVersion.supports(Feature.FILE_ACCESS_TIME, imageVersion))

View File

@ -80,7 +80,9 @@ abstract class ImageVisitor {
DELEGATION_TOKEN_IDENTIFIER_MAX_DATE, DELEGATION_TOKEN_IDENTIFIER_MAX_DATE,
DELEGATION_TOKEN_IDENTIFIER_EXPIRY_TIME, DELEGATION_TOKEN_IDENTIFIER_EXPIRY_TIME,
DELEGATION_TOKEN_IDENTIFIER_MASTER_KEY_ID, DELEGATION_TOKEN_IDENTIFIER_MASTER_KEY_ID,
TRANSACTION_ID TRANSACTION_ID,
LAST_INODE_ID,
INODE_ID
} }
/** /**

View File

@ -217,7 +217,8 @@ public abstract class FSImageTestUtil {
FsPermission.createImmutable((short)0755)); FsPermission.createImmutable((short)0755));
for (int i = 1; i <= numDirs; i++) { for (int i = 1; i <= numDirs; i++) {
String dirName = "dir" + i; String dirName = "dir" + i;
INodeDirectory dir = new INodeDirectory(newInodeId + i -1, dirName, perms); INodeDirectory dir = new INodeDirectory(newInodeId + i - 1, dirName,
perms);
editLog.logMkDir("/" + dirName, dir); editLog.logMkDir("/" + dirName, dir);
} }
editLog.logSync(); editLog.logSync();

View File

@ -26,12 +26,14 @@ import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataOutputStream;
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.fs.PathIsNotDirectoryException; import org.apache.hadoop.fs.PathIsNotDirectoryException;
import org.apache.hadoop.fs.permission.FsPermission; import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.fs.permission.PermissionStatus; import org.apache.hadoop.fs.permission.PermissionStatus;
import org.apache.hadoop.hdfs.DFSConfigKeys; import org.apache.hadoop.hdfs.DFSConfigKeys;
import org.apache.hadoop.hdfs.DFSTestUtil;
import org.apache.hadoop.hdfs.MiniDFSCluster; import org.apache.hadoop.hdfs.MiniDFSCluster;
import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfo; import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfo;
import org.junit.Test; import org.junit.Test;
@ -334,6 +336,72 @@ public class TestINodeFile {
Configuration conf = new Configuration(); Configuration conf = new Configuration();
conf.setInt(DFSConfigKeys.DFS_BLOCK_SIZE_KEY, conf.setInt(DFSConfigKeys.DFS_BLOCK_SIZE_KEY,
DFSConfigKeys.DFS_BYTES_PER_CHECKSUM_DEFAULT); DFSConfigKeys.DFS_BYTES_PER_CHECKSUM_DEFAULT);
MiniDFSCluster cluster = null;
try {
cluster = new MiniDFSCluster.Builder(conf).numDataNodes(1).build();
cluster.waitActive();
FSNamesystem fsn = cluster.getNamesystem();
assertTrue(fsn.getLastInodeId() == 1001);
// Create one directory and the last inode id should increase to 1002
FileSystem fs = cluster.getFileSystem();
Path path = new Path("/test1");
assertTrue(fs.mkdirs(path));
assertTrue(fsn.getLastInodeId() == 1002);
int fileLen = 1024;
Path filePath = new Path("/test1/file");
DFSTestUtil.createFile(fs, filePath, fileLen, (short) 1, 0);
assertTrue(fsn.getLastInodeId() == 1003);
// Rename doesn't increase inode id
Path renamedPath = new Path("/test2");
fs.rename(path, renamedPath);
assertTrue(fsn.getLastInodeId() == 1003);
cluster.restartNameNode();
cluster.waitActive();
// Make sure empty editlog can be handled
cluster.restartNameNode();
cluster.waitActive();
fsn = cluster.getNamesystem();
assertTrue(fsn.getLastInodeId() == 1003);
DFSTestUtil.createFile(fs, new Path("/test2/file2"), fileLen, (short) 1,
0);
long id = fsn.getLastInodeId();
assertTrue(id == 1004);
fs.delete(new Path("/test2"), true);
// create a file under construction
FSDataOutputStream outStream = fs.create(new Path("/test3/file"));
assertTrue(outStream != null);
assertTrue(fsn.getLastInodeId() == 1006);
// Apply editlogs to fsimage, test fsimage with inodeUnderConstruction can
// be handled
fsn.enterSafeMode(false);
fsn.saveNamespace();
fsn.leaveSafeMode();
outStream.close();
// The lastInodeId in fsimage should remain 1006 after reboot
cluster.restartNameNode();
cluster.waitActive();
fsn = cluster.getNamesystem();
assertTrue(fsn.getLastInodeId() == 1006);
} finally {
if (cluster != null) {
cluster.shutdown();
}
}
}
@Test
public void testWriteToRenamedFile() throws IOException {
Configuration conf = new Configuration();
MiniDFSCluster cluster = new MiniDFSCluster.Builder(conf).numDataNodes(1) MiniDFSCluster cluster = new MiniDFSCluster.Builder(conf).numDataNodes(1)
.build(); .build();
cluster.waitActive(); cluster.waitActive();

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<EDITS> <EDITS>
<EDITS_VERSION>-40</EDITS_VERSION> <EDITS_VERSION>-42</EDITS_VERSION>
<RECORD> <RECORD>
<OPCODE>OP_START_LOG_SEGMENT</OPCODE> <OPCODE>OP_START_LOG_SEGMENT</OPCODE>
<DATA> <DATA>
@ -41,6 +41,7 @@
<DATA> <DATA>
<TXID>5</TXID> <TXID>5</TXID>
<LENGTH>0</LENGTH> <LENGTH>0</LENGTH>
<INODEID>1002</INODEID>
<PATH>/file_create</PATH> <PATH>/file_create</PATH>
<REPLICATION>1</REPLICATION> <REPLICATION>1</REPLICATION>
<MTIME>1330405685834</MTIME> <MTIME>1330405685834</MTIME>
@ -60,6 +61,7 @@
<DATA> <DATA>
<TXID>6</TXID> <TXID>6</TXID>
<LENGTH>0</LENGTH> <LENGTH>0</LENGTH>
<INODEID>0</INODEID>
<PATH>/file_create</PATH> <PATH>/file_create</PATH>
<REPLICATION>1</REPLICATION> <REPLICATION>1</REPLICATION>
<MTIME>1330405685848</MTIME> <MTIME>1330405685848</MTIME>
@ -98,6 +100,7 @@
<DATA> <DATA>
<TXID>9</TXID> <TXID>9</TXID>
<LENGTH>0</LENGTH> <LENGTH>0</LENGTH>
<INODEID>1003</INODEID>
<PATH>/directory_mkdir</PATH> <PATH>/directory_mkdir</PATH>
<TIMESTAMP>1330405685861</TIMESTAMP> <TIMESTAMP>1330405685861</TIMESTAMP>
<PERMISSION_STATUS> <PERMISSION_STATUS>
@ -119,6 +122,7 @@
<DATA> <DATA>
<TXID>11</TXID> <TXID>11</TXID>
<LENGTH>0</LENGTH> <LENGTH>0</LENGTH>
<INODEID>1004</INODEID>
<PATH>/file_create</PATH> <PATH>/file_create</PATH>
<REPLICATION>1</REPLICATION> <REPLICATION>1</REPLICATION>
<MTIME>1330405685866</MTIME> <MTIME>1330405685866</MTIME>
@ -138,6 +142,7 @@
<DATA> <DATA>
<TXID>12</TXID> <TXID>12</TXID>
<LENGTH>0</LENGTH> <LENGTH>0</LENGTH>
<INODEID>0</INODEID>
<PATH>/file_create</PATH> <PATH>/file_create</PATH>
<REPLICATION>1</REPLICATION> <REPLICATION>1</REPLICATION>
<MTIME>1330405685868</MTIME> <MTIME>1330405685868</MTIME>
@ -218,6 +223,7 @@
<DATA> <DATA>
<TXID>20</TXID> <TXID>20</TXID>
<LENGTH>0</LENGTH> <LENGTH>0</LENGTH>
<INODEID>1005</INODEID>
<PATH>/file_concat_target</PATH> <PATH>/file_concat_target</PATH>
<REPLICATION>1</REPLICATION> <REPLICATION>1</REPLICATION>
<MTIME>1330405685889</MTIME> <MTIME>1330405685889</MTIME>
@ -309,6 +315,7 @@
<DATA> <DATA>
<TXID>27</TXID> <TXID>27</TXID>
<LENGTH>0</LENGTH> <LENGTH>0</LENGTH>
<INODEID>0</INODEID>
<PATH>/file_concat_target</PATH> <PATH>/file_concat_target</PATH>
<REPLICATION>1</REPLICATION> <REPLICATION>1</REPLICATION>
<MTIME>1330405685978</MTIME> <MTIME>1330405685978</MTIME>
@ -350,6 +357,7 @@
<DATA> <DATA>
<TXID>29</TXID> <TXID>29</TXID>
<LENGTH>0</LENGTH> <LENGTH>0</LENGTH>
<INODEID>1006</INODEID>
<PATH>/file_concat_0</PATH> <PATH>/file_concat_0</PATH>
<REPLICATION>1</REPLICATION> <REPLICATION>1</REPLICATION>
<MTIME>1330405685983</MTIME> <MTIME>1330405685983</MTIME>
@ -441,6 +449,7 @@
<DATA> <DATA>
<TXID>36</TXID> <TXID>36</TXID>
<LENGTH>0</LENGTH> <LENGTH>0</LENGTH>
<INODEID>0</INODEID>
<PATH>/file_concat_0</PATH> <PATH>/file_concat_0</PATH>
<REPLICATION>1</REPLICATION> <REPLICATION>1</REPLICATION>
<MTIME>1330405686013</MTIME> <MTIME>1330405686013</MTIME>
@ -482,6 +491,7 @@
<DATA> <DATA>
<TXID>38</TXID> <TXID>38</TXID>
<LENGTH>0</LENGTH> <LENGTH>0</LENGTH>
<INODEID>1007</INODEID>
<PATH>/file_concat_1</PATH> <PATH>/file_concat_1</PATH>
<REPLICATION>1</REPLICATION> <REPLICATION>1</REPLICATION>
<MTIME>1330405686017</MTIME> <MTIME>1330405686017</MTIME>
@ -573,6 +583,7 @@
<DATA> <DATA>
<TXID>45</TXID> <TXID>45</TXID>
<LENGTH>0</LENGTH> <LENGTH>0</LENGTH>
<INODEID>0</INODEID>
<PATH>/file_concat_1</PATH> <PATH>/file_concat_1</PATH>
<REPLICATION>1</REPLICATION> <REPLICATION>1</REPLICATION>
<MTIME>1330405686042</MTIME> <MTIME>1330405686042</MTIME>
@ -620,6 +631,7 @@
<DATA> <DATA>
<TXID>47</TXID> <TXID>47</TXID>
<LENGTH>0</LENGTH> <LENGTH>0</LENGTH>
<INODEID>1008</INODEID>
<PATH>/file_symlink</PATH> <PATH>/file_symlink</PATH>
<VALUE>/file_concat_target</VALUE> <VALUE>/file_concat_target</VALUE>
<MTIME>1330405686051</MTIME> <MTIME>1330405686051</MTIME>
@ -693,6 +705,7 @@
<DATA> <DATA>
<TXID>52</TXID> <TXID>52</TXID>
<LENGTH>0</LENGTH> <LENGTH>0</LENGTH>
<INODEID>1009</INODEID>
<PATH>/hard-lease-recovery-test</PATH> <PATH>/hard-lease-recovery-test</PATH>
<REPLICATION>1</REPLICATION> <REPLICATION>1</REPLICATION>
<MTIME>1330405686084</MTIME> <MTIME>1330405686084</MTIME>
@ -759,6 +772,7 @@
<DATA> <DATA>
<TXID>58</TXID> <TXID>58</TXID>
<LENGTH>0</LENGTH> <LENGTH>0</LENGTH>
<INODEID>0</INODEID>
<PATH>/hard-lease-recovery-test</PATH> <PATH>/hard-lease-recovery-test</PATH>
<REPLICATION>1</REPLICATION> <REPLICATION>1</REPLICATION>
<MTIME>1330405688726</MTIME> <MTIME>1330405688726</MTIME>