HDFS-4334. Add a unique id to INode. Contributed by Brandon Li

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1426429 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Tsz-wo Sze 2012-12-28 08:26:33 +00:00
parent a7d444d002
commit 0fa9c7a825
20 changed files with 369 additions and 131 deletions

View File

@ -172,6 +172,8 @@ Trunk (Unreleased)
HDFS-4234. Use generic code for choosing datanode in Balancer. (szetszwo) HDFS-4234. Use generic code for choosing datanode in Balancer. (szetszwo)
HDFS-4334. Add a unique id to INode. (Brandon Li via szetszwo)
OPTIMIZATIONS OPTIMIZATIONS
BUG FIXES BUG FIXES

View File

@ -76,8 +76,9 @@ import com.google.common.base.Preconditions;
*************************************************/ *************************************************/
public class FSDirectory implements Closeable { public class FSDirectory implements Closeable {
private static INodeDirectoryWithQuota createRoot(FSNamesystem namesystem) { private static INodeDirectoryWithQuota createRoot(FSNamesystem namesystem) {
return new INodeDirectoryWithQuota(INodeDirectory.ROOT_NAME, return new INodeDirectoryWithQuota(namesystem.allocateNewInodeId(),
namesystem.createFsOwnerPermissions(new FsPermission((short)0755))); INodeDirectory.ROOT_NAME,
namesystem.createFsOwnerPermissions(new FsPermission((short) 0755)));
} }
INodeDirectoryWithQuota rootDir; INodeDirectoryWithQuota rootDir;
@ -253,7 +254,9 @@ public class FSDirectory implements Closeable {
if (!mkdirs(parent.toString(), permissions, true, modTime)) { if (!mkdirs(parent.toString(), permissions, true, modTime)) {
return null; return null;
} }
long id = namesystem.allocateNewInodeId();
INodeFileUnderConstruction newNode = new INodeFileUnderConstruction( INodeFileUnderConstruction newNode = new INodeFileUnderConstruction(
id,
permissions,replication, permissions,replication,
preferredBlockSize, modTime, clientName, preferredBlockSize, modTime, clientName,
clientMachine, clientNode); clientMachine, clientNode);
@ -275,7 +278,8 @@ public class FSDirectory implements Closeable {
return newNode; return newNode;
} }
INode unprotectedAddFile( String path, INode unprotectedAddFile( long id,
String path,
PermissionStatus permissions, PermissionStatus permissions,
short replication, short replication,
long modificationTime, long modificationTime,
@ -287,13 +291,11 @@ public class FSDirectory implements Closeable {
final INode newNode; final INode newNode;
assert hasWriteLock(); assert hasWriteLock();
if (underConstruction) { if (underConstruction) {
newNode = new INodeFileUnderConstruction( newNode = new INodeFileUnderConstruction(id, permissions, replication,
permissions, replication, preferredBlockSize, modificationTime, clientName, clientMachine, null);
preferredBlockSize, modificationTime, clientName,
clientMachine, null);
} else { } else {
newNode = new INodeFile(permissions, BlockInfo.EMPTY_ARRAY, replication, newNode = new INodeFile(id, permissions, BlockInfo.EMPTY_ARRAY,
modificationTime, atime, preferredBlockSize); replication, modificationTime, atime, preferredBlockSize);
} }
try { try {
@ -1428,8 +1430,9 @@ public class FSDirectory implements Closeable {
// create directories beginning from the first null index // create directories beginning from the first null index
for(; i < inodes.length; i++) { for(; i < inodes.length; i++) {
pathbuilder.append(Path.SEPARATOR + names[i]); pathbuilder.append(Path.SEPARATOR + names[i]);
unprotectedMkdir(inodesInPath, i, components[i], unprotectedMkdir(namesystem.allocateNewInodeId(), inodesInPath, i,
(i < lastInodeIndex) ? parentPermissions : permissions, now); components[i], (i < lastInodeIndex) ? parentPermissions
: permissions, now);
if (inodes[i] == null) { if (inodes[i] == null) {
return false; return false;
} }
@ -1451,7 +1454,7 @@ public class FSDirectory implements Closeable {
return true; return true;
} }
INode unprotectedMkdir(String src, PermissionStatus permissions, INode unprotectedMkdir(long inodeId, String src, PermissionStatus permissions,
long timestamp) throws QuotaExceededException, long timestamp) throws QuotaExceededException,
UnresolvedLinkException { UnresolvedLinkException {
assert hasWriteLock(); assert hasWriteLock();
@ -1460,7 +1463,8 @@ public class FSDirectory implements Closeable {
components.length, false); components.length, false);
INode[] inodes = inodesInPath.getINodes(); INode[] inodes = inodesInPath.getINodes();
final int pos = inodes.length - 1; final int pos = inodes.length - 1;
unprotectedMkdir(inodesInPath, pos, components[pos], permissions, timestamp); unprotectedMkdir(inodeId, inodesInPath, pos, components[pos], permissions,
timestamp);
return inodes[pos]; return inodes[pos];
} }
@ -1468,11 +1472,12 @@ public class FSDirectory implements Closeable {
* The parent path to the directory is at [0, pos-1]. * The parent path to the directory is at [0, pos-1].
* All ancestors exist. Newly created one stored at index pos. * All ancestors exist. Newly created one stored at index pos.
*/ */
private void unprotectedMkdir(INodesInPath inodesInPath, int pos, private void unprotectedMkdir(long inodeId, INodesInPath inodesInPath,
byte[] name, PermissionStatus permission, int pos, byte[] name, PermissionStatus permission, long timestamp)
long timestamp) throws QuotaExceededException { throws QuotaExceededException {
assert hasWriteLock(); assert hasWriteLock();
final INodeDirectory dir = new INodeDirectory(name, permission, timestamp); final INodeDirectory dir = new INodeDirectory(inodeId, name, permission,
timestamp);
if (addChild(inodesInPath, pos, dir, true)) { if (addChild(inodesInPath, pos, dir, true)) {
inodesInPath.setINode(pos, dir); inodesInPath.setINode(pos, dir);
} }
@ -2042,9 +2047,10 @@ public class FSDirectory implements Closeable {
} }
final String userName = dirPerms.getUserName(); final String userName = dirPerms.getUserName();
INodeSymlink newNode = null; INodeSymlink newNode = null;
long id = namesystem.allocateNewInodeId();
writeLock(); writeLock();
try { try {
newNode = unprotectedAddSymlink(path, target, modTime, modTime, newNode = unprotectedAddSymlink(id, path, target, modTime, modTime,
new PermissionStatus(userName, null, FsPermission.getDefault())); new PermissionStatus(userName, null, FsPermission.getDefault()));
} finally { } finally {
writeUnlock(); writeUnlock();
@ -2064,12 +2070,13 @@ public class FSDirectory implements Closeable {
/** /**
* Add the specified path into the namespace. Invoked from edit log processing. * Add the specified path into the namespace. Invoked from edit log processing.
*/ */
INodeSymlink unprotectedAddSymlink(String path, String target, long mtime, INodeSymlink unprotectedAddSymlink(long id, String path, String target,
long atime, PermissionStatus perm) long mtime, long atime, PermissionStatus perm)
throws UnresolvedLinkException, QuotaExceededException { throws UnresolvedLinkException, QuotaExceededException {
assert hasWriteLock(); assert hasWriteLock();
final INodeSymlink symlink = new INodeSymlink(target, mtime, atime, perm); final INodeSymlink symlink = new INodeSymlink(id, target, mtime, atime,
return addINode(path, symlink)? symlink: null; perm);
return addINode(path, symlink) ? symlink : null;
} }
/** /**

View File

@ -120,7 +120,8 @@ public class FSEditLogLoader {
long lastTxId = in.getLastTxId(); long lastTxId = in.getLastTxId();
long numTxns = (lastTxId - expectedStartingTxId) + 1; long numTxns = (lastTxId - expectedStartingTxId) + 1;
long lastLogTime = now(); long lastLogTime = now();
long lastInodeId = fsNamesys.getLastInodeId();
if (LOG.isDebugEnabled()) { if (LOG.isDebugEnabled()) {
LOG.debug("edit log length: " + in.length() + ", start txid: " LOG.debug("edit log length: " + in.length() + ", start txid: "
+ expectedStartingTxId + ", last txid: " + lastTxId); + expectedStartingTxId + ", last txid: " + lastTxId);
@ -170,7 +171,10 @@ public class FSEditLogLoader {
} }
} }
try { try {
applyEditLogOp(op, fsDir, in.getVersion()); long inodeId = applyEditLogOp(op, fsDir, in.getVersion());
if (lastInodeId < inodeId) {
lastInodeId = inodeId;
}
} catch (Throwable e) { } catch (Throwable e) {
LOG.error("Encountered exception on operation " + op, e); LOG.error("Encountered exception on operation " + op, e);
MetaRecoveryContext.editLogLoaderPrompt("Failed to " + MetaRecoveryContext.editLogLoaderPrompt("Failed to " +
@ -205,6 +209,7 @@ public class FSEditLogLoader {
} }
} }
} finally { } finally {
fsNamesys.resetLastInodeId(lastInodeId);
if(closeOnExit) { if(closeOnExit) {
in.close(); in.close();
} }
@ -223,9 +228,9 @@ public class FSEditLogLoader {
} }
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
private void applyEditLogOp(FSEditLogOp op, FSDirectory fsDir, private long applyEditLogOp(FSEditLogOp op, FSDirectory fsDir,
int logVersion) throws IOException { int logVersion) throws IOException {
long inodeId = INodeId.GRANDFATHER_INODE_ID;
if (LOG.isTraceEnabled()) { if (LOG.isTraceEnabled()) {
LOG.trace("replaying edit log: " + op); LOG.trace("replaying edit log: " + op);
} }
@ -255,11 +260,11 @@ public class FSEditLogLoader {
assert addCloseOp.blocks.length == 0; assert addCloseOp.blocks.length == 0;
// add to the file tree // add to the file tree
newFile = (INodeFile)fsDir.unprotectedAddFile( inodeId = fsNamesys.allocateNewInodeId();
addCloseOp.path, addCloseOp.permissions, newFile = (INodeFile) fsDir.unprotectedAddFile(inodeId,
replication, addCloseOp.mtime, addCloseOp.path, addCloseOp.permissions, replication,
addCloseOp.atime, addCloseOp.blockSize, addCloseOp.mtime, addCloseOp.atime, addCloseOp.blockSize, true,
true, addCloseOp.clientName, addCloseOp.clientMachine); addCloseOp.clientName, addCloseOp.clientMachine);
fsNamesys.leaseManager.addLease(addCloseOp.clientName, addCloseOp.path); fsNamesys.leaseManager.addLease(addCloseOp.clientName, addCloseOp.path);
} else { // This is OP_ADD on an existing file } else { // This is OP_ADD on an existing file
@ -370,7 +375,8 @@ public class FSEditLogLoader {
} }
case OP_MKDIR: { case OP_MKDIR: {
MkdirOp mkdirOp = (MkdirOp)op; MkdirOp mkdirOp = (MkdirOp)op;
fsDir.unprotectedMkdir(mkdirOp.path, mkdirOp.permissions, inodeId = fsNamesys.allocateNewInodeId();
fsDir.unprotectedMkdir(inodeId, mkdirOp.path, mkdirOp.permissions,
mkdirOp.timestamp); mkdirOp.timestamp);
break; break;
} }
@ -423,9 +429,10 @@ public class FSEditLogLoader {
} }
case OP_SYMLINK: { case OP_SYMLINK: {
SymlinkOp symlinkOp = (SymlinkOp)op; SymlinkOp symlinkOp = (SymlinkOp)op;
fsDir.unprotectedAddSymlink(symlinkOp.path, symlinkOp.value, inodeId = fsNamesys.allocateNewInodeId();
symlinkOp.mtime, symlinkOp.atime, fsDir.unprotectedAddSymlink(inodeId, symlinkOp.path,
symlinkOp.permissionStatus); symlinkOp.value, symlinkOp.mtime,
symlinkOp.atime, symlinkOp.permissionStatus);
break; break;
} }
case OP_RENAME: { case OP_RENAME: {
@ -485,6 +492,7 @@ public class FSEditLogLoader {
default: default:
throw new IOException("Invalid operation read " + op.opCode); throw new IOException("Invalid operation read " + op.opCode);
} }
return inodeId;
} }
private static String formatEditLogReplayError(EditLogInputStream in, private static String formatEditLogReplayError(EditLogInputStream in,

View File

@ -166,7 +166,8 @@ 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,
@ -334,6 +335,8 @@ class FSImageFormat {
long blockSize = 0; long blockSize = 0;
int imgVersion = getLayoutVersion(); int imgVersion = getLayoutVersion();
long inodeId = namesystem.allocateNewInodeId();
short replication = in.readShort(); short replication = in.readShort();
replication = namesystem.getBlockManager().adjustReplication(replication); replication = namesystem.getBlockManager().adjustReplication(replication);
modificationTime = in.readLong(); modificationTime = in.readLong();
@ -371,7 +374,7 @@ class FSImageFormat {
PermissionStatus permissions = PermissionStatus.read(in); PermissionStatus permissions = PermissionStatus.read(in);
return INode.newINode(permissions, blocks, symlink, replication, return INode.newINode(inodeId, permissions, blocks, symlink, replication,
modificationTime, atime, nsQuota, dsQuota, blockSize); modificationTime, atime, nsQuota, dsQuota, blockSize);
} }

View File

@ -107,7 +107,9 @@ public class FSImageSerialization {
int numLocs = in.readInt(); int numLocs = in.readInt();
assert numLocs == 0 : "Unexpected block locations"; assert numLocs == 0 : "Unexpected block locations";
return new INodeFileUnderConstruction(name, //TODO: get inodeId from fsimage after inodeId is persisted
return new INodeFileUnderConstruction(INodeId.GRANDFATHER_INODE_ID,
name,
blockReplication, blockReplication,
modificationTime, modificationTime,
preferredBlockSize, preferredBlockSize,

View File

@ -375,6 +375,30 @@ public class FSNamesystem implements Namesystem, FSClusterStats,
private final boolean haEnabled; private final boolean haEnabled;
private INodeId inodeId;
/**
* Set the last allocated inode id when fsimage is loaded or editlog is
* applied.
* @throws IOException
*/
public void resetLastInodeId(long newValue) throws IOException {
inodeId.resetLastInodeId(newValue);
}
/** Should only be used for tests to reset to any value */
void resetLastInodeIdWithoutChecking(long newValue) {
inodeId.resetLastInodeIdWithoutChecking(newValue);
}
public long getLastInodeId() {
return inodeId.getLastInodeId();
}
public long allocateNewInodeId() {
return inodeId.allocateNewInodeId();
}
/** /**
* Clear all loaded data * Clear all loaded data
*/ */
@ -383,6 +407,7 @@ public class FSNamesystem implements Namesystem, FSClusterStats,
dtSecretManager.reset(); dtSecretManager.reset();
generationStamp.setStamp(GenerationStamp.FIRST_VALID_STAMP); generationStamp.setStamp(GenerationStamp.FIRST_VALID_STAMP);
leaseManager.removeAllLeases(); leaseManager.removeAllLeases();
inodeId.resetLastInodeIdWithoutChecking(INodeId.LAST_RESERVED_ID);
} }
@VisibleForTesting @VisibleForTesting
@ -534,6 +559,8 @@ public class FSNamesystem implements Namesystem, FSClusterStats,
this.standbyShouldCheckpoint = conf.getBoolean( this.standbyShouldCheckpoint = conf.getBoolean(
DFS_HA_STANDBY_CHECKPOINTS_KEY, DFS_HA_STANDBY_CHECKPOINTS_DEFAULT); DFS_HA_STANDBY_CHECKPOINTS_KEY, DFS_HA_STANDBY_CHECKPOINTS_DEFAULT);
this.inodeId = new INodeId();
// For testing purposes, allow the DT secret manager to be started regardless // For testing purposes, allow the DT secret manager to be started regardless
// of whether security is enabled. // of whether security is enabled.
alwaysUseDelegationTokensForTests = conf.getBoolean( alwaysUseDelegationTokensForTests = conf.getBoolean(
@ -1931,6 +1958,7 @@ public class FSNamesystem implements Namesystem, FSClusterStats,
String leaseHolder, String clientMachine, DatanodeDescriptor clientNode, String leaseHolder, String clientMachine, DatanodeDescriptor clientNode,
boolean writeToEditLog) throws IOException { boolean writeToEditLog) throws IOException {
INodeFileUnderConstruction cons = new INodeFileUnderConstruction( INodeFileUnderConstruction cons = new INodeFileUnderConstruction(
file.getId(),
file.getLocalNameBytes(), file.getLocalNameBytes(),
file.getBlockReplication(), file.getBlockReplication(),
file.getModificationTime(), file.getModificationTime(),

View File

@ -17,6 +17,7 @@
*/ */
package org.apache.hadoop.hdfs.server.namenode; package org.apache.hadoop.hdfs.server.namenode;
import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.StringWriter; import java.io.StringWriter;
import java.util.ArrayList; import java.util.ArrayList;
@ -101,6 +102,11 @@ abstract class INode implements Comparable<byte[]> {
} }
} }
/**
* The inode id
*/
final private long id;
/** /**
* The inode name is in java UTF8 encoding; * The inode name is in java UTF8 encoding;
* The name in HdfsFileStatus should keep the same encoding as this. * The name in HdfsFileStatus should keep the same encoding as this.
@ -120,8 +126,9 @@ abstract class INode implements Comparable<byte[]> {
protected long modificationTime = 0L; protected long modificationTime = 0L;
protected long accessTime = 0L; protected long accessTime = 0L;
private INode(byte[] name, long permission, INodeDirectory parent, private INode(long id, byte[] name, long permission, INodeDirectory parent,
long modificationTime, long accessTime) { long modificationTime, long accessTime) {
this.id = id;
this.name = name; this.name = name;
this.permission = permission; this.permission = permission;
this.parent = parent; this.parent = parent;
@ -129,26 +136,31 @@ abstract class INode implements Comparable<byte[]> {
this.accessTime = accessTime; this.accessTime = accessTime;
} }
INode(byte[] name, PermissionStatus permissions, INodeDirectory parent, INode(long id, byte[] name, PermissionStatus permissions,
long modificationTime, long accessTime) { INodeDirectory parent, long modificationTime, long accessTime) {
this(name, PermissionStatusFormat.toLong(permissions), parent, this(id, name, PermissionStatusFormat.toLong(permissions), parent,
modificationTime, accessTime); modificationTime, accessTime);
} }
INode(PermissionStatus permissions, long mtime, long atime) { INode(long id, PermissionStatus permissions, long mtime, long atime) {
this(null, permissions, null, mtime, atime); this(id, null, PermissionStatusFormat.toLong(permissions), null, mtime, atime);
} }
protected INode(String name, PermissionStatus permissions) { protected INode(long id, String name, PermissionStatus permissions) {
this(DFSUtil.string2Bytes(name), permissions, null, 0L, 0L); this(id, DFSUtil.string2Bytes(name), permissions, null, 0L, 0L);
} }
/** @param other Other node to be copied */ /** @param other Other node to be copied */
INode(INode other) { INode(INode other) {
this(other.getLocalNameBytes(), other.permission, other.getParent(), this(other.getId(), other.getLocalNameBytes(), other.permission, other
other.getModificationTime(), other.getAccessTime()); .getParent(), other.getModificationTime(), other.getAccessTime());
} }
/** Get inode id */
public long getId() {
return this.id;
}
/** /**
* Check whether this is the root inode. * Check whether this is the root inode.
*/ */
@ -459,6 +471,7 @@ abstract class INode implements Comparable<byte[]> {
/** /**
* Create an INode; the inode's name is not set yet * Create an INode; the inode's name is not set yet
* *
* @param id preassigned inode id
* @param permissions permissions * @param permissions permissions
* @param blocks blocks if a file * @param blocks blocks if a file
* @param symlink symblic link if a symbolic link * @param symlink symblic link if a symbolic link
@ -470,7 +483,8 @@ abstract class INode implements Comparable<byte[]> {
* @param preferredBlockSize block size * @param preferredBlockSize block size
* @return an inode * @return an inode
*/ */
static INode newINode(PermissionStatus permissions, static INode newINode(long id,
PermissionStatus permissions,
BlockInfo[] blocks, BlockInfo[] blocks,
String symlink, String symlink,
short replication, short replication,
@ -480,17 +494,17 @@ abstract class INode implements Comparable<byte[]> {
long dsQuota, long dsQuota,
long preferredBlockSize) { long preferredBlockSize) {
if (symlink.length() != 0) { // check if symbolic link if (symlink.length() != 0) { // check if symbolic link
return new INodeSymlink(symlink, modificationTime, atime, permissions); return new INodeSymlink(id, symlink, modificationTime, atime, permissions);
} else if (blocks == null) { //not sym link and blocks null? directory! } else if (blocks == null) { //not sym link and blocks null? directory!
if (nsQuota >= 0 || dsQuota >= 0) { if (nsQuota >= 0 || dsQuota >= 0) {
return new INodeDirectoryWithQuota( return new INodeDirectoryWithQuota(
permissions, modificationTime, nsQuota, dsQuota); id, permissions, modificationTime, nsQuota, dsQuota);
} }
// regular directory // regular directory
return new INodeDirectory(permissions, modificationTime); return new INodeDirectory(id, permissions, modificationTime);
} }
// file // file
return new INodeFile(permissions, blocks, replication, return new INodeFile(id, permissions, blocks, replication,
modificationTime, atime, preferredBlockSize); modificationTime, atime, preferredBlockSize);
} }

View File

@ -53,17 +53,17 @@ class INodeDirectory extends INode {
private List<INode> children = null; private List<INode> children = null;
INodeDirectory(String name, PermissionStatus permissions) { INodeDirectory(long id, String name, PermissionStatus permissions) {
super(name, permissions); super(id, name, permissions);
} }
public INodeDirectory(PermissionStatus permissions, long mTime) { public INodeDirectory(long id, PermissionStatus permissions, long mTime) {
super(permissions, mTime, 0); super(id, permissions, mTime, 0);
} }
/** constructor */ /** constructor */
INodeDirectory(byte[] name, PermissionStatus permissions, long mtime) { INodeDirectory(long id, byte[] name, PermissionStatus permissions, long mtime) {
super(name, permissions, null, mtime, 0L); super(id, name, permissions, null, mtime, 0L);
} }
/** copy constructor /** copy constructor

View File

@ -54,16 +54,16 @@ class INodeDirectoryWithQuota extends INodeDirectory {
} }
/** constructor with no quota verification */ /** constructor with no quota verification */
INodeDirectoryWithQuota(PermissionStatus permissions, long modificationTime, INodeDirectoryWithQuota(long id, PermissionStatus permissions,
long nsQuota, long dsQuota) { long modificationTime, long nsQuota, long dsQuota) {
super(permissions, modificationTime); super(id, permissions, modificationTime);
this.nsQuota = nsQuota; this.nsQuota = nsQuota;
this.dsQuota = dsQuota; this.dsQuota = dsQuota;
} }
/** constructor with no quota verification */ /** constructor with no quota verification */
INodeDirectoryWithQuota(String name, PermissionStatus permissions) { INodeDirectoryWithQuota(long id, String name, PermissionStatus permissions) {
super(name, permissions); super(id, name, permissions);
} }
/** Get this directory's namespace quota /** Get this directory's namespace quota

View File

@ -86,15 +86,15 @@ public class INodeFile extends INode implements BlockCollection {
private BlockInfo[] blocks; private BlockInfo[] blocks;
INodeFile(PermissionStatus permissions, BlockInfo[] blklist, INodeFile(long id, PermissionStatus permissions, BlockInfo[] blklist,
short replication, long modificationTime, short replication, long modificationTime, long atime,
long atime, long preferredBlockSize) { long preferredBlockSize) {
super(permissions, modificationTime, atime); super(id, permissions, modificationTime, atime);
header = HeaderFormat.combineReplication(header, replication); header = HeaderFormat.combineReplication(header, replication);
header = HeaderFormat.combinePreferredBlockSize(header, preferredBlockSize); header = HeaderFormat.combinePreferredBlockSize(header, preferredBlockSize);
this.blocks = blklist; this.blocks = blklist;
} }
/** @return true unconditionally. */ /** @return true unconditionally. */
@Override @Override
public final boolean isFile() { public final boolean isFile() {

View File

@ -49,21 +49,23 @@ class INodeFileUnderConstruction extends INodeFile implements MutableBlockCollec
private final String clientMachine; private final String clientMachine;
private final DatanodeDescriptor clientNode; // if client is a cluster node too. private final DatanodeDescriptor clientNode; // if client is a cluster node too.
INodeFileUnderConstruction(PermissionStatus permissions, INodeFileUnderConstruction(long id,
PermissionStatus permissions,
short replication, short replication,
long preferredBlockSize, long preferredBlockSize,
long modTime, long modTime,
String clientName, String clientName,
String clientMachine, String clientMachine,
DatanodeDescriptor clientNode) { DatanodeDescriptor clientNode) {
super(permissions.applyUMask(UMASK), BlockInfo.EMPTY_ARRAY, replication, super(id, permissions.applyUMask(UMASK), BlockInfo.EMPTY_ARRAY,
modTime, modTime, preferredBlockSize); replication, modTime, modTime, preferredBlockSize);
this.clientName = clientName; this.clientName = clientName;
this.clientMachine = clientMachine; this.clientMachine = clientMachine;
this.clientNode = clientNode; this.clientNode = clientNode;
} }
INodeFileUnderConstruction(byte[] name, INodeFileUnderConstruction(long id,
byte[] name,
short blockReplication, short blockReplication,
long modificationTime, long modificationTime,
long preferredBlockSize, long preferredBlockSize,
@ -72,8 +74,8 @@ class INodeFileUnderConstruction extends INodeFile implements MutableBlockCollec
String clientName, String clientName,
String clientMachine, String clientMachine,
DatanodeDescriptor clientNode) { DatanodeDescriptor clientNode) {
super(perm, blocks, blockReplication, modificationTime, modificationTime, super(id, perm, blocks, blockReplication, modificationTime,
preferredBlockSize); modificationTime, preferredBlockSize);
setLocalName(name); setLocalName(name);
this.clientName = clientName; this.clientName = clientName;
this.clientMachine = clientMachine; this.clientMachine = clientMachine;
@ -112,7 +114,8 @@ class INodeFileUnderConstruction extends INodeFile implements MutableBlockCollec
assert allBlocksComplete() : "Can't finalize inode " + this assert allBlocksComplete() : "Can't finalize inode " + this
+ " since it contains non-complete blocks! Blocks are " + " since it contains non-complete blocks! Blocks are "
+ Arrays.asList(getBlocks()); + Arrays.asList(getBlocks());
INodeFile obj = new INodeFile(getPermissionStatus(), INodeFile obj = new INodeFile(getId(),
getPermissionStatus(),
getBlocks(), getBlocks(),
getBlockReplication(), getBlockReplication(),
getModificationTime(), getModificationTime(),

View File

@ -0,0 +1,105 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.hdfs.server.namenode;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.hadoop.classification.InterfaceAudience;
/**
* An id which uniquely identifies an inode
*/
@InterfaceAudience.Private
class INodeId implements Comparable<INodeId> {
/**
* The last reserved inode id. Reserve id 1 to 1000 for potential future
* usage. The id won't be recycled and is not expected to wrap around in a
* very long time. Root inode id will be 1001.
*/
public static final long LAST_RESERVED_ID = 1000L;
/**
* The inode id validation of lease check will be skipped when the request
* uses GRANDFATHER_INODE_ID for backward compatibility.
*/
public static final long GRANDFATHER_INODE_ID = 0;
private AtomicLong lastInodeId = new AtomicLong();
/**
* Create a new instance, initialized to LAST_RESERVED_ID.
*/
INodeId() {
lastInodeId.set(INodeId.LAST_RESERVED_ID);
}
/**
* Set the last allocated inode id when fsimage is loaded or editlog is
* applied.
* @throws IOException
*/
void resetLastInodeId(long newValue) throws IOException {
if (newValue < getLastInodeId()) {
throw new IOException(
"Can't reset lastInodeId to be less than its current value "
+ getLastInodeId() + ", newValue=" + newValue);
}
lastInodeId.set(newValue);
}
void resetLastInodeIdWithoutChecking(long newValue) {
lastInodeId.set(newValue);
}
long getLastInodeId() {
return lastInodeId.get();
}
/**
* First increment the counter and then get the id.
*/
long allocateNewInodeId() {
return lastInodeId.incrementAndGet();
}
@Override
// Comparable
public int compareTo(INodeId that) {
long id1 = this.getLastInodeId();
long id2 = that.getLastInodeId();
return id1 < id2 ? -1 : id1 > id2 ? 1 : 0;
}
@Override
// Object
public boolean equals(Object o) {
if (!(o instanceof INodeId)) {
return false;
}
return compareTo((INodeId) o) == 0;
}
@Override
// Object
public int hashCode() {
long id = getLastInodeId();
return (int) (id ^ (id >>> 32));
}
}

View File

@ -28,9 +28,9 @@ import org.apache.hadoop.hdfs.DFSUtil;
public class INodeSymlink extends INode { public class INodeSymlink extends INode {
private final byte[] symlink; // The target URI private final byte[] symlink; // The target URI
INodeSymlink(String value, long mtime, long atime, INodeSymlink(long id, String value, long mtime, long atime,
PermissionStatus permissions) { PermissionStatus permissions) {
super(permissions, mtime, atime); super(id, permissions, mtime, atime);
this.symlink = DFSUtil.string2Bytes(value); this.symlink = DFSUtil.string2Bytes(value);
} }

View File

@ -62,7 +62,8 @@ public class CreateEditsLog {
PermissionStatus p = new PermissionStatus("joeDoe", "people", PermissionStatus p = new PermissionStatus("joeDoe", "people",
new FsPermission((short)0777)); new FsPermission((short)0777));
INodeDirectory dirInode = new INodeDirectory(p, 0L); INodeDirectory dirInode = new INodeDirectory(INodeId.GRANDFATHER_INODE_ID,
p, 0L);
editLog.logMkDir(BASE_PATH, dirInode); editLog.logMkDir(BASE_PATH, dirInode);
long blockSize = 10; long blockSize = 10;
BlockInfo[] blocks = new BlockInfo[blocksPerFile]; BlockInfo[] blocks = new BlockInfo[blocksPerFile];
@ -81,8 +82,9 @@ public class CreateEditsLog {
} }
INodeFileUnderConstruction inode = new INodeFileUnderConstruction( INodeFileUnderConstruction inode = new INodeFileUnderConstruction(
null, replication, 0, blockSize, blocks, p, "", "", null); INodeId.GRANDFATHER_INODE_ID, null, replication, 0, blockSize,
// Append path to filename with information about blockIDs blocks, p, "", "", null);
// Append path to filename with information about blockIDs
String path = "_" + iF + "_B" + blocks[0].getBlockId() + String path = "_" + iF + "_B" + blocks[0].getBlockId() +
"_to_B" + blocks[blocksPerFile-1].getBlockId() + "_"; "_to_B" + blocks[blocksPerFile-1].getBlockId() + "_";
String filePath = nameGenerator.getNextFileName(""); String filePath = nameGenerator.getNextFileName("");
@ -90,12 +92,12 @@ public class CreateEditsLog {
// Log the new sub directory in edits // Log the new sub directory in edits
if ((iF % nameGenerator.getFilesPerDirectory()) == 0) { if ((iF % nameGenerator.getFilesPerDirectory()) == 0) {
String currentDir = nameGenerator.getCurrentDir(); String currentDir = nameGenerator.getCurrentDir();
dirInode = new INodeDirectory(p, 0L); dirInode = new INodeDirectory(INodeId.GRANDFATHER_INODE_ID, p, 0L);
editLog.logMkDir(currentDir, dirInode); editLog.logMkDir(currentDir, dirInode);
} }
editLog.logOpenFile(filePath, editLog.logOpenFile(filePath, new INodeFileUnderConstruction(
new INodeFileUnderConstruction( INodeId.GRANDFATHER_INODE_ID, p, replication, 0, blockSize, "", "",
p, replication, 0, blockSize, "", "", null)); null));
editLog.logCloseFile(filePath, inode); editLog.logCloseFile(filePath, inode);
if (currentBlockId - bidAtSync >= 2000) { // sync every 2K blocks if (currentBlockId - bidAtSync >= 2000) { // sync every 2K blocks

View File

@ -208,7 +208,7 @@ public abstract class FSImageTestUtil {
* only a specified number of "mkdirs" operations. * only a specified number of "mkdirs" operations.
*/ */
public static void createAbortedLogWithMkdirs(File editsLogDir, int numDirs, public static void createAbortedLogWithMkdirs(File editsLogDir, int numDirs,
long firstTxId) throws IOException { long firstTxId, long newInodeId) throws IOException {
FSEditLog editLog = FSImageTestUtil.createStandaloneEditLog(editsLogDir); FSEditLog editLog = FSImageTestUtil.createStandaloneEditLog(editsLogDir);
editLog.setNextTxId(firstTxId); editLog.setNextTxId(firstTxId);
editLog.openForWrite(); editLog.openForWrite();
@ -217,7 +217,7 @@ 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(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

@ -152,7 +152,8 @@ public class TestEditLog {
for (int i = 0; i < numTransactions; i++) { for (int i = 0; i < numTransactions; i++) {
INodeFileUnderConstruction inode = new INodeFileUnderConstruction( INodeFileUnderConstruction inode = new INodeFileUnderConstruction(
p, replication, blockSize, 0, "", "", null); namesystem.allocateNewInodeId(), p, replication, blockSize, 0, "",
"", null);
editLog.logOpenFile("/filename" + (startIndex + i), inode); editLog.logOpenFile("/filename" + (startIndex + i), inode);
editLog.logCloseFile("/filename" + (startIndex + i), inode); editLog.logCloseFile("/filename" + (startIndex + i), inode);
editLog.logSync(); editLog.logSync();
@ -317,6 +318,11 @@ public class TestEditLog {
// we should now be writing to edits_inprogress_3 // we should now be writing to edits_inprogress_3
fsimage.rollEditLog(); fsimage.rollEditLog();
// Remember the current lastInodeId and will reset it back to test
// loading editlog segments.The transactions in the following allocate new
// inode id to write to editlogs but doesn't create ionde in namespace
long originalLastInodeId = namesystem.getLastInodeId();
// Create threads and make them run transactions concurrently. // Create threads and make them run transactions concurrently.
Thread threadId[] = new Thread[NUM_THREADS]; Thread threadId[] = new Thread[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; i++) { for (int i = 0; i < NUM_THREADS; i++) {
@ -349,6 +355,7 @@ public class TestEditLog {
// If there were any corruptions, it is likely that the reading in // If there were any corruptions, it is likely that the reading in
// of these transactions will throw an exception. // of these transactions will throw an exception.
// //
namesystem.resetLastInodeIdWithoutChecking(originalLastInodeId);
for (Iterator<StorageDirectory> it = for (Iterator<StorageDirectory> it =
fsimage.getStorage().dirIterator(NameNodeDirType.EDITS); it.hasNext();) { fsimage.getStorage().dirIterator(NameNodeDirType.EDITS); it.hasNext();) {
FSEditLogLoader loader = new FSEditLogLoader(namesystem, 0); FSEditLogLoader loader = new FSEditLogLoader(namesystem, 0);

View File

@ -73,7 +73,8 @@ public class TestFsLimits {
fileAsURI(new File(MiniDFSCluster.getBaseDirectory(), fileAsURI(new File(MiniDFSCluster.getBaseDirectory(),
"namenode")).toString()); "namenode")).toString());
rootInode = new INodeDirectoryWithQuota(INodeDirectory.ROOT_NAME, perms); rootInode = new INodeDirectoryWithQuota(getMockNamesystem()
.allocateNewInodeId(), INodeDirectory.ROOT_NAME, perms);
inodes = new INode[]{ rootInode, null }; inodes = new INode[]{ rootInode, null };
fs = null; fs = null;
fsIsReady = true; fsIsReady = true;
@ -152,7 +153,8 @@ public class TestFsLimits {
// have to create after the caller has had a chance to set conf values // have to create after the caller has had a chance to set conf values
if (fs == null) fs = new MockFSDirectory(); if (fs == null) fs = new MockFSDirectory();
INode child = new INodeDirectory(name, perms); INode child = new INodeDirectory(getMockNamesystem().allocateNewInodeId(),
name, perms);
child.setLocalName(name); child.setLocalName(name);
Class<?> generated = null; Class<?> generated = null;

View File

@ -26,14 +26,18 @@ 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.Options; import org.apache.hadoop.fs.Options;
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.DFSTestUtil; import org.apache.hadoop.hdfs.DFSTestUtil;
import org.apache.hadoop.hdfs.DistributedFileSystem; import org.apache.hadoop.hdfs.DistributedFileSystem;
import org.apache.hadoop.hdfs.MiniDFSCluster; import org.apache.hadoop.hdfs.MiniDFSCluster;
import org.apache.hadoop.hdfs.protocol.HdfsFileStatus;
import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfo; import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfo;
import org.junit.Test; import org.junit.Test;
@ -54,9 +58,9 @@ public class TestINodeFile {
public void testReplication () { public void testReplication () {
replication = 3; replication = 3;
preferredBlockSize = 128*1024*1024; preferredBlockSize = 128*1024*1024;
INodeFile inf = new INodeFile(new PermissionStatus(userName, null, INodeFile inf = new INodeFile(INodeId.GRANDFATHER_INODE_ID,
FsPermission.getDefault()), null, replication, new PermissionStatus(userName, null, FsPermission.getDefault()), null,
0L, 0L, preferredBlockSize); replication, 0L, 0L, preferredBlockSize);
assertEquals("True has to be returned in this case", replication, assertEquals("True has to be returned in this case", replication,
inf.getBlockReplication()); inf.getBlockReplication());
} }
@ -71,9 +75,9 @@ public class TestINodeFile {
throws IllegalArgumentException { throws IllegalArgumentException {
replication = -1; replication = -1;
preferredBlockSize = 128*1024*1024; preferredBlockSize = 128*1024*1024;
new INodeFile(new PermissionStatus(userName, null, new INodeFile(INodeId.GRANDFATHER_INODE_ID, new PermissionStatus(userName,
FsPermission.getDefault()), null, replication, null, FsPermission.getDefault()), null, replication, 0L, 0L,
0L, 0L, preferredBlockSize); preferredBlockSize);
} }
/** /**
@ -84,20 +88,20 @@ public class TestINodeFile {
public void testPreferredBlockSize () { public void testPreferredBlockSize () {
replication = 3; replication = 3;
preferredBlockSize = 128*1024*1024; preferredBlockSize = 128*1024*1024;
INodeFile inf = new INodeFile(new PermissionStatus(userName, null, INodeFile inf = new INodeFile(INodeId.GRANDFATHER_INODE_ID,
FsPermission.getDefault()), null, replication, new PermissionStatus(userName, null, FsPermission.getDefault()), null,
0L, 0L, preferredBlockSize); replication, 0L, 0L, preferredBlockSize);
assertEquals("True has to be returned in this case", preferredBlockSize, assertEquals("True has to be returned in this case", preferredBlockSize,
inf.getPreferredBlockSize()); inf.getPreferredBlockSize());
} }
@Test @Test
public void testPreferredBlockSizeUpperBound () { public void testPreferredBlockSizeUpperBound () {
replication = 3; replication = 3;
preferredBlockSize = BLKSIZE_MAXVALUE; preferredBlockSize = BLKSIZE_MAXVALUE;
INodeFile inf = new INodeFile(new PermissionStatus(userName, null, INodeFile inf = new INodeFile(INodeId.GRANDFATHER_INODE_ID,
FsPermission.getDefault()), null, replication, new PermissionStatus(userName, null, FsPermission.getDefault()), null,
0L, 0L, preferredBlockSize); replication, 0L, 0L, preferredBlockSize);
assertEquals("True has to be returned in this case", BLKSIZE_MAXVALUE, assertEquals("True has to be returned in this case", BLKSIZE_MAXVALUE,
inf.getPreferredBlockSize()); inf.getPreferredBlockSize());
} }
@ -112,9 +116,9 @@ public class TestINodeFile {
throws IllegalArgumentException { throws IllegalArgumentException {
replication = 3; replication = 3;
preferredBlockSize = -1; preferredBlockSize = -1;
new INodeFile(new PermissionStatus(userName, null, new INodeFile(INodeId.GRANDFATHER_INODE_ID, new PermissionStatus(userName,
FsPermission.getDefault()), null, replication, null, FsPermission.getDefault()), null, replication, 0L, 0L,
0L, 0L, preferredBlockSize); preferredBlockSize);
} }
/** /**
@ -127,10 +131,10 @@ public class TestINodeFile {
throws IllegalArgumentException { throws IllegalArgumentException {
replication = 3; replication = 3;
preferredBlockSize = BLKSIZE_MAXVALUE+1; preferredBlockSize = BLKSIZE_MAXVALUE+1;
new INodeFile(new PermissionStatus(userName, null, new INodeFile(INodeId.GRANDFATHER_INODE_ID, new PermissionStatus(userName,
FsPermission.getDefault()), null, replication, null, FsPermission.getDefault()), null, replication, 0L, 0L,
0L, 0L, preferredBlockSize); preferredBlockSize);
} }
@Test @Test
public void testGetFullPathName() { public void testGetFullPathName() {
@ -139,12 +143,14 @@ public class TestINodeFile {
replication = 3; replication = 3;
preferredBlockSize = 128*1024*1024; preferredBlockSize = 128*1024*1024;
INodeFile inf = new INodeFile(perms, null, replication, INodeFile inf = new INodeFile(INodeId.GRANDFATHER_INODE_ID, perms, null,
0L, 0L, preferredBlockSize); replication, 0L, 0L, preferredBlockSize);
inf.setLocalName("f"); inf.setLocalName("f");
INodeDirectory root = new INodeDirectory(INodeDirectory.ROOT_NAME, perms); INodeDirectory root = new INodeDirectory(INodeId.GRANDFATHER_INODE_ID,
INodeDirectory dir = new INodeDirectory("d", perms); INodeDirectory.ROOT_NAME, perms);
INodeDirectory dir = new INodeDirectory(INodeId.GRANDFATHER_INODE_ID, "d",
perms);
assertEquals("f", inf.getFullPathName()); assertEquals("f", inf.getFullPathName());
assertEquals("", inf.getLocalParentDir()); assertEquals("", inf.getLocalParentDir());
@ -242,7 +248,7 @@ public class TestINodeFile {
for (int i = 0; i < nCount; i++) { for (int i = 0; i < nCount; i++) {
PermissionStatus perms = new PermissionStatus(userName, null, PermissionStatus perms = new PermissionStatus(userName, null,
FsPermission.getDefault()); FsPermission.getDefault());
iNodes[i] = new INodeFile(perms, null, replication, 0L, 0L, iNodes[i] = new INodeFile(i, perms, null, replication, 0L, 0L,
preferredBlockSize); preferredBlockSize);
iNodes[i].setLocalName(fileNamePrefix + Integer.toString(i)); iNodes[i].setLocalName(fileNamePrefix + Integer.toString(i));
BlockInfo newblock = new BlockInfo(replication); BlockInfo newblock = new BlockInfo(replication);
@ -293,10 +299,10 @@ public class TestINodeFile {
} }
{//cast from INodeFile {//cast from INodeFile
final INode from = new INodeFile( final INode from = new INodeFile(INodeId.GRANDFATHER_INODE_ID, perm,
perm, null, replication, 0L, 0L, preferredBlockSize); null, replication, 0L, 0L, preferredBlockSize);
//cast to INodeFile, should success //cast to INodeFile, should success
final INodeFile f = INodeFile.valueOf(from, path); final INodeFile f = INodeFile.valueOf(from, path);
assertTrue(f == from); assertTrue(f == from);
@ -318,8 +324,9 @@ public class TestINodeFile {
{//cast from INodeFileUnderConstruction {//cast from INodeFileUnderConstruction
final INode from = new INodeFileUnderConstruction( final INode from = new INodeFileUnderConstruction(
perm, replication, 0L, 0L, "client", "machine", null); INodeId.GRANDFATHER_INODE_ID, perm, replication, 0L, 0L, "client",
"machine", null);
//cast to INodeFile, should success //cast to INodeFile, should success
final INodeFile f = INodeFile.valueOf(from, path); final INodeFile f = INodeFile.valueOf(from, path);
assertTrue(f == from); assertTrue(f == from);
@ -338,7 +345,8 @@ public class TestINodeFile {
} }
{//cast from INodeDirectory {//cast from INodeDirectory
final INode from = new INodeDirectory(perm, 0L); final INode from = new INodeDirectory(INodeId.GRANDFATHER_INODE_ID, perm,
0L);
//cast to INodeFile, should fail //cast to INodeFile, should fail
try { try {
@ -361,4 +369,47 @@ public class TestINodeFile {
assertTrue(d == from); assertTrue(d == from);
} }
} }
/**
* Verify root always has inode id 1001 and new formated fsimage has last
* allocated inode id 1000. Validate correct lastInodeId is persisted.
* @throws IOException
*/
@Test
public void TestInodeId() throws IOException {
Configuration conf = new Configuration();
conf.setInt(DFSConfigKeys.DFS_BLOCK_SIZE_KEY,
DFSConfigKeys.DFS_BYTES_PER_CHECKSUM_DEFAULT);
MiniDFSCluster cluster = new MiniDFSCluster.Builder(conf).numDataNodes(1)
.build();
cluster.waitActive();
FSNamesystem fsn = cluster.getNamesystem();
long lastId = fsn.getLastInodeId();
assertTrue(lastId == 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);
Path filePath = new Path("/test1/file");
fs.create(filePath);
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();
assertTrue(fsn.getLastInodeId() == 1003);
}
} }

View File

@ -36,6 +36,7 @@ import org.apache.hadoop.hdfs.MiniDFSCluster;
import org.apache.hadoop.hdfs.MiniDFSNNTopology; import org.apache.hadoop.hdfs.MiniDFSNNTopology;
import org.apache.hadoop.hdfs.server.namenode.EditLogFileOutputStream; import org.apache.hadoop.hdfs.server.namenode.EditLogFileOutputStream;
import org.apache.hadoop.hdfs.server.namenode.FSImageTestUtil; import org.apache.hadoop.hdfs.server.namenode.FSImageTestUtil;
import org.apache.hadoop.hdfs.server.namenode.FSNamesystem;
import org.apache.hadoop.hdfs.server.namenode.NNStorage; import org.apache.hadoop.hdfs.server.namenode.NNStorage;
import org.apache.hadoop.hdfs.server.namenode.NameNodeAdapter; import org.apache.hadoop.hdfs.server.namenode.NameNodeAdapter;
import org.apache.hadoop.io.IOUtils; import org.apache.hadoop.io.IOUtils;
@ -139,7 +140,9 @@ public class TestEditLogsDuringFailover {
// Create a fake in-progress edit-log in the shared directory // Create a fake in-progress edit-log in the shared directory
URI sharedUri = cluster.getSharedEditsDir(0, 1); URI sharedUri = cluster.getSharedEditsDir(0, 1);
File sharedDir = new File(sharedUri.getPath(), "current"); File sharedDir = new File(sharedUri.getPath(), "current");
FSImageTestUtil.createAbortedLogWithMkdirs(sharedDir, NUM_DIRS_IN_LOG, 1); FSNamesystem fsn = cluster.getNamesystem(0);
FSImageTestUtil.createAbortedLogWithMkdirs(sharedDir, NUM_DIRS_IN_LOG, 1,
fsn.getLastInodeId() + 1);
assertEditFiles(Collections.singletonList(sharedUri), assertEditFiles(Collections.singletonList(sharedUri),
NNStorage.getInProgressEditsFileName(1)); NNStorage.getInProgressEditsFileName(1));

View File

@ -204,8 +204,9 @@ public class TestStandbyCheckpoints {
File sharedDir = new File(sharedUri.getPath(), "current"); File sharedDir = new File(sharedUri.getPath(), "current");
File tmpDir = new File(MiniDFSCluster.getBaseDirectory(), File tmpDir = new File(MiniDFSCluster.getBaseDirectory(),
"testCheckpointCancellation-tmp"); "testCheckpointCancellation-tmp");
FSImageTestUtil.createAbortedLogWithMkdirs(tmpDir, NUM_DIRS_IN_LOG, FSNamesystem fsn = cluster.getNamesystem(0);
3); FSImageTestUtil.createAbortedLogWithMkdirs(tmpDir, NUM_DIRS_IN_LOG, 3,
fsn.getLastInodeId() + 1);
String fname = NNStorage.getInProgressEditsFileName(3); String fname = NNStorage.getInProgressEditsFileName(3);
new File(tmpDir, fname).renameTo(new File(sharedDir, fname)); new File(tmpDir, fname).renameTo(new File(sharedDir, fname));