in hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketEndpoint.java [106:293]
public Response get(
@PathParam("bucket") String bucketName,
@QueryParam("delimiter") String delimiter,
@QueryParam("encoding-type") String encodingType,
@QueryParam("marker") String marker,
@DefaultValue("1000") @QueryParam("max-keys") int maxKeys,
@QueryParam("prefix") String prefix,
@QueryParam("continuation-token") String continueToken,
@QueryParam("start-after") String startAfter,
@QueryParam("uploads") String uploads,
@QueryParam("acl") String aclMarker,
@QueryParam("key-marker") String keyMarker,
@QueryParam("upload-id-marker") String uploadIdMarker,
@DefaultValue("1000") @QueryParam("max-uploads") int maxUploads,
@Context HttpHeaders hh) throws OS3Exception, IOException {
long startNanos = Time.monotonicNowNanos();
S3GAction s3GAction = S3GAction.GET_BUCKET;
PerformanceStringBuilder perf = new PerformanceStringBuilder();
Iterator<? extends OzoneKey> ozoneKeyIterator = null;
ContinueToken decodedToken =
ContinueToken.decodeFromString(continueToken);
OzoneBucket bucket = null;
try {
if (aclMarker != null) {
s3GAction = S3GAction.GET_ACL;
S3BucketAcl result = getAcl(bucketName);
getMetrics().updateGetAclSuccessStats(startNanos);
AUDIT.logReadSuccess(
buildAuditMessageForSuccess(s3GAction, getAuditParameters()));
return Response.ok(result, MediaType.APPLICATION_XML_TYPE).build();
}
if (uploads != null) {
s3GAction = S3GAction.LIST_MULTIPART_UPLOAD;
return listMultipartUploads(bucketName, prefix, keyMarker, uploadIdMarker, maxUploads);
}
if (prefix == null) {
prefix = "";
}
// Assign marker to startAfter. for the compatibility of aws api v1
if (startAfter == null && marker != null) {
startAfter = marker;
}
// If continuation token and start after both are provided, then we
// ignore start After
String prevKey = continueToken != null ? decodedToken.getLastKey()
: startAfter;
// If shallow is true, only list immediate children
// delimited by OZONE_URI_DELIMITER
boolean shallow = listKeysShallowEnabled
&& OZONE_URI_DELIMITER.equals(delimiter);
bucket = getBucket(bucketName);
ozoneKeyIterator = bucket.listKeys(prefix, prevKey, shallow);
} catch (OMException ex) {
AUDIT.logReadFailure(
buildAuditMessageForFailure(s3GAction, getAuditParameters(), ex));
getMetrics().updateGetBucketFailureStats(startNanos);
if (isAccessDenied(ex)) {
throw newError(S3ErrorTable.ACCESS_DENIED, bucketName, ex);
} else if (ex.getResult() == ResultCodes.FILE_NOT_FOUND) {
// File not found, continue and send normal response with 0 keyCount
LOG.debug("Key Not found prefix: {}", prefix);
} else {
throw ex;
}
} catch (Exception ex) {
getMetrics().updateGetBucketFailureStats(startNanos);
AUDIT.logReadFailure(
buildAuditMessageForFailure(s3GAction, getAuditParameters(), ex));
throw ex;
}
// The valid encodingType Values is "url"
if (encodingType != null && !encodingType.equals(ENCODING_TYPE)) {
throw S3ErrorTable.newError(S3ErrorTable.INVALID_ARGUMENT, encodingType);
}
// If you specify the encoding-type request parameter,should return
// encoded key name values in the following response elements:
// Delimiter, Prefix, Key, and StartAfter.
//
// For detail refer:
// https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectsV2.html
// #AmazonS3-ListObjectsV2-response-EncodingType
//
ListObjectResponse response = new ListObjectResponse();
response.setDelimiter(
EncodingTypeObject.createNullable(delimiter, encodingType));
response.setName(bucketName);
response.setPrefix(EncodingTypeObject.createNullable(prefix, encodingType));
response.setMarker(marker == null ? "" : marker);
response.setMaxKeys(maxKeys);
response.setEncodingType(encodingType);
response.setTruncated(false);
response.setContinueToken(continueToken);
response.setStartAfter(
EncodingTypeObject.createNullable(startAfter, encodingType));
String prevDir = null;
if (continueToken != null) {
prevDir = decodedToken.getLastDir();
}
String lastKey = null;
int count = 0;
while (ozoneKeyIterator != null && ozoneKeyIterator.hasNext()) {
OzoneKey next = ozoneKeyIterator.next();
if (bucket != null && bucket.getBucketLayout().isFileSystemOptimized() &&
StringUtils.isNotEmpty(prefix) &&
!next.getName().startsWith(prefix)) {
// prefix has delimiter but key don't have
// example prefix: dir1/ key: dir123
continue;
}
if (startAfter != null && count == 0 && Objects.equals(startAfter, next.getName())) {
continue;
}
String relativeKeyName = next.getName().substring(prefix.length());
int depth = StringUtils.countMatches(relativeKeyName, delimiter);
if (!StringUtils.isEmpty(delimiter)) {
if (depth > 0) {
// means key has multiple delimiters in its value.
// ex: dir/dir1/dir2, where delimiter is "/" and prefix is dir/
String dirName = relativeKeyName.substring(0, relativeKeyName
.indexOf(delimiter));
if (!dirName.equals(prevDir)) {
response.addPrefix(EncodingTypeObject.createNullable(
prefix + dirName + delimiter, encodingType));
prevDir = dirName;
count++;
}
} else if (relativeKeyName.endsWith(delimiter)) {
// means or key is same as prefix with delimiter at end and ends with
// delimiter. ex: dir/, where prefix is dir and delimiter is /
response.addPrefix(
EncodingTypeObject.createNullable(relativeKeyName, encodingType));
count++;
} else {
// means our key is matched with prefix if prefix is given and it
// does not have any common prefix.
addKey(response, next);
count++;
}
} else {
addKey(response, next);
count++;
}
if (count == maxKeys) {
lastKey = next.getName();
break;
}
}
response.setKeyCount(count);
if (count < maxKeys) {
response.setTruncated(false);
} else if (ozoneKeyIterator.hasNext()) {
response.setTruncated(true);
ContinueToken nextToken = new ContinueToken(lastKey, prevDir);
response.setNextToken(nextToken.encodeToString());
// Set nextMarker to be lastKey. for the compatibility of aws api v1
response.setNextMarker(lastKey);
} else {
response.setTruncated(false);
}
int keyCount =
response.getCommonPrefixes().size() + response.getContents().size();
long opLatencyNs =
getMetrics().updateGetBucketSuccessStats(startNanos);
getMetrics().incListKeyCount(keyCount);
perf.appendCount(keyCount);
perf.appendOpLatencyNanos(opLatencyNs);
AUDIT.logReadSuccess(buildAuditMessageForSuccess(s3GAction,
getAuditParameters(), perf));
response.setKeyCount(keyCount);
return Response.ok(response).build();
}