HDFS-5647. Merge INodeDirectory.Feature and INodeFile.Feature. Contributed by Haohui Mai.
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1550469 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
329093ae1b
commit
5fd7230671
|
@ -246,6 +246,9 @@ Trunk (Unreleased)
|
||||||
HDFS-5629. Support HTTPS in JournalNode and SecondaryNameNode.
|
HDFS-5629. Support HTTPS in JournalNode and SecondaryNameNode.
|
||||||
(Haohui Mai via jing9)
|
(Haohui Mai via jing9)
|
||||||
|
|
||||||
|
HDFS-5647. Merge INodeDirectory.Feature and INodeFile.Feature. (Haohui Mai
|
||||||
|
via jing9)
|
||||||
|
|
||||||
OPTIMIZATIONS
|
OPTIMIZATIONS
|
||||||
HDFS-5349. DNA_CACHE and DNA_UNCACHE should be by blockId only. (cmccabe)
|
HDFS-5349. DNA_CACHE and DNA_UNCACHE should be by blockId only. (cmccabe)
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,23 +41,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
|
||||||
|
@ -120,8 +103,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) {
|
||||||
|
@ -135,7 +116,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) {
|
||||||
|
@ -144,14 +125,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() {
|
||||||
|
@ -171,7 +144,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;
|
||||||
}
|
}
|
||||||
|
@ -283,7 +256,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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
@ -921,6 +922,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();
|
||||||
|
@ -933,7 +935,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());
|
||||||
|
|
||||||
|
@ -943,6 +945,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();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue