Search in sources :

Example 1 with FutureResult

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;
}
Also used : GetBlobResult(com.github.ambry.router.GetBlobResult) FutureResult(com.github.ambry.router.FutureResult) BlobInfo(com.github.ambry.messageformat.BlobInfo)

Example 2 with 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);
        }
    }
}
Also used : Arrays(java.util.Arrays) FrontendConfig(com.github.ambry.config.FrontendConfig) BlobProperties(com.github.ambry.messageformat.BlobProperties) URISyntaxException(java.net.URISyntaxException) ResponseStatus(com.github.ambry.rest.ResponseStatus) FutureResult(com.github.ambry.router.FutureResult) ByteBufferReadableStreamChannel(com.github.ambry.commons.ByteBufferReadableStreamChannel) ContainerBuilder(com.github.ambry.account.ContainerBuilder) ByteBuffer(java.nio.ByteBuffer) ThrowingConsumer(com.github.ambry.utils.ThrowingConsumer) JSONObject(org.json.JSONObject) TestUtils(com.github.ambry.utils.TestUtils) Map(java.util.Map) ChunkInfo(com.github.ambry.router.ChunkInfo) Container(com.github.ambry.account.Container) RestResponseChannel(com.github.ambry.rest.RestResponseChannel) RestServiceErrorCode(com.github.ambry.rest.RestServiceErrorCode) Utils(com.github.ambry.utils.Utils) UUID(java.util.UUID) AccountBuilder(com.github.ambry.account.AccountBuilder) Collectors(java.util.stream.Collectors) StandardCharsets(java.nio.charset.StandardCharsets) List(java.util.List) RestServiceException(com.github.ambry.rest.RestServiceException) Stream(java.util.stream.Stream) MockRestResponseChannel(com.github.ambry.rest.MockRestResponseChannel) MockTime(com.github.ambry.utils.MockTime) QuotaTestUtils(com.github.ambry.quota.QuotaTestUtils) Account(com.github.ambry.account.Account) RestUtils(com.github.ambry.rest.RestUtils) UnsupportedEncodingException(java.io.UnsupportedEncodingException) InMemAccountService(com.github.ambry.account.InMemAccountService) InMemoryRouter(com.github.ambry.router.InMemoryRouter) ByteArrayOutputStream(java.io.ByteArrayOutputStream) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) RequestPath(com.github.ambry.rest.RequestPath) LinkedList(java.util.LinkedList) MetricRegistry(com.codahale.metrics.MetricRegistry) Properties(java.util.Properties) RestMethod(com.github.ambry.rest.RestMethod) VerifiableProperties(com.github.ambry.config.VerifiableProperties) ClusterMap(com.github.ambry.clustermap.ClusterMap) Test(org.junit.Test) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) PutBlobOptionsBuilder(com.github.ambry.router.PutBlobOptionsBuilder) Assert(org.junit.Assert) RestRequest(com.github.ambry.rest.RestRequest) Collections(java.util.Collections) MockClusterMap(com.github.ambry.clustermap.MockClusterMap) ByteArrayOutputStream(java.io.ByteArrayOutputStream) MockRestResponseChannel(com.github.ambry.rest.MockRestResponseChannel) InMemoryRouter(com.github.ambry.router.InMemoryRouter) RestRequest(com.github.ambry.rest.RestRequest) JSONObject(org.json.JSONObject) FutureResult(com.github.ambry.router.FutureResult) RestResponseChannel(com.github.ambry.rest.RestResponseChannel) MockRestResponseChannel(com.github.ambry.rest.MockRestResponseChannel)

Example 3 with FutureResult

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);
    }
}
Also used : InMemoryRouter(com.github.ambry.router.InMemoryRouter) RestRequest(com.github.ambry.rest.RestRequest) JSONObject(org.json.JSONObject) FutureResult(com.github.ambry.router.FutureResult) RestResponseChannel(com.github.ambry.rest.RestResponseChannel) MockRestResponseChannel(com.github.ambry.rest.MockRestResponseChannel) MockRestResponseChannel(com.github.ambry.rest.MockRestResponseChannel)

Example 4 with FutureResult

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);
    }
}
Also used : HashMap(java.util.HashMap) MockRestResponseChannel(com.github.ambry.rest.MockRestResponseChannel) InMemoryRouter(com.github.ambry.router.InMemoryRouter) RestRequest(com.github.ambry.rest.RestRequest) JSONObject(org.json.JSONObject) FutureResult(com.github.ambry.router.FutureResult) RestResponseChannel(com.github.ambry.rest.RestResponseChannel) MockRestResponseChannel(com.github.ambry.rest.MockRestResponseChannel) JSONObject(org.json.JSONObject)

Example 5 with FutureResult

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);
    }
}
Also used : Arrays(java.util.Arrays) FrontendConfig(com.github.ambry.config.FrontendConfig) BlobProperties(com.github.ambry.messageformat.BlobProperties) URISyntaxException(java.net.URISyntaxException) FutureResult(com.github.ambry.router.FutureResult) ByteBufferReadableStreamChannel(com.github.ambry.commons.ByteBufferReadableStreamChannel) ContainerBuilder(com.github.ambry.account.ContainerBuilder) ByteBuffer(java.nio.ByteBuffer) ThrowingConsumer(com.github.ambry.utils.ThrowingConsumer) JSONObject(org.json.JSONObject) TestUtils(com.github.ambry.utils.TestUtils) Map(java.util.Map) ChunkInfo(com.github.ambry.router.ChunkInfo) RouterErrorCode(com.github.ambry.router.RouterErrorCode) Container(com.github.ambry.account.Container) RestResponseChannel(com.github.ambry.rest.RestResponseChannel) RestServiceErrorCode(com.github.ambry.rest.RestServiceErrorCode) Utils(com.github.ambry.utils.Utils) UUID(java.util.UUID) AccountBuilder(com.github.ambry.account.AccountBuilder) Collectors(java.util.stream.Collectors) StandardCharsets(java.nio.charset.StandardCharsets) List(java.util.List) RestServiceException(com.github.ambry.rest.RestServiceException) Stream(java.util.stream.Stream) MockRestResponseChannel(com.github.ambry.rest.MockRestResponseChannel) MockTime(com.github.ambry.utils.MockTime) QuotaTestUtils(com.github.ambry.quota.QuotaTestUtils) Account(com.github.ambry.account.Account) RestUtils(com.github.ambry.rest.RestUtils) UnsupportedEncodingException(java.io.UnsupportedEncodingException) InMemAccountService(com.github.ambry.account.InMemAccountService) InMemoryRouter(com.github.ambry.router.InMemoryRouter) ByteArrayOutputStream(java.io.ByteArrayOutputStream) AccountService(com.github.ambry.account.AccountService) HashMap(java.util.HashMap) QuotaManager(com.github.ambry.quota.QuotaManager) ArrayList(java.util.ArrayList) QuotaConfig(com.github.ambry.config.QuotaConfig) RequestPath(com.github.ambry.rest.RequestPath) QuotaMode(com.github.ambry.quota.QuotaMode) LinkedList(java.util.LinkedList) MetricRegistry(com.codahale.metrics.MetricRegistry) Properties(java.util.Properties) RestMethod(com.github.ambry.rest.RestMethod) VerifiableProperties(com.github.ambry.config.VerifiableProperties) ClusterMap(com.github.ambry.clustermap.ClusterMap) Test(org.junit.Test) RouterException(com.github.ambry.router.RouterException) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) AmbryQuotaManager(com.github.ambry.quota.AmbryQuotaManager) Mockito(org.mockito.Mockito) QuotaMetrics(com.github.ambry.quota.QuotaMetrics) PutBlobOptionsBuilder(com.github.ambry.router.PutBlobOptionsBuilder) SimpleQuotaRecommendationMergePolicy(com.github.ambry.quota.SimpleQuotaRecommendationMergePolicy) Assert(org.junit.Assert) RestRequest(com.github.ambry.rest.RestRequest) Collections(java.util.Collections) MockClusterMap(com.github.ambry.clustermap.MockClusterMap) InMemoryRouter(com.github.ambry.router.InMemoryRouter) RestRequest(com.github.ambry.rest.RestRequest) JSONObject(org.json.JSONObject) FutureResult(com.github.ambry.router.FutureResult) RestResponseChannel(com.github.ambry.rest.RestResponseChannel) MockRestResponseChannel(com.github.ambry.rest.MockRestResponseChannel) ByteArrayOutputStream(java.io.ByteArrayOutputStream) MockRestResponseChannel(com.github.ambry.rest.MockRestResponseChannel)

Aggregations

FutureResult (com.github.ambry.router.FutureResult)22 IOException (java.io.IOException)8 RestRequest (com.github.ambry.rest.RestRequest)7 RestServiceException (com.github.ambry.rest.RestServiceException)7 JSONObject (org.json.JSONObject)7 MockRestResponseChannel (com.github.ambry.rest.MockRestResponseChannel)6 RestResponseChannel (com.github.ambry.rest.RestResponseChannel)6 RouterException (com.github.ambry.router.RouterException)6 ClosedChannelException (java.nio.channels.ClosedChannelException)6 ExecutionException (java.util.concurrent.ExecutionException)5 GetBlobResult (com.github.ambry.router.GetBlobResult)4 InMemoryRouter (com.github.ambry.router.InMemoryRouter)4 UnsupportedEncodingException (java.io.UnsupportedEncodingException)4 URISyntaxException (java.net.URISyntaxException)4 ByteBufferReadableStreamChannel (com.github.ambry.commons.ByteBufferReadableStreamChannel)3 BlobInfo (com.github.ambry.messageformat.BlobInfo)3 ByteBuffer (java.nio.ByteBuffer)3 HashMap (java.util.HashMap)3 AtomicLong (java.util.concurrent.atomic.AtomicLong)3 MetricRegistry (com.codahale.metrics.MetricRegistry)2