HDFS-4215. Merge r1411947 from trunk.
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/branch-2@1471530 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
876c1c9098
commit
19198ea31d
|
@ -65,6 +65,9 @@ Release 2.0.5-beta - UNRELEASED
|
||||||
HDFS-4206. Change the fields in INode and its subclasses to private.
|
HDFS-4206. Change the fields in INode and its subclasses to private.
|
||||||
(szetszwo)
|
(szetszwo)
|
||||||
|
|
||||||
|
HDFS-4215. Remove locking from addToParent(..) since it is used in image
|
||||||
|
loading, and add INode.isFile(). (szetszwo)
|
||||||
|
|
||||||
OPTIMIZATIONS
|
OPTIMIZATIONS
|
||||||
|
|
||||||
BUG FIXES
|
BUG FIXES
|
||||||
|
|
|
@ -74,6 +74,10 @@ import com.google.common.base.Preconditions;
|
||||||
*
|
*
|
||||||
*************************************************/
|
*************************************************/
|
||||||
public class FSDirectory implements Closeable {
|
public class FSDirectory implements Closeable {
|
||||||
|
private static INodeDirectoryWithQuota createRoot(FSNamesystem namesystem) {
|
||||||
|
return new INodeDirectoryWithQuota(INodeDirectory.ROOT_NAME,
|
||||||
|
namesystem.createFsOwnerPermissions(new FsPermission((short)0755)));
|
||||||
|
}
|
||||||
|
|
||||||
INodeDirectoryWithQuota rootDir;
|
INodeDirectoryWithQuota rootDir;
|
||||||
FSImage fsImage;
|
FSImage fsImage;
|
||||||
|
@ -122,9 +126,7 @@ public class FSDirectory implements Closeable {
|
||||||
FSDirectory(FSImage fsImage, FSNamesystem ns, Configuration conf) {
|
FSDirectory(FSImage fsImage, FSNamesystem ns, Configuration conf) {
|
||||||
this.dirLock = new ReentrantReadWriteLock(true); // fair
|
this.dirLock = new ReentrantReadWriteLock(true); // fair
|
||||||
this.cond = dirLock.writeLock().newCondition();
|
this.cond = dirLock.writeLock().newCondition();
|
||||||
rootDir = new INodeDirectoryWithQuota(INodeDirectory.ROOT_NAME,
|
rootDir = createRoot(ns);
|
||||||
ns.createFsOwnerPermissions(new FsPermission((short)0755)),
|
|
||||||
Integer.MAX_VALUE, UNKNOWN_DISK_SPACE);
|
|
||||||
this.fsImage = fsImage;
|
this.fsImage = fsImage;
|
||||||
int configuredLimit = conf.getInt(
|
int configuredLimit = conf.getInt(
|
||||||
DFSConfigKeys.DFS_LIST_LIMIT, DFSConfigKeys.DFS_LIST_LIMIT_DEFAULT);
|
DFSConfigKeys.DFS_LIST_LIMIT, DFSConfigKeys.DFS_LIST_LIMIT_DEFAULT);
|
||||||
|
@ -305,35 +307,6 @@ public class FSDirectory implements Closeable {
|
||||||
return newNode;
|
return newNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
INodeDirectory addToParent(INodeDirectory parentINode,
|
|
||||||
INode newNode, boolean propagateModTime) {
|
|
||||||
// NOTE: This does not update space counts for parents
|
|
||||||
INodeDirectory newParent = null;
|
|
||||||
writeLock();
|
|
||||||
try {
|
|
||||||
try {
|
|
||||||
newParent = rootDir.addToParent(newNode, parentINode,
|
|
||||||
propagateModTime);
|
|
||||||
cacheName(newNode);
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if(newParent == null)
|
|
||||||
return null;
|
|
||||||
if(!newNode.isDirectory() && !newNode.isSymlink()) {
|
|
||||||
// Add file->block mapping
|
|
||||||
INodeFile newF = (INodeFile)newNode;
|
|
||||||
BlockInfo[] blocks = newF.getBlocks();
|
|
||||||
for (int i = 0; i < blocks.length; i++) {
|
|
||||||
newF.setBlock(i, getBlockManager().addBlockCollection(blocks[i], newF));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
writeUnlock();
|
|
||||||
}
|
|
||||||
return newParent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a block to the file. Returns a reference to the added block.
|
* Add a block to the file. Returns a reference to the added block.
|
||||||
*/
|
*/
|
||||||
|
@ -825,11 +798,7 @@ public class FSDirectory implements Closeable {
|
||||||
|
|
||||||
INode[] inodes = rootDir.getExistingPathINodes(src, true);
|
INode[] inodes = rootDir.getExistingPathINodes(src, true);
|
||||||
INode inode = inodes[inodes.length - 1];
|
INode inode = inodes[inodes.length - 1];
|
||||||
if (inode == null) {
|
if (inode == null || !inode.isFile()) {
|
||||||
return null;
|
|
||||||
}
|
|
||||||
assert !inode.isSymlink();
|
|
||||||
if (inode.isDirectory()) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
INodeFile fileNode = (INodeFile)inode;
|
INodeFile fileNode = (INodeFile)inode;
|
||||||
|
@ -848,22 +817,15 @@ public class FSDirectory implements Closeable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the blocksize of a file
|
* @param path the file path
|
||||||
* @param filename the filename
|
* @return the block size of the file.
|
||||||
* @return the number of bytes
|
|
||||||
*/
|
*/
|
||||||
long getPreferredBlockSize(String filename) throws UnresolvedLinkException,
|
long getPreferredBlockSize(String path) throws UnresolvedLinkException,
|
||||||
FileNotFoundException, IOException {
|
FileNotFoundException, IOException {
|
||||||
readLock();
|
readLock();
|
||||||
try {
|
try {
|
||||||
INode inode = rootDir.getNode(filename, false);
|
return INodeFile.valueOf(rootDir.getNode(path, false), path
|
||||||
if (inode == null) {
|
).getPreferredBlockSize();
|
||||||
throw new FileNotFoundException("File does not exist: " + filename);
|
|
||||||
}
|
|
||||||
if (inode.isDirectory() || inode.isSymlink()) {
|
|
||||||
throw new IOException("Getting block size of non-file: "+ filename);
|
|
||||||
}
|
|
||||||
return ((INodeFile)inode).getPreferredBlockSize();
|
|
||||||
} finally {
|
} finally {
|
||||||
readUnlock();
|
readUnlock();
|
||||||
}
|
}
|
||||||
|
@ -877,9 +839,7 @@ public class FSDirectory implements Closeable {
|
||||||
if (inode == null) {
|
if (inode == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return inode.isDirectory() || inode.isSymlink()
|
return !inode.isFile() || ((INodeFile)inode).getBlocks() != null;
|
||||||
? true
|
|
||||||
: ((INodeFile)inode).getBlocks() != null;
|
|
||||||
} finally {
|
} finally {
|
||||||
readUnlock();
|
readUnlock();
|
||||||
}
|
}
|
||||||
|
@ -1212,14 +1172,8 @@ public class FSDirectory implements Closeable {
|
||||||
waitForReady();
|
waitForReady();
|
||||||
readLock();
|
readLock();
|
||||||
try {
|
try {
|
||||||
INode targetNode = rootDir.getNode(src, false);
|
final INode i = rootDir.getNode(src, false);
|
||||||
if (targetNode == null)
|
return i != null && i.isFile()? ((INodeFile)i).getBlocks(): null;
|
||||||
return null;
|
|
||||||
if (targetNode.isDirectory())
|
|
||||||
return null;
|
|
||||||
if (targetNode.isSymlink())
|
|
||||||
return null;
|
|
||||||
return ((INodeFile)targetNode).getBlocks();
|
|
||||||
} finally {
|
} finally {
|
||||||
readUnlock();
|
readUnlock();
|
||||||
}
|
}
|
||||||
|
@ -2023,9 +1977,7 @@ public class FSDirectory implements Closeable {
|
||||||
writeLock();
|
writeLock();
|
||||||
try {
|
try {
|
||||||
setReady(false);
|
setReady(false);
|
||||||
rootDir = new INodeDirectoryWithQuota(INodeDirectory.ROOT_NAME,
|
rootDir = createRoot(getFSNamesystem());
|
||||||
getFSNamesystem().createFsOwnerPermissions(new FsPermission((short)0755)),
|
|
||||||
Integer.MAX_VALUE, -1);
|
|
||||||
nameCache.reset();
|
nameCache.reset();
|
||||||
} finally {
|
} finally {
|
||||||
writeUnlock();
|
writeUnlock();
|
||||||
|
@ -2168,7 +2120,7 @@ public class FSDirectory implements Closeable {
|
||||||
*/
|
*/
|
||||||
void cacheName(INode inode) {
|
void cacheName(INode inode) {
|
||||||
// Name is cached only for files
|
// Name is cached only for files
|
||||||
if (inode.isDirectory() || inode.isSymlink()) {
|
if (!inode.isFile()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ByteArray name = new ByteArray(inode.getLocalNameBytes());
|
ByteArray name = new ByteArray(inode.getLocalNameBytes());
|
||||||
|
|
|
@ -43,6 +43,7 @@ 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.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.BlockManager;
|
||||||
import org.apache.hadoop.hdfs.server.common.InconsistentFSStateException;
|
import org.apache.hadoop.hdfs.server.common.InconsistentFSStateException;
|
||||||
import org.apache.hadoop.io.MD5Hash;
|
import org.apache.hadoop.io.MD5Hash;
|
||||||
import org.apache.hadoop.io.Text;
|
import org.apache.hadoop.io.Text;
|
||||||
|
@ -252,7 +253,7 @@ class FSImageFormat {
|
||||||
fsDir.rootDir.setQuota(nsQuota, dsQuota);
|
fsDir.rootDir.setQuota(nsQuota, dsQuota);
|
||||||
}
|
}
|
||||||
fsDir.rootDir.setModificationTime(root.getModificationTime());
|
fsDir.rootDir.setModificationTime(root.getModificationTime());
|
||||||
fsDir.rootDir.setPermissionStatus(root.getPermissionStatus());
|
fsDir.rootDir.clonePermissionStatus(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -308,7 +309,7 @@ class FSImageFormat {
|
||||||
|
|
||||||
// add to parent
|
// add to parent
|
||||||
newNode.setLocalName(localName);
|
newNode.setLocalName(localName);
|
||||||
namesystem.dir.addToParent(parent, newNode, false);
|
addToParent(parent, newNode);
|
||||||
}
|
}
|
||||||
return numChildren;
|
return numChildren;
|
||||||
}
|
}
|
||||||
|
@ -343,7 +344,30 @@ class FSImageFormat {
|
||||||
|
|
||||||
// add new inode
|
// add new inode
|
||||||
newNode.setLocalName(pathComponents[pathComponents.length-1]);
|
newNode.setLocalName(pathComponents[pathComponents.length-1]);
|
||||||
parentINode = fsDir.addToParent(parentINode, newNode, false);
|
addToParent(parentINode, newNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the child node to parent and, if child is a file, update block map.
|
||||||
|
* This method is only used for image loading so that synchronization,
|
||||||
|
* modification time update and space count update are not needed.
|
||||||
|
*/
|
||||||
|
void addToParent(INodeDirectory parent, INode child) {
|
||||||
|
// NOTE: This does not update space counts for parents
|
||||||
|
if (parent.addChild(child, false) == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
namesystem.dir.cacheName(child);
|
||||||
|
|
||||||
|
if (child.isFile()) {
|
||||||
|
// Add file->block mapping
|
||||||
|
final INodeFile file = (INodeFile)child;
|
||||||
|
final BlockInfo[] blocks = file.getBlocks();
|
||||||
|
final BlockManager bm = namesystem.getBlockManager();
|
||||||
|
for (int i = 0; i < blocks.length; i++) {
|
||||||
|
file.setBlock(i, bm.addBlockCollection(blocks[i], file));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,17 +86,17 @@ abstract class INode implements Comparable<byte[]> {
|
||||||
return (record & ~MASK) | (bits << OFFSET);
|
return (record & ~MASK) | (bits << OFFSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set the {@link PermissionStatus} */
|
/** Encode the {@link PermissionStatus} to a long. */
|
||||||
static long toLong(PermissionStatus ps) {
|
static long toLong(PermissionStatus ps) {
|
||||||
long permission = 0L;
|
long permission = 0L;
|
||||||
final int user = SerialNumberManager.INSTANCE.getUserSerialNumber(
|
final int user = SerialNumberManager.INSTANCE.getUserSerialNumber(
|
||||||
ps.getUserName());
|
ps.getUserName());
|
||||||
permission = PermissionStatusFormat.USER.combine(user, permission);
|
permission = USER.combine(user, permission);
|
||||||
final int group = SerialNumberManager.INSTANCE.getGroupSerialNumber(
|
final int group = SerialNumberManager.INSTANCE.getGroupSerialNumber(
|
||||||
ps.getGroupName());
|
ps.getGroupName());
|
||||||
permission = PermissionStatusFormat.GROUP.combine(group, permission);
|
permission = GROUP.combine(group, permission);
|
||||||
final int mode = ps.getPermission().toShort();
|
final int mode = ps.getPermission().toShort();
|
||||||
permission = PermissionStatusFormat.MODE.combine(mode, permission);
|
permission = MODE.combine(mode, permission);
|
||||||
return permission;
|
return permission;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,8 +110,9 @@ abstract class INode implements Comparable<byte[]> {
|
||||||
*/
|
*/
|
||||||
private byte[] name = null;
|
private byte[] name = null;
|
||||||
/**
|
/**
|
||||||
* Permission encoded using PermissionStatusFormat.
|
* Permission encoded using {@link PermissionStatusFormat}.
|
||||||
* Codes other than {@link #updatePermissionStatus(PermissionStatusFormat, long)}.
|
* Codes other than {@link #clonePermissionStatus(INode)}
|
||||||
|
* and {@link #updatePermissionStatus(PermissionStatusFormat, long)}
|
||||||
* should not modify it.
|
* should not modify it.
|
||||||
*/
|
*/
|
||||||
private long permission = 0L;
|
private long permission = 0L;
|
||||||
|
@ -155,11 +156,9 @@ abstract class INode implements Comparable<byte[]> {
|
||||||
return name.length == 0;
|
return name.length == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set the {@link PermissionStatus} */
|
/** Clone the {@link PermissionStatus}. */
|
||||||
protected void setPermissionStatus(PermissionStatus ps) {
|
void clonePermissionStatus(INode that) {
|
||||||
setUser(ps.getUserName());
|
this.permission = that.permission;
|
||||||
setGroup(ps.getGroupName());
|
|
||||||
setPermission(ps.getPermission());
|
|
||||||
}
|
}
|
||||||
/** Get the {@link PermissionStatus} */
|
/** Get the {@link PermissionStatus} */
|
||||||
protected PermissionStatus getPermissionStatus() {
|
protected PermissionStatus getPermissionStatus() {
|
||||||
|
@ -201,6 +200,13 @@ abstract class INode implements Comparable<byte[]> {
|
||||||
updatePermissionStatus(PermissionStatusFormat.MODE, permission.toShort());
|
updatePermissionStatus(PermissionStatusFormat.MODE, permission.toShort());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether it's a file.
|
||||||
|
*/
|
||||||
|
public boolean isFile() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether it's a directory
|
* Check whether it's a directory
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -317,23 +317,6 @@ class INodeDirectory extends INode {
|
||||||
return addToParent(pathComponents, newNode, true) == null? null: newNode;
|
return addToParent(pathComponents, newNode, true) == null? null: newNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add new inode to the parent if specified.
|
|
||||||
* Optimized version of addNode() if parent is not null.
|
|
||||||
*
|
|
||||||
* @return parent INode if new inode is inserted
|
|
||||||
* or null if it already exists.
|
|
||||||
* @throws FileNotFoundException if parent does not exist or
|
|
||||||
* is not a directory.
|
|
||||||
*/
|
|
||||||
INodeDirectory addToParent(INode newNode, INodeDirectory parent,
|
|
||||||
boolean propagateModTime) throws FileNotFoundException {
|
|
||||||
// insert into the parent children list
|
|
||||||
if(parent.addChild(newNode, propagateModTime) == null)
|
|
||||||
return null;
|
|
||||||
return parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
INodeDirectory getParent(byte[][] pathComponents
|
INodeDirectory getParent(byte[][] pathComponents
|
||||||
) throws FileNotFoundException, UnresolvedLinkException {
|
) throws FileNotFoundException, UnresolvedLinkException {
|
||||||
if (pathComponents.length < 2) // add root
|
if (pathComponents.length < 2) // add root
|
||||||
|
|
|
@ -19,6 +19,7 @@ package org.apache.hadoop.hdfs.server.namenode;
|
||||||
|
|
||||||
import org.apache.hadoop.fs.permission.PermissionStatus;
|
import org.apache.hadoop.fs.permission.PermissionStatus;
|
||||||
import org.apache.hadoop.hdfs.protocol.DSQuotaExceededException;
|
import org.apache.hadoop.hdfs.protocol.DSQuotaExceededException;
|
||||||
|
import org.apache.hadoop.hdfs.protocol.HdfsConstants;
|
||||||
import org.apache.hadoop.hdfs.protocol.NSQuotaExceededException;
|
import org.apache.hadoop.hdfs.protocol.NSQuotaExceededException;
|
||||||
import org.apache.hadoop.hdfs.protocol.QuotaExceededException;
|
import org.apache.hadoop.hdfs.protocol.QuotaExceededException;
|
||||||
|
|
||||||
|
@ -26,9 +27,13 @@ import org.apache.hadoop.hdfs.protocol.QuotaExceededException;
|
||||||
* Directory INode class that has a quota restriction
|
* Directory INode class that has a quota restriction
|
||||||
*/
|
*/
|
||||||
class INodeDirectoryWithQuota extends INodeDirectory {
|
class INodeDirectoryWithQuota extends INodeDirectory {
|
||||||
private long nsQuota; /// NameSpace quota
|
/** Name space quota */
|
||||||
|
private long nsQuota = Long.MAX_VALUE;
|
||||||
|
/** Name space count */
|
||||||
private long nsCount = 1L;
|
private long nsCount = 1L;
|
||||||
private long dsQuota; /// disk space quota
|
/** Disk space quota */
|
||||||
|
private long dsQuota = HdfsConstants.QUOTA_RESET;
|
||||||
|
/** Disk space count */
|
||||||
private long diskspace = 0L;
|
private long diskspace = 0L;
|
||||||
|
|
||||||
/** Convert an existing directory inode to one with the given quota
|
/** Convert an existing directory inode to one with the given quota
|
||||||
|
@ -57,11 +62,8 @@ class INodeDirectoryWithQuota extends INodeDirectory {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** constructor with no quota verification */
|
/** constructor with no quota verification */
|
||||||
INodeDirectoryWithQuota(String name, PermissionStatus permissions,
|
INodeDirectoryWithQuota(String name, PermissionStatus permissions) {
|
||||||
long nsQuota, long dsQuota) {
|
|
||||||
super(name, permissions);
|
super(name, permissions);
|
||||||
this.nsQuota = nsQuota;
|
|
||||||
this.dsQuota = dsQuota;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get this directory's namespace quota
|
/** Get this directory's namespace quota
|
||||||
|
|
|
@ -94,6 +94,12 @@ class INodeFile extends INode implements BlockCollection {
|
||||||
this.blocks = blklist;
|
this.blocks = blklist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return true unconditionally. */
|
||||||
|
@Override
|
||||||
|
public final boolean isFile() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the {@link FsPermission} of this {@link INodeFile}.
|
* Set the {@link FsPermission} of this {@link INodeFile}.
|
||||||
* Since this is a file,
|
* Since this is a file,
|
||||||
|
|
|
@ -73,7 +73,7 @@ public class TestFsLimits {
|
||||||
fileAsURI(new File(MiniDFSCluster.getBaseDirectory(),
|
fileAsURI(new File(MiniDFSCluster.getBaseDirectory(),
|
||||||
"namenode")).toString());
|
"namenode")).toString());
|
||||||
|
|
||||||
rootInode = new INodeDirectoryWithQuota(INodeDirectory.ROOT_NAME, perms, 0L, 0L);
|
rootInode = new INodeDirectoryWithQuota(INodeDirectory.ROOT_NAME, perms);
|
||||||
inodes = new INode[]{ rootInode, null };
|
inodes = new INode[]{ rootInode, null };
|
||||||
fs = null;
|
fs = null;
|
||||||
fsIsReady = true;
|
fsIsReady = true;
|
||||||
|
|
Loading…
Reference in New Issue