HDFS-10779. Rename does not need to re-solve destination. Contributed by Daryn Sharp.
(cherry picked from commit 5f34402ada
)
Conflicts:
hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java
This commit is contained in:
parent
c4f81f199f
commit
5294eec729
|
@ -38,23 +38,18 @@ import org.apache.hadoop.util.Time;
|
||||||
|
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.AbstractMap;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import static org.apache.hadoop.hdfs.protocol.FSLimitException.MaxDirectoryItemsExceededException;
|
import static org.apache.hadoop.hdfs.protocol.FSLimitException.MaxDirectoryItemsExceededException;
|
||||||
import static org.apache.hadoop.hdfs.protocol.FSLimitException.PathComponentTooLongException;
|
import static org.apache.hadoop.hdfs.protocol.FSLimitException.PathComponentTooLongException;
|
||||||
|
|
||||||
class FSDirRenameOp {
|
class FSDirRenameOp {
|
||||||
@Deprecated
|
@Deprecated
|
||||||
static RenameOldResult renameToInt(
|
static RenameResult renameToInt(
|
||||||
FSDirectory fsd, final String srcArg, final String dstArg,
|
FSDirectory fsd, final String src, final String dst,
|
||||||
boolean logRetryCache)
|
boolean logRetryCache)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
String src = srcArg;
|
|
||||||
String dst = dstArg;
|
|
||||||
if (NameNode.stateChangeLog.isDebugEnabled()) {
|
if (NameNode.stateChangeLog.isDebugEnabled()) {
|
||||||
NameNode.stateChangeLog.debug("DIR* NameSystem.renameTo: " + src +
|
NameNode.stateChangeLog.debug("DIR* NameSystem.renameTo: " + src +
|
||||||
" to " + dst);
|
" to " + dst);
|
||||||
|
@ -64,18 +59,12 @@ class FSDirRenameOp {
|
||||||
}
|
}
|
||||||
FSPermissionChecker pc = fsd.getPermissionChecker();
|
FSPermissionChecker pc = fsd.getPermissionChecker();
|
||||||
|
|
||||||
HdfsFileStatus resultingStat = null;
|
|
||||||
// Rename does not operate on link targets
|
// Rename does not operate on link targets
|
||||||
// Do not resolveLink when checking permissions of src and dst
|
// Do not resolveLink when checking permissions of src and dst
|
||||||
INodesInPath srcIIP = fsd.resolvePathForWrite(pc, src, false);
|
INodesInPath srcIIP = fsd.resolvePathForWrite(pc, src, false);
|
||||||
INodesInPath dstIIP = fsd.resolvePathForWrite(pc, dst, false);
|
INodesInPath dstIIP = fsd.resolvePathForWrite(pc, dst, false);
|
||||||
@SuppressWarnings("deprecation")
|
dstIIP = dstForRenameTo(srcIIP, dstIIP);
|
||||||
final boolean status = renameTo(fsd, pc, srcIIP, dstIIP, logRetryCache);
|
return renameTo(fsd, pc, srcIIP, dstIIP, logRetryCache);
|
||||||
if (status) {
|
|
||||||
dstIIP = fsd.getINodesInPath(dstIIP.getPath(), false);
|
|
||||||
resultingStat = fsd.getAuditFileInfo(dstIIP);
|
|
||||||
}
|
|
||||||
return new RenameOldResult(status, resultingStat);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -124,15 +113,30 @@ class FSDirRenameOp {
|
||||||
* <br>
|
* <br>
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@SuppressWarnings("deprecation")
|
static INodesInPath renameForEditLog(FSDirectory fsd, String src, String dst,
|
||||||
static boolean renameForEditLog(FSDirectory fsd, String src, String dst,
|
|
||||||
long timestamp) throws IOException {
|
long timestamp) throws IOException {
|
||||||
if (fsd.isDir(dst)) {
|
|
||||||
dst += Path.SEPARATOR + new Path(src).getName();
|
|
||||||
}
|
|
||||||
final INodesInPath srcIIP = fsd.getINodesInPath4Write(src, false);
|
final INodesInPath srcIIP = fsd.getINodesInPath4Write(src, false);
|
||||||
final INodesInPath dstIIP = fsd.getINodesInPath4Write(dst, false);
|
INodesInPath dstIIP = fsd.getINodesInPath4Write(dst, false);
|
||||||
return unprotectedRenameTo(fsd, src, dst, srcIIP, dstIIP, timestamp);
|
// this is wrong but accidentally works. the edit contains the full path
|
||||||
|
// so the following will do nothing, but shouldn't change due to backward
|
||||||
|
// compatibility when maybe full path wasn't logged.
|
||||||
|
dstIIP = dstForRenameTo(srcIIP, dstIIP);
|
||||||
|
return unprotectedRenameTo(fsd, srcIIP, dstIIP, timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if destination is a directory, append source child's name, else return
|
||||||
|
// iip as-is.
|
||||||
|
private static INodesInPath dstForRenameTo(
|
||||||
|
INodesInPath srcIIP, INodesInPath dstIIP) throws IOException {
|
||||||
|
INode dstINode = dstIIP.getLastINode();
|
||||||
|
if (dstINode != null && dstINode.isDirectory()) {
|
||||||
|
byte[] childName = srcIIP.getLastLocalName();
|
||||||
|
// new dest might exist so look it up.
|
||||||
|
INode childINode = dstINode.asDirectory().getChild(
|
||||||
|
childName, dstIIP.getPathSnapshotId());
|
||||||
|
dstIIP = INodesInPath.append(dstIIP, childINode, childName);
|
||||||
|
}
|
||||||
|
return dstIIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -141,12 +145,12 @@ class FSDirRenameOp {
|
||||||
* @param fsd FSDirectory
|
* @param fsd FSDirectory
|
||||||
* @param src source path
|
* @param src source path
|
||||||
* @param dst destination path
|
* @param dst destination path
|
||||||
* @return true if rename succeeds; false otherwise
|
* @return true INodesInPath if rename succeeds; null otherwise
|
||||||
* @deprecated See {@link #renameToInt(FSDirectory, String, String,
|
* @deprecated See {@link #renameToInt(FSDirectory, String, String,
|
||||||
* boolean, Options.Rename...)}
|
* boolean, Options.Rename...)}
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
static boolean unprotectedRenameTo(FSDirectory fsd, String src, String dst,
|
static INodesInPath unprotectedRenameTo(FSDirectory fsd,
|
||||||
final INodesInPath srcIIP, final INodesInPath dstIIP, long timestamp)
|
final INodesInPath srcIIP, final INodesInPath dstIIP, long timestamp)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
assert fsd.hasWriteLock();
|
assert fsd.hasWriteLock();
|
||||||
|
@ -156,32 +160,34 @@ class FSDirRenameOp {
|
||||||
} catch (SnapshotException e) {
|
} catch (SnapshotException e) {
|
||||||
throw e;
|
throw e;
|
||||||
} catch (IOException ignored) {
|
} catch (IOException ignored) {
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String src = srcIIP.getPath();
|
||||||
|
String dst = dstIIP.getPath();
|
||||||
// validate the destination
|
// validate the destination
|
||||||
if (dst.equals(src)) {
|
if (dst.equals(src)) {
|
||||||
return true;
|
return dstIIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
validateDestination(src, dst, srcInode);
|
validateDestination(src, dst, srcInode);
|
||||||
} catch (IOException ignored) {
|
} catch (IOException ignored) {
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dstIIP.getLastINode() != null) {
|
if (dstIIP.getLastINode() != null) {
|
||||||
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: " +
|
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: " +
|
||||||
"failed to rename " + src + " to " + dst + " because destination " +
|
"failed to rename " + src + " to " + dst + " because destination " +
|
||||||
"exists");
|
"exists");
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
INode dstParent = dstIIP.getINode(-2);
|
INode dstParent = dstIIP.getINode(-2);
|
||||||
if (dstParent == null) {
|
if (dstParent == null) {
|
||||||
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: " +
|
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: " +
|
||||||
"failed to rename " + src + " to " + dst + " because destination's " +
|
"failed to rename " + src + " to " + dst + " because destination's " +
|
||||||
"parent does not exist");
|
"parent does not exist");
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fsd.ezManager.checkMoveValidity(srcIIP, dstIIP, src);
|
fsd.ezManager.checkMoveValidity(srcIIP, dstIIP, src);
|
||||||
|
@ -189,17 +195,19 @@ class FSDirRenameOp {
|
||||||
verifyFsLimitsForRename(fsd, srcIIP, dstIIP);
|
verifyFsLimitsForRename(fsd, srcIIP, dstIIP);
|
||||||
verifyQuotaForRename(fsd, srcIIP, dstIIP);
|
verifyQuotaForRename(fsd, srcIIP, dstIIP);
|
||||||
|
|
||||||
RenameOperation tx = new RenameOperation(fsd, src, dst, srcIIP, dstIIP);
|
RenameOperation tx = new RenameOperation(fsd, srcIIP, dstIIP);
|
||||||
|
|
||||||
boolean added = false;
|
boolean added = false;
|
||||||
|
|
||||||
|
INodesInPath renamedIIP = null;
|
||||||
try {
|
try {
|
||||||
// remove src
|
// remove src
|
||||||
if (!tx.removeSrc4OldRename()) {
|
if (!tx.removeSrc4OldRename()) {
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
added = tx.addSourceToDestination();
|
renamedIIP = tx.addSourceToDestination();
|
||||||
|
added = (renamedIIP != null);
|
||||||
if (added) {
|
if (added) {
|
||||||
if (NameNode.stateChangeLog.isDebugEnabled()) {
|
if (NameNode.stateChangeLog.isDebugEnabled()) {
|
||||||
NameNode.stateChangeLog.debug("DIR* FSDirectory" +
|
NameNode.stateChangeLog.debug("DIR* FSDirectory" +
|
||||||
|
@ -209,7 +217,7 @@ class FSDirRenameOp {
|
||||||
tx.updateMtimeAndLease(timestamp);
|
tx.updateMtimeAndLease(timestamp);
|
||||||
tx.updateQuotasInSourceTree(fsd.getBlockStoragePolicySuite());
|
tx.updateQuotasInSourceTree(fsd.getBlockStoragePolicySuite());
|
||||||
|
|
||||||
return true;
|
return renamedIIP;
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
if (!added) {
|
if (!added) {
|
||||||
|
@ -218,13 +226,13 @@ class FSDirRenameOp {
|
||||||
}
|
}
|
||||||
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: " +
|
NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: " +
|
||||||
"failed to rename " + src + " to " + dst);
|
"failed to rename " + src + " to " + dst);
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The new rename which has the POSIX semantic.
|
* The new rename which has the POSIX semantic.
|
||||||
*/
|
*/
|
||||||
static Map.Entry<BlocksMapUpdateInfo, HdfsFileStatus> renameToInt(
|
static RenameResult renameToInt(
|
||||||
FSDirectory fsd, final String srcArg, final String dstArg,
|
FSDirectory fsd, final String srcArg, final String dstArg,
|
||||||
boolean logRetryCache, Options.Rename... options)
|
boolean logRetryCache, Options.Rename... options)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
@ -241,25 +249,19 @@ class FSDirRenameOp {
|
||||||
|
|
||||||
BlocksMapUpdateInfo collectedBlocks = new BlocksMapUpdateInfo();
|
BlocksMapUpdateInfo collectedBlocks = new BlocksMapUpdateInfo();
|
||||||
// returns resolved path
|
// returns resolved path
|
||||||
dst = renameTo(fsd, pc, src, dst, collectedBlocks, logRetryCache, options);
|
return renameTo(fsd, pc, src, dst, collectedBlocks, logRetryCache, options);
|
||||||
INodesInPath dstIIP = fsd.getINodesInPath(dst, false);
|
|
||||||
HdfsFileStatus resultingStat = fsd.getAuditFileInfo(dstIIP);
|
|
||||||
|
|
||||||
return new AbstractMap.SimpleImmutableEntry<>(
|
|
||||||
collectedBlocks, resultingStat);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see {@link #unprotectedRenameTo(FSDirectory, String, String, INodesInPath,
|
* @see {@link #unprotectedRenameTo(FSDirectory, String, String, INodesInPath,
|
||||||
* INodesInPath, long, BlocksMapUpdateInfo, Options.Rename...)}
|
* INodesInPath, long, BlocksMapUpdateInfo, Options.Rename...)}
|
||||||
*/
|
*/
|
||||||
static String renameTo(FSDirectory fsd, FSPermissionChecker pc, String src,
|
static RenameResult renameTo(FSDirectory fsd, FSPermissionChecker pc,
|
||||||
String dst, BlocksMapUpdateInfo collectedBlocks, boolean logRetryCache,
|
String src, String dst, BlocksMapUpdateInfo collectedBlocks,
|
||||||
Options.Rename... options) throws IOException {
|
boolean logRetryCache,Options.Rename... options)
|
||||||
|
throws IOException {
|
||||||
final INodesInPath srcIIP = fsd.resolvePathForWrite(pc, src, false);
|
final INodesInPath srcIIP = fsd.resolvePathForWrite(pc, src, false);
|
||||||
final INodesInPath dstIIP = fsd.resolvePathForWrite(pc, dst, false);
|
final INodesInPath dstIIP = fsd.resolvePathForWrite(pc, dst, false);
|
||||||
src = srcIIP.getPath();
|
|
||||||
dst = dstIIP.getPath();
|
|
||||||
if (fsd.isPermissionEnabled()) {
|
if (fsd.isPermissionEnabled()) {
|
||||||
// Rename does not operate on link targets
|
// Rename does not operate on link targets
|
||||||
// Do not resolveLink when checking permissions of src and dst
|
// Do not resolveLink when checking permissions of src and dst
|
||||||
|
@ -277,16 +279,19 @@ class FSDirRenameOp {
|
||||||
}
|
}
|
||||||
final long mtime = Time.now();
|
final long mtime = Time.now();
|
||||||
fsd.writeLock();
|
fsd.writeLock();
|
||||||
|
final RenameResult result;
|
||||||
try {
|
try {
|
||||||
if (unprotectedRenameTo(fsd, src, dst, srcIIP, dstIIP, mtime,
|
result = unprotectedRenameTo(fsd, srcIIP, dstIIP, mtime,
|
||||||
collectedBlocks, options)) {
|
collectedBlocks, options);
|
||||||
|
if (result.filesDeleted) {
|
||||||
FSDirDeleteOp.incrDeletedFileCount(1);
|
FSDirDeleteOp.incrDeletedFileCount(1);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
fsd.writeUnlock();
|
fsd.writeUnlock();
|
||||||
}
|
}
|
||||||
fsd.getEditLog().logRename(src, dst, mtime, logRetryCache, options);
|
fsd.getEditLog().logRename(
|
||||||
return dst;
|
srcIIP.getPath(), dstIIP.getPath(), mtime, logRetryCache, options);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -309,7 +314,7 @@ class FSDirRenameOp {
|
||||||
BlocksMapUpdateInfo collectedBlocks = new BlocksMapUpdateInfo();
|
BlocksMapUpdateInfo collectedBlocks = new BlocksMapUpdateInfo();
|
||||||
final INodesInPath srcIIP = fsd.getINodesInPath4Write(src, false);
|
final INodesInPath srcIIP = fsd.getINodesInPath4Write(src, false);
|
||||||
final INodesInPath dstIIP = fsd.getINodesInPath4Write(dst, false);
|
final INodesInPath dstIIP = fsd.getINodesInPath4Write(dst, false);
|
||||||
unprotectedRenameTo(fsd, src, dst, srcIIP, dstIIP, timestamp,
|
unprotectedRenameTo(fsd, srcIIP, dstIIP, timestamp,
|
||||||
collectedBlocks, options);
|
collectedBlocks, options);
|
||||||
if (!collectedBlocks.getToDeleteList().isEmpty()) {
|
if (!collectedBlocks.getToDeleteList().isEmpty()) {
|
||||||
fsd.getFSNamesystem().removeBlocksAndUpdateSafemodeTotal(collectedBlocks);
|
fsd.getFSNamesystem().removeBlocksAndUpdateSafemodeTotal(collectedBlocks);
|
||||||
|
@ -329,7 +334,7 @@ class FSDirRenameOp {
|
||||||
* @param options Rename options
|
* @param options Rename options
|
||||||
* @return whether a file/directory gets overwritten in the dst path
|
* @return whether a file/directory gets overwritten in the dst path
|
||||||
*/
|
*/
|
||||||
static boolean unprotectedRenameTo(FSDirectory fsd, String src, String dst,
|
static RenameResult unprotectedRenameTo(FSDirectory fsd,
|
||||||
final INodesInPath srcIIP, final INodesInPath dstIIP, long timestamp,
|
final INodesInPath srcIIP, final INodesInPath dstIIP, long timestamp,
|
||||||
BlocksMapUpdateInfo collectedBlocks, Options.Rename... options)
|
BlocksMapUpdateInfo collectedBlocks, Options.Rename... options)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
@ -337,6 +342,8 @@ class FSDirRenameOp {
|
||||||
boolean overwrite = options != null
|
boolean overwrite = options != null
|
||||||
&& Arrays.asList(options).contains(Options.Rename.OVERWRITE);
|
&& Arrays.asList(options).contains(Options.Rename.OVERWRITE);
|
||||||
|
|
||||||
|
final String src = srcIIP.getPath();
|
||||||
|
final String dst = dstIIP.getPath();
|
||||||
final String error;
|
final String error;
|
||||||
final INode srcInode = srcIIP.getLastINode();
|
final INode srcInode = srcIIP.getLastINode();
|
||||||
validateRenameSource(srcIIP);
|
validateRenameSource(srcIIP);
|
||||||
|
@ -382,7 +389,7 @@ class FSDirRenameOp {
|
||||||
verifyFsLimitsForRename(fsd, srcIIP, dstIIP);
|
verifyFsLimitsForRename(fsd, srcIIP, dstIIP);
|
||||||
verifyQuotaForRename(fsd, srcIIP, dstIIP);
|
verifyQuotaForRename(fsd, srcIIP, dstIIP);
|
||||||
|
|
||||||
RenameOperation tx = new RenameOperation(fsd, src, dst, srcIIP, dstIIP);
|
RenameOperation tx = new RenameOperation(fsd, srcIIP, dstIIP);
|
||||||
|
|
||||||
boolean undoRemoveSrc = true;
|
boolean undoRemoveSrc = true;
|
||||||
tx.removeSrc();
|
tx.removeSrc();
|
||||||
|
@ -398,7 +405,8 @@ class FSDirRenameOp {
|
||||||
}
|
}
|
||||||
|
|
||||||
// add src as dst to complete rename
|
// add src as dst to complete rename
|
||||||
if (tx.addSourceToDestination()) {
|
INodesInPath renamedIIP = tx.addSourceToDestination();
|
||||||
|
if (renamedIIP != null) {
|
||||||
undoRemoveSrc = false;
|
undoRemoveSrc = false;
|
||||||
if (NameNode.stateChangeLog.isDebugEnabled()) {
|
if (NameNode.stateChangeLog.isDebugEnabled()) {
|
||||||
NameNode.stateChangeLog.debug("DIR* FSDirectory.unprotectedRenameTo: "
|
NameNode.stateChangeLog.debug("DIR* FSDirectory.unprotectedRenameTo: "
|
||||||
|
@ -423,7 +431,8 @@ class FSDirRenameOp {
|
||||||
}
|
}
|
||||||
|
|
||||||
tx.updateQuotasInSourceTree(bsps);
|
tx.updateQuotasInSourceTree(bsps);
|
||||||
return filesDeleted;
|
return createRenameResult(
|
||||||
|
fsd, renamedIIP, filesDeleted, collectedBlocks);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
if (undoRemoveSrc) {
|
if (undoRemoveSrc) {
|
||||||
|
@ -443,17 +452,9 @@ class FSDirRenameOp {
|
||||||
* boolean, Options.Rename...)}
|
* boolean, Options.Rename...)}
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@SuppressWarnings("deprecation")
|
private static RenameResult renameTo(FSDirectory fsd, FSPermissionChecker pc,
|
||||||
private static boolean renameTo(FSDirectory fsd, FSPermissionChecker pc,
|
|
||||||
INodesInPath srcIIP, INodesInPath dstIIP, boolean logRetryCache)
|
INodesInPath srcIIP, INodesInPath dstIIP, boolean logRetryCache)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
String src = srcIIP.getPath();
|
|
||||||
String dst = dstIIP.getPath();
|
|
||||||
// Note: We should not be doing this. This is move() not renameTo().
|
|
||||||
if (fsd.isDir(dst)) {
|
|
||||||
dstIIP = INodesInPath.append(dstIIP, null, srcIIP.getLastLocalName());
|
|
||||||
}
|
|
||||||
final String actualDst = dstIIP.getPath();
|
|
||||||
if (fsd.isPermissionEnabled()) {
|
if (fsd.isPermissionEnabled()) {
|
||||||
// Check write access to parent of src
|
// Check write access to parent of src
|
||||||
fsd.checkPermission(pc, srcIIP, false, null, FsAction.WRITE, null, null,
|
fsd.checkPermission(pc, srcIIP, false, null, FsAction.WRITE, null, null,
|
||||||
|
@ -464,22 +465,24 @@ class FSDirRenameOp {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NameNode.stateChangeLog.isDebugEnabled()) {
|
if (NameNode.stateChangeLog.isDebugEnabled()) {
|
||||||
NameNode.stateChangeLog.debug("DIR* FSDirectory.renameTo: " + src + " to "
|
NameNode.stateChangeLog.debug("DIR* FSDirectory.renameTo: " +
|
||||||
+ dst);
|
srcIIP.getPath() + " to " + dstIIP.getPath());
|
||||||
}
|
}
|
||||||
final long mtime = Time.now();
|
final long mtime = Time.now();
|
||||||
boolean stat = false;
|
INodesInPath renameIIP;
|
||||||
fsd.writeLock();
|
fsd.writeLock();
|
||||||
try {
|
try {
|
||||||
stat = unprotectedRenameTo(fsd, src, actualDst, srcIIP, dstIIP, mtime);
|
renameIIP = unprotectedRenameTo(fsd, srcIIP, dstIIP, mtime);
|
||||||
} finally {
|
} finally {
|
||||||
fsd.writeUnlock();
|
fsd.writeUnlock();
|
||||||
}
|
}
|
||||||
if (stat) {
|
if (renameIIP != null) {
|
||||||
fsd.getEditLog().logRename(src, actualDst, mtime, logRetryCache);
|
fsd.getEditLog().logRename(
|
||||||
return true;
|
srcIIP.getPath(), dstIIP.getPath(), mtime, logRetryCache);
|
||||||
}
|
}
|
||||||
return false;
|
// this rename never overwrites the dest so files deleted and collected
|
||||||
|
// are irrelevant.
|
||||||
|
return createRenameResult(fsd, renameIIP, false, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void validateDestination(
|
private static void validateDestination(
|
||||||
|
@ -565,8 +568,6 @@ class FSDirRenameOp {
|
||||||
private final INodesInPath srcParentIIP;
|
private final INodesInPath srcParentIIP;
|
||||||
private INodesInPath dstIIP;
|
private INodesInPath dstIIP;
|
||||||
private final INodesInPath dstParentIIP;
|
private final INodesInPath dstParentIIP;
|
||||||
private final String src;
|
|
||||||
private final String dst;
|
|
||||||
private final INodeReference.WithCount withCount;
|
private final INodeReference.WithCount withCount;
|
||||||
private final int srcRefDstSnapshot;
|
private final int srcRefDstSnapshot;
|
||||||
private final INodeDirectory srcParent;
|
private final INodeDirectory srcParent;
|
||||||
|
@ -577,12 +578,9 @@ class FSDirRenameOp {
|
||||||
private INode srcChild;
|
private INode srcChild;
|
||||||
private INode oldDstChild;
|
private INode oldDstChild;
|
||||||
|
|
||||||
RenameOperation(FSDirectory fsd, String src, String dst,
|
RenameOperation(FSDirectory fsd, INodesInPath srcIIP, INodesInPath dstIIP)
|
||||||
INodesInPath srcIIP, INodesInPath dstIIP)
|
|
||||||
throws QuotaExceededException {
|
throws QuotaExceededException {
|
||||||
this.fsd = fsd;
|
this.fsd = fsd;
|
||||||
this.src = src;
|
|
||||||
this.dst = dst;
|
|
||||||
this.srcIIP = srcIIP;
|
this.srcIIP = srcIIP;
|
||||||
this.dstIIP = dstIIP;
|
this.dstIIP = dstIIP;
|
||||||
this.srcParentIIP = srcIIP.getParentINodesInPath();
|
this.srcParentIIP = srcIIP.getParentINodesInPath();
|
||||||
|
@ -628,8 +626,8 @@ class FSDirRenameOp {
|
||||||
long removeSrc() throws IOException {
|
long removeSrc() throws IOException {
|
||||||
long removedNum = fsd.removeLastINode(srcIIP);
|
long removedNum = fsd.removeLastINode(srcIIP);
|
||||||
if (removedNum == -1) {
|
if (removedNum == -1) {
|
||||||
String error = "Failed to rename " + src + " to " + dst +
|
String error = "Failed to rename " + srcIIP.getPath() + " to " +
|
||||||
" because the source can not be removed";
|
dstIIP.getPath() + " because the source can not be removed";
|
||||||
NameNode.stateChangeLog.warn("DIR* FSDirRenameOp.unprotectedRenameTo:" +
|
NameNode.stateChangeLog.warn("DIR* FSDirRenameOp.unprotectedRenameTo:" +
|
||||||
error);
|
error);
|
||||||
throw new IOException(error);
|
throw new IOException(error);
|
||||||
|
@ -645,8 +643,8 @@ class FSDirRenameOp {
|
||||||
final long removedSrc = fsd.removeLastINode(srcIIP);
|
final long removedSrc = fsd.removeLastINode(srcIIP);
|
||||||
if (removedSrc == -1) {
|
if (removedSrc == -1) {
|
||||||
NameNode.stateChangeLog.warn("DIR* FSDirRenameOp.unprotectedRenameTo: "
|
NameNode.stateChangeLog.warn("DIR* FSDirRenameOp.unprotectedRenameTo: "
|
||||||
+ "failed to rename " + src + " to " + dst + " because the source" +
|
+ "failed to rename " + srcIIP.getPath() + " to "
|
||||||
" can not be removed");
|
+ dstIIP.getPath() + " because the source can not be removed");
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
// update the quota count if necessary
|
// update the quota count if necessary
|
||||||
|
@ -667,7 +665,7 @@ class FSDirRenameOp {
|
||||||
return removedNum;
|
return removedNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean addSourceToDestination() {
|
INodesInPath addSourceToDestination() {
|
||||||
final INode dstParent = dstParentIIP.getLastINode();
|
final INode dstParent = dstParentIIP.getLastINode();
|
||||||
final byte[] dstChildName = dstIIP.getLastLocalName();
|
final byte[] dstChildName = dstIIP.getLastLocalName();
|
||||||
final INode toDst;
|
final INode toDst;
|
||||||
|
@ -679,7 +677,7 @@ class FSDirRenameOp {
|
||||||
toDst = new INodeReference.DstReference(dstParent.asDirectory(),
|
toDst = new INodeReference.DstReference(dstParent.asDirectory(),
|
||||||
withCount, dstIIP.getLatestSnapshotId());
|
withCount, dstIIP.getLatestSnapshotId());
|
||||||
}
|
}
|
||||||
return fsd.addLastINodeNoQuotaCheck(dstParentIIP, toDst) != null;
|
return fsd.addLastINodeNoQuotaCheck(dstParentIIP, toDst);
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateMtimeAndLease(long timestamp) throws QuotaExceededException {
|
void updateMtimeAndLease(long timestamp) throws QuotaExceededException {
|
||||||
|
@ -766,13 +764,27 @@ class FSDirRenameOp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class RenameOldResult {
|
private static RenameResult createRenameResult(FSDirectory fsd,
|
||||||
|
INodesInPath dst, boolean filesDeleted,
|
||||||
|
BlocksMapUpdateInfo collectedBlocks) throws IOException {
|
||||||
|
boolean success = (dst != null);
|
||||||
|
HdfsFileStatus auditStat = success ? fsd.getAuditFileInfo(dst) : null;
|
||||||
|
return new RenameResult(
|
||||||
|
success, auditStat, filesDeleted, collectedBlocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
static class RenameResult {
|
||||||
final boolean success;
|
final boolean success;
|
||||||
final HdfsFileStatus auditStat;
|
final HdfsFileStatus auditStat;
|
||||||
|
final boolean filesDeleted;
|
||||||
|
final BlocksMapUpdateInfo collectedBlocks;
|
||||||
|
|
||||||
RenameOldResult(boolean success, HdfsFileStatus auditStat) {
|
RenameResult(boolean success, HdfsFileStatus auditStat,
|
||||||
|
boolean filesDeleted, BlocksMapUpdateInfo collectedBlocks) {
|
||||||
this.success = success;
|
this.success = success;
|
||||||
this.auditStat = auditStat;
|
this.auditStat = auditStat;
|
||||||
|
this.filesDeleted = filesDeleted;
|
||||||
|
this.collectedBlocks = collectedBlocks;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -585,20 +585,6 @@ public class FSDirectory implements Closeable {
|
||||||
iip.getLastINode() == null;
|
iip.getLastINode() == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check whether the path specifies a directory
|
|
||||||
*/
|
|
||||||
boolean isDir(String src) throws UnresolvedLinkException {
|
|
||||||
src = normalizePath(src);
|
|
||||||
readLock();
|
|
||||||
try {
|
|
||||||
INode node = getINode(src, false);
|
|
||||||
return node != null && node.isDirectory();
|
|
||||||
} finally {
|
|
||||||
readUnlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tell the block manager to update the replication factors when delete
|
* Tell the block manager to update the replication factors when delete
|
||||||
* happens. Deleting a file or a snapshot might decrease the replication
|
* happens. Deleting a file or a snapshot might decrease the replication
|
||||||
|
|
|
@ -2818,7 +2818,7 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
|
||||||
boolean renameTo(String src, String dst, boolean logRetryCache)
|
boolean renameTo(String src, String dst, boolean logRetryCache)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
waitForLoadingFSImage();
|
waitForLoadingFSImage();
|
||||||
FSDirRenameOp.RenameOldResult ret = null;
|
FSDirRenameOp.RenameResult ret = null;
|
||||||
writeLock();
|
writeLock();
|
||||||
try {
|
try {
|
||||||
checkOperation(OperationCategory.WRITE);
|
checkOperation(OperationCategory.WRITE);
|
||||||
|
@ -2830,7 +2830,7 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
|
||||||
} finally {
|
} finally {
|
||||||
writeUnlock();
|
writeUnlock();
|
||||||
}
|
}
|
||||||
boolean success = ret != null && ret.success;
|
boolean success = ret.success;
|
||||||
if (success) {
|
if (success) {
|
||||||
getEditLog().logSync();
|
getEditLog().logSync();
|
||||||
}
|
}
|
||||||
|
@ -2843,7 +2843,7 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
|
||||||
boolean logRetryCache, Options.Rename... options)
|
boolean logRetryCache, Options.Rename... options)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
waitForLoadingFSImage();
|
waitForLoadingFSImage();
|
||||||
Map.Entry<BlocksMapUpdateInfo, HdfsFileStatus> res = null;
|
FSDirRenameOp.RenameResult res = null;
|
||||||
writeLock();
|
writeLock();
|
||||||
try {
|
try {
|
||||||
checkOperation(OperationCategory.WRITE);
|
checkOperation(OperationCategory.WRITE);
|
||||||
|
@ -2859,15 +2859,14 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
|
||||||
|
|
||||||
getEditLog().logSync();
|
getEditLog().logSync();
|
||||||
|
|
||||||
BlocksMapUpdateInfo collectedBlocks = res.getKey();
|
BlocksMapUpdateInfo collectedBlocks = res.collectedBlocks;
|
||||||
HdfsFileStatus auditStat = res.getValue();
|
|
||||||
if (!collectedBlocks.getToDeleteList().isEmpty()) {
|
if (!collectedBlocks.getToDeleteList().isEmpty()) {
|
||||||
removeBlocks(collectedBlocks);
|
removeBlocks(collectedBlocks);
|
||||||
collectedBlocks.clear();
|
collectedBlocks.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
logAuditEvent(true, "rename (options=" + Arrays.toString(options) +
|
logAuditEvent(true, "rename (options=" + Arrays.toString(options) +
|
||||||
")", src, dst, auditStat);
|
")", src, dst, res.auditStat);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue