use of com.google.appengine.tools.cloudstorage.BadRangeException in project appengine-gcs-client by GoogleCloudPlatform.
the class OauthRawGcsService method readObjectAsync.
/**
* Might not fill all of dst.
*/
@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);
}
};
}
use of com.google.appengine.tools.cloudstorage.BadRangeException in project appengine-gcs-client by GoogleCloudPlatform.
the class LocalRawGcsService method readObjectAsync.
@Override
public Future<GcsFileMetadata> readObjectAsync(ByteBuffer dst, GcsFilename filename, long offset, long timeoutMillis) {
Preconditions.checkArgument(offset >= 0, "%s: offset must be non-negative: %s", this, offset);
try {
ensureInitialized();
GcsFileMetadata meta = getObjectMetadata(filename, timeoutMillis);
if (meta == null) {
return Futures.immediateFailedFuture(new FileNotFoundException(this + ": No such file: " + filename));
}
if (offset >= meta.getLength()) {
return Futures.immediateFailedFuture(new BadRangeException("The requested range cannot be satisfied. bytes=" + Long.toString(offset) + "-" + Long.toString(offset + dst.remaining()) + " the file is only " + meta.getLength()));
}
int read = 0;
try (ReadableByteChannel readChannel = Channels.newChannel(blobStorage.fetchBlob(getBlobKeyForFilename(filename)))) {
if (offset > 0) {
long bytesRemaining = offset;
ByteBuffer seekBuffer = ByteBuffer.allocate(1024);
while (bytesRemaining > 0) {
if (bytesRemaining < seekBuffer.limit()) {
seekBuffer.limit((int) bytesRemaining);
}
read = readChannel.read(seekBuffer);
if (read == -1) {
return Futures.immediateFailedFuture(new BadRangeException("The requested range cannot be satisfied; seek failed with " + Long.toString(bytesRemaining) + " bytes remaining."));
}
bytesRemaining -= read;
seekBuffer.clear();
}
read = 0;
}
while (read != -1 && dst.hasRemaining()) {
read = readChannel.read(dst);
}
}
return Futures.immediateFuture(meta);
} catch (IOException e) {
return Futures.immediateFailedFuture(e);
}
}
Aggregations