in hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyRenameRequestWithFSO.java [74:236]
public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager, ExecutionContext context) {
final long trxnLogIndex = context.getIndex();
RenameKeyRequest renameKeyRequest = getOmRequest().getRenameKeyRequest();
KeyArgs keyArgs = renameKeyRequest.getKeyArgs();
Map<String, String> auditMap = buildAuditMap(keyArgs, renameKeyRequest);
String volumeName = keyArgs.getVolumeName();
String bucketName = keyArgs.getBucketName();
String fromKeyName = keyArgs.getKeyName();
String toKeyName = renameKeyRequest.getToKeyName();
OMMetrics omMetrics = ozoneManager.getMetrics();
omMetrics.incNumKeyRenames();
AuditLogger auditLogger = ozoneManager.getAuditLogger();
OMResponse.Builder omResponse = OmResponseUtil.getOMResponseBuilder(
getOmRequest());
OMMetadataManager omMetadataManager = ozoneManager.getMetadataManager();
boolean acquiredLock = false;
OMClientResponse omClientResponse = null;
Exception exception = null;
OmKeyInfo fromKeyValue;
Result result;
try {
if (fromKeyName.isEmpty()) {
throw new OMException("Source key name is empty",
OMException.ResultCodes.INVALID_KEY_NAME);
}
mergeOmLockDetails(omMetadataManager.getLock()
.acquireWriteLock(BUCKET_LOCK, volumeName, bucketName));
acquiredLock = getOmLockDetails().isLockAcquired();
// Validate bucket and volume exists or not.
validateBucketAndVolume(omMetadataManager, volumeName, bucketName);
// Check if fromKey exists
OzoneFileStatus fromKeyFileStatus = OMFileRequest.getOMKeyInfoIfExists(
omMetadataManager, volumeName, bucketName, fromKeyName, 0,
ozoneManager.getDefaultReplicationConfig());
// case-1) fromKeyName should exist, otw throws exception
if (fromKeyFileStatus == null) {
// TODO: Add support for renaming open key
throw new OMException("Key not found " + fromKeyName, KEY_NOT_FOUND);
}
if (fromKeyFileStatus.getKeyInfo().isHsync()) {
throw new OMException("Open file cannot be renamed since it is " +
"hsync'ed: volumeName=" + volumeName + ", bucketName=" +
bucketName + ", key=" + fromKeyName, RENAME_OPEN_FILE);
}
// source existed
fromKeyValue = fromKeyFileStatus.getKeyInfo();
boolean isRenameDirectory = fromKeyFileStatus.isDirectory();
// case-2) Cannot rename a directory to its own subdirectory
OMFileRequest.verifyToDirIsASubDirOfFromDirectory(fromKeyName,
toKeyName, fromKeyFileStatus.isDirectory());
OzoneFileStatus toKeyFileStatus = OMFileRequest.getOMKeyInfoIfExists(
omMetadataManager, volumeName, bucketName, toKeyName, 0,
ozoneManager.getDefaultReplicationConfig());
// Check if toKey exists.
if (toKeyFileStatus != null) {
// Destination exists and following are different cases:
OmKeyInfo toKeyValue = toKeyFileStatus.getKeyInfo();
if (fromKeyValue.getKeyName().equals(toKeyValue.getKeyName())) {
// case-3) If src == destin then check source and destin of same type
// (a) If dst is a file then return true.
// (b) Otherwise throws exception.
// TODO: Discuss do we need to throw exception for file as well.
if (toKeyFileStatus.isFile()) {
result = Result.SUCCESS;
} else {
throw new OMException("Key already exists " + toKeyName,
OMException.ResultCodes.KEY_ALREADY_EXISTS);
}
} else if (toKeyFileStatus.isDirectory()) {
// case-4) If dst is a directory then rename source as sub-path of it
// For example: rename /source to /dst will lead to /dst/source
String fromFileName = OzoneFSUtils.getFileName(fromKeyName);
String newToKeyName = OzoneFSUtils.appendFileNameToKeyPath(toKeyName,
fromFileName);
OzoneFileStatus newToOzoneFileStatus =
OMFileRequest.getOMKeyInfoIfExists(omMetadataManager,
volumeName, bucketName, newToKeyName, 0,
ozoneManager.getDefaultReplicationConfig());
if (newToOzoneFileStatus != null) {
// case-5) If new destin '/dst/source' exists then throws exception
throw new OMException(String.format(
"Failed to rename %s to %s, file already exists or not " +
"empty!", fromKeyName, newToKeyName),
OMException.ResultCodes.KEY_ALREADY_EXISTS);
}
omClientResponse = renameKey(toKeyValue, newToKeyName, fromKeyValue,
fromKeyName, isRenameDirectory, keyArgs.getModificationTime(),
ozoneManager, omResponse, trxnLogIndex);
result = Result.SUCCESS;
} else {
// case-6) If destination is a file type and if exists then throws
// key already exists exception.
throw new OMException("Failed to rename, key already exists "
+ toKeyName, OMException.ResultCodes.KEY_ALREADY_EXISTS);
}
} else {
// Destination doesn't exist and the cases are:
// case-7) Check whether dst parent dir exists or not. If parent
// doesn't exist then throw exception, otw the source can be renamed to
// destination path.
OmKeyInfo toKeyParent = OMFileRequest.getKeyParentDir(volumeName,
bucketName, toKeyName, ozoneManager, omMetadataManager);
omClientResponse = renameKey(toKeyParent, toKeyName, fromKeyValue,
fromKeyName, isRenameDirectory, keyArgs.getModificationTime(),
ozoneManager, omResponse, trxnLogIndex);
result = Result.SUCCESS;
}
} catch (IOException | InvalidPathException ex) {
result = Result.FAILURE;
exception = ex;
omClientResponse = new OMKeyRenameResponseWithFSO(createErrorOMResponse(
omResponse, exception), getBucketLayout());
} finally {
if (acquiredLock) {
mergeOmLockDetails(omMetadataManager.getLock()
.releaseWriteLock(BUCKET_LOCK, volumeName, bucketName));
}
if (omClientResponse != null) {
omClientResponse.setOmLockDetails(getOmLockDetails());
}
}
markForAudit(auditLogger, buildAuditMessage(OMAction.RENAME_KEY, auditMap,
exception, getOmRequest().getUserInfo()));
switch (result) {
case SUCCESS:
LOG.debug("Rename Key is successfully completed for volume:{} bucket:{}" +
" fromKey:{} toKey:{}. ", volumeName, bucketName,
fromKeyName, toKeyName);
break;
case FAILURE:
ozoneManager.getMetrics().incNumKeyRenameFails();
LOG.error("Rename key failed for volume:{} bucket:{} fromKey:{} " +
"toKey:{}. Exception: {}.", volumeName, bucketName,
fromKeyName, toKeyName, exception.getMessage());
break;
default:
LOG.error("Unrecognized Result for OMKeyRenameRequest: {}",
renameKeyRequest);
}
return omClientResponse;
}