|
@@ -1749,27 +1749,76 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
|
|
|
logAuditEvent(true, "setOwner", srcArg, null, resultingStat);
|
|
|
}
|
|
|
|
|
|
+ static class GetBlockLocationsResult {
|
|
|
+ final INodesInPath iip;
|
|
|
+ final LocatedBlocks blocks;
|
|
|
+ boolean updateAccessTime() {
|
|
|
+ return iip != null;
|
|
|
+ }
|
|
|
+ private GetBlockLocationsResult(INodesInPath iip, LocatedBlocks blocks) {
|
|
|
+ this.iip = iip;
|
|
|
+ this.blocks = blocks;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Get block locations within the specified range.
|
|
|
* @see ClientProtocol#getBlockLocations(String, long, long)
|
|
|
*/
|
|
|
LocatedBlocks getBlockLocations(String clientMachine, String src,
|
|
|
- long offset, long length) throws AccessControlException,
|
|
|
- FileNotFoundException, UnresolvedLinkException, IOException {
|
|
|
- LocatedBlocks blocks = getBlockLocations(src, offset, length, true, true,
|
|
|
- true);
|
|
|
+ long offset, long length) throws IOException {
|
|
|
+ checkOperation(OperationCategory.READ);
|
|
|
+ GetBlockLocationsResult res = null;
|
|
|
+ readLock();
|
|
|
+ try {
|
|
|
+ checkOperation(OperationCategory.READ);
|
|
|
+ res = getBlockLocations(src, offset, length, true, true);
|
|
|
+ } catch (AccessControlException e) {
|
|
|
+ logAuditEvent(false, "open", src);
|
|
|
+ throw e;
|
|
|
+ } finally {
|
|
|
+ readUnlock();
|
|
|
+ }
|
|
|
+
|
|
|
+ logAuditEvent(true, "open", src);
|
|
|
+
|
|
|
+ if (res == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (res.updateAccessTime()) {
|
|
|
+ writeLock();
|
|
|
+ final long now = now();
|
|
|
+ try {
|
|
|
+ checkOperation(OperationCategory.WRITE);
|
|
|
+ INode inode = res.iip.getLastINode();
|
|
|
+ boolean updateAccessTime = now > inode.getAccessTime() +
|
|
|
+ getAccessTimePrecision();
|
|
|
+ if (!isInSafeMode() && updateAccessTime) {
|
|
|
+ boolean changed = dir.setTimes(
|
|
|
+ inode, -1, now, false, res.iip.getLatestSnapshotId());
|
|
|
+ if (changed) {
|
|
|
+ getEditLog().logTimes(src, -1, now);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Throwable e) {
|
|
|
+ LOG.warn("Failed to update the access time of " + src, e);
|
|
|
+ } finally {
|
|
|
+ writeUnlock();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ LocatedBlocks blocks = res.blocks;
|
|
|
if (blocks != null) {
|
|
|
- blockManager.getDatanodeManager().sortLocatedBlocks(clientMachine,
|
|
|
- blocks.getLocatedBlocks());
|
|
|
+ blockManager.getDatanodeManager().sortLocatedBlocks(
|
|
|
+ clientMachine, blocks.getLocatedBlocks());
|
|
|
|
|
|
// lastBlock is not part of getLocatedBlocks(), might need to sort it too
|
|
|
LocatedBlock lastBlock = blocks.getLastLocatedBlock();
|
|
|
if (lastBlock != null) {
|
|
|
- ArrayList<LocatedBlock> lastBlockList =
|
|
|
- Lists.newArrayListWithCapacity(1);
|
|
|
- lastBlockList.add(lastBlock);
|
|
|
- blockManager.getDatanodeManager().sortLocatedBlocks(clientMachine,
|
|
|
- lastBlockList);
|
|
|
+ ArrayList<LocatedBlock> lastBlockList = Lists.newArrayList(lastBlock);
|
|
|
+ blockManager.getDatanodeManager().sortLocatedBlocks(
|
|
|
+ clientMachine, lastBlockList);
|
|
|
}
|
|
|
}
|
|
|
return blocks;
|
|
@@ -1778,24 +1827,11 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
|
|
|
/**
|
|
|
* Get block locations within the specified range.
|
|
|
* @see ClientProtocol#getBlockLocations(String, long, long)
|
|
|
- * @throws FileNotFoundException, UnresolvedLinkException, IOException
|
|
|
+ * @throws IOException
|
|
|
*/
|
|
|
- LocatedBlocks getBlockLocations(String src, long offset, long length,
|
|
|
- boolean doAccessTime, boolean needBlockToken, boolean checkSafeMode)
|
|
|
- throws FileNotFoundException, UnresolvedLinkException, IOException {
|
|
|
- try {
|
|
|
- return getBlockLocationsInt(src, offset, length, doAccessTime,
|
|
|
- needBlockToken, checkSafeMode);
|
|
|
- } catch (AccessControlException e) {
|
|
|
- logAuditEvent(false, "open", src);
|
|
|
- throw e;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private LocatedBlocks getBlockLocationsInt(String src, long offset,
|
|
|
- long length, boolean doAccessTime, boolean needBlockToken,
|
|
|
- boolean checkSafeMode)
|
|
|
- throws FileNotFoundException, UnresolvedLinkException, IOException {
|
|
|
+ GetBlockLocationsResult getBlockLocations(
|
|
|
+ String src, long offset, long length, boolean needBlockToken,
|
|
|
+ boolean checkSafeMode) throws IOException {
|
|
|
if (offset < 0) {
|
|
|
throw new HadoopIllegalArgumentException(
|
|
|
"Negative offset is not supported. File: " + src);
|
|
@@ -1804,16 +1840,16 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
|
|
|
throw new HadoopIllegalArgumentException(
|
|
|
"Negative length is not supported. File: " + src);
|
|
|
}
|
|
|
- final LocatedBlocks ret = getBlockLocationsUpdateTimes(src,
|
|
|
- offset, length, doAccessTime, needBlockToken);
|
|
|
- logAuditEvent(true, "open", src);
|
|
|
+ final GetBlockLocationsResult ret = getBlockLocationsInt(
|
|
|
+ src, offset, length, needBlockToken);
|
|
|
+
|
|
|
if (checkSafeMode && isInSafeMode()) {
|
|
|
- for (LocatedBlock b : ret.getLocatedBlocks()) {
|
|
|
+ for (LocatedBlock b : ret.blocks.getLocatedBlocks()) {
|
|
|
// if safemode & no block locations yet then throw safemodeException
|
|
|
if ((b.getLocations() == null) || (b.getLocations().length == 0)) {
|
|
|
SafeModeException se = new SafeModeException(
|
|
|
"Zero blocklocations for " + src, safeMode);
|
|
|
- if (haEnabled && haContext != null &&
|
|
|
+ if (haEnabled && haContext != null &&
|
|
|
haContext.getState().getServiceState() == HAServiceState.ACTIVE) {
|
|
|
throw new RetriableException(se);
|
|
|
} else {
|
|
@@ -1825,95 +1861,49 @@ public class FSNamesystem implements Namesystem, FSNamesystemMBean,
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- * Get block locations within the specified range, updating the
|
|
|
- * access times if necessary.
|
|
|
- */
|
|
|
- private LocatedBlocks getBlockLocationsUpdateTimes(final String srcArg,
|
|
|
- long offset, long length, boolean doAccessTime, boolean needBlockToken)
|
|
|
+ private GetBlockLocationsResult getBlockLocationsInt(
|
|
|
+ final String srcArg, long offset, long length, boolean needBlockToken)
|
|
|
throws IOException {
|
|
|
String src = srcArg;
|
|
|
FSPermissionChecker pc = getPermissionChecker();
|
|
|
byte[][] pathComponents = FSDirectory.getPathComponentsForReservedPath(src);
|
|
|
- for (int attempt = 0; attempt < 2; attempt++) {
|
|
|
- boolean isReadOp = (attempt == 0);
|
|
|
- if (isReadOp) { // first attempt is with readlock
|
|
|
- checkOperation(OperationCategory.READ);
|
|
|
- readLock();
|
|
|
- } else { // second attempt is with write lock
|
|
|
- checkOperation(OperationCategory.WRITE);
|
|
|
- writeLock(); // writelock is needed to set accesstime
|
|
|
- }
|
|
|
- try {
|
|
|
- if (isReadOp) {
|
|
|
- checkOperation(OperationCategory.READ);
|
|
|
- } else {
|
|
|
- checkOperation(OperationCategory.WRITE);
|
|
|
- }
|
|
|
- src = dir.resolvePath(pc, src, pathComponents);
|
|
|
- final INodesInPath iip = dir.getINodesInPath(src, true);
|
|
|
- if (isPermissionEnabled) {
|
|
|
- dir.checkPathAccess(pc, iip, FsAction.READ);
|
|
|
- }
|
|
|
+ src = dir.resolvePath(pc, src, pathComponents);
|
|
|
+ final INodesInPath iip = dir.getINodesInPath(src, true);
|
|
|
+ final INodeFile inode = INodeFile.valueOf(iip.getLastINode(), src);
|
|
|
+ if (isPermissionEnabled) {
|
|
|
+ dir.checkPathAccess(pc, iip, FsAction.READ);
|
|
|
+ checkUnreadableBySuperuser(pc, inode, iip.getPathSnapshotId());
|
|
|
+ }
|
|
|
|
|
|
- // if the namenode is in safemode, then do not update access time
|
|
|
- if (isInSafeMode()) {
|
|
|
- doAccessTime = false;
|
|
|
- }
|
|
|
+ final long fileSize = iip.isSnapshot()
|
|
|
+ ? inode.computeFileSize(iip.getPathSnapshotId())
|
|
|
+ : inode.computeFileSizeNotIncludingLastUcBlock();
|
|
|
+ boolean isUc = inode.isUnderConstruction();
|
|
|
+ if (iip.isSnapshot()) {
|
|
|
+ // if src indicates a snapshot file, we need to make sure the returned
|
|
|
+ // blocks do not exceed the size of the snapshot file.
|
|
|
+ length = Math.min(length, fileSize - offset);
|
|
|
+ isUc = false;
|
|
|
+ }
|
|
|
|
|
|
- final INodeFile inode = INodeFile.valueOf(iip.getLastINode(), src);
|
|
|
- if (isPermissionEnabled) {
|
|
|
- checkUnreadableBySuperuser(pc, inode, iip.getPathSnapshotId());
|
|
|
- }
|
|
|
- if (!iip.isSnapshot() //snapshots are readonly, so don't update atime.
|
|
|
- && doAccessTime && isAccessTimeSupported()) {
|
|
|
- final long now = now();
|
|
|
- if (now > inode.getAccessTime() + getAccessTimePrecision()) {
|
|
|
- // if we have to set access time but we only have the readlock, then
|
|
|
- // restart this entire operation with the writeLock.
|
|
|
- if (isReadOp) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- boolean changed = dir.setTimes(inode, -1, now, false,
|
|
|
- iip.getLatestSnapshotId());
|
|
|
- if (changed) {
|
|
|
- getEditLog().logTimes(src, -1, now);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- final long fileSize = iip.isSnapshot() ?
|
|
|
- inode.computeFileSize(iip.getPathSnapshotId())
|
|
|
- : inode.computeFileSizeNotIncludingLastUcBlock();
|
|
|
- boolean isUc = inode.isUnderConstruction();
|
|
|
- if (iip.isSnapshot()) {
|
|
|
- // if src indicates a snapshot file, we need to make sure the returned
|
|
|
- // blocks do not exceed the size of the snapshot file.
|
|
|
- length = Math.min(length, fileSize - offset);
|
|
|
- isUc = false;
|
|
|
- }
|
|
|
+ final FileEncryptionInfo feInfo =
|
|
|
+ FSDirectory.isReservedRawName(srcArg) ? null
|
|
|
+ : dir.getFileEncryptionInfo(inode, iip.getPathSnapshotId(), iip);
|
|
|
|
|
|
- final FileEncryptionInfo feInfo =
|
|
|
- FSDirectory.isReservedRawName(srcArg) ?
|
|
|
- null : dir.getFileEncryptionInfo(inode, iip.getPathSnapshotId(),
|
|
|
- iip);
|
|
|
-
|
|
|
- final LocatedBlocks blocks =
|
|
|
- blockManager.createLocatedBlocks(inode.getBlocks(), fileSize,
|
|
|
- isUc, offset, length, needBlockToken, iip.isSnapshot(), feInfo);
|
|
|
- // Set caching information for the located blocks.
|
|
|
- for (LocatedBlock lb: blocks.getLocatedBlocks()) {
|
|
|
- cacheManager.setCachedLocations(lb);
|
|
|
- }
|
|
|
- return blocks;
|
|
|
- } finally {
|
|
|
- if (isReadOp) {
|
|
|
- readUnlock();
|
|
|
- } else {
|
|
|
- writeUnlock();
|
|
|
- }
|
|
|
- }
|
|
|
+ final LocatedBlocks blocks = blockManager.createLocatedBlocks(
|
|
|
+ inode.getBlocks(), fileSize, isUc, offset, length, needBlockToken,
|
|
|
+ iip.isSnapshot(), feInfo);
|
|
|
+
|
|
|
+ // Set caching information for the located blocks.
|
|
|
+ for (LocatedBlock lb : blocks.getLocatedBlocks()) {
|
|
|
+ cacheManager.setCachedLocations(lb);
|
|
|
}
|
|
|
- return null; // can never reach here
|
|
|
+
|
|
|
+ final long now = now();
|
|
|
+ boolean updateAccessTime = isAccessTimeSupported() && !isInSafeMode()
|
|
|
+ && !iip.isSnapshot()
|
|
|
+ && now > inode.getAccessTime() + getAccessTimePrecision();
|
|
|
+ return new GetBlockLocationsResult(updateAccessTime ? iip : null, blocks);
|
|
|
}
|
|
|
|
|
|
/**
|