Search in sources :

Example 11 with Callback

use of com.github.ambry.commons.Callback in project ambry by linkedin.

the class GetBlobOperationTest method getAndAssertSuccess.

/**
 * Construct GetBlob operations with appropriate callbacks, then poll those operations until they complete,
 * and ensure that the whole blob data is read out and the contents match.
 * @param getChunksBeforeRead {@code true} if all chunks should be cached by the router before reading from the
 *                            stream.
 * @param initiateReadBeforeChunkGet Whether readInto() should be initiated immediately before data chunks are
 *                                   fetched by the router to simulate chunk arrival delay.
 * @param expectedLifeVersion the expected lifeVersion from get operation.
 */
private void getAndAssertSuccess(final boolean getChunksBeforeRead, final boolean initiateReadBeforeChunkGet, short expectedLifeVersion) throws Exception {
    final CountDownLatch readCompleteLatch = new CountDownLatch(1);
    final AtomicReference<Throwable> readCompleteThrowable = new AtomicReference<>(null);
    final AtomicLong readCompleteResult = new AtomicLong(0);
    final AtomicReference<Exception> operationException = new AtomicReference<>(null);
    final int numChunks = ((blobSize + maxChunkSize - 1) / maxChunkSize) + (blobSize > maxChunkSize ? 1 : 0);
    mockNetworkClient.resetProcessedResponseCount();
    Callback<GetBlobResultInternal> callback = (result, exception) -> {
        if (exception != null) {
            operationException.set(exception);
            readCompleteLatch.countDown();
        } else {
            try {
                if (options.getChunkIdsOnly) {
                    Assert.assertNull("Unexpected blob result when getChunkIdsOnly", result.getBlobResult);
                    if (blobSize > maxChunkSize) {
                        // CompositeBlob
                        Assert.assertNotNull("CompositeBlob should return a list of blob ids when getting chunk ids", result.storeKeys);
                        Assert.assertEquals(result.storeKeys.size(), (blobSize + maxChunkSize - 1) / maxChunkSize);
                    } else {
                        // SimpleBlob
                        Assert.assertNull("Unexpected list of blob id when getChunkIdsOnly is true on a simple blob", result.storeKeys);
                    }
                    readCompleteLatch.countDown();
                    return;
                }
                BlobInfo blobInfo;
                switch(options.getBlobOptions.getOperationType()) {
                    case All:
                        if (!options.getBlobOptions.isRawMode()) {
                            blobInfo = result.getBlobResult.getBlobInfo();
                            Assert.assertTrue("Blob properties must be the same", RouterTestHelpers.arePersistedFieldsEquivalent(blobProperties, blobInfo.getBlobProperties()));
                            Assert.assertEquals("Blob size should in received blobProperties should be the same as actual", blobSize, blobInfo.getBlobProperties().getBlobSize());
                            Assert.assertArrayEquals("User metadata must be the same", userMetadata, blobInfo.getUserMetadata());
                            Assert.assertEquals("LifeVersion mismatch", expectedLifeVersion, blobInfo.getLifeVersion());
                        }
                        break;
                    case Data:
                        Assert.assertNull("Unexpected blob info in operation result", result.getBlobResult.getBlobInfo());
                        break;
                    case BlobInfo:
                        blobInfo = result.getBlobResult.getBlobInfo();
                        Assert.assertTrue("Blob properties must be the same", RouterTestHelpers.arePersistedFieldsEquivalent(blobProperties, blobInfo.getBlobProperties()));
                        Assert.assertEquals("Blob size should in received blobProperties should be the same as actual", blobSize, blobInfo.getBlobProperties().getBlobSize());
                        Assert.assertNull("Unexpected blob data in operation result", result.getBlobResult.getBlobDataChannel());
                        Assert.assertEquals("LifeVersion mismatch", expectedLifeVersion, blobInfo.getLifeVersion());
                }
            } catch (Throwable e) {
                readCompleteThrowable.set(e);
            }
            if (options.getBlobOptions.getOperationType() != GetBlobOptions.OperationType.BlobInfo) {
                final ByteBufferAsyncWritableChannel asyncWritableChannel = new ByteBufferAsyncWritableChannel();
                final Future<Long> preSetReadIntoFuture = initiateReadBeforeChunkGet ? result.getBlobResult.getBlobDataChannel().readInto(asyncWritableChannel, null) : null;
                Utils.newThread(() -> {
                    if (getChunksBeforeRead) {
                        // wait for all chunks (data + metadata) to be received
                        while (mockNetworkClient.getProcessedResponseCount() < numChunks * routerConfig.routerGetRequestParallelism) {
                            Thread.yield();
                        }
                    }
                    Future<Long> readIntoFuture = initiateReadBeforeChunkGet ? preSetReadIntoFuture : result.getBlobResult.getBlobDataChannel().readInto(asyncWritableChannel, null);
                    assertBlobReadSuccess(options.getBlobOptions, readIntoFuture, asyncWritableChannel, result.getBlobResult.getBlobDataChannel(), readCompleteLatch, readCompleteResult, readCompleteThrowable);
                }, false).start();
            } else {
                readCompleteLatch.countDown();
            }
        }
    };
    GetBlobOperation op = createOperationAndComplete(callback);
    readCompleteLatch.await();
    Assert.assertTrue("Operation should be complete at this time", op.isOperationComplete());
    if (operationException.get() != null) {
        throw operationException.get();
    }
    if (readCompleteThrowable.get() != null) {
        throw new IllegalStateException(readCompleteThrowable.get());
    }
    // Ensure that a ChannelClosed exception is not set when the ReadableStreamChannel is closed correctly.
    Assert.assertNull("Callback operation exception should be null", op.getOperationException());
    if (options.getBlobOptions.getOperationType() != GetBlobOptions.OperationType.BlobInfo && !options.getBlobOptions.isRawMode() && !options.getChunkIdsOnly) {
        int sizeWritten = blobSize;
        if (options.getBlobOptions.getRange() != null) {
            ByteRange range = options.getBlobOptions.getRange().toResolvedByteRange(blobSize, options.getBlobOptions.resolveRangeOnEmptyBlob());
            sizeWritten = (int) range.getRangeSize();
        }
        Assert.assertEquals("Size read must equal size written", sizeWritten, readCompleteResult.get());
    }
}
Also used : ResponseInfo(com.github.ambry.network.ResponseInfo) GetOption(com.github.ambry.protocol.GetOption) Arrays(java.util.Arrays) BlobProperties(com.github.ambry.messageformat.BlobProperties) ByteBufferReadableStreamChannel(com.github.ambry.commons.ByteBufferReadableStreamChannel) BlobAll(com.github.ambry.messageformat.BlobAll) Random(java.util.Random) ByteBuffer(java.nio.ByteBuffer) GetResponse(com.github.ambry.protocol.GetResponse) Future(java.util.concurrent.Future) ByteArrayInputStream(java.io.ByteArrayInputStream) NetworkClientErrorCode(com.github.ambry.network.NetworkClientErrorCode) TestUtils(com.github.ambry.utils.TestUtils) Map(java.util.Map) After(org.junit.After) Counter(com.codahale.metrics.Counter) NettyByteBufLeakHelper(com.github.ambry.utils.NettyByteBufLeakHelper) GetRequest(com.github.ambry.protocol.GetRequest) EnumSet(java.util.EnumSet) Parameterized(org.junit.runners.Parameterized) PartitionState(com.github.ambry.clustermap.PartitionState) RestServiceErrorCode(com.github.ambry.rest.RestServiceErrorCode) Set(java.util.Set) Utils(com.github.ambry.utils.Utils) MockPartitionId(com.github.ambry.clustermap.MockPartitionId) PooledByteBufAllocator(io.netty.buffer.PooledByteBufAllocator) Collectors(java.util.stream.Collectors) CryptoServiceConfig(com.github.ambry.config.CryptoServiceConfig) BlobInfo(com.github.ambry.messageformat.BlobInfo) RouterConfig(com.github.ambry.config.RouterConfig) CountDownLatch(java.util.concurrent.CountDownLatch) StoreKey(com.github.ambry.store.StoreKey) List(java.util.List) RestServiceException(com.github.ambry.rest.RestServiceException) MockTime(com.github.ambry.utils.MockTime) MessageFormatFlags(com.github.ambry.messageformat.MessageFormatFlags) QuotaTestUtils(com.github.ambry.quota.QuotaTestUtils) Callback(com.github.ambry.commons.Callback) LoggingNotificationSystem(com.github.ambry.commons.LoggingNotificationSystem) BlobType(com.github.ambry.messageformat.BlobType) InMemAccountService(com.github.ambry.account.InMemAccountService) PartitionId(com.github.ambry.clustermap.PartitionId) BlobId(com.github.ambry.commons.BlobId) ResponseHandler(com.github.ambry.commons.ResponseHandler) CompositeBlobInfo(com.github.ambry.messageformat.CompositeBlobInfo) PartitionRequestInfo(com.github.ambry.protocol.PartitionRequestInfo) Histogram(com.codahale.metrics.Histogram) DataInputStream(java.io.DataInputStream) ByteBufferChannel(com.github.ambry.utils.ByteBufferChannel) ServerErrorCode(com.github.ambry.server.ServerErrorCode) RunWith(org.junit.runner.RunWith) HashMap(java.util.HashMap) AtomicReference(java.util.concurrent.atomic.AtomicReference) ArrayList(java.util.ArrayList) NettyByteBufDataInputStream(com.github.ambry.utils.NettyByteBufDataInputStream) HashSet(java.util.HashSet) PutManagerTest(com.github.ambry.router.PutManagerTest) ByteBuf(io.netty.buffer.ByteBuf) SocketNetworkClient(com.github.ambry.network.SocketNetworkClient) Assume(org.junit.Assume) PutRequest(com.github.ambry.protocol.PutRequest) Before(org.junit.Before) MockDataNodeId(com.github.ambry.clustermap.MockDataNodeId) Properties(java.util.Properties) Iterator(java.util.Iterator) ByteBufferAsyncWritableChannel(com.github.ambry.commons.ByteBufferAsyncWritableChannel) VerifiableProperties(com.github.ambry.config.VerifiableProperties) RouterTestHelpers(com.github.ambry.router.RouterTestHelpers) QuotaChargeCallback(com.github.ambry.quota.QuotaChargeCallback) MetadataContentSerDe(com.github.ambry.messageformat.MetadataContentSerDe) IOException(java.io.IOException) Test(org.junit.Test) BlobIdFactory(com.github.ambry.commons.BlobIdFactory) RequestInfo(com.github.ambry.network.RequestInfo) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) AtomicLong(java.util.concurrent.atomic.AtomicLong) KMSConfig(com.github.ambry.config.KMSConfig) ReplicaId(com.github.ambry.clustermap.ReplicaId) ByteBufferInputStream(com.github.ambry.utils.ByteBufferInputStream) MessageFormatRecord(com.github.ambry.messageformat.MessageFormatRecord) Assert(org.junit.Assert) Collections(java.util.Collections) MockClusterMap(com.github.ambry.clustermap.MockClusterMap) AtomicReference(java.util.concurrent.atomic.AtomicReference) BlobInfo(com.github.ambry.messageformat.BlobInfo) CompositeBlobInfo(com.github.ambry.messageformat.CompositeBlobInfo) CountDownLatch(java.util.concurrent.CountDownLatch) ByteBufferAsyncWritableChannel(com.github.ambry.commons.ByteBufferAsyncWritableChannel) RestServiceException(com.github.ambry.rest.RestServiceException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) AtomicLong(java.util.concurrent.atomic.AtomicLong) AtomicLong(java.util.concurrent.atomic.AtomicLong) Future(java.util.concurrent.Future)

Example 12 with Callback

use of com.github.ambry.commons.Callback in project ambry by linkedin.

the class GetManagerTest method testBadCallback.

/**
 * Test that a bad user defined callback will not crash the router.
 * @param getBlobCallback User defined callback to be called after getBlob operation.
 * @param getBlobCallbackCalled This latch should be at 0 after {@code getBlobCallback} has been called.
 * @param checkBadCallbackBlob {@code true} if the blob contents provided by the getBlob operation with the bad
 *                             callback should be inspected for correctness.
 * @throws Exception
 */
private void testBadCallback(Callback<GetBlobResult> getBlobCallback, CountDownLatch getBlobCallbackCalled, Boolean checkBadCallbackBlob) throws Exception {
    router = getNonBlockingRouter();
    setOperationParams(LARGE_BLOB_SIZE, new GetBlobOptionsBuilder().build());
    final CountDownLatch getBlobInfoCallbackCalled = new CountDownLatch(1);
    String blobId = router.putBlob(putBlobProperties, putUserMetadata, putChannel, new PutBlobOptionsBuilder().build()).get();
    List<Future<GetBlobResult>> getBlobInfoFutures = new ArrayList<>();
    List<Future<GetBlobResult>> getBlobDataFutures = new ArrayList<>();
    GetBlobOptions infoOptions = new GetBlobOptionsBuilder().operationType(GetBlobOptions.OperationType.BlobInfo).build();
    GetBlobOptions dataOptions = new GetBlobOptionsBuilder().operationType(GetBlobOptions.OperationType.Data).build();
    for (int i = 0; i < 5; i++) {
        if (i == 1) {
            getBlobInfoFutures.add(router.getBlob(blobId, infoOptions, new Callback<GetBlobResult>() {

                @Override
                public void onCompletion(GetBlobResult result, Exception exception) {
                    getBlobInfoCallbackCalled.countDown();
                    throw new RuntimeException("Throwing an exception in the user callback");
                }
            }, quotaChargeCallback));
            getBlobDataFutures.add(router.getBlob(blobId, dataOptions, getBlobCallback, quotaChargeCallback));
        } else {
            getBlobInfoFutures.add(router.getBlob(blobId, infoOptions));
            getBlobDataFutures.add(router.getBlob(blobId, dataOptions));
        }
    }
    options = dataOptions;
    for (int i = 0; i < getBlobDataFutures.size(); i++) {
        if (i != 1 || checkBadCallbackBlob) {
            compareContent(getBlobDataFutures.get(i).get().getBlobDataChannel());
        }
    }
    options = infoOptions;
    for (Future<GetBlobResult> future : getBlobInfoFutures) {
        compareBlobInfo(future.get().getBlobInfo(), -1);
    }
    Assert.assertTrue("getBlobInfo callback not called.", getBlobInfoCallbackCalled.await(2, TimeUnit.SECONDS));
    Assert.assertTrue("getBlob callback not called.", getBlobCallbackCalled.await(2, TimeUnit.SECONDS));
    Assert.assertEquals("All operations should be finished.", 0, router.getOperationsCount());
    Assert.assertTrue("Router should not be closed", router.isOpen());
    // Test that GetManager is still operational
    setOperationParams(CHUNK_SIZE, new GetBlobOptionsBuilder().build());
    blobId = router.putBlob(putBlobProperties, putUserMetadata, putChannel, new PutBlobOptionsBuilder().build()).get();
    getBlobAndCompareContent(blobId, -1);
    this.options = infoOptions;
    getBlobAndCompareContent(blobId, -1);
    router.close();
}
Also used : ArrayList(java.util.ArrayList) GetBlobOptions(com.github.ambry.router.GetBlobOptions) CountDownLatch(java.util.concurrent.CountDownLatch) GeneralSecurityException(java.security.GeneralSecurityException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) QuotaChargeCallback(com.github.ambry.quota.QuotaChargeCallback) Callback(com.github.ambry.commons.Callback) Future(java.util.concurrent.Future)

Example 13 with Callback

use of com.github.ambry.commons.Callback in project ambry by linkedin.

the class AmbryServerSecurityServiceTest method validateRequestTest.

/**
 * Tests for {@link AmbryServerSecurityService#validateRequest(RestRequest, Callback)}
 * @throws Exception
 */
@Test
public void validateRequestTest() throws Exception {
    // request is null
    TestUtils.assertException(IllegalArgumentException.class, () -> serverSecurityService.validateRequest(null).get(), null);
    // success case
    RestRequest request = new MockRestRequest(MockRestRequest.DUMMY_DATA, null);
    serverSecurityService.validateRequest(request, (r, e) -> {
        Assert.assertNull("result not null", r);
        Assert.assertNull("exception not null", e);
    });
    // service is closed
    serverSecurityService.close();
    ThrowingConsumer<ExecutionException> errorAction = e -> {
        Assert.assertTrue("Exception should have been an instance of RestServiceException", e.getCause() instanceof RestServiceException);
        RestServiceException re = (RestServiceException) e.getCause();
        Assert.assertEquals("Unexpected RestServerErrorCode (Future)", RestServiceErrorCode.ServiceUnavailable, re.getErrorCode());
    };
    TestUtils.assertException(ExecutionException.class, () -> serverSecurityService.validateRequest(request).get(), errorAction);
}
Also used : MockRestRequest(com.github.ambry.rest.MockRestRequest) ServerSecurityService(com.github.ambry.rest.ServerSecurityService) MetricRegistry(com.codahale.metrics.MetricRegistry) Properties(java.util.Properties) VerifiableProperties(com.github.ambry.config.VerifiableProperties) RestServiceErrorCode(com.github.ambry.rest.RestServiceErrorCode) ServerConfig(com.github.ambry.config.ServerConfig) Test(org.junit.Test) ThrowingConsumer(com.github.ambry.utils.ThrowingConsumer) ExecutionException(java.util.concurrent.ExecutionException) AmbryRequests(com.github.ambry.protocol.AmbryRequests) Mockito(org.mockito.Mockito) RestServiceException(com.github.ambry.rest.RestServiceException) SSLSession(javax.net.ssl.SSLSession) TestUtils(com.github.ambry.utils.TestUtils) ServerMetrics(com.github.ambry.commons.ServerMetrics) Callback(com.github.ambry.commons.Callback) Assert(org.junit.Assert) RestRequest(com.github.ambry.rest.RestRequest) RestServiceException(com.github.ambry.rest.RestServiceException) MockRestRequest(com.github.ambry.rest.MockRestRequest) RestRequest(com.github.ambry.rest.RestRequest) MockRestRequest(com.github.ambry.rest.MockRestRequest) ExecutionException(java.util.concurrent.ExecutionException) Test(org.junit.Test)

Aggregations

Callback (com.github.ambry.commons.Callback)13 RestServiceException (com.github.ambry.rest.RestServiceException)9 ExecutionException (java.util.concurrent.ExecutionException)9 IOException (java.io.IOException)8 VerifiableProperties (com.github.ambry.config.VerifiableProperties)7 Properties (java.util.Properties)7 Test (org.junit.Test)7 QuotaChargeCallback (com.github.ambry.quota.QuotaChargeCallback)6 RestServiceErrorCode (com.github.ambry.rest.RestServiceErrorCode)6 CountDownLatch (java.util.concurrent.CountDownLatch)6 Assert (org.junit.Assert)6 BlobId (com.github.ambry.commons.BlobId)5 BlobInfo (com.github.ambry.messageformat.BlobInfo)5 BlobProperties (com.github.ambry.messageformat.BlobProperties)5 TestUtils (com.github.ambry.utils.TestUtils)5 Utils (com.github.ambry.utils.Utils)5 ByteBuffer (java.nio.ByteBuffer)5 Future (java.util.concurrent.Future)5 AccountService (com.github.ambry.account.AccountService)4 InMemAccountService (com.github.ambry.account.InMemAccountService)4