HDFS-5647. Merge change r1548796 from trunk.

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/branch-2@1568207 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Jing Zhao 2014-02-14 07:38:34 +00:00
parent 99a661e449
commit 7fb827fb1d
9 changed files with 60 additions and 103 deletions

View File

@ -51,6 +51,9 @@ Release 2.4.0 - UNRELEASED
HDFS-5554. Flatten INodeFile hierarchy: Replace INodeFileWithSnapshot with HDFS-5554. Flatten INodeFile hierarchy: Replace INodeFileWithSnapshot with
FileWithSnapshotFeature. (jing9 via szetszwo) FileWithSnapshotFeature. (jing9 via szetszwo)
HDFS-5647. Merge INodeDirectory.Feature and INodeFile.Feature. (Haohui Mai
via jing9)
OPTIMIZATIONS OPTIMIZATIONS
HDFS-5790. LeaseManager.findPath is very slow when many leases need recovery HDFS-5790. LeaseManager.findPath is very slow when many leases need recovery

View File

@ -25,7 +25,7 @@ import org.apache.hadoop.hdfs.protocol.QuotaExceededException;
/** /**
* Quota feature for {@link INodeDirectory}. * Quota feature for {@link INodeDirectory}.
*/ */
public final class DirectoryWithQuotaFeature extends INodeDirectory.Feature { public final class DirectoryWithQuotaFeature implements INode.Feature {
public static final long DEFAULT_NAMESPACE_QUOTA = Long.MAX_VALUE; public static final long DEFAULT_NAMESPACE_QUOTA = Long.MAX_VALUE;
public static final long DEFAULT_DISKSPACE_QUOTA = HdfsConstants.QUOTA_RESET; public static final long DEFAULT_DISKSPACE_QUOTA = HdfsConstants.QUOTA_RESET;

View File

@ -29,7 +29,7 @@ import org.apache.hadoop.hdfs.server.namenode.INode.BlocksMapUpdateInfo;
* Feature for under-construction file. * Feature for under-construction file.
*/ */
@InterfaceAudience.Private @InterfaceAudience.Private
public class FileUnderConstructionFeature extends INodeFile.Feature { public class FileUnderConstructionFeature implements INode.Feature {
private String clientName; // lease holder private String clientName; // lease holder
private final String clientMachine; private final String clientMachine;
// if client is a cluster node too. // if client is a cluster node too.

View File

@ -756,47 +756,6 @@ public abstract class INode implements INodeAttributes, Diff.Element<byte[]> {
/** INode feature such as {@link FileUnderConstructionFeature} /** INode feature such as {@link FileUnderConstructionFeature}
* and {@link DirectoryWithQuotaFeature}. * and {@link DirectoryWithQuotaFeature}.
*/ */
interface Feature<F extends Feature<F>> { public interface Feature {
/** @return the next feature. */
public F getNextFeature();
/** Set the next feature. */
public void setNextFeature(F next);
/** Utility methods such as addFeature and removeFeature. */
static class Util {
/**
* Add a feature to the linked list.
* @return the new head.
*/
static <F extends Feature<F>> F addFeature(F feature, F head) {
feature.setNextFeature(head);
return feature;
}
/**
* Remove a feature from the linked list.
* @return the new head.
*/
static <F extends Feature<F>> F removeFeature(F feature, F head) {
if (feature == head) {
final F newHead = head.getNextFeature();
head.setNextFeature(null);
return newHead;
} else if (head != null) {
F prev = head;
F curr = head.getNextFeature();
for (; curr != null && curr != feature;
prev = curr, curr = curr.getNextFeature())
;
if (curr != null) {
prev.setNextFeature(curr.getNextFeature());
curr.setNextFeature(null);
return head;
}
}
throw new IllegalStateException("Feature " + feature + " not found.");
}
}
} }
} }

View File

@ -45,20 +45,6 @@ import com.google.common.base.Preconditions;
*/ */
public class INodeDirectory extends INodeWithAdditionalFields public class INodeDirectory extends INodeWithAdditionalFields
implements INodeDirectoryAttributes { implements INodeDirectoryAttributes {
/** Directory related features such as quota and snapshots. */
public static abstract class Feature implements INode.Feature<Feature> {
private Feature nextFeature;
@Override
public Feature getNextFeature() {
return nextFeature;
}
@Override
public void setNextFeature(Feature next) {
this.nextFeature = next;
}
}
/** Cast INode to INodeDirectory. */ /** Cast INode to INodeDirectory. */
public static INodeDirectory valueOf(INode inode, Object path public static INodeDirectory valueOf(INode inode, Object path
@ -78,9 +64,6 @@ public class INodeDirectory extends INodeWithAdditionalFields
private List<INode> children = null; private List<INode> children = null;
/** A linked list of {@link Feature}s. */
private Feature headFeature = null;
/** constructor */ /** constructor */
public INodeDirectory(long id, byte[] name, PermissionStatus permissions, public INodeDirectory(long id, byte[] name, PermissionStatus permissions,
long mtime) { long mtime) {
@ -102,7 +85,7 @@ public class INodeDirectory extends INodeWithAdditionalFields
} }
} }
if (copyFeatures) { if (copyFeatures) {
this.headFeature = other.headFeature; this.features = other.features;
} }
} }
@ -160,7 +143,7 @@ public class INodeDirectory extends INodeWithAdditionalFields
* otherwise, return null. * otherwise, return null.
*/ */
public final DirectoryWithQuotaFeature getDirectoryWithQuotaFeature() { public final DirectoryWithQuotaFeature getDirectoryWithQuotaFeature() {
for(Feature f = headFeature; f != null; f = f.nextFeature) { for (Feature f : features) {
if (f instanceof DirectoryWithQuotaFeature) { if (f instanceof DirectoryWithQuotaFeature) {
return (DirectoryWithQuotaFeature)f; return (DirectoryWithQuotaFeature)f;
} }
@ -182,14 +165,6 @@ public class INodeDirectory extends INodeWithAdditionalFields
return quota; return quota;
} }
private void addFeature(Feature f) {
headFeature = INode.Feature.Util.addFeature(f, headFeature);
}
private void removeFeature(Feature f) {
headFeature = INode.Feature.Util.removeFeature(f, headFeature);
}
private int searchChildren(byte[] name) { private int searchChildren(byte[] name) {
return children == null? -1: Collections.binarySearch(children, name); return children == null? -1: Collections.binarySearch(children, name);
} }

View File

@ -45,23 +45,6 @@ import com.google.common.base.Preconditions;
@InterfaceAudience.Private @InterfaceAudience.Private
public class INodeFile extends INodeWithAdditionalFields public class INodeFile extends INodeWithAdditionalFields
implements INodeFileAttributes, BlockCollection { implements INodeFileAttributes, BlockCollection {
/**
* A feature contains specific information for a type of INodeFile. E.g.,
* we can have separate features for Under-Construction and Snapshot.
*/
public static abstract class Feature implements INode.Feature<Feature> {
private Feature nextFeature;
@Override
public Feature getNextFeature() {
return nextFeature;
}
@Override
public void setNextFeature(Feature next) {
this.nextFeature = next;
}
}
/** The same as valueOf(inode, path, false). */ /** The same as valueOf(inode, path, false). */
public static INodeFile valueOf(INode inode, String path public static INodeFile valueOf(INode inode, String path
@ -124,8 +107,6 @@ public class INodeFile extends INodeWithAdditionalFields
private BlockInfo[] blocks; private BlockInfo[] blocks;
private Feature headFeature;
INodeFile(long id, byte[] name, PermissionStatus permissions, long mtime, INodeFile(long id, byte[] name, PermissionStatus permissions, long mtime,
long atime, BlockInfo[] blklist, short replication, long atime, BlockInfo[] blklist, short replication,
long preferredBlockSize) { long preferredBlockSize) {
@ -139,7 +120,7 @@ public class INodeFile extends INodeWithAdditionalFields
super(that); super(that);
this.header = that.header; this.header = that.header;
this.blocks = that.blocks; this.blocks = that.blocks;
this.headFeature = that.headFeature; this.features = that.features;
} }
public INodeFile(INodeFile that, FileDiffList diffs) { public INodeFile(INodeFile that, FileDiffList diffs) {
@ -148,14 +129,6 @@ public class INodeFile extends INodeWithAdditionalFields
this.addSnapshotFeature(diffs); this.addSnapshotFeature(diffs);
} }
private void addFeature(Feature f) {
headFeature = INode.Feature.Util.addFeature(f, headFeature);
}
private void removeFeature(Feature f) {
headFeature = INode.Feature.Util.removeFeature(f, headFeature);
}
/** @return true unconditionally. */ /** @return true unconditionally. */
@Override @Override
public final boolean isFile() { public final boolean isFile() {
@ -175,7 +148,7 @@ public class INodeFile extends INodeWithAdditionalFields
* otherwise, return null. * otherwise, return null.
*/ */
public final FileUnderConstructionFeature getFileUnderConstructionFeature() { public final FileUnderConstructionFeature getFileUnderConstructionFeature() {
for (Feature f = this.headFeature; f != null; f = f.nextFeature) { for (Feature f : features) {
if (f instanceof FileUnderConstructionFeature) { if (f instanceof FileUnderConstructionFeature) {
return (FileUnderConstructionFeature) f; return (FileUnderConstructionFeature) f;
} }
@ -287,7 +260,7 @@ public class INodeFile extends INodeWithAdditionalFields
* otherwise, return null. * otherwise, return null.
*/ */
public final FileWithSnapshotFeature getFileWithSnapshotFeature() { public final FileWithSnapshotFeature getFileWithSnapshotFeature() {
for (Feature f = headFeature; f != null; f = f.nextFeature) { for (Feature f: features) {
if (f instanceof FileWithSnapshotFeature) { if (f instanceof FileWithSnapshotFeature) {
return (FileWithSnapshotFeature) f; return (FileWithSnapshotFeature) f;
} }

View File

@ -95,6 +95,9 @@ public abstract class INodeWithAdditionalFields extends INode
/** For implementing {@link LinkedElement}. */ /** For implementing {@link LinkedElement}. */
private LinkedElement next = null; private LinkedElement next = null;
/** An array {@link Feature}s. */
private static final Feature[] EMPTY_FEATURE = new Feature[0];
protected Feature[] features = EMPTY_FEATURE;
private INodeWithAdditionalFields(INode parent, long id, byte[] name, private INodeWithAdditionalFields(INode parent, long id, byte[] name,
long permission, long modificationTime, long accessTime) { long permission, long modificationTime, long accessTime) {
@ -262,4 +265,45 @@ public abstract class INodeWithAdditionalFields extends INode
public final void setAccessTime(long accessTime) { public final void setAccessTime(long accessTime) {
this.accessTime = accessTime; this.accessTime = accessTime;
} }
protected void addFeature(Feature f) {
int size = features.length;
Feature[] arr = new Feature[size + 1];
if (size != 0) {
System.arraycopy(features, 0, arr, 0, size);
}
arr[size] = f;
features = arr;
}
protected void removeFeature(Feature f) {
int size = features.length;
Preconditions.checkState(size > 0, "Feature "
+ f.getClass().getSimpleName() + " not found.");
if (size == 1) {
Preconditions.checkState(features[0] == f, "Feature "
+ f.getClass().getSimpleName() + " not found.");
features = EMPTY_FEATURE;
return;
}
Feature[] arr = new Feature[size - 1];
int j = 0;
boolean overflow = false;
for (Feature f1 : features) {
if (f1 != f) {
if (j == size - 1) {
overflow = true;
break;
} else {
arr[j++] = f1;
}
}
}
Preconditions.checkState(!overflow && j == size - 1, "Feature "
+ f.getClass().getSimpleName() + " not found.");
features = arr;
}
} }

View File

@ -32,7 +32,7 @@ import org.apache.hadoop.hdfs.server.namenode.Quota;
* Feature for file with snapshot-related information. * Feature for file with snapshot-related information.
*/ */
@InterfaceAudience.Private @InterfaceAudience.Private
public class FileWithSnapshotFeature extends INodeFile.Feature { public class FileWithSnapshotFeature implements INode.Feature {
private final FileDiffList diffs; private final FileDiffList diffs;
private boolean isCurrentFileDeleted = false; private boolean isCurrentFileDeleted = false;

View File

@ -61,6 +61,7 @@ import org.apache.hadoop.hdfs.protocol.LocatedBlocks;
import org.apache.hadoop.hdfs.protocol.QuotaExceededException; import org.apache.hadoop.hdfs.protocol.QuotaExceededException;
import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfo; import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfo;
import org.apache.hadoop.hdfs.server.protocol.NamenodeProtocols; import org.apache.hadoop.hdfs.server.protocol.NamenodeProtocols;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.util.Time; import org.apache.hadoop.util.Time;
import org.junit.Test; import org.junit.Test;
import org.mockito.Mockito; import org.mockito.Mockito;
@ -885,6 +886,7 @@ public class TestINodeFile {
public void testDotdotInodePath() throws Exception { public void testDotdotInodePath() throws Exception {
final Configuration conf = new Configuration(); final Configuration conf = new Configuration();
MiniDFSCluster cluster = null; MiniDFSCluster cluster = null;
DFSClient client = null;
try { try {
cluster = new MiniDFSCluster.Builder(conf).numDataNodes(1).build(); cluster = new MiniDFSCluster.Builder(conf).numDataNodes(1).build();
cluster.waitActive(); cluster.waitActive();
@ -897,7 +899,7 @@ public class TestINodeFile {
long parentId = fsdir.getINode("/").getId(); long parentId = fsdir.getINode("/").getId();
String testPath = "/.reserved/.inodes/" + dirId + "/.."; String testPath = "/.reserved/.inodes/" + dirId + "/..";
DFSClient client = new DFSClient(NameNode.getAddress(conf), conf); client = new DFSClient(NameNode.getAddress(conf), conf);
HdfsFileStatus status = client.getFileInfo(testPath); HdfsFileStatus status = client.getFileInfo(testPath);
assertTrue(parentId == status.getFileId()); assertTrue(parentId == status.getFileId());
@ -907,6 +909,7 @@ public class TestINodeFile {
assertTrue(parentId == status.getFileId()); assertTrue(parentId == status.getFileId());
} finally { } finally {
IOUtils.cleanup(LOG, client);
if (cluster != null) { if (cluster != null) {
cluster.shutdown(); cluster.shutdown();
} }