public Response get()

in hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ObjectEndpoint.java [416:584]


  public Response get(
      @PathParam("bucket") String bucketName,
      @PathParam("path") String keyPath,
      @QueryParam("partNumber") int partNumber,
      @QueryParam("uploadId") String uploadId,
      @QueryParam("max-parts") @DefaultValue("1000") int maxParts,
      @QueryParam("part-number-marker") String partNumberMarker,
      @QueryParam("tagging") String taggingMarker)
      throws IOException, OS3Exception {
    long startNanos = Time.monotonicNowNanos();
    S3GAction s3GAction = S3GAction.GET_KEY;
    PerformanceStringBuilder perf = new PerformanceStringBuilder();
    try {
      if (taggingMarker != null) {
        s3GAction = S3GAction.GET_OBJECT_TAGGING;
        return getObjectTagging(bucketName, keyPath);
      }

      if (uploadId != null) {
        // When we have uploadId, this is the request for list Parts.
        s3GAction = S3GAction.LIST_PARTS;
        int partMarker = parsePartNumberMarker(partNumberMarker);
        Response response = listParts(bucketName, keyPath, uploadId,
            partMarker, maxParts, perf);
        AUDIT.logReadSuccess(buildAuditMessageForSuccess(s3GAction,
            getAuditParameters(), perf));
        return response;
      }

      OzoneKeyDetails keyDetails = (partNumber != 0) ?
          getClientProtocol().getS3KeyDetails(bucketName, keyPath, partNumber) :
          getClientProtocol().getS3KeyDetails(bucketName, keyPath);

      isFile(keyPath, keyDetails);

      long length = keyDetails.getDataSize();

      LOG.debug("Data length of the key {} is {}", keyPath, length);

      String rangeHeaderVal = headers.getHeaderString(RANGE_HEADER);
      RangeHeader rangeHeader = null;

      LOG.debug("range Header provided value: {}", rangeHeaderVal);

      if (rangeHeaderVal != null) {
        rangeHeader = RangeHeaderParserUtil.parseRangeHeader(rangeHeaderVal,
            length);
        LOG.debug("range Header provided: {}", rangeHeader);
        if (rangeHeader.isInValidRange()) {
          throw newError(S3ErrorTable.INVALID_RANGE, rangeHeaderVal);
        }
      }
      ResponseBuilder responseBuilder;

      if (rangeHeaderVal == null || rangeHeader.isReadFull()) {
        StreamingOutput output = dest -> {
          try (OzoneInputStream key = keyDetails.getContent()) {
            long readLength = IOUtils.copy(key, dest, getIOBufferSize(keyDetails.getDataSize()));
            getMetrics().incGetKeySuccessLength(readLength);
            perf.appendSizeBytes(readLength);
          }
          long opLatencyNs =  getMetrics().updateGetKeySuccessStats(startNanos);
          perf.appendOpLatencyNanos(opLatencyNs);
          AUDIT.logReadSuccess(buildAuditMessageForSuccess(S3GAction.GET_KEY,
              getAuditParameters(), perf));
        };
        responseBuilder = Response
            .ok(output)
            .header(CONTENT_LENGTH, keyDetails.getDataSize());

      } else {

        long startOffset = rangeHeader.getStartOffset();
        long endOffset = rangeHeader.getEndOffset();
        // eg. if range header is given as bytes=0-0, then we should return 1
        // byte from start offset
        long copyLength = endOffset - startOffset + 1;
        StreamingOutput output = dest -> {
          try (OzoneInputStream ozoneInputStream = keyDetails.getContent()) {
            ozoneInputStream.seek(startOffset);
            long readLength = IOUtils.copyLarge(ozoneInputStream, dest, 0,
                copyLength, new byte[getIOBufferSize(copyLength)]);
            getMetrics().incGetKeySuccessLength(readLength);
            perf.appendSizeBytes(readLength);
          }
          long opLatencyNs = getMetrics().updateGetKeySuccessStats(startNanos);
          perf.appendOpLatencyNanos(opLatencyNs);
          AUDIT.logReadSuccess(buildAuditMessageForSuccess(S3GAction.GET_KEY,
              getAuditParameters(), perf));
        };
        responseBuilder = Response
            .status(Status.PARTIAL_CONTENT)
            .entity(output)
            .header(CONTENT_LENGTH, copyLength);

        String contentRangeVal = RANGE_HEADER_SUPPORTED_UNIT + " " +
            rangeHeader.getStartOffset() + "-" + rangeHeader.getEndOffset() +
            "/" + length;

        responseBuilder.header(CONTENT_RANGE_HEADER, contentRangeVal);
      }
      responseBuilder
          .header(ACCEPT_RANGE_HEADER, RANGE_HEADER_SUPPORTED_UNIT);

      String eTag = keyDetails.getMetadata().get(ETAG);
      if (eTag != null) {
        responseBuilder.header(ETAG, wrapInQuotes(eTag));
        String partsCount = extractPartsCount(eTag);
        if (partsCount != null) {
          responseBuilder.header(MP_PARTS_COUNT, partsCount);
        }
      }

      // if multiple query parameters having same name,
      // Only the first parameters will be recognized
      // eg:
      // http://localhost:9878/bucket/key?response-expires=1&response-expires=2
      // only response-expires=1 is valid
      MultivaluedMap<String, String> queryParams = context
          .getUriInfo().getQueryParameters();

      for (Map.Entry<String, String> entry :
          overrideQueryParameter.entrySet()) {
        String headerValue = headers.getHeaderString(entry.getKey());

        /* "Overriding Response Header" by query parameter, See:
        https://docs.aws.amazon.com/de_de/AmazonS3/latest/API/API_GetObject.html
        */
        String queryValue = queryParams.getFirst(entry.getValue());
        if (queryValue != null) {
          headerValue = queryValue;
        }
        if (headerValue != null) {
          responseBuilder.header(entry.getKey(), headerValue);
        }
      }
      addLastModifiedDate(responseBuilder, keyDetails);
      addTagCountIfAny(responseBuilder, keyDetails);
      long metadataLatencyNs =
          getMetrics().updateGetKeyMetadataStats(startNanos);
      perf.appendMetaLatencyNanos(metadataLatencyNs);
      return responseBuilder.build();
    } catch (OMException ex) {
      AUDIT.logReadFailure(
          buildAuditMessageForFailure(s3GAction, getAuditParameters(), ex)
      );
      if (taggingMarker != null) {
        getMetrics().updateGetObjectTaggingFailureStats(startNanos);
      } else if (uploadId != null) {
        getMetrics().updateListPartsFailureStats(startNanos);
      } else {
        getMetrics().updateGetKeyFailureStats(startNanos);
      }
      if (ex.getResult() == ResultCodes.KEY_NOT_FOUND) {
        throw newError(S3ErrorTable.NO_SUCH_KEY, keyPath, ex);
      } else if (isAccessDenied(ex)) {
        throw newError(S3ErrorTable.ACCESS_DENIED, keyPath, ex);
      } else if (ex.getResult() == ResultCodes.BUCKET_NOT_FOUND) {
        throw newError(S3ErrorTable.NO_SUCH_BUCKET, bucketName, ex);
      } else {
        throw ex;
      }
    } catch (Exception ex) {
      AUDIT.logReadFailure(
          buildAuditMessageForFailure(s3GAction, getAuditParameters(), ex)
      );
      throw ex;
    }
  }