@Override
  public Future<GcsFileMetadata> readObjectAsync(final ByteBuffer dst, final GcsFilename filename,
      long startOffsetBytes, long timeoutMillis) {
    Preconditions.checkArgument(startOffsetBytes >= 0, "%s: offset must be non-negative: %s", this,
        startOffsetBytes);
    final int n = dst.remaining();
    Preconditions.checkArgument(n > 0, "%s: dst full: %s", this, dst);
    final int want = Math.min(READ_LIMIT_BYTES, n);

    final HTTPRequest req = makeRequest(filename, null, GET, timeoutMillis);
    req.setHeader(
        new HTTPHeader(RANGE, "bytes=" + startOffsetBytes + "-" + (startOffsetBytes + want - 1)));
    final HTTPRequestInfo info = new HTTPRequestInfo(req);
    return new FutureWrapper<HTTPResponse, GcsFileMetadata>(urlfetch.fetchAsync(req)) {
      @Override
      protected GcsFileMetadata wrap(HTTPResponse resp) throws IOException {
        long totalLength;
        switch (resp.getResponseCode()) {
          case 200:
            totalLength = getLengthFromHeader(resp, X_GOOG_CONTENT_LENGTH);
            break;
          case 206:
            totalLength = getLengthFromContentRange(resp);
            break;
          case 404:
            throw new FileNotFoundException("Could not find: " + filename);
          case 416:
            throw new BadRangeException("Requested Range not satisfiable; perhaps read past EOF? "
                + URLFetchUtils.describeRequestAndResponse(info, resp));
          default:
            throw HttpErrorHandler.error(info, resp);
        }
        byte[] content = resp.getContent();
        Preconditions.checkState(content.length <= want, "%s: got %s > wanted %s", this,
            content.length, want);
        dst.put(content);
        return getMetadataFromResponse(filename, resp, totalLength);
      }

      @Override
      protected Throwable convertException(Throwable e) {
        return OauthRawGcsService.convertException(info, e);
      }
    };
  }
@ Override public Future < GcsFileMetadata > readObjectAsync ( final ByteBuffer dst , final GcsFilename filename , long startOffsetBytes , long timeoutMillis ) { Preconditions . checkArgument ( startOffsetBytes >= 0 , "%s: offset must be non-negative: %s" , this , startOffsetBytes ) ; final int n = dst . remaining ( ) ; Preconditions . checkArgument ( n > 0 , "%s: dst full: %s" , this , dst ) ; final int want = Math . min ( READ_LIMIT_BYTES , n ) ; final HTTPRequest req = makeRequest ( filename , null , GET , timeoutMillis ) ; req . setHeader ( new HTTPHeader ( RANGE , "bytes=" + startOffsetBytes + "-" + ( startOffsetBytes + want - 1 ) ) ) ; final HTTPRequestInfo info = new HTTPRequestInfo ( req ) ; return new FutureWrapper < HTTPResponse , GcsFileMetadata > ( urlfetch . fetchAsync ( req ) ) { @ Override protected GcsFileMetadata wrap ( HTTPResponse resp ) throws IOException { long totalLength ; switch ( resp . getResponseCode ( ) ) { case 200 : totalLength = getLengthFromHeader ( resp , X_GOOG_CONTENT_LENGTH ) ; break ; case 206 : totalLength = getLengthFromContentRange ( resp ) ; break ; case 404 : throw new FileNotFoundException ( "Could not find: " + filename ) ; case 416 : throw new BadRangeException ( "Requested Range not satisfiable; perhaps read past EOF? " + URLFetchUtils . describeRequestAndResponse ( info , resp ) ) ; default : throw HttpErrorHandler . error ( info , resp ) ; } byte [ ] content = resp . getContent ( ) ; Preconditions . checkState ( content . length <= want , "%s: got %s > wanted %s" , this , content . length , want ) ; dst . put ( content ) ; return getMetadataFromResponse ( filename , resp , totalLength ) ; } @ Override protected Throwable convertException ( Throwable e ) { return OauthRawGcsService . convertException ( info , e ) ; } } ; }
Might not fill all of dst.