use of com.github.ambry.router.FutureResult in project ambry by linkedin.
the class PerfRouter method getBlob.
@Override
public Future<GetBlobResult> getBlob(String blobId, GetBlobOptions options, Callback<GetBlobResult> callback) {
logger.trace("Received getBlob call");
FutureResult<GetBlobResult> futureResult = new FutureResult<>();
if (!routerOpen) {
completeOperation(futureResult, callback, null, ROUTER_CLOSED_EXCEPTION);
} else {
GetBlobResult result = null;
switch(options.getOperationType()) {
case All:
result = new GetBlobResult(new BlobInfo(blobProperties, usermetadata), new PerfRSC(chunk, blobProperties.getBlobSize()));
break;
case Data:
result = new GetBlobResult(null, new PerfRSC(chunk, blobProperties.getBlobSize()));
break;
case BlobInfo:
result = new GetBlobResult(new BlobInfo(blobProperties, usermetadata), null);
break;
}
completeOperation(futureResult, callback, result, null);
}
return futureResult;
}
use of com.github.ambry.router.FutureResult in project ambry by linkedin.
the class NamedBlobPutHandlerTest method stitchBlobAndVerify.
/**
* Make a stitch blob call using {@link PostBlobHandler} and verify the result of the operation.
* @param requestBody the body of the stitch request to supply.
* @param expectedStitchedChunks the expected chunks stitched together.
* @param errorChecker if non-null, expect an exception to be thrown by the post flow and verify it using this
* {@link ThrowingConsumer}.
* @throws Exception
*/
private void stitchBlobAndVerify(byte[] requestBody, List<ChunkInfo> expectedStitchedChunks, ThrowingConsumer<ExecutionException> errorChecker) throws Exception {
// call
for (long ttl : new long[] { TestUtils.TTL_SECS, Utils.Infinite_Time }) {
JSONObject headers = new JSONObject();
FrontendRestRequestServiceTest.setAmbryHeadersForPut(headers, ttl, !REF_CONTAINER.isCacheable(), SERVICE_ID, CONTENT_TYPE, OWNER_ID, null, null, "STITCH");
RestRequest request = getRestRequest(headers, request_path, requestBody);
RestResponseChannel restResponseChannel = new MockRestResponseChannel();
FutureResult<Void> future = new FutureResult<>();
idConverterFactory.lastInput = null;
idConverterFactory.lastBlobInfo = null;
idConverterFactory.lastConvertedId = null;
namedBlobPutHandler.handle(request, restResponseChannel, future::done);
if (errorChecker == null) {
future.get(TIMEOUT_SECS, TimeUnit.SECONDS);
assertEquals("Unexpected location header", idConverterFactory.lastConvertedId, restResponseChannel.getHeader(RestUtils.Headers.LOCATION));
InMemoryRouter.InMemoryBlob blob = router.getActiveBlobs().get(idConverterFactory.lastInput);
assertEquals("List of chunks stitched does not match expected", expectedStitchedChunks, blob.getStitchedChunks());
ByteArrayOutputStream expectedContent = new ByteArrayOutputStream();
expectedStitchedChunks.stream().map(chunkInfo -> router.getActiveBlobs().get(chunkInfo.getBlobId()).getBlob().array()).forEach(buf -> expectedContent.write(buf, 0, buf.length));
assertEquals("Unexpected blob content stored", ByteBuffer.wrap(expectedContent.toByteArray()), blob.getBlob());
// check actual size of stitched blob
assertEquals("Unexpected blob size", Long.toString(getStitchedBlobSize(expectedStitchedChunks)), restResponseChannel.getHeader(RestUtils.Headers.BLOB_SIZE));
assertEquals("Unexpected TTL in named blob DB", ttl, idConverterFactory.lastBlobInfo.getBlobProperties().getTimeToLiveInSeconds());
assertEquals("Unexpected TTL in blob", ttl, blob.getBlobProperties().getTimeToLiveInSeconds());
} else {
TestUtils.assertException(ExecutionException.class, () -> future.get(TIMEOUT_SECS, TimeUnit.SECONDS), errorChecker);
}
}
}
use of com.github.ambry.router.FutureResult in project ambry by linkedin.
the class NamedBlobPutHandlerTest method putBlobAndVerify.
/**
* Make a stitch blob call using {@link PostBlobHandler} and verify the result of the operation.
* @param errorChecker if non-null, expect an exception to be thrown by the post flow and verify it using this
* {@link ThrowingConsumer}.
* @param ttl the ttl used for the blob
* @throws Exception
*/
private void putBlobAndVerify(ThrowingConsumer<ExecutionException> errorChecker, long ttl) throws Exception {
JSONObject headers = new JSONObject();
FrontendRestRequestServiceTest.setAmbryHeadersForPut(headers, ttl, !REF_CONTAINER.isCacheable(), SERVICE_ID, CONTENT_TYPE, OWNER_ID, null, null, null);
byte[] content = TestUtils.getRandomBytes(1024);
RestRequest request = getRestRequest(headers, request_path, content);
RestResponseChannel restResponseChannel = new MockRestResponseChannel();
FutureResult<Void> future = new FutureResult<>();
idConverterFactory.lastInput = null;
idConverterFactory.lastBlobInfo = null;
idConverterFactory.lastConvertedId = null;
namedBlobPutHandler.handle(request, restResponseChannel, future::done);
if (errorChecker == null) {
future.get(TIMEOUT_SECS, TimeUnit.SECONDS);
assertEquals("Unexpected location header", idConverterFactory.lastConvertedId, restResponseChannel.getHeader(RestUtils.Headers.LOCATION));
InMemoryRouter.InMemoryBlob blob = router.getActiveBlobs().get(idConverterFactory.lastInput);
assertEquals("Unexpected blob content stored", ByteBuffer.wrap(content), blob.getBlob());
assertEquals("Unexpected TTL in blob", ttl, blob.getBlobProperties().getTimeToLiveInSeconds());
assertEquals("Unexpected TTL in named blob DB", ttl, idConverterFactory.lastBlobInfo.getBlobProperties().getTimeToLiveInSeconds());
assertEquals("Unexpected response status", restResponseChannel.getStatus(), ResponseStatus.Ok);
} else {
TestUtils.assertException(ExecutionException.class, () -> future.get(TIMEOUT_SECS, TimeUnit.SECONDS), errorChecker);
}
}
use of com.github.ambry.router.FutureResult in project ambry by linkedin.
the class PostBlobHandlerTest method doChunkUploadTest.
// chunkUploadTest() helpers
/**
* Make a post request and verify behavior related to chunk uploads (for stitched blobs).
* @param contentLength the size of the blob to upload.
* @param chunkUpload {@code true} to send the "x-ambry-chunk-upload" header, or {@code false} to test full uploads.
* @param uploadSession the value for the "x-ambry-chunk-upload-session" request header, or null to not set it.
* @param maxUploadSize the value for the "x-ambry-max-upload-size" request header, or null to not set it.
* @param blobTtlSecs the blob TTL to use.
* @param errorChecker if non-null, expect an exception to be thrown by the post flow and verify it using this
* {@link ThrowingConsumer}.
* @throws Exception
*/
private void doChunkUploadTest(int contentLength, boolean chunkUpload, String uploadSession, Integer maxUploadSize, long blobTtlSecs, ThrowingConsumer<ExecutionException> errorChecker) throws Exception {
JSONObject headers = new JSONObject();
FrontendRestRequestServiceTest.setAmbryHeadersForPut(headers, blobTtlSecs, !REF_CONTAINER.isCacheable(), SERVICE_ID, CONTENT_TYPE, OWNER_ID, REF_ACCOUNT.getName(), REF_CONTAINER.getName(), null);
if (chunkUpload) {
headers.put(RestUtils.Headers.CHUNK_UPLOAD, true);
}
if (uploadSession != null) {
headers.put(RestUtils.Headers.SESSION, uploadSession);
}
if (maxUploadSize != null) {
headers.put(RestUtils.Headers.MAX_UPLOAD_SIZE, maxUploadSize);
}
byte[] content = TestUtils.getRandomBytes(contentLength);
RestRequest request = getRestRequest(headers, "/", content);
long creationTimeMs = System.currentTimeMillis();
time.setCurrentMilliseconds(creationTimeMs);
RestResponseChannel restResponseChannel = new MockRestResponseChannel();
FutureResult<Void> future = new FutureResult<>();
idConverterFactory.lastInput = null;
postBlobHandler.handle(request, restResponseChannel, future::done);
if (errorChecker == null) {
future.get(TIMEOUT_SECS, TimeUnit.SECONDS);
assertEquals("Unexpected converted ID", CONVERTED_ID, restResponseChannel.getHeader(RestUtils.Headers.LOCATION));
Object metadata = request.getArgs().get(RestUtils.InternalKeys.SIGNED_ID_METADATA_KEY);
if (chunkUpload) {
Map<String, String> expectedMetadata = new HashMap<>(3);
expectedMetadata.put(RestUtils.Headers.BLOB_SIZE, Integer.toString(contentLength));
expectedMetadata.put(RestUtils.Headers.SESSION, uploadSession);
expectedMetadata.put(PostBlobHandler.EXPIRATION_TIME_MS_KEY, Long.toString(Utils.addSecondsToEpochTime(creationTimeMs, blobTtlSecs)));
assertEquals("Unexpected signed ID metadata", expectedMetadata, metadata);
} else {
assertNull("Signed id metadata should not be set on non-chunk uploads", metadata);
}
InMemoryRouter.InMemoryBlob blob = router.getActiveBlobs().get(idConverterFactory.lastInput);
assertEquals("Unexpected blob content stored", ByteBuffer.wrap(content), blob.getBlob());
assertEquals("Unexpected ttl stored", blobTtlSecs, blob.getBlobProperties().getTimeToLiveInSeconds());
// check that blob size matches the actual upload size
assertEquals("Invalid blob size", Integer.toString(contentLength), restResponseChannel.getHeader(RestUtils.Headers.BLOB_SIZE));
} else {
TestUtils.assertException(ExecutionException.class, () -> future.get(TIMEOUT_SECS, TimeUnit.SECONDS), errorChecker);
}
}
use of com.github.ambry.router.FutureResult in project ambry by linkedin.
the class PostBlobHandlerTest method stitchBlobAndVerify.
/**
* Make a stitch blob call using {@link PostBlobHandler} and verify the result of the operation.
* @param requestBody the body of the stitch request to supply.
* @param expectedStitchedChunks the expected chunks stitched together.
* @param errorChecker if non-null, expect an exception to be thrown by the post flow and verify it using this
* {@link ThrowingConsumer}.
* @throws Exception
*/
private void stitchBlobAndVerify(byte[] requestBody, List<ChunkInfo> expectedStitchedChunks, ThrowingConsumer<ExecutionException> errorChecker) throws Exception {
JSONObject headers = new JSONObject();
FrontendRestRequestServiceTest.setAmbryHeadersForPut(headers, TestUtils.TTL_SECS, !REF_CONTAINER.isCacheable(), SERVICE_ID, CONTENT_TYPE, OWNER_ID, REF_ACCOUNT.getName(), REF_CONTAINER.getName(), null);
RestRequest request = getRestRequest(headers, "/" + Operations.STITCH, requestBody);
RestResponseChannel restResponseChannel = new MockRestResponseChannel();
FutureResult<Void> future = new FutureResult<>();
idConverterFactory.lastInput = null;
postBlobHandler.handle(request, restResponseChannel, future::done);
if (errorChecker == null) {
future.get(TIMEOUT_SECS, TimeUnit.SECONDS);
assertEquals("Unexpected converted ID", CONVERTED_ID, restResponseChannel.getHeader(RestUtils.Headers.LOCATION));
InMemoryRouter.InMemoryBlob blob = router.getActiveBlobs().get(idConverterFactory.lastInput);
assertEquals("List of chunks stitched does not match expected", expectedStitchedChunks, blob.getStitchedChunks());
ByteArrayOutputStream expectedContent = new ByteArrayOutputStream();
expectedStitchedChunks.stream().map(chunkInfo -> router.getActiveBlobs().get(chunkInfo.getBlobId()).getBlob().array()).forEach(buf -> expectedContent.write(buf, 0, buf.length));
assertEquals("Unexpected blob content stored", ByteBuffer.wrap(expectedContent.toByteArray()), blob.getBlob());
// check actual size of stitched blob
assertEquals("Unexpected blob size", Long.toString(getStitchedBlobSize(expectedStitchedChunks)), restResponseChannel.getHeader(RestUtils.Headers.BLOB_SIZE));
} else {
TestUtils.assertException(ExecutionException.class, () -> future.get(TIMEOUT_SECS, TimeUnit.SECONDS), errorChecker);
}
}
Aggregations