HDFS-4545. With snapshots, FSDirectory.unprotectedSetReplication(..) always changes file replication but it may or may not changes block replication.
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/HDFS-2802@1452636 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
c7cf85ccb4
commit
b1333e5b56
@ -181,3 +181,7 @@ Branch-2802 Snapshot (Unreleased)
|
|||||||
merge. (szetszwo)
|
merge. (szetszwo)
|
||||||
|
|
||||||
HDFS-4507. Update quota verification for snapshots. (szetszwo)
|
HDFS-4507. Update quota verification for snapshots. (szetszwo)
|
||||||
|
|
||||||
|
HDFS-4545. With snapshots, FSDirectory.unprotectedSetReplication(..) always
|
||||||
|
changes file replication but it may or may not changes block replication.
|
||||||
|
(szetszwo)
|
||||||
|
@ -289,7 +289,7 @@ INodeFileUnderConstruction addFile(String path,
|
|||||||
return newNode;
|
return newNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
INode unprotectedAddFile( long id,
|
INodeFile unprotectedAddFile( long id,
|
||||||
String path,
|
String path,
|
||||||
PermissionStatus permissions,
|
PermissionStatus permissions,
|
||||||
short replication,
|
short replication,
|
||||||
@ -299,7 +299,7 @@ INode unprotectedAddFile( long id,
|
|||||||
boolean underConstruction,
|
boolean underConstruction,
|
||||||
String clientName,
|
String clientName,
|
||||||
String clientMachine) {
|
String clientMachine) {
|
||||||
final INode newNode;
|
final INodeFile newNode;
|
||||||
assert hasWriteLock();
|
assert hasWriteLock();
|
||||||
if (underConstruction) {
|
if (underConstruction) {
|
||||||
newNode = new INodeFileUnderConstruction(id, permissions, replication,
|
newNode = new INodeFileUnderConstruction(id, permissions, replication,
|
||||||
@ -496,9 +496,8 @@ boolean unprotectedRenameTo(String src, String dst, long timestamp)
|
|||||||
throws QuotaExceededException, UnresolvedLinkException,
|
throws QuotaExceededException, UnresolvedLinkException,
|
||||||
FileAlreadyExistsException, SnapshotAccessControlException {
|
FileAlreadyExistsException, SnapshotAccessControlException {
|
||||||
assert hasWriteLock();
|
assert hasWriteLock();
|
||||||
INodesInPath srcInodesInPath = rootDir.getINodesInPath4Write(src, false);
|
INodesInPath srcIIP = rootDir.getINodesInPath4Write(src, false);
|
||||||
INode[] srcInodes = srcInodesInPath.getINodes();
|
final INode srcInode = srcIIP.getLastINode();
|
||||||
INode srcInode = srcInodes[srcInodes.length-1];
|
|
||||||
|
|
||||||
// check the validation of the source
|
// check the validation of the source
|
||||||
if (srcInode == null) {
|
if (srcInode == null) {
|
||||||
@ -507,7 +506,7 @@ boolean unprotectedRenameTo(String src, String dst, long timestamp)
|
|||||||
+ " because source does not exist");
|
+ " because source does not exist");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (srcInodes.length == 1) {
|
if (srcIIP.getINodes().length == 1) {
|
||||||
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
|
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
|
||||||
+"failed to rename "+src+" to "+dst+ " because source is the root");
|
+"failed to rename "+src+" to "+dst+ " because source is the root");
|
||||||
return false;
|
return false;
|
||||||
@ -521,7 +520,7 @@ boolean unprotectedRenameTo(String src, String dst, long timestamp)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (srcInode.isSymlink() &&
|
if (srcInode.isSymlink() &&
|
||||||
dst.equals(((INodeSymlink)srcInode).getSymlinkString())) {
|
dst.equals(srcInode.asSymlink().getSymlinkString())) {
|
||||||
throw new FileAlreadyExistsException(
|
throw new FileAlreadyExistsException(
|
||||||
"Cannot rename symlink "+src+" to its target "+dst);
|
"Cannot rename symlink "+src+" to its target "+dst);
|
||||||
}
|
}
|
||||||
@ -536,20 +535,19 @@ boolean unprotectedRenameTo(String src, String dst, long timestamp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
byte[][] dstComponents = INode.getPathComponents(dst);
|
byte[][] dstComponents = INode.getPathComponents(dst);
|
||||||
INodesInPath dstInodesInPath = rootDir.getExistingPathINodes(dstComponents,
|
final INodesInPath dstIIP = getExistingPathINodes(dstComponents);
|
||||||
dstComponents.length, false);
|
if (dstIIP.isSnapshot()) {
|
||||||
if (dstInodesInPath.isSnapshot()) {
|
|
||||||
throw new SnapshotAccessControlException(
|
throw new SnapshotAccessControlException(
|
||||||
"Modification on RO snapshot is disallowed");
|
"Modification on RO snapshot is disallowed");
|
||||||
}
|
}
|
||||||
INode[] dstInodes = dstInodesInPath.getINodes();
|
if (dstIIP.getLastINode() != null) {
|
||||||
if (dstInodes[dstInodes.length-1] != null) {
|
|
||||||
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
|
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
|
||||||
+"failed to rename "+src+" to "+dst+
|
+"failed to rename "+src+" to "+dst+
|
||||||
" because destination exists");
|
" because destination exists");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (dstInodes[dstInodes.length-2] == null) {
|
final INode dstParent = dstIIP.getINode(-2);
|
||||||
|
if (dstParent == null) {
|
||||||
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
|
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
|
||||||
+"failed to rename "+src+" to "+dst+
|
+"failed to rename "+src+" to "+dst+
|
||||||
" because destination's parent does not exist");
|
" because destination's parent does not exist");
|
||||||
@ -557,14 +555,14 @@ boolean unprotectedRenameTo(String src, String dst, long timestamp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure dst has quota to accommodate rename
|
// Ensure dst has quota to accommodate rename
|
||||||
verifyQuotaForRename(srcInodes, dstInodes);
|
verifyQuotaForRename(srcIIP.getINodes(), dstIIP.getINodes());
|
||||||
|
|
||||||
boolean added = false;
|
boolean added = false;
|
||||||
INode srcChild = null;
|
INode srcChild = null;
|
||||||
byte[] srcChildName = null;
|
byte[] srcChildName = null;
|
||||||
try {
|
try {
|
||||||
// remove src
|
// remove src
|
||||||
srcChild = removeLastINode(srcInodesInPath);
|
srcChild = removeLastINode(srcIIP);
|
||||||
if (srcChild == null) {
|
if (srcChild == null) {
|
||||||
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
|
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
|
||||||
+ "failed to rename " + src + " to " + dst
|
+ "failed to rename " + src + " to " + dst
|
||||||
@ -572,10 +570,10 @@ boolean unprotectedRenameTo(String src, String dst, long timestamp)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
srcChildName = srcChild.getLocalNameBytes();
|
srcChildName = srcChild.getLocalNameBytes();
|
||||||
srcChild.setLocalName(dstComponents[dstInodes.length-1]);
|
srcChild.setLocalName(dstComponents[dstComponents.length - 1]);
|
||||||
|
|
||||||
// add src to the destination
|
// add src to the destination
|
||||||
added = addLastINodeNoQuotaCheck(dstInodesInPath, srcChild);
|
added = addLastINodeNoQuotaCheck(dstIIP, srcChild);
|
||||||
if (added) {
|
if (added) {
|
||||||
srcChild = null;
|
srcChild = null;
|
||||||
if (NameNode.stateChangeLog.isDebugEnabled()) {
|
if (NameNode.stateChangeLog.isDebugEnabled()) {
|
||||||
@ -583,10 +581,9 @@ boolean unprotectedRenameTo(String src, String dst, long timestamp)
|
|||||||
+ src + " is renamed to " + dst);
|
+ src + " is renamed to " + dst);
|
||||||
}
|
}
|
||||||
// update modification time of dst and the parent of src
|
// update modification time of dst and the parent of src
|
||||||
srcInodes[srcInodes.length-2].updateModificationTime(timestamp,
|
final INode srcParent = srcIIP.getINode(-2);
|
||||||
srcInodesInPath.getLatestSnapshot());
|
srcParent.updateModificationTime(timestamp, srcIIP.getLatestSnapshot());
|
||||||
dstInodes[dstInodes.length-2].updateModificationTime(timestamp,
|
dstParent.updateModificationTime(timestamp, dstIIP.getLatestSnapshot());
|
||||||
dstInodesInPath.getLatestSnapshot());
|
|
||||||
// update moved leases with new filename
|
// update moved leases with new filename
|
||||||
getFSNamesystem().unprotectedChangeLease(src, dst);
|
getFSNamesystem().unprotectedChangeLease(src, dst);
|
||||||
return true;
|
return true;
|
||||||
@ -595,7 +592,7 @@ boolean unprotectedRenameTo(String src, String dst, long timestamp)
|
|||||||
if (!added && srcChild != null) {
|
if (!added && srcChild != null) {
|
||||||
// put it back
|
// put it back
|
||||||
srcChild.setLocalName(srcChildName);
|
srcChild.setLocalName(srcChildName);
|
||||||
addLastINodeNoQuotaCheck(srcInodesInPath, srcChild);
|
addLastINodeNoQuotaCheck(srcIIP, srcChild);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
|
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
|
||||||
@ -627,10 +624,8 @@ boolean unprotectedRenameTo(String src, String dst, long timestamp,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
String error = null;
|
String error = null;
|
||||||
final INodesInPath srcInodesInPath = rootDir.getINodesInPath4Write(src,
|
final INodesInPath srcIIP = rootDir.getINodesInPath4Write(src, false);
|
||||||
false);
|
final INode srcInode = srcIIP.getLastINode();
|
||||||
final INode[] srcInodes = srcInodesInPath.getINodes();
|
|
||||||
final INode srcInode = srcInodes[srcInodes.length - 1];
|
|
||||||
// validate source
|
// validate source
|
||||||
if (srcInode == null) {
|
if (srcInode == null) {
|
||||||
error = "rename source " + src + " is not found.";
|
error = "rename source " + src + " is not found.";
|
||||||
@ -638,7 +633,7 @@ boolean unprotectedRenameTo(String src, String dst, long timestamp,
|
|||||||
+ error);
|
+ error);
|
||||||
throw new FileNotFoundException(error);
|
throw new FileNotFoundException(error);
|
||||||
}
|
}
|
||||||
if (srcInodes.length == 1) {
|
if (srcIIP.getINodes().length == 1) {
|
||||||
error = "rename source cannot be the root";
|
error = "rename source cannot be the root";
|
||||||
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
|
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
|
||||||
+ error);
|
+ error);
|
||||||
@ -651,7 +646,7 @@ boolean unprotectedRenameTo(String src, String dst, long timestamp,
|
|||||||
"The source "+src+" and destination "+dst+" are the same");
|
"The source "+src+" and destination "+dst+" are the same");
|
||||||
}
|
}
|
||||||
if (srcInode.isSymlink() &&
|
if (srcInode.isSymlink() &&
|
||||||
dst.equals(((INodeSymlink)srcInode).getSymlinkString())) {
|
dst.equals(srcInode.asSymlink().getSymlinkString())) {
|
||||||
throw new FileAlreadyExistsException(
|
throw new FileAlreadyExistsException(
|
||||||
"Cannot rename symlink "+src+" to its target "+dst);
|
"Cannot rename symlink "+src+" to its target "+dst);
|
||||||
}
|
}
|
||||||
@ -664,11 +659,8 @@ boolean unprotectedRenameTo(String src, String dst, long timestamp,
|
|||||||
+ error);
|
+ error);
|
||||||
throw new IOException(error);
|
throw new IOException(error);
|
||||||
}
|
}
|
||||||
final INodesInPath dstInodesInPath = rootDir.getINodesInPath4Write(
|
final INodesInPath dstIIP = rootDir.getINodesInPath4Write(dst, false);
|
||||||
dst, false);
|
if (dstIIP.getINodes().length == 1) {
|
||||||
final INode[] dstInodes = dstInodesInPath.getINodes();
|
|
||||||
INode dstInode = dstInodes[dstInodes.length - 1];
|
|
||||||
if (dstInodes.length == 1) {
|
|
||||||
error = "rename destination cannot be the root";
|
error = "rename destination cannot be the root";
|
||||||
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
|
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
|
||||||
+ error);
|
+ error);
|
||||||
@ -676,6 +668,8 @@ boolean unprotectedRenameTo(String src, String dst, long timestamp,
|
|||||||
}
|
}
|
||||||
List<INodeDirectorySnapshottable> snapshottableDirs =
|
List<INodeDirectorySnapshottable> snapshottableDirs =
|
||||||
new ArrayList<INodeDirectorySnapshottable>();
|
new ArrayList<INodeDirectorySnapshottable>();
|
||||||
|
|
||||||
|
final INode dstInode = dstIIP.getLastINode();
|
||||||
if (dstInode != null) { // Destination exists
|
if (dstInode != null) { // Destination exists
|
||||||
// It's OK to rename a file to a symlink and vice versa
|
// It's OK to rename a file to a symlink and vice versa
|
||||||
if (dstInode.isDirectory() != srcInode.isDirectory()) {
|
if (dstInode.isDirectory() != srcInode.isDirectory()) {
|
||||||
@ -692,8 +686,8 @@ boolean unprotectedRenameTo(String src, String dst, long timestamp,
|
|||||||
throw new FileAlreadyExistsException(error);
|
throw new FileAlreadyExistsException(error);
|
||||||
}
|
}
|
||||||
if (dstInode.isDirectory()) {
|
if (dstInode.isDirectory()) {
|
||||||
final ReadOnlyList<INode> children = ((INodeDirectory) dstInode
|
final ReadOnlyList<INode> children = dstInode.asDirectory()
|
||||||
).getChildrenList(dstInodesInPath.getPathSnapshot());
|
.getChildrenList(null);
|
||||||
if (!children.isEmpty()) {
|
if (!children.isEmpty()) {
|
||||||
error = "rename destination directory is not empty: " + dst;
|
error = "rename destination directory is not empty: " + dst;
|
||||||
NameNode.stateChangeLog.warn(
|
NameNode.stateChangeLog.warn(
|
||||||
@ -712,13 +706,15 @@ boolean unprotectedRenameTo(String src, String dst, long timestamp,
|
|||||||
throw new IOException(error);
|
throw new IOException(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dstInodes[dstInodes.length - 2] == null) {
|
|
||||||
|
final INode dstParent = dstIIP.getINode(-2);
|
||||||
|
if (dstParent == null) {
|
||||||
error = "rename destination parent " + dst + " not found.";
|
error = "rename destination parent " + dst + " not found.";
|
||||||
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
|
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
|
||||||
+ error);
|
+ error);
|
||||||
throw new FileNotFoundException(error);
|
throw new FileNotFoundException(error);
|
||||||
}
|
}
|
||||||
if (!dstInodes[dstInodes.length - 2].isDirectory()) {
|
if (!dstParent.isDirectory()) {
|
||||||
error = "rename destination parent " + dst + " is a file.";
|
error = "rename destination parent " + dst + " is a file.";
|
||||||
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
|
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
|
||||||
+ error);
|
+ error);
|
||||||
@ -726,8 +722,8 @@ boolean unprotectedRenameTo(String src, String dst, long timestamp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure dst has quota to accommodate rename
|
// Ensure dst has quota to accommodate rename
|
||||||
verifyQuotaForRename(srcInodes, dstInodes);
|
verifyQuotaForRename(srcIIP.getINodes(), dstIIP.getINodes());
|
||||||
INode removedSrc = removeLastINode(srcInodesInPath);
|
INode removedSrc = removeLastINode(srcIIP);
|
||||||
if (removedSrc == null) {
|
if (removedSrc == null) {
|
||||||
error = "Failed to rename " + src + " to " + dst
|
error = "Failed to rename " + src + " to " + dst
|
||||||
+ " because the source can not be removed";
|
+ " because the source can not be removed";
|
||||||
@ -740,23 +736,23 @@ boolean unprotectedRenameTo(String src, String dst, long timestamp,
|
|||||||
INode removedDst = null;
|
INode removedDst = null;
|
||||||
try {
|
try {
|
||||||
if (dstInode != null) { // dst exists remove it
|
if (dstInode != null) { // dst exists remove it
|
||||||
removedDst = removeLastINode(dstInodesInPath);
|
removedDst = removeLastINode(dstIIP);
|
||||||
dstChildName = removedDst.getLocalNameBytes();
|
dstChildName = removedDst.getLocalNameBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
removedSrc.setLocalName(dstInodesInPath.getLastLocalName());
|
removedSrc.setLocalName(dstIIP.getLastLocalName());
|
||||||
// add src as dst to complete rename
|
// add src as dst to complete rename
|
||||||
if (addLastINodeNoQuotaCheck(dstInodesInPath, removedSrc)) {
|
if (addLastINodeNoQuotaCheck(dstIIP, removedSrc)) {
|
||||||
removedSrc = null;
|
removedSrc = null;
|
||||||
if (NameNode.stateChangeLog.isDebugEnabled()) {
|
if (NameNode.stateChangeLog.isDebugEnabled()) {
|
||||||
NameNode.stateChangeLog.debug(
|
NameNode.stateChangeLog.debug(
|
||||||
"DIR* FSDirectory.unprotectedRenameTo: " + src
|
"DIR* FSDirectory.unprotectedRenameTo: " + src
|
||||||
+ " is renamed to " + dst);
|
+ " is renamed to " + dst);
|
||||||
}
|
}
|
||||||
srcInodes[srcInodes.length - 2].updateModificationTime(timestamp,
|
|
||||||
srcInodesInPath.getLatestSnapshot());
|
final INode srcParent = srcIIP.getINode(-2);
|
||||||
dstInodes[dstInodes.length - 2].updateModificationTime(timestamp,
|
srcParent.updateModificationTime(timestamp, srcIIP.getLatestSnapshot());
|
||||||
dstInodesInPath.getLatestSnapshot());
|
dstParent.updateModificationTime(timestamp, dstIIP.getLatestSnapshot());
|
||||||
// update moved lease with new filename
|
// update moved lease with new filename
|
||||||
getFSNamesystem().unprotectedChangeLease(src, dst);
|
getFSNamesystem().unprotectedChangeLease(src, dst);
|
||||||
|
|
||||||
@ -767,7 +763,7 @@ boolean unprotectedRenameTo(String src, String dst, long timestamp,
|
|||||||
removedDst = null;
|
removedDst = null;
|
||||||
BlocksMapUpdateInfo collectedBlocks = new BlocksMapUpdateInfo();
|
BlocksMapUpdateInfo collectedBlocks = new BlocksMapUpdateInfo();
|
||||||
filesDeleted = rmdst.cleanSubtree(null,
|
filesDeleted = rmdst.cleanSubtree(null,
|
||||||
dstInodesInPath.getLatestSnapshot(), collectedBlocks);
|
dstIIP.getLatestSnapshot(), collectedBlocks);
|
||||||
getFSNamesystem().removePathAndBlocks(src, collectedBlocks);
|
getFSNamesystem().removePathAndBlocks(src, collectedBlocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -782,12 +778,12 @@ boolean unprotectedRenameTo(String src, String dst, long timestamp,
|
|||||||
if (removedSrc != null) {
|
if (removedSrc != null) {
|
||||||
// Rename failed - restore src
|
// Rename failed - restore src
|
||||||
removedSrc.setLocalName(srcChildName);
|
removedSrc.setLocalName(srcChildName);
|
||||||
addLastINodeNoQuotaCheck(srcInodesInPath, removedSrc);
|
addLastINodeNoQuotaCheck(srcIIP, removedSrc);
|
||||||
}
|
}
|
||||||
if (removedDst != null) {
|
if (removedDst != null) {
|
||||||
// Rename failed - restore dst
|
// Rename failed - restore dst
|
||||||
removedDst.setLocalName(dstChildName);
|
removedDst.setLocalName(dstChildName);
|
||||||
addLastINodeNoQuotaCheck(dstInodesInPath, removedDst);
|
addLastINodeNoQuotaCheck(dstIIP, removedDst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
|
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
|
||||||
@ -800,19 +796,19 @@ boolean unprotectedRenameTo(String src, String dst, long timestamp,
|
|||||||
*
|
*
|
||||||
* @param src file name
|
* @param src file name
|
||||||
* @param replication new replication
|
* @param replication new replication
|
||||||
* @param oldReplication old replication - output parameter
|
* @param blockRepls block replications - output parameter
|
||||||
* @return array of file blocks
|
* @return array of file blocks
|
||||||
* @throws QuotaExceededException
|
* @throws QuotaExceededException
|
||||||
* @throws SnapshotAccessControlException
|
* @throws SnapshotAccessControlException
|
||||||
*/
|
*/
|
||||||
Block[] setReplication(String src, short replication, short[] oldReplication)
|
Block[] setReplication(String src, short replication, short[] blockRepls)
|
||||||
throws QuotaExceededException, UnresolvedLinkException,
|
throws QuotaExceededException, UnresolvedLinkException,
|
||||||
SnapshotAccessControlException {
|
SnapshotAccessControlException {
|
||||||
waitForReady();
|
waitForReady();
|
||||||
Block[] fileBlocks = null;
|
|
||||||
writeLock();
|
writeLock();
|
||||||
try {
|
try {
|
||||||
fileBlocks = unprotectedSetReplication(src, replication, oldReplication);
|
final Block[] fileBlocks = unprotectedSetReplication(
|
||||||
|
src, replication, blockRepls);
|
||||||
if (fileBlocks != null) // log replication change
|
if (fileBlocks != null) // log replication change
|
||||||
fsImage.getEditLog().logSetReplication(src, replication);
|
fsImage.getEditLog().logSetReplication(src, replication);
|
||||||
return fileBlocks;
|
return fileBlocks;
|
||||||
@ -822,30 +818,40 @@ Block[] setReplication(String src, short replication, short[] oldReplication)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Block[] unprotectedSetReplication(String src, short replication,
|
Block[] unprotectedSetReplication(String src, short replication,
|
||||||
short[] oldReplication) throws QuotaExceededException,
|
short[] blockRepls) throws QuotaExceededException,
|
||||||
UnresolvedLinkException, SnapshotAccessControlException {
|
UnresolvedLinkException, SnapshotAccessControlException {
|
||||||
assert hasWriteLock();
|
assert hasWriteLock();
|
||||||
|
|
||||||
final INodesInPath inodesInPath = rootDir.getINodesInPath4Write(src, true);
|
final INodesInPath iip = rootDir.getINodesInPath4Write(src, true);
|
||||||
final INode[] inodes = inodesInPath.getINodes();
|
final INode inode = iip.getLastINode();
|
||||||
INode inode = inodes[inodes.length - 1];
|
|
||||||
if (inode == null || !inode.isFile()) {
|
if (inode == null || !inode.isFile()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
INodeFile fileNode = (INodeFile)inode;
|
INodeFile file = inode.asFile();
|
||||||
final short oldRepl = fileNode.getFileReplication();
|
final short oldBR = file.getBlockReplication();
|
||||||
|
|
||||||
// check disk quota
|
// before setFileReplication, check for increasing block replication.
|
||||||
long dsDelta = (replication - oldRepl) * (fileNode.diskspaceConsumed()/oldRepl);
|
// if replication > oldBR, then newBR == replication.
|
||||||
updateCount(inodesInPath, 0, dsDelta, true);
|
// if replication < oldBR, we don't know newBR yet.
|
||||||
|
if (replication > oldBR) {
|
||||||
fileNode = fileNode.setFileReplication(
|
long dsDelta = (replication - oldBR)*(file.diskspaceConsumed()/oldBR);
|
||||||
replication, inodesInPath.getLatestSnapshot());
|
updateCount(iip, 0, dsDelta, true);
|
||||||
|
|
||||||
if (oldReplication != null) {
|
|
||||||
oldReplication[0] = oldRepl;
|
|
||||||
}
|
}
|
||||||
return fileNode.getBlocks();
|
|
||||||
|
file = file.setFileReplication(replication, iip.getLatestSnapshot());
|
||||||
|
|
||||||
|
final short newBR = file.getBlockReplication();
|
||||||
|
// check newBR < oldBR case.
|
||||||
|
if (newBR < oldBR) {
|
||||||
|
long dsDelta = (newBR - oldBR)*(file.diskspaceConsumed()/newBR);
|
||||||
|
updateCount(iip, 0, dsDelta, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (blockRepls != null) {
|
||||||
|
blockRepls[0] = oldBR;
|
||||||
|
blockRepls[1] = newBR;
|
||||||
|
}
|
||||||
|
return file.getBlocks();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -871,7 +877,7 @@ boolean exists(String src) throws UnresolvedLinkException {
|
|||||||
if (inode == null) {
|
if (inode == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return !inode.isFile() || ((INodeFile)inode).getBlocks() != null;
|
return !inode.isFile() || inode.asFile().getBlocks() != null;
|
||||||
} finally {
|
} finally {
|
||||||
readUnlock();
|
readUnlock();
|
||||||
}
|
}
|
||||||
@ -949,16 +955,12 @@ public void concat(String target, String [] srcs)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Concat all the blocks from srcs to trg and delete the srcs files
|
* Concat all the blocks from srcs to trg and delete the srcs files
|
||||||
* @param target target file to move the blocks to
|
* @param target target file to move the blocks to
|
||||||
* @param srcs list of file to move the blocks from
|
* @param srcs list of file to move the blocks from
|
||||||
* Must be public because also called from EditLogs
|
|
||||||
* NOTE: - it does not update quota (not needed for concat)
|
|
||||||
*/
|
*/
|
||||||
public void unprotectedConcat(String target, String [] srcs, long timestamp)
|
void unprotectedConcat(String target, String [] srcs, long timestamp)
|
||||||
throws UnresolvedLinkException, NSQuotaExceededException,
|
throws UnresolvedLinkException, NSQuotaExceededException,
|
||||||
SnapshotAccessControlException {
|
SnapshotAccessControlException {
|
||||||
assert hasWriteLock();
|
assert hasWriteLock();
|
||||||
@ -967,15 +969,15 @@ public void unprotectedConcat(String target, String [] srcs, long timestamp)
|
|||||||
}
|
}
|
||||||
// do the move
|
// do the move
|
||||||
|
|
||||||
final INodesInPath trgINodesInPath = rootDir.getINodesInPath4Write(target, true);
|
final INodesInPath trgIIP = rootDir.getINodesInPath4Write(target, true);
|
||||||
final INode[] trgINodes = trgINodesInPath.getINodes();
|
final INode[] trgINodes = trgIIP.getINodes();
|
||||||
INodeFile trgInode = (INodeFile) trgINodes[trgINodes.length-1];
|
final INodeFile trgInode = trgIIP.getLastINode().asFile();
|
||||||
INodeDirectory trgParent = (INodeDirectory)trgINodes[trgINodes.length-2];
|
INodeDirectory trgParent = trgINodes[trgINodes.length-2].asDirectory();
|
||||||
final Snapshot trgLatestSnapshot = trgINodesInPath.getLatestSnapshot();
|
final Snapshot trgLatestSnapshot = trgIIP.getLatestSnapshot();
|
||||||
|
|
||||||
final INodeFile [] allSrcInodes = new INodeFile[srcs.length];
|
final INodeFile [] allSrcInodes = new INodeFile[srcs.length];
|
||||||
for(int i = 0; i < srcs.length; i++) {
|
for(int i = 0; i < srcs.length; i++) {
|
||||||
allSrcInodes[i] = (INodeFile)getINode4Write(srcs[i]);
|
allSrcInodes[i] = getINode4Write(srcs[i]).asFile();
|
||||||
}
|
}
|
||||||
trgInode.concatBlocks(allSrcInodes);
|
trgInode.concatBlocks(allSrcInodes);
|
||||||
|
|
||||||
@ -992,7 +994,7 @@ public void unprotectedConcat(String target, String [] srcs, long timestamp)
|
|||||||
trgInode.setModificationTime(timestamp, trgLatestSnapshot);
|
trgInode.setModificationTime(timestamp, trgLatestSnapshot);
|
||||||
trgParent.updateModificationTime(timestamp, trgLatestSnapshot);
|
trgParent.updateModificationTime(timestamp, trgLatestSnapshot);
|
||||||
// update quota on the parent directory ('count' files removed, 0 space)
|
// update quota on the parent directory ('count' files removed, 0 space)
|
||||||
unprotectedUpdateCount(trgINodesInPath, trgINodes.length-1, -count, 0);
|
unprotectedUpdateCount(trgIIP, trgINodes.length-1, -count, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1081,7 +1083,7 @@ boolean isNonEmptyDirectory(String path) throws UnresolvedLinkException {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
final Snapshot s = inodesInPath.getPathSnapshot();
|
final Snapshot s = inodesInPath.getPathSnapshot();
|
||||||
return !((INodeDirectory)inode).getChildrenList(s).isEmpty();
|
return !inode.asDirectory().getChildrenList(s).isEmpty();
|
||||||
} finally {
|
} finally {
|
||||||
readUnlock();
|
readUnlock();
|
||||||
}
|
}
|
||||||
@ -1114,29 +1116,28 @@ void unprotectedDelete(String src, long mtime) throws UnresolvedLinkException,
|
|||||||
/**
|
/**
|
||||||
* Delete a path from the name space
|
* Delete a path from the name space
|
||||||
* Update the count at each ancestor directory with quota
|
* Update the count at each ancestor directory with quota
|
||||||
* @param inodes the INode array resolved from the path
|
* @param iip the inodes resolved from the path
|
||||||
* @param collectedBlocks blocks collected from the deleted path
|
* @param collectedBlocks blocks collected from the deleted path
|
||||||
* @param mtime the time the inode is removed
|
* @param mtime the time the inode is removed
|
||||||
* @return the number of inodes deleted; 0 if no inodes are deleted.
|
* @return the number of inodes deleted; 0 if no inodes are deleted.
|
||||||
*/
|
*/
|
||||||
int unprotectedDelete(INodesInPath inodesInPath,
|
int unprotectedDelete(INodesInPath iip, BlocksMapUpdateInfo collectedBlocks,
|
||||||
BlocksMapUpdateInfo collectedBlocks, long mtime)
|
long mtime) throws NSQuotaExceededException {
|
||||||
throws NSQuotaExceededException {
|
|
||||||
assert hasWriteLock();
|
assert hasWriteLock();
|
||||||
|
|
||||||
// check if target node exists
|
// check if target node exists
|
||||||
INode targetNode = inodesInPath.getLastINode();
|
INode targetNode = iip.getLastINode();
|
||||||
if (targetNode == null) {
|
if (targetNode == null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// record modification
|
// record modification
|
||||||
final Snapshot latestSnapshot = inodesInPath.getLatestSnapshot();
|
final Snapshot latestSnapshot = iip.getLatestSnapshot();
|
||||||
targetNode = targetNode.recordModification(latestSnapshot);
|
targetNode = targetNode.recordModification(latestSnapshot);
|
||||||
inodesInPath.setLastINode(targetNode);
|
iip.setLastINode(targetNode);
|
||||||
|
|
||||||
// Remove the node from the namespace
|
// Remove the node from the namespace
|
||||||
removeLastINode(inodesInPath);
|
removeLastINode(iip);
|
||||||
|
|
||||||
// set the parent's modification time
|
// set the parent's modification time
|
||||||
targetNode.getParent().updateModificationTime(mtime, latestSnapshot);
|
targetNode.getParent().updateModificationTime(mtime, latestSnapshot);
|
||||||
@ -1164,8 +1165,8 @@ int unprotectedDelete(INodesInPath inodesInPath,
|
|||||||
*/
|
*/
|
||||||
private static INode hasSnapshot(INode target,
|
private static INode hasSnapshot(INode target,
|
||||||
List<INodeDirectorySnapshottable> snapshottableDirs) {
|
List<INodeDirectorySnapshottable> snapshottableDirs) {
|
||||||
if (target instanceof INodeDirectory) {
|
if (target.isDirectory()) {
|
||||||
INodeDirectory targetDir = (INodeDirectory) target;
|
INodeDirectory targetDir = target.asDirectory();
|
||||||
if (targetDir.isSnapshottable()) {
|
if (targetDir.isSnapshottable()) {
|
||||||
INodeDirectorySnapshottable ssTargetDir =
|
INodeDirectorySnapshottable ssTargetDir =
|
||||||
(INodeDirectorySnapshottable) targetDir;
|
(INodeDirectorySnapshottable) targetDir;
|
||||||
@ -1245,7 +1246,7 @@ DirectoryListing getListing(String src, byte[] startAfter,
|
|||||||
targetNode, needLocation, snapshot)}, 0);
|
targetNode, needLocation, snapshot)}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
INodeDirectory dirInode = (INodeDirectory)targetNode;
|
final INodeDirectory dirInode = targetNode.asDirectory();
|
||||||
final ReadOnlyList<INode> contents = dirInode.getChildrenList(snapshot);
|
final ReadOnlyList<INode> contents = dirInode.getChildrenList(snapshot);
|
||||||
int startChild = INodeDirectory.nextChild(contents, startAfter);
|
int startChild = INodeDirectory.nextChild(contents, startAfter);
|
||||||
int totalNumChildren = contents.size();
|
int totalNumChildren = contents.size();
|
||||||
@ -1325,7 +1326,8 @@ private HdfsFileStatus getFileInfo4DotSnapshot(String src)
|
|||||||
src.length() - HdfsConstants.DOT_SNAPSHOT_DIR.length()));
|
src.length() - HdfsConstants.DOT_SNAPSHOT_DIR.length()));
|
||||||
|
|
||||||
final INode node = this.getINode(dirPath);
|
final INode node = this.getINode(dirPath);
|
||||||
if (node instanceof INodeDirectorySnapshottable) {
|
if (node.isDirectory()
|
||||||
|
&& node.asDirectory() instanceof INodeDirectorySnapshottable) {
|
||||||
return new HdfsFileStatus(0, true, 0, 0, 0, 0, null, null, null, null,
|
return new HdfsFileStatus(0, true, 0, 0, 0, 0, null, null, null, null,
|
||||||
HdfsFileStatus.EMPTY_NAME, -1L);
|
HdfsFileStatus.EMPTY_NAME, -1L);
|
||||||
}
|
}
|
||||||
@ -1340,12 +1342,18 @@ Block[] getFileBlocks(String src) throws UnresolvedLinkException {
|
|||||||
readLock();
|
readLock();
|
||||||
try {
|
try {
|
||||||
final INode i = rootDir.getNode(src, false);
|
final INode i = rootDir.getNode(src, false);
|
||||||
return i != null && i.isFile()? ((INodeFile)i).getBlocks(): null;
|
return i != null && i.isFile()? i.asFile().getBlocks(): null;
|
||||||
} finally {
|
} finally {
|
||||||
readUnlock();
|
readUnlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
INodesInPath getExistingPathINodes(byte[][] components)
|
||||||
|
throws UnresolvedLinkException {
|
||||||
|
return rootDir.getExistingPathINodes(components, components.length, false);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get {@link INode} associated with the file / directory.
|
* Get {@link INode} associated with the file / directory.
|
||||||
*/
|
*/
|
||||||
@ -1474,14 +1482,14 @@ private void updateCount(INodesInPath iip, long nsDelta, long dsDelta,
|
|||||||
|
|
||||||
/** update count of each inode with quota
|
/** update count of each inode with quota
|
||||||
*
|
*
|
||||||
* @param inodes an array of inodes on a path
|
* @param iip inodes in a path
|
||||||
* @param numOfINodes the number of inodes to update starting from index 0
|
* @param numOfINodes the number of inodes to update starting from index 0
|
||||||
* @param nsDelta the delta change of namespace
|
* @param nsDelta the delta change of namespace
|
||||||
* @param dsDelta the delta change of diskspace
|
* @param dsDelta the delta change of diskspace
|
||||||
* @param checkQuota if true then check if quota is exceeded
|
* @param checkQuota if true then check if quota is exceeded
|
||||||
* @throws QuotaExceededException if the new count violates any quota limit
|
* @throws QuotaExceededException if the new count violates any quota limit
|
||||||
*/
|
*/
|
||||||
private void updateCount(INodesInPath inodesInPath, int numOfINodes,
|
private void updateCount(INodesInPath iip, int numOfINodes,
|
||||||
long nsDelta, long dsDelta, boolean checkQuota)
|
long nsDelta, long dsDelta, boolean checkQuota)
|
||||||
throws QuotaExceededException {
|
throws QuotaExceededException {
|
||||||
assert hasWriteLock();
|
assert hasWriteLock();
|
||||||
@ -1489,14 +1497,14 @@ private void updateCount(INodesInPath inodesInPath, int numOfINodes,
|
|||||||
//still initializing. do not check or update quotas.
|
//still initializing. do not check or update quotas.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final INode[] inodes = inodesInPath.getINodes();
|
final INode[] inodes = iip.getINodes();
|
||||||
if (numOfINodes > inodes.length) {
|
if (numOfINodes > inodes.length) {
|
||||||
numOfINodes = inodes.length;
|
numOfINodes = inodes.length;
|
||||||
}
|
}
|
||||||
if (checkQuota) {
|
if (checkQuota) {
|
||||||
verifyQuota(inodes, numOfINodes, nsDelta, dsDelta, null);
|
verifyQuota(inodes, numOfINodes, nsDelta, dsDelta, null);
|
||||||
}
|
}
|
||||||
unprotectedUpdateCount(inodesInPath, numOfINodes, nsDelta, dsDelta);
|
unprotectedUpdateCount(iip, numOfINodes, nsDelta, dsDelta);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1622,13 +1630,12 @@ boolean mkdirs(String src, PermissionStatus permissions,
|
|||||||
|
|
||||||
writeLock();
|
writeLock();
|
||||||
try {
|
try {
|
||||||
INodesInPath inodesInPath = rootDir.getExistingPathINodes(components,
|
INodesInPath iip = getExistingPathINodes(components);
|
||||||
components.length, false);
|
if (iip.isSnapshot()) {
|
||||||
if (inodesInPath.isSnapshot()) {
|
|
||||||
throw new SnapshotAccessControlException(
|
throw new SnapshotAccessControlException(
|
||||||
"Modification on RO snapshot is disallowed");
|
"Modification on RO snapshot is disallowed");
|
||||||
}
|
}
|
||||||
INode[] inodes = inodesInPath.getINodes();
|
INode[] inodes = iip.getINodes();
|
||||||
|
|
||||||
// find the index of the first null in inodes[]
|
// find the index of the first null in inodes[]
|
||||||
StringBuilder pathbuilder = new StringBuilder();
|
StringBuilder pathbuilder = new StringBuilder();
|
||||||
@ -1676,7 +1683,7 @@ boolean mkdirs(String src, PermissionStatus permissions,
|
|||||||
// 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(namesystem.allocateNewInodeId(), inodesInPath, i,
|
unprotectedMkdir(namesystem.allocateNewInodeId(), iip, i,
|
||||||
components[i], (i < lastInodeIndex) ? parentPermissions
|
components[i], (i < lastInodeIndex) ? parentPermissions
|
||||||
: permissions, now);
|
: permissions, now);
|
||||||
if (inodes[i] == null) {
|
if (inodes[i] == null) {
|
||||||
@ -1705,11 +1712,10 @@ INode unprotectedMkdir(long inodeId, String src, PermissionStatus permissions,
|
|||||||
UnresolvedLinkException {
|
UnresolvedLinkException {
|
||||||
assert hasWriteLock();
|
assert hasWriteLock();
|
||||||
byte[][] components = INode.getPathComponents(src);
|
byte[][] components = INode.getPathComponents(src);
|
||||||
INodesInPath inodesInPath = rootDir.getExistingPathINodes(components,
|
INodesInPath iip = getExistingPathINodes(components);
|
||||||
components.length, false);
|
INode[] inodes = iip.getINodes();
|
||||||
INode[] inodes = inodesInPath.getINodes();
|
|
||||||
final int pos = inodes.length - 1;
|
final int pos = inodes.length - 1;
|
||||||
unprotectedMkdir(inodeId, inodesInPath, pos, components[pos], permissions,
|
unprotectedMkdir(inodeId, iip, pos, components[pos], permissions,
|
||||||
timestamp);
|
timestamp);
|
||||||
return inodes[pos];
|
return inodes[pos];
|
||||||
}
|
}
|
||||||
@ -1741,9 +1747,7 @@ private boolean addINode(String src, INode child
|
|||||||
cacheName(child);
|
cacheName(child);
|
||||||
writeLock();
|
writeLock();
|
||||||
try {
|
try {
|
||||||
INodesInPath inodesInPath = rootDir.getExistingPathINodes(components,
|
return addLastINode(getExistingPathINodes(components), child, true);
|
||||||
components.length, false);
|
|
||||||
return addLastINode(inodesInPath, child, true);
|
|
||||||
} finally {
|
} finally {
|
||||||
writeUnlock();
|
writeUnlock();
|
||||||
}
|
}
|
||||||
@ -1860,7 +1864,7 @@ private void verifyMaxDirItems(INode[] pathComponents, int pos)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final INodeDirectory parent = (INodeDirectory)pathComponents[pos-1];
|
final INodeDirectory parent = pathComponents[pos-1].asDirectory();
|
||||||
final int count = parent.getChildrenList(null).size();
|
final int count = parent.getChildrenList(null).size();
|
||||||
if (count >= maxDirItems) {
|
if (count >= maxDirItems) {
|
||||||
final MaxDirectoryItemsExceededException e
|
final MaxDirectoryItemsExceededException e
|
||||||
@ -1892,9 +1896,9 @@ private boolean addLastINode(INodesInPath inodesInPath,
|
|||||||
* otherwise return true;
|
* otherwise return true;
|
||||||
* @throw QuotaExceededException is thrown if it violates quota limit
|
* @throw QuotaExceededException is thrown if it violates quota limit
|
||||||
*/
|
*/
|
||||||
private boolean addChild(INodesInPath inodesInPath, int pos,
|
private boolean addChild(INodesInPath iip, int pos,
|
||||||
INode child, boolean checkQuota) throws QuotaExceededException {
|
INode child, boolean checkQuota) throws QuotaExceededException {
|
||||||
final INode[] inodes = inodesInPath.getINodes();
|
final INode[] inodes = iip.getINodes();
|
||||||
// The filesystem limits are not really quotas, so this check may appear
|
// The filesystem limits are not really quotas, so this check may appear
|
||||||
// odd. It's because a rename operation deletes the src, tries to add
|
// odd. It's because a rename operation deletes the src, tries to add
|
||||||
// to the dest, if that fails, re-adds the src from whence it came.
|
// to the dest, if that fails, re-adds the src from whence it came.
|
||||||
@ -1906,12 +1910,12 @@ private boolean addChild(INodesInPath inodesInPath, int pos,
|
|||||||
}
|
}
|
||||||
|
|
||||||
final Quota.Counts counts = child.computeQuotaUsage();
|
final Quota.Counts counts = child.computeQuotaUsage();
|
||||||
updateCount(inodesInPath, pos,
|
updateCount(iip, pos,
|
||||||
counts.get(Quota.NAMESPACE), counts.get(Quota.DISKSPACE), checkQuota);
|
counts.get(Quota.NAMESPACE), counts.get(Quota.DISKSPACE), checkQuota);
|
||||||
final boolean added = ((INodeDirectory)inodes[pos-1]).addChild(child, true,
|
final INodeDirectory parent = inodes[pos-1].asDirectory();
|
||||||
inodesInPath.getLatestSnapshot());
|
final boolean added = parent.addChild(child, true, iip.getLatestSnapshot());
|
||||||
if (!added) {
|
if (!added) {
|
||||||
updateCountNoQuotaCheck(inodesInPath, pos,
|
updateCountNoQuotaCheck(iip, pos,
|
||||||
-counts.get(Quota.NAMESPACE), -counts.get(Quota.DISKSPACE));
|
-counts.get(Quota.NAMESPACE), -counts.get(Quota.DISKSPACE));
|
||||||
}
|
}
|
||||||
return added;
|
return added;
|
||||||
@ -1937,8 +1941,8 @@ private INode removeLastINode(final INodesInPath inodesInPath)
|
|||||||
final Snapshot latestSnapshot = inodesInPath.getLatestSnapshot();
|
final Snapshot latestSnapshot = inodesInPath.getLatestSnapshot();
|
||||||
final INode[] inodes = inodesInPath.getINodes();
|
final INode[] inodes = inodesInPath.getINodes();
|
||||||
final int pos = inodes.length - 1;
|
final int pos = inodes.length - 1;
|
||||||
final boolean removed = ((INodeDirectory)inodes[pos-1]).removeChild(
|
final INodeDirectory parent = inodes[pos-1].asDirectory();
|
||||||
inodes[pos], latestSnapshot);
|
final boolean removed = parent.removeChild(inodes[pos], latestSnapshot);
|
||||||
if (removed && latestSnapshot == null) {
|
if (removed && latestSnapshot == null) {
|
||||||
inodesInPath.setINode(pos - 1, inodes[pos].getParent());
|
inodesInPath.setINode(pos - 1, inodes[pos].getParent());
|
||||||
final Quota.Counts counts = inodes[pos].computeQuotaUsage();
|
final Quota.Counts counts = inodes[pos].computeQuotaUsage();
|
||||||
@ -2149,8 +2153,8 @@ private HdfsFileStatus createFileStatus(byte[] path, INode node,
|
|||||||
long size = 0; // length is zero for directories
|
long size = 0; // length is zero for directories
|
||||||
short replication = 0;
|
short replication = 0;
|
||||||
long blocksize = 0;
|
long blocksize = 0;
|
||||||
if (node instanceof INodeFile) {
|
if (node.isFile()) {
|
||||||
INodeFile fileNode = (INodeFile)node;
|
final INodeFile fileNode = node.asFile();
|
||||||
size = fileNode.computeFileSize(snapshot);
|
size = fileNode.computeFileSize(snapshot);
|
||||||
replication = fileNode.getFileReplication(snapshot);
|
replication = fileNode.getFileReplication(snapshot);
|
||||||
blocksize = fileNode.getPreferredBlockSize();
|
blocksize = fileNode.getPreferredBlockSize();
|
||||||
@ -2165,7 +2169,7 @@ private HdfsFileStatus createFileStatus(byte[] path, INode node,
|
|||||||
node.getFsPermission(snapshot),
|
node.getFsPermission(snapshot),
|
||||||
node.getUserName(snapshot),
|
node.getUserName(snapshot),
|
||||||
node.getGroupName(snapshot),
|
node.getGroupName(snapshot),
|
||||||
node.isSymlink() ? ((INodeSymlink)node).getSymlink() : null,
|
node.isSymlink() ? node.asSymlink().getSymlink() : null,
|
||||||
path,
|
path,
|
||||||
node.getId());
|
node.getId());
|
||||||
}
|
}
|
||||||
@ -2180,8 +2184,8 @@ private HdfsLocatedFileStatus createLocatedFileStatus(
|
|||||||
short replication = 0;
|
short replication = 0;
|
||||||
long blocksize = 0;
|
long blocksize = 0;
|
||||||
LocatedBlocks loc = null;
|
LocatedBlocks loc = null;
|
||||||
if (node instanceof INodeFile) {
|
if (node.isFile()) {
|
||||||
INodeFile fileNode = (INodeFile)node;
|
final INodeFile fileNode = node.asFile();
|
||||||
size = fileNode.computeFileSize(snapshot);
|
size = fileNode.computeFileSize(snapshot);
|
||||||
replication = fileNode.getFileReplication(snapshot);
|
replication = fileNode.getFileReplication(snapshot);
|
||||||
blocksize = fileNode.getPreferredBlockSize();
|
blocksize = fileNode.getPreferredBlockSize();
|
||||||
@ -2205,7 +2209,7 @@ private HdfsLocatedFileStatus createLocatedFileStatus(
|
|||||||
node.getFsPermission(snapshot),
|
node.getFsPermission(snapshot),
|
||||||
node.getUserName(snapshot),
|
node.getUserName(snapshot),
|
||||||
node.getGroupName(snapshot),
|
node.getGroupName(snapshot),
|
||||||
node.isSymlink() ? ((INodeSymlink)node).getSymlink() : null,
|
node.isSymlink() ? node.asSymlink().getSymlink() : null,
|
||||||
path,
|
path,
|
||||||
node.getId(),
|
node.getId(),
|
||||||
loc);
|
loc);
|
||||||
|
@ -254,7 +254,8 @@ private long applyEditLogOp(FSEditLogOp op, FSDirectory fsDir,
|
|||||||
|
|
||||||
// See if the file already exists (persistBlocks call)
|
// See if the file already exists (persistBlocks call)
|
||||||
final INodesInPath iip = fsDir.getLastINodeInPath(addCloseOp.path);
|
final INodesInPath iip = fsDir.getLastINodeInPath(addCloseOp.path);
|
||||||
final INodeFile oldFile = toINodeFile(iip.getINode(0), addCloseOp.path);
|
final INodeFile oldFile = INodeFile.valueOf(
|
||||||
|
iip.getINode(0), addCloseOp.path, true);
|
||||||
INodeFile newFile = oldFile;
|
INodeFile newFile = oldFile;
|
||||||
if (oldFile == null) { // this is OP_ADD on a new file (case 1)
|
if (oldFile == null) { // this is OP_ADD on a new file (case 1)
|
||||||
// versions > 0 support per file replication
|
// versions > 0 support per file replication
|
||||||
@ -265,7 +266,7 @@ private long applyEditLogOp(FSEditLogOp op, FSDirectory fsDir,
|
|||||||
|
|
||||||
// add to the file tree
|
// add to the file tree
|
||||||
inodeId = fsNamesys.allocateNewInodeId();
|
inodeId = fsNamesys.allocateNewInodeId();
|
||||||
newFile = (INodeFile) fsDir.unprotectedAddFile(inodeId,
|
newFile = fsDir.unprotectedAddFile(inodeId,
|
||||||
addCloseOp.path, addCloseOp.permissions, replication,
|
addCloseOp.path, addCloseOp.permissions, replication,
|
||||||
addCloseOp.mtime, addCloseOp.atime, addCloseOp.blockSize, true,
|
addCloseOp.mtime, addCloseOp.atime, addCloseOp.blockSize, true,
|
||||||
addCloseOp.clientName, addCloseOp.clientMachine);
|
addCloseOp.clientName, addCloseOp.clientMachine);
|
||||||
@ -281,7 +282,8 @@ private long applyEditLogOp(FSEditLogOp op, FSDirectory fsDir,
|
|||||||
fsNamesys.prepareFileForWrite(addCloseOp.path, oldFile,
|
fsNamesys.prepareFileForWrite(addCloseOp.path, oldFile,
|
||||||
addCloseOp.clientName, addCloseOp.clientMachine, null,
|
addCloseOp.clientName, addCloseOp.clientMachine, null,
|
||||||
false, iip.getLatestSnapshot());
|
false, iip.getLatestSnapshot());
|
||||||
newFile = getINodeFile(fsDir, addCloseOp.path);
|
newFile = INodeFile.valueOf(fsDir.getINode(addCloseOp.path),
|
||||||
|
addCloseOp.path, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Fall-through for case 2.
|
// Fall-through for case 2.
|
||||||
@ -305,11 +307,7 @@ private long applyEditLogOp(FSEditLogOp op, FSDirectory fsDir,
|
|||||||
}
|
}
|
||||||
|
|
||||||
final INodesInPath iip = fsDir.getLastINodeInPath(addCloseOp.path);
|
final INodesInPath iip = fsDir.getLastINodeInPath(addCloseOp.path);
|
||||||
final INodeFile oldFile = toINodeFile(iip.getINode(0), addCloseOp.path);
|
final INodeFile oldFile = INodeFile.valueOf(iip.getINode(0), addCloseOp.path);
|
||||||
if (oldFile == null) {
|
|
||||||
throw new IOException("Operation trying to close non-existent file " +
|
|
||||||
addCloseOp.path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the salient file attributes.
|
// Update the salient file attributes.
|
||||||
oldFile.setAccessTime(addCloseOp.atime, null);
|
oldFile.setAccessTime(addCloseOp.atime, null);
|
||||||
@ -341,13 +339,8 @@ private long applyEditLogOp(FSEditLogOp op, FSDirectory fsDir,
|
|||||||
FSNamesystem.LOG.debug(op.opCode + ": " + updateOp.path +
|
FSNamesystem.LOG.debug(op.opCode + ": " + updateOp.path +
|
||||||
" numblocks : " + updateOp.blocks.length);
|
" numblocks : " + updateOp.blocks.length);
|
||||||
}
|
}
|
||||||
INodeFile oldFile = getINodeFile(fsDir, updateOp.path);
|
INodeFile oldFile = INodeFile.valueOf(fsDir.getINode(updateOp.path),
|
||||||
if (oldFile == null) {
|
|
||||||
throw new IOException(
|
|
||||||
"Operation trying to update blocks in non-existent file " +
|
|
||||||
updateOp.path);
|
updateOp.path);
|
||||||
}
|
|
||||||
|
|
||||||
// Update in-memory data structures
|
// Update in-memory data structures
|
||||||
updateBlocks(fsDir, updateOp, oldFile);
|
updateBlocks(fsDir, updateOp, oldFile);
|
||||||
break;
|
break;
|
||||||
@ -552,21 +545,6 @@ private static String formatEditLogReplayError(EditLogInputStream in,
|
|||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static INodeFile getINodeFile(FSDirectory fsDir, String path)
|
|
||||||
throws IOException {
|
|
||||||
return toINodeFile(fsDir.getINode(path), path);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static INodeFile toINodeFile(INode inode, String path)
|
|
||||||
throws IOException {
|
|
||||||
if (inode != null) {
|
|
||||||
if (!(inode instanceof INodeFile)) {
|
|
||||||
throw new IOException("Operation trying to get non-file " + path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (INodeFile)inode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update in-memory data structures with new block information.
|
* Update in-memory data structures with new block information.
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
|
@ -744,7 +744,7 @@ private static void updateCountForQuotaRecursively(INodeDirectory dir,
|
|||||||
|
|
||||||
for (INode child : dir.getChildrenList(null)) {
|
for (INode child : dir.getChildrenList(null)) {
|
||||||
if (child.isDirectory()) {
|
if (child.isDirectory()) {
|
||||||
updateCountForQuotaRecursively((INodeDirectory)child, counts);
|
updateCountForQuotaRecursively(child.asDirectory(), counts);
|
||||||
} else {
|
} else {
|
||||||
// file or symlink: count here to reduce recursive calls.
|
// file or symlink: count here to reduce recursive calls.
|
||||||
child.computeQuotaUsage(counts, false);
|
child.computeQuotaUsage(counts, false);
|
||||||
|
@ -491,9 +491,9 @@ private INodeDirectory getParentINodeDirectory(byte[][] pathComponents
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// Gets the parent INode
|
// Gets the parent INode
|
||||||
final INodesInPath inodes = namesystem.dir.rootDir.getExistingPathINodes(
|
final INodesInPath inodes = namesystem.dir.getExistingPathINodes(
|
||||||
pathComponents, 2, false);
|
pathComponents);
|
||||||
return INodeDirectory.valueOf(inodes.getINode(0), pathComponents);
|
return INodeDirectory.valueOf(inodes.getINode(-2), pathComponents);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -510,7 +510,7 @@ private void addToParent(INodeDirectory parent, INode child) {
|
|||||||
|
|
||||||
if (child.isFile()) {
|
if (child.isFile()) {
|
||||||
// Add file->block mapping
|
// Add file->block mapping
|
||||||
final INodeFile file = (INodeFile)child;
|
final INodeFile file = child.asFile();
|
||||||
final BlockInfo[] blocks = file.getBlocks();
|
final BlockInfo[] blocks = file.getBlocks();
|
||||||
if (blocks != null) {
|
if (blocks != null) {
|
||||||
final BlockManager bm = namesystem.getBlockManager();
|
final BlockManager bm = namesystem.getBlockManager();
|
||||||
@ -936,7 +936,7 @@ private void saveImage(ByteBuffer currentDirName, INodeDirectory current,
|
|||||||
if(!child.isDirectory())
|
if(!child.isDirectory())
|
||||||
continue;
|
continue;
|
||||||
currentDirName.put(PATH_SEPARATOR).put(child.getLocalNameBytes());
|
currentDirName.put(PATH_SEPARATOR).put(child.getLocalNameBytes());
|
||||||
saveImage(currentDirName, (INodeDirectory)child, out, snapshot);
|
saveImage(currentDirName, child.asDirectory(), out, snapshot);
|
||||||
currentDirName.position(prefixLen);
|
currentDirName.position(prefixLen);
|
||||||
}
|
}
|
||||||
if (snapshotDirMap != null) {
|
if (snapshotDirMap != null) {
|
||||||
|
@ -176,7 +176,7 @@ public static void writeINodeFile(INodeFile file, DataOutputStream out,
|
|||||||
SnapshotFSImageFormat.saveFileDiffList(file, out);
|
SnapshotFSImageFormat.saveFileDiffList(file, out);
|
||||||
|
|
||||||
if (writeUnderConstruction) {
|
if (writeUnderConstruction) {
|
||||||
if (file instanceof INodeFileUnderConstruction) {
|
if (file.isUnderConstruction()) {
|
||||||
out.writeBoolean(true);
|
out.writeBoolean(true);
|
||||||
final INodeFileUnderConstruction uc = (INodeFileUnderConstruction)file;
|
final INodeFileUnderConstruction uc = (INodeFileUnderConstruction)file;
|
||||||
writeString(uc.getClientName(), out);
|
writeString(uc.getClientName(), out);
|
||||||
@ -240,11 +240,11 @@ public static void saveINode2Image(INode node, DataOutputStream out,
|
|||||||
boolean writeUnderConstruction)
|
boolean writeUnderConstruction)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
if (node.isDirectory()) {
|
if (node.isDirectory()) {
|
||||||
writeINodeDirectory((INodeDirectory) node, out);
|
writeINodeDirectory(node.asDirectory(), out);
|
||||||
} else if (node.isSymlink()) {
|
} else if (node.isSymlink()) {
|
||||||
writeINodeSymlink((INodeSymlink) node, out);
|
writeINodeSymlink(node.asSymlink(), out);
|
||||||
} else {
|
} else {
|
||||||
writeINodeFile((INodeFile) node, out, writeUnderConstruction);
|
writeINodeFile(node.asFile(), out, writeUnderConstruction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1767,11 +1767,11 @@ private boolean setReplicationInt(final String src, final short replication)
|
|||||||
checkPathAccess(pc, src, FsAction.WRITE);
|
checkPathAccess(pc, src, FsAction.WRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
final short[] oldReplication = new short[1];
|
final short[] blockRepls = new short[2]; // 0: old, 1: new
|
||||||
final Block[] blocks = dir.setReplication(src, replication, oldReplication);
|
final Block[] blocks = dir.setReplication(src, replication, blockRepls);
|
||||||
isFile = blocks != null;
|
isFile = blocks != null;
|
||||||
if (isFile) {
|
if (isFile) {
|
||||||
blockManager.setReplication(oldReplication[0], replication, src, blocks);
|
blockManager.setReplication(blockRepls[0], blockRepls[1], src, blocks);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
writeUnlock();
|
writeUnlock();
|
||||||
@ -1921,11 +1921,12 @@ private LocatedBlock startFileInternal(FSPermissionChecker pc, String src,
|
|||||||
|
|
||||||
// Verify that the destination does not exist as a directory already.
|
// Verify that the destination does not exist as a directory already.
|
||||||
final INodesInPath iip = dir.getINodesInPath4Write(src);
|
final INodesInPath iip = dir.getINodesInPath4Write(src);
|
||||||
final INode myFile = iip.getLastINode();
|
final INode inode = iip.getLastINode();
|
||||||
if (myFile != null && myFile.isDirectory()) {
|
if (inode != null && inode.isDirectory()) {
|
||||||
throw new FileAlreadyExistsException("Cannot create file " + src
|
throw new FileAlreadyExistsException("Cannot create file " + src
|
||||||
+ "; already exists as a directory.");
|
+ "; already exists as a directory.");
|
||||||
}
|
}
|
||||||
|
final INodeFile myFile = INodeFile.valueOf(inode, src, true);
|
||||||
|
|
||||||
boolean overwrite = flag.contains(CreateFlag.OVERWRITE);
|
boolean overwrite = flag.contains(CreateFlag.OVERWRITE);
|
||||||
boolean append = flag.contains(CreateFlag.APPEND);
|
boolean append = flag.contains(CreateFlag.APPEND);
|
||||||
@ -2085,7 +2086,7 @@ boolean recoverLease(String src, String holder, String clientMachine)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void recoverLeaseInternal(INode fileInode,
|
private void recoverLeaseInternal(INodeFile fileInode,
|
||||||
String src, String holder, String clientMachine, boolean force)
|
String src, String holder, String clientMachine, boolean force)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
assert hasWriteLock();
|
assert hasWriteLock();
|
||||||
@ -2345,10 +2346,9 @@ INodesInPath analyzeFileState(String src,
|
|||||||
checkFsObjectLimit();
|
checkFsObjectLimit();
|
||||||
|
|
||||||
Block previousBlock = ExtendedBlock.getLocalBlock(previous);
|
Block previousBlock = ExtendedBlock.getLocalBlock(previous);
|
||||||
final INodesInPath inodesInPath = dir.getINodesInPath4Write(src);
|
final INodesInPath iip = dir.getINodesInPath4Write(src);
|
||||||
final INode[] inodes = inodesInPath.getINodes();
|
|
||||||
final INodeFileUnderConstruction pendingFile
|
final INodeFileUnderConstruction pendingFile
|
||||||
= checkLease(src, fileId, clientName, inodes[inodes.length - 1]);
|
= checkLease(src, fileId, clientName, iip.getLastINode());
|
||||||
BlockInfo lastBlockInFile = pendingFile.getLastBlock();
|
BlockInfo lastBlockInFile = pendingFile.getLastBlock();
|
||||||
if (!Block.matchingIdAndGenStamp(previousBlock, lastBlockInFile)) {
|
if (!Block.matchingIdAndGenStamp(previousBlock, lastBlockInFile)) {
|
||||||
// The block that the client claims is the current last block
|
// The block that the client claims is the current last block
|
||||||
@ -2406,7 +2406,7 @@ INodesInPath analyzeFileState(String src,
|
|||||||
onRetryBlock[0] = makeLocatedBlock(lastBlockInFile,
|
onRetryBlock[0] = makeLocatedBlock(lastBlockInFile,
|
||||||
((BlockInfoUnderConstruction)lastBlockInFile).getExpectedLocations(),
|
((BlockInfoUnderConstruction)lastBlockInFile).getExpectedLocations(),
|
||||||
offset);
|
offset);
|
||||||
return inodesInPath;
|
return iip;
|
||||||
} else {
|
} else {
|
||||||
// Case 3
|
// Case 3
|
||||||
throw new IOException("Cannot allocate block in " + src + ": " +
|
throw new IOException("Cannot allocate block in " + src + ": " +
|
||||||
@ -2419,7 +2419,7 @@ INodesInPath analyzeFileState(String src,
|
|||||||
if (!checkFileProgress(pendingFile, false)) {
|
if (!checkFileProgress(pendingFile, false)) {
|
||||||
throw new NotReplicatedYetException("Not replicated yet: " + src);
|
throw new NotReplicatedYetException("Not replicated yet: " + src);
|
||||||
}
|
}
|
||||||
return inodesInPath;
|
return iip;
|
||||||
}
|
}
|
||||||
|
|
||||||
LocatedBlock makeLocatedBlock(Block blk,
|
LocatedBlock makeLocatedBlock(Block blk,
|
||||||
@ -2525,16 +2525,17 @@ private INodeFileUnderConstruction checkLease(String src, String holder)
|
|||||||
}
|
}
|
||||||
|
|
||||||
private INodeFileUnderConstruction checkLease(String src, long fileId,
|
private INodeFileUnderConstruction checkLease(String src, long fileId,
|
||||||
String holder, INode file) throws LeaseExpiredException,
|
String holder, INode inode) throws LeaseExpiredException,
|
||||||
FileNotFoundException {
|
FileNotFoundException {
|
||||||
assert hasReadOrWriteLock();
|
assert hasReadOrWriteLock();
|
||||||
if (file == null || !(file instanceof INodeFile)) {
|
if (inode == null || !inode.isFile()) {
|
||||||
Lease lease = leaseManager.getLease(holder);
|
Lease lease = leaseManager.getLease(holder);
|
||||||
throw new LeaseExpiredException(
|
throw new LeaseExpiredException(
|
||||||
"No lease on " + src + ": File does not exist. "
|
"No lease on " + src + ": File does not exist. "
|
||||||
+ (lease != null ? lease.toString()
|
+ (lease != null ? lease.toString()
|
||||||
: "Holder " + holder + " does not have any open files."));
|
: "Holder " + holder + " does not have any open files."));
|
||||||
}
|
}
|
||||||
|
final INodeFile file = inode.asFile();
|
||||||
if (!file.isUnderConstruction()) {
|
if (!file.isUnderConstruction()) {
|
||||||
Lease lease = leaseManager.getLease(holder);
|
Lease lease = leaseManager.getLease(holder);
|
||||||
throw new LeaseExpiredException(
|
throw new LeaseExpiredException(
|
||||||
@ -2593,14 +2594,16 @@ private boolean completeFileInternal(String src,
|
|||||||
holder, iip.getINode(0));
|
holder, iip.getINode(0));
|
||||||
} catch (LeaseExpiredException lee) {
|
} catch (LeaseExpiredException lee) {
|
||||||
final INode inode = dir.getINode(src);
|
final INode inode = dir.getINode(src);
|
||||||
if (inode != null && inode instanceof INodeFile && !inode.isUnderConstruction()) {
|
if (inode != null
|
||||||
|
&& inode.isFile()
|
||||||
|
&& !inode.asFile().isUnderConstruction()) {
|
||||||
// This could be a retry RPC - i.e the client tried to close
|
// This could be a retry RPC - i.e the client tried to close
|
||||||
// the file, but missed the RPC response. Thus, it is trying
|
// the file, but missed the RPC response. Thus, it is trying
|
||||||
// again to close the file. If the file still exists and
|
// again to close the file. If the file still exists and
|
||||||
// the client's view of the last block matches the actual
|
// the client's view of the last block matches the actual
|
||||||
// last block, then we'll treat it as a successful close.
|
// last block, then we'll treat it as a successful close.
|
||||||
// See HDFS-3031.
|
// See HDFS-3031.
|
||||||
final Block realLastBlock = ((INodeFile)inode).getLastBlock();
|
final Block realLastBlock = inode.asFile().getLastBlock();
|
||||||
if (Block.matchingIdAndGenStamp(last, realLastBlock)) {
|
if (Block.matchingIdAndGenStamp(last, realLastBlock)) {
|
||||||
NameNode.stateChangeLog.info("DIR* completeFile: " +
|
NameNode.stateChangeLog.info("DIR* completeFile: " +
|
||||||
"request from " + holder + " to complete " + src +
|
"request from " + holder + " to complete " + src +
|
||||||
@ -3403,7 +3406,7 @@ void commitBlockSynchronization(ExtendedBlock lastblock,
|
|||||||
if (storedBlock == null) {
|
if (storedBlock == null) {
|
||||||
throw new IOException("Block (=" + lastblock + ") not found");
|
throw new IOException("Block (=" + lastblock + ") not found");
|
||||||
}
|
}
|
||||||
INodeFile iFile = (INodeFile) storedBlock.getBlockCollection();
|
INodeFile iFile = ((INode)storedBlock.getBlockCollection()).asFile();
|
||||||
if (!iFile.isUnderConstruction() || storedBlock.isComplete()) {
|
if (!iFile.isUnderConstruction() || storedBlock.isComplete()) {
|
||||||
throw new IOException("Unexpected block (=" + lastblock
|
throw new IOException("Unexpected block (=" + lastblock
|
||||||
+ ") since the file (=" + iFile.getLocalName()
|
+ ") since the file (=" + iFile.getLocalName()
|
||||||
@ -4934,7 +4937,7 @@ private INodeFileUnderConstruction checkUCBlock(ExtendedBlock block,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check file inode
|
// check file inode
|
||||||
INodeFile file = (INodeFile) storedBlock.getBlockCollection();
|
final INodeFile file = ((INode)storedBlock.getBlockCollection()).asFile();
|
||||||
if (file==null || !file.isUnderConstruction()) {
|
if (file==null || !file.isUnderConstruction()) {
|
||||||
throw new IOException("The file " + storedBlock +
|
throw new IOException("The file " + storedBlock +
|
||||||
" belonged to does not exist or it is not under construction.");
|
" belonged to does not exist or it is not under construction.");
|
||||||
@ -5209,7 +5212,7 @@ Collection<CorruptFileBlockInfo> listCorruptFileBlocks(String path,
|
|||||||
|
|
||||||
while (blkIterator.hasNext()) {
|
while (blkIterator.hasNext()) {
|
||||||
Block blk = blkIterator.next();
|
Block blk = blkIterator.next();
|
||||||
INode inode = (INodeFile) blockManager.getBlockCollection(blk);
|
final INode inode = (INode)blockManager.getBlockCollection(blk);
|
||||||
skip++;
|
skip++;
|
||||||
if (inode != null && blockManager.countNodes(blk).liveReplicas() == 0) {
|
if (inode != null && blockManager.countNodes(blk).liveReplicas() == 0) {
|
||||||
String src = FSDirectory.getFullPathName(inode);
|
String src = FSDirectory.getFullPathName(inode);
|
||||||
|
@ -189,13 +189,13 @@ private void checkSubAccess(INode inode, Snapshot snapshot, FsAction access
|
|||||||
}
|
}
|
||||||
|
|
||||||
Stack<INodeDirectory> directories = new Stack<INodeDirectory>();
|
Stack<INodeDirectory> directories = new Stack<INodeDirectory>();
|
||||||
for(directories.push((INodeDirectory)inode); !directories.isEmpty(); ) {
|
for(directories.push(inode.asDirectory()); !directories.isEmpty(); ) {
|
||||||
INodeDirectory d = directories.pop();
|
INodeDirectory d = directories.pop();
|
||||||
check(d, snapshot, access);
|
check(d, snapshot, access);
|
||||||
|
|
||||||
for(INode child : d.getChildrenList(snapshot)) {
|
for(INode child : d.getChildrenList(snapshot)) {
|
||||||
if (child.isDirectory()) {
|
if (child.isDirectory()) {
|
||||||
directories.push((INodeDirectory)child);
|
directories.push(child.asDirectory());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -293,6 +293,12 @@ public boolean isFile() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Cast this inode to an {@link INodeFile}. */
|
||||||
|
public INodeFile asFile() {
|
||||||
|
throw new IllegalStateException("Current inode is not a file: "
|
||||||
|
+ this.toDetailString());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether it's a directory
|
* Check whether it's a directory
|
||||||
*/
|
*/
|
||||||
@ -300,6 +306,12 @@ public boolean isDirectory() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Cast this inode to an {@link INodeDirectory}. */
|
||||||
|
public INodeDirectory asDirectory() {
|
||||||
|
throw new IllegalStateException("Current inode is not a directory: "
|
||||||
|
+ this.toDetailString());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clean the subtree under this inode and collect the blocks from the descents
|
* Clean the subtree under this inode and collect the blocks from the descents
|
||||||
* for further block deletion/update. The current inode can either resides in
|
* for further block deletion/update. The current inode can either resides in
|
||||||
@ -470,7 +482,7 @@ public long getDsQuota() {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean isQuotaSet() {
|
public final boolean isQuotaSet() {
|
||||||
return getNsQuota() >= 0 || getDsQuota() >= 0;
|
return getNsQuota() >= 0 || getDsQuota() >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -666,13 +678,6 @@ public INode setAccessTime(long accessTime, Snapshot latest)
|
|||||||
return nodeToUpdate;
|
return nodeToUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Is this inode being constructed?
|
|
||||||
*/
|
|
||||||
public boolean isUnderConstruction() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether it's a symlink
|
* Check whether it's a symlink
|
||||||
*/
|
*/
|
||||||
@ -680,6 +685,12 @@ public boolean isSymlink() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Cast this inode to an {@link INodeSymlink}. */
|
||||||
|
public INodeSymlink asSymlink() {
|
||||||
|
throw new IllegalStateException("Current inode is not a symlink: "
|
||||||
|
+ this.toDetailString());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Breaks file path into components.
|
* Breaks file path into components.
|
||||||
* @param path
|
* @param path
|
||||||
|
@ -57,7 +57,7 @@ public static INodeDirectory valueOf(INode inode, Object path
|
|||||||
if (!inode.isDirectory()) {
|
if (!inode.isDirectory()) {
|
||||||
throw new PathIsNotDirectoryException(DFSUtil.path2String(path));
|
throw new PathIsNotDirectoryException(DFSUtil.path2String(path));
|
||||||
}
|
}
|
||||||
return (INodeDirectory)inode;
|
return inode.asDirectory();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static final int DEFAULT_FILES_PER_DIRECTORY = 5;
|
protected static final int DEFAULT_FILES_PER_DIRECTORY = 5;
|
||||||
@ -93,6 +93,12 @@ public final boolean isDirectory() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return this object. */
|
||||||
|
@Override
|
||||||
|
public final INodeDirectory asDirectory() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/** Is this a snapshottable directory? */
|
/** Is this a snapshottable directory? */
|
||||||
public boolean isSnapshottable() {
|
public boolean isSnapshottable() {
|
||||||
return false;
|
return false;
|
||||||
@ -384,11 +390,13 @@ INodesInPath getExistingPathINodes(byte[][] components, int numOfINodes,
|
|||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
existing.addNode(curNode);
|
existing.addNode(curNode);
|
||||||
}
|
}
|
||||||
if (curNode instanceof INodeDirectoryWithSnapshot) {
|
final boolean isDir = curNode.isDirectory();
|
||||||
|
final INodeDirectory dir = isDir? curNode.asDirectory(): null;
|
||||||
|
if (isDir && dir instanceof INodeDirectoryWithSnapshot) {
|
||||||
//if the path is a non-snapshot path, update the latest snapshot.
|
//if the path is a non-snapshot path, update the latest snapshot.
|
||||||
if (!existing.isSnapshot()) {
|
if (!existing.isSnapshot()) {
|
||||||
existing.updateLatestSnapshot(
|
existing.updateLatestSnapshot(
|
||||||
((INodeDirectoryWithSnapshot)curNode).getLastSnapshot());
|
((INodeDirectoryWithSnapshot)dir).getLastSnapshot());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (curNode.isSymlink() && (!lastComp || (lastComp && resolveLink))) {
|
if (curNode.isSymlink() && (!lastComp || (lastComp && resolveLink))) {
|
||||||
@ -397,7 +405,7 @@ INodesInPath getExistingPathINodes(byte[][] components, int numOfINodes,
|
|||||||
final String remainder =
|
final String remainder =
|
||||||
constructPath(components, count + 1, components.length);
|
constructPath(components, count + 1, components.length);
|
||||||
final String link = DFSUtil.bytes2String(components[count]);
|
final String link = DFSUtil.bytes2String(components[count]);
|
||||||
final String target = ((INodeSymlink)curNode).getSymlinkString();
|
final String target = curNode.asSymlink().getSymlinkString();
|
||||||
if (NameNode.stateChangeLog.isDebugEnabled()) {
|
if (NameNode.stateChangeLog.isDebugEnabled()) {
|
||||||
NameNode.stateChangeLog.debug("UnresolvedPathException " +
|
NameNode.stateChangeLog.debug("UnresolvedPathException " +
|
||||||
" path: " + path + " preceding: " + preceding +
|
" path: " + path + " preceding: " + preceding +
|
||||||
@ -406,15 +414,14 @@ INodesInPath getExistingPathINodes(byte[][] components, int numOfINodes,
|
|||||||
}
|
}
|
||||||
throw new UnresolvedPathException(path, preceding, remainder, target);
|
throw new UnresolvedPathException(path, preceding, remainder, target);
|
||||||
}
|
}
|
||||||
if (lastComp || !curNode.isDirectory()) {
|
if (lastComp || !isDir) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
final INodeDirectory parentDir = (INodeDirectory)curNode;
|
|
||||||
final byte[] childName = components[count + 1];
|
final byte[] childName = components[count + 1];
|
||||||
|
|
||||||
// check if the next byte[] in components is for ".snapshot"
|
// check if the next byte[] in components is for ".snapshot"
|
||||||
if (isDotSnapshotDir(childName)
|
if (isDotSnapshotDir(childName)
|
||||||
&& (curNode instanceof INodeDirectorySnapshottable)) {
|
&& isDir && dir instanceof INodeDirectoryWithSnapshot) {
|
||||||
// skip the ".snapshot" in components
|
// skip the ".snapshot" in components
|
||||||
count++;
|
count++;
|
||||||
index++;
|
index++;
|
||||||
@ -427,7 +434,7 @@ INodesInPath getExistingPathINodes(byte[][] components, int numOfINodes,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Resolve snapshot root
|
// Resolve snapshot root
|
||||||
final Snapshot s = ((INodeDirectorySnapshottable)parentDir).getSnapshot(
|
final Snapshot s = ((INodeDirectorySnapshottable)dir).getSnapshot(
|
||||||
components[count + 1]);
|
components[count + 1]);
|
||||||
if (s == null) {
|
if (s == null) {
|
||||||
//snapshot not found
|
//snapshot not found
|
||||||
@ -441,7 +448,7 @@ INodesInPath getExistingPathINodes(byte[][] components, int numOfINodes,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// normal case, and also for resolving file/dir under snapshot root
|
// normal case, and also for resolving file/dir under snapshot root
|
||||||
curNode = parentDir.getChild(childName, existing.getPathSnapshot());
|
curNode = dir.getChild(childName, existing.getPathSnapshot());
|
||||||
}
|
}
|
||||||
count++;
|
count++;
|
||||||
index++;
|
index++;
|
||||||
@ -725,9 +732,7 @@ private void updateLatestSnapshot(Snapshot s) {
|
|||||||
INode[] getINodes() {
|
INode[] getINodes() {
|
||||||
if (capacity < inodes.length) {
|
if (capacity < inodes.length) {
|
||||||
INode[] newNodes = new INode[capacity];
|
INode[] newNodes = new INode[capacity];
|
||||||
for (int i = 0; i < capacity; i++) {
|
System.arraycopy(inodes, 0, newNodes, 0, capacity);
|
||||||
newNodes[i] = inodes[i];
|
|
||||||
}
|
|
||||||
inodes = newNodes;
|
inodes = newNodes;
|
||||||
}
|
}
|
||||||
return inodes;
|
return inodes;
|
||||||
|
@ -43,16 +43,26 @@
|
|||||||
/** I-node for closed file. */
|
/** I-node for closed file. */
|
||||||
@InterfaceAudience.Private
|
@InterfaceAudience.Private
|
||||||
public class INodeFile extends INode implements BlockCollection {
|
public class INodeFile extends INode implements BlockCollection {
|
||||||
/** Cast INode to INodeFile. */
|
/** The same as valueOf(inode, path, false). */
|
||||||
public static INodeFile valueOf(INode inode, String path
|
public static INodeFile valueOf(INode inode, String path
|
||||||
) throws FileNotFoundException {
|
) throws FileNotFoundException {
|
||||||
|
return valueOf(inode, path, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Cast INode to INodeFile. */
|
||||||
|
public static INodeFile valueOf(INode inode, String path, boolean acceptNull)
|
||||||
|
throws FileNotFoundException {
|
||||||
if (inode == null) {
|
if (inode == null) {
|
||||||
|
if (acceptNull) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
throw new FileNotFoundException("File does not exist: " + path);
|
throw new FileNotFoundException("File does not exist: " + path);
|
||||||
}
|
}
|
||||||
if (!(inode instanceof INodeFile)) {
|
}
|
||||||
|
if (!inode.isFile()) {
|
||||||
throw new FileNotFoundException("Path is not a file: " + path);
|
throw new FileNotFoundException("Path is not a file: " + path);
|
||||||
}
|
}
|
||||||
return (INodeFile)inode;
|
return inode.asFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
static final FsPermission UMASK = FsPermission.createImmutable((short)0111);
|
static final FsPermission UMASK = FsPermission.createImmutable((short)0111);
|
||||||
@ -116,12 +126,23 @@ public final boolean isFile() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return this object. */
|
||||||
|
@Override
|
||||||
|
public final INodeFile asFile() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Is this file under construction? */
|
||||||
|
public boolean isUnderConstruction() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/** Convert this file to an {@link INodeFileUnderConstruction}. */
|
/** Convert this file to an {@link INodeFileUnderConstruction}. */
|
||||||
public INodeFileUnderConstruction toUnderConstruction(
|
public INodeFileUnderConstruction toUnderConstruction(
|
||||||
String clientName,
|
String clientName,
|
||||||
String clientMachine,
|
String clientMachine,
|
||||||
DatanodeDescriptor clientNode) {
|
DatanodeDescriptor clientNode) {
|
||||||
Preconditions.checkArgument(!(this instanceof INodeFileUnderConstruction),
|
Preconditions.checkState(!isUnderConstruction(),
|
||||||
"file is already an INodeFileUnderConstruction");
|
"file is already an INodeFileUnderConstruction");
|
||||||
return new INodeFileUnderConstruction(this,
|
return new INodeFileUnderConstruction(this,
|
||||||
clientName, clientMachine, clientNode);
|
clientName, clientMachine, clientNode);
|
||||||
|
@ -108,11 +108,9 @@ public DatanodeDescriptor getClientNode() {
|
|||||||
return clientNode;
|
return clientNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @return true unconditionally. */
|
||||||
* Is this inode being constructed?
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isUnderConstruction() {
|
public final boolean isUnderConstruction() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,6 +57,12 @@ public boolean isSymlink() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return this object. */
|
||||||
|
@Override
|
||||||
|
public INodeSymlink asSymlink() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public String getSymlinkString() {
|
public String getSymlinkString() {
|
||||||
return DFSUtil.bytes2String(symlink);
|
return DFSUtil.bytes2String(symlink);
|
||||||
}
|
}
|
||||||
|
@ -790,7 +790,7 @@ static class XMLBlockInfo {
|
|||||||
this.inode = null;
|
this.inode = null;
|
||||||
} else {
|
} else {
|
||||||
this.block = new Block(blockId);
|
this.block = new Block(blockId);
|
||||||
this.inode = (INodeFile) blockManager.getBlockCollection(block);
|
this.inode = ((INode)blockManager.getBlockCollection(block)).asFile();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ public final List<D> asList() {
|
|||||||
return Collections.unmodifiableList(diffs);
|
return Collections.unmodifiableList(diffs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** clear the diff list, */
|
/** Get the size of the list and then clear it. */
|
||||||
int clear() {
|
int clear() {
|
||||||
final int n = diffs.size();
|
final int n = diffs.size();
|
||||||
diffs.clear();
|
diffs.clear();
|
||||||
|
@ -397,8 +397,8 @@ private Snapshot getSnapshotByName(String snapshotName)
|
|||||||
private void computeDiffRecursively(INode node,
|
private void computeDiffRecursively(INode node,
|
||||||
SnapshotDiffInfo diffReport) {
|
SnapshotDiffInfo diffReport) {
|
||||||
ChildrenDiff diff = new ChildrenDiff();
|
ChildrenDiff diff = new ChildrenDiff();
|
||||||
if (node instanceof INodeDirectory) {
|
if (node.isDirectory()) {
|
||||||
INodeDirectory dir = (INodeDirectory) node;
|
INodeDirectory dir = node.asDirectory();
|
||||||
if (dir instanceof INodeDirectoryWithSnapshot) {
|
if (dir instanceof INodeDirectoryWithSnapshot) {
|
||||||
INodeDirectoryWithSnapshot sdir = (INodeDirectoryWithSnapshot) dir;
|
INodeDirectoryWithSnapshot sdir = (INodeDirectoryWithSnapshot) dir;
|
||||||
boolean change = sdir.computeDiffBetweenSnapshots(
|
boolean change = sdir.computeDiffBetweenSnapshots(
|
||||||
@ -415,8 +415,8 @@ private void computeDiffRecursively(INode node,
|
|||||||
computeDiffRecursively(child, diffReport);
|
computeDiffRecursively(child, diffReport);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (node instanceof FileWithSnapshot) {
|
} else if (node.isFile() && node.asFile() instanceof FileWithSnapshot) {
|
||||||
FileWithSnapshot file = (FileWithSnapshot) node;
|
FileWithSnapshot file = (FileWithSnapshot) node.asFile();
|
||||||
Snapshot earlierSnapshot = diffReport.isFromEarlier() ? diffReport.from
|
Snapshot earlierSnapshot = diffReport.isFromEarlier() ? diffReport.from
|
||||||
: diffReport.to;
|
: diffReport.to;
|
||||||
Snapshot laterSnapshot = diffReport.isFromEarlier() ? diffReport.to
|
Snapshot laterSnapshot = diffReport.isFromEarlier() ? diffReport.to
|
||||||
|
@ -130,7 +130,7 @@ private List<INodeDirectory> getDirsInDeleted() {
|
|||||||
List<INodeDirectory> dirList = new ArrayList<INodeDirectory>();
|
List<INodeDirectory> dirList = new ArrayList<INodeDirectory>();
|
||||||
for (INode node : getDeletedList()) {
|
for (INode node : getDeletedList()) {
|
||||||
if (node.isDirectory()) {
|
if (node.isDirectory()) {
|
||||||
dirList.add((INodeDirectory) node);
|
dirList.add(node.asDirectory());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return dirList;
|
return dirList;
|
||||||
@ -351,7 +351,7 @@ DirectoryDiff createDiff(Snapshot snapshot, INodeDirectory currentDir) {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
INodeDirectory createSnapshotCopy(INodeDirectory currentDir) {
|
INodeDirectory createSnapshotCopy(INodeDirectory currentDir) {
|
||||||
final INodeDirectory copy = currentDir instanceof INodeDirectoryWithQuota?
|
final INodeDirectory copy = currentDir.isQuotaSet()?
|
||||||
new INodeDirectoryWithQuota(currentDir, false,
|
new INodeDirectoryWithQuota(currentDir, false,
|
||||||
currentDir.getNsQuota(), currentDir.getDsQuota())
|
currentDir.getNsQuota(), currentDir.getDsQuota())
|
||||||
: new INodeDirectory(currentDir, false);
|
: new INodeDirectory(currentDir, false);
|
||||||
|
@ -64,8 +64,10 @@ public int compare(Snapshot left, Snapshot right) {
|
|||||||
public static Snapshot findLatestSnapshot(INode inode, Snapshot anchor) {
|
public static Snapshot findLatestSnapshot(INode inode, Snapshot anchor) {
|
||||||
Snapshot latest = null;
|
Snapshot latest = null;
|
||||||
for(; inode != null; inode = inode.getParent()) {
|
for(; inode != null; inode = inode.getParent()) {
|
||||||
if (inode instanceof INodeDirectoryWithSnapshot) {
|
if (inode.isDirectory()) {
|
||||||
final Snapshot s = ((INodeDirectoryWithSnapshot) inode).getDiffs()
|
final INodeDirectory dir = inode.asDirectory();
|
||||||
|
if (dir instanceof INodeDirectoryWithSnapshot) {
|
||||||
|
final Snapshot s = ((INodeDirectoryWithSnapshot)dir).getDiffs()
|
||||||
.getPrior(anchor);
|
.getPrior(anchor);
|
||||||
if (latest == null
|
if (latest == null
|
||||||
|| (s != null && ID_COMPARATOR.compare(latest, s) < 0)) {
|
|| (s != null && ID_COMPARATOR.compare(latest, s) < 0)) {
|
||||||
@ -73,6 +75,7 @@ public static Snapshot findLatestSnapshot(INode inode, Snapshot anchor) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return latest;
|
return latest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +125,7 @@ private static FileDiff loadFileDiff(FileDiff posterior, DataInputStream in,
|
|||||||
|
|
||||||
// 3. Load snapshotINode
|
// 3. Load snapshotINode
|
||||||
final INodeFile snapshotINode = in.readBoolean()?
|
final INodeFile snapshotINode = in.readBoolean()?
|
||||||
(INodeFile) loader.loadINodeWithLocalName(true, in): null;
|
loader.loadINodeWithLocalName(true, in).asFile(): null;
|
||||||
|
|
||||||
return new FileDiff(snapshot, snapshotINode, posterior, fileSize);
|
return new FileDiff(snapshot, snapshotINode, posterior, fileSize);
|
||||||
}
|
}
|
||||||
@ -233,9 +233,8 @@ public static void loadSnapshotList(
|
|||||||
private static Snapshot loadSnapshot(INodeDirectorySnapshottable parent,
|
private static Snapshot loadSnapshot(INodeDirectorySnapshottable parent,
|
||||||
DataInputStream in, FSImageFormat.Loader loader) throws IOException {
|
DataInputStream in, FSImageFormat.Loader loader) throws IOException {
|
||||||
int snapshotId = in.readInt();
|
int snapshotId = in.readInt();
|
||||||
INodeDirectory rootNode = (INodeDirectory)loader.loadINodeWithLocalName(
|
final INode root = loader.loadINodeWithLocalName(false, in);
|
||||||
false, in);
|
return new Snapshot(snapshotId, root.asDirectory(), parent);
|
||||||
return new Snapshot(snapshotId, rootNode, parent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -292,7 +291,7 @@ private static INodeDirectory loadSnapshotINodeInDirectoryDiff(
|
|||||||
} else {
|
} else {
|
||||||
// another boolean is used to indicate whether snapshotINode is non-null
|
// another boolean is used to indicate whether snapshotINode is non-null
|
||||||
return in.readBoolean()?
|
return in.readBoolean()?
|
||||||
(INodeDirectory) loader.loadINodeWithLocalName(true, in): null;
|
loader.loadINodeWithLocalName(true, in).asDirectory(): null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user