Search in sources :

Example 1 with RetainingAsyncWritableChannel

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

the class PostAccountContainersHandlerTest method validRequestsTest.

/**
 * Test valid request cases.
 * @throws Exception
 */
@Test
public void validRequestsTest() throws Exception {
    String accountName = theAccount.getName();
    short accountId = theAccount.getId();
    ThrowingConsumer<Collection<Container>> testAction = inputContainers -> {
        String requestBody = new String(AccountCollectionSerde.serializeContainersInJson(inputContainers));
        RestResponseChannel restResponseChannel = new MockRestResponseChannel();
        RestRequest request = createRestRequest(requestBody, accountName, null);
        ReadableStreamChannel responseChannel = sendRequestGetResponse(request, restResponseChannel);
        assertNotNull("Date has not been set", restResponseChannel.getHeader(RestUtils.Headers.DATE));
        assertEquals("Content-length is not as expected", responseChannel.getSize(), Integer.parseInt((String) restResponseChannel.getHeader(RestUtils.Headers.CONTENT_LENGTH)));
        assertEquals("Account id in response header is not as expected", accountId, Short.parseShort((String) restResponseChannel.getHeader(RestUtils.Headers.TARGET_ACCOUNT_ID)));
        RetainingAsyncWritableChannel asyncWritableChannel = new RetainingAsyncWritableChannel((int) responseChannel.getSize());
        responseChannel.readInto(asyncWritableChannel, null).get();
        Collection<Container> outputContainers = AccountCollectionSerde.containersFromInputStreamInJson(asyncWritableChannel.consumeContentAsInputStream(), accountId);
        assertEquals("Unexpected count returned", inputContainers.size(), outputContainers.size());
        for (Container container : outputContainers) {
            assertEquals("Container in account service not as expected", container, accountService.getContainerByName(accountName, container.getName()));
        }
    };
    // add new container
    testAction.accept(Collections.singleton(accountService.getRandomContainer(accountId)));
    // add multiple containers
    List<Container> containerList = new ArrayList<>();
    for (int j = 0; j < 10; j++) {
        containerList.add(new ContainerBuilder(Container.UNKNOWN_CONTAINER_ID, "Test-" + j, Container.ContainerStatus.ACTIVE, "", accountId).build());
    }
    testAction.accept(containerList);
// TODO: update existing containers when support is added
}
Also used : MockRestRequest(com.github.ambry.rest.MockRestRequest) FrontendConfig(com.github.ambry.config.FrontendConfig) FutureResult(com.github.ambry.router.FutureResult) ContainerBuilder(com.github.ambry.account.ContainerBuilder) ByteBuffer(java.nio.ByteBuffer) ThrowingConsumer(com.github.ambry.utils.ThrowingConsumer) ArrayList(java.util.ArrayList) AccountCollectionSerde(com.github.ambry.account.AccountCollectionSerde) RequestPath(com.github.ambry.rest.RequestPath) JSONObject(org.json.JSONObject) TestUtils(com.github.ambry.utils.TestUtils) LinkedList(java.util.LinkedList) RetainingAsyncWritableChannel(com.github.ambry.commons.RetainingAsyncWritableChannel) Container(com.github.ambry.account.Container) ReadableStreamChannel(com.github.ambry.router.ReadableStreamChannel) MetricRegistry(com.codahale.metrics.MetricRegistry) Properties(java.util.Properties) RestMethod(com.github.ambry.rest.RestMethod) VerifiableProperties(com.github.ambry.config.VerifiableProperties) Collection(java.util.Collection) RestResponseChannel(com.github.ambry.rest.RestResponseChannel) RestServiceErrorCode(com.github.ambry.rest.RestServiceErrorCode) Test(org.junit.Test) ThrowingBiConsumer(com.github.ambry.utils.ThrowingBiConsumer) StandardCharsets(java.nio.charset.StandardCharsets) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) List(java.util.List) RestServiceException(com.github.ambry.rest.RestServiceException) MockRestResponseChannel(com.github.ambry.rest.MockRestResponseChannel) Account(com.github.ambry.account.Account) RestUtils(com.github.ambry.rest.RestUtils) Assert(org.junit.Assert) RestRequest(com.github.ambry.rest.RestRequest) Collections(java.util.Collections) InMemAccountService(com.github.ambry.account.InMemAccountService) RetainingAsyncWritableChannel(com.github.ambry.commons.RetainingAsyncWritableChannel) ArrayList(java.util.ArrayList) MockRestResponseChannel(com.github.ambry.rest.MockRestResponseChannel) Container(com.github.ambry.account.Container) MockRestRequest(com.github.ambry.rest.MockRestRequest) RestRequest(com.github.ambry.rest.RestRequest) ContainerBuilder(com.github.ambry.account.ContainerBuilder) ReadableStreamChannel(com.github.ambry.router.ReadableStreamChannel) RestResponseChannel(com.github.ambry.rest.RestResponseChannel) MockRestResponseChannel(com.github.ambry.rest.MockRestResponseChannel) Collection(java.util.Collection) Test(org.junit.Test)

Example 2 with RetainingAsyncWritableChannel

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

the class GetAccountsHandlerTest method getSingleContainerSuccessTest.

/**
 * Test success case of getting single container.
 * @throws Exception
 */
@Test
public void getSingleContainerSuccessTest() throws Exception {
    Account existingAccount = accountService.createAndAddRandomAccount();
    Container existingContainer = existingAccount.getAllContainers().iterator().next();
    ThrowingBiConsumer<RestRequest, Container> testAction = (request, expectedContainer) -> {
        RestResponseChannel restResponseChannel = new MockRestResponseChannel();
        ReadableStreamChannel channel = sendRequestGetResponse(request, restResponseChannel);
        assertNotNull("There should be a response", channel);
        Assert.assertNotNull("Date has not been set", restResponseChannel.getHeader(RestUtils.Headers.DATE));
        assertEquals("Content-type is not as expected", RestUtils.JSON_CONTENT_TYPE, restResponseChannel.getHeader(RestUtils.Headers.CONTENT_TYPE));
        assertEquals("Content-length is not as expected", channel.getSize(), Integer.parseInt((String) restResponseChannel.getHeader(RestUtils.Headers.CONTENT_LENGTH)));
        RetainingAsyncWritableChannel asyncWritableChannel = new RetainingAsyncWritableChannel((int) channel.getSize());
        channel.readInto(asyncWritableChannel, null).get();
        assertEquals("Container does not match", Collections.singletonList(expectedContainer), AccountCollectionSerde.containersFromInputStreamInJson(asyncWritableChannel.consumeContentAsInputStream(), existingAccount.getId()));
    };
    testAction.accept(createRestRequest(existingAccount.getName(), null, existingContainer.getName(), Operations.ACCOUNTS_CONTAINERS), existingContainer);
}
Also used : MockRestRequest(com.github.ambry.rest.MockRestRequest) FutureResult(com.github.ambry.router.FutureResult) ThrowingConsumer(com.github.ambry.utils.ThrowingConsumer) AccountCollectionSerde(com.github.ambry.account.AccountCollectionSerde) RequestPath(com.github.ambry.rest.RequestPath) HashSet(java.util.HashSet) JSONObject(org.json.JSONObject) TestUtils(com.github.ambry.utils.TestUtils) RetainingAsyncWritableChannel(com.github.ambry.commons.RetainingAsyncWritableChannel) Container(com.github.ambry.account.Container) ReadableStreamChannel(com.github.ambry.router.ReadableStreamChannel) MetricRegistry(com.codahale.metrics.MetricRegistry) RestMethod(com.github.ambry.rest.RestMethod) Collection(java.util.Collection) RestResponseChannel(com.github.ambry.rest.RestResponseChannel) RestServiceErrorCode(com.github.ambry.rest.RestServiceErrorCode) Test(org.junit.Test) ThrowingBiConsumer(com.github.ambry.utils.ThrowingBiConsumer) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) RestServiceException(com.github.ambry.rest.RestServiceException) MockRestResponseChannel(com.github.ambry.rest.MockRestResponseChannel) Account(com.github.ambry.account.Account) RestUtils(com.github.ambry.rest.RestUtils) Assert(org.junit.Assert) RestRequest(com.github.ambry.rest.RestRequest) Collections(java.util.Collections) InMemAccountService(com.github.ambry.account.InMemAccountService) Account(com.github.ambry.account.Account) Container(com.github.ambry.account.Container) MockRestRequest(com.github.ambry.rest.MockRestRequest) RestRequest(com.github.ambry.rest.RestRequest) ReadableStreamChannel(com.github.ambry.router.ReadableStreamChannel) RetainingAsyncWritableChannel(com.github.ambry.commons.RetainingAsyncWritableChannel) RestResponseChannel(com.github.ambry.rest.RestResponseChannel) MockRestResponseChannel(com.github.ambry.rest.MockRestResponseChannel) MockRestResponseChannel(com.github.ambry.rest.MockRestResponseChannel) Test(org.junit.Test)

Example 3 with RetainingAsyncWritableChannel

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

the class RestTestUtils method getJsonizedResponseBody.

/**
 * Reads the response received from the {@code channel} and decodes it into a {@link JSONObject}.
 * @param channel the {@link ReadableStreamChannel} that contains the response
 * @return the response decoded into a {@link JSONObject}.
 * @throws Exception
 */
public static JSONObject getJsonizedResponseBody(ReadableStreamChannel channel) throws Exception {
    RetainingAsyncWritableChannel asyncWritableChannel = new RetainingAsyncWritableChannel((int) channel.getSize());
    channel.readInto(asyncWritableChannel, null).get();
    try (InputStream is = asyncWritableChannel.consumeContentAsInputStream()) {
        return new JSONObject(new String(Utils.readBytesFromStream(is, (int) asyncWritableChannel.getBytesWritten())));
    }
}
Also used : JSONObject(org.json.JSONObject) RetainingAsyncWritableChannel(com.github.ambry.commons.RetainingAsyncWritableChannel) InputStream(java.io.InputStream)

Example 4 with RetainingAsyncWritableChannel

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

the class RestTestUtils method getResponseBody.

/**
 * Reads the response received from the {@code channel}.
 * @param channel the {@link ReadableStreamChannel} that contains the response
 * @return the response in byte array.
 * @throws Exception
 */
public static byte[] getResponseBody(ReadableStreamChannel channel) throws Exception {
    RetainingAsyncWritableChannel asyncWritableChannel = new RetainingAsyncWritableChannel((int) channel.getSize());
    channel.readInto(asyncWritableChannel, null).get();
    byte[] result = new byte[(int) asyncWritableChannel.getBytesWritten()];
    asyncWritableChannel.consumeContentAsByteBuf().readBytes(result);
    return result;
}
Also used : RetainingAsyncWritableChannel(com.github.ambry.commons.RetainingAsyncWritableChannel)

Example 5 with RetainingAsyncWritableChannel

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

the class NonBlockingRouterQuotaCallbackTest method testRouterWithQuotaCallback.

/**
 * Test Router with single scaling unit for correct accounting in {@link QuotaChargeCallback}.
 */
@Test
public void testRouterWithQuotaCallback() throws Exception {
    try {
        setRouter();
        assertExpectedThreadCounts(2, 1);
        AtomicLong listenerCalledCount = new AtomicLong(0);
        int expectedChargeCallbackCount = 0;
        // create a quota charge listener that increments an atomic counter everytime its called.
        // Also tests that in case quota if charged in tracking mode with throttleInProgress config set to false
        // then the requests go through even in case of exception.
        QuotaChargeCallback quotaChargeCallback = new QuotaChargeCallback() {

            @Override
            public void charge(long chunkSize) throws QuotaException {
                listenerCalledCount.addAndGet(chunkSize);
                throw new QuotaException("exception during check and charge", new RouterException("Quota exceeded.", RouterErrorCode.TooManyRequests), false);
            }

            @Override
            public void charge() throws QuotaException {
                charge(quotaAccountingSize);
            }

            @Override
            public boolean check() {
                return false;
            }

            @Override
            public boolean quotaExceedAllowed() {
                return false;
            }

            @Override
            public QuotaResource getQuotaResource() {
                return null;
            }

            @Override
            public QuotaMethod getQuotaMethod() {
                return null;
            }
        };
        // test for a composite blob.
        int blobSize = 3000;
        setOperationParams(blobSize, TTL_SECS);
        String compositeBlobId = router.putBlob(putBlobProperties, putUserMetadata, putChannel, PutBlobOptions.DEFAULT, null, quotaChargeCallback).get();
        expectedChargeCallbackCount += blobSize;
        assertEquals(expectedChargeCallbackCount, listenerCalledCount.get());
        RetainingAsyncWritableChannel retainingAsyncWritableChannel = new RetainingAsyncWritableChannel();
        router.getBlob(compositeBlobId, new GetBlobOptionsBuilder().build(), null, quotaChargeCallback).get().getBlobDataChannel().readInto(retainingAsyncWritableChannel, null).get();
        expectedChargeCallbackCount += blobSize;
        // read out all the chunks to make sure all the chunks are consumed and accounted for.
        retainingAsyncWritableChannel.consumeContentAsInputStream().close();
        assertEquals(expectedChargeCallbackCount, listenerCalledCount.get());
        // test for regular blobs.
        setOperationParams();
        List<String> blobIds = new ArrayList<>();
        for (int i = 0; i < 2; i++) {
            setOperationParams();
            String blobId = router.putBlob(putBlobProperties, putUserMetadata, putChannel, PutBlobOptions.DEFAULT, null, quotaChargeCallback).get();
            assertEquals(expectedChargeCallbackCount += PUT_CONTENT_SIZE, listenerCalledCount.get());
            logger.info("Put blob {}", blobId);
            blobIds.add(blobId);
        }
        setOperationParams();
        for (String blobId : blobIds) {
            router.getBlob(blobId, new GetBlobOptionsBuilder().build(), null, quotaChargeCallback).get();
            assertEquals(expectedChargeCallbackCount += PUT_CONTENT_SIZE, listenerCalledCount.get());
            router.updateBlobTtl(blobId, null, Utils.Infinite_Time, null, quotaChargeCallback).get();
            assertEquals(expectedChargeCallbackCount += quotaAccountingSize, listenerCalledCount.get());
            router.getBlob(blobId, new GetBlobOptionsBuilder().build(), null, quotaChargeCallback).get();
            assertEquals(expectedChargeCallbackCount += PUT_CONTENT_SIZE, listenerCalledCount.get());
            router.getBlob(blobId, new GetBlobOptionsBuilder().operationType(GetBlobOptions.OperationType.BlobInfo).build(), null, quotaChargeCallback).get();
            assertEquals(expectedChargeCallbackCount += quotaAccountingSize, listenerCalledCount.get());
            router.deleteBlob(blobId, null, null, quotaChargeCallback).get();
            assertEquals(expectedChargeCallbackCount += quotaAccountingSize, listenerCalledCount.get());
            try {
                router.getBlob(blobId, new GetBlobOptionsBuilder().build(), null, quotaChargeCallback).get();
                fail("Get blob should fail");
            } catch (ExecutionException e) {
                RouterException r = (RouterException) e.getCause();
                Assert.assertEquals("BlobDeleted error is expected", RouterErrorCode.BlobDeleted, r.getErrorCode());
                assertEquals(expectedChargeCallbackCount, listenerCalledCount.get());
            }
            router.getBlob(blobId, new GetBlobOptionsBuilder().getOption(GetOption.Include_Deleted_Blobs).build(), null, quotaChargeCallback).get();
            assertEquals(expectedChargeCallbackCount += PUT_CONTENT_SIZE, listenerCalledCount.get());
            router.getBlob(blobId, new GetBlobOptionsBuilder().getOption(GetOption.Include_All).build(), null, quotaChargeCallback).get();
            assertEquals(expectedChargeCallbackCount += PUT_CONTENT_SIZE, listenerCalledCount.get());
        }
        // test for stitched blobs.
        blobIds = new ArrayList<>();
        int stitchedBlobCount = 2;
        for (int i = 0; i < stitchedBlobCount; i++) {
            setOperationParams();
            String blobId = router.putBlob(putBlobProperties, putUserMetadata, putChannel, PutBlobOptions.DEFAULT, null, quotaChargeCallback).get();
            assertEquals(expectedChargeCallbackCount += PUT_CONTENT_SIZE, listenerCalledCount.get());
            logger.info("Put blob {}", blobId);
            blobIds.add(blobId);
        }
        String stitchedBlobId = router.stitchBlob(putBlobProperties, putUserMetadata, blobIds.stream().map(blobId -> new ChunkInfo(blobId, PUT_CONTENT_SIZE, Utils.Infinite_Time)).collect(Collectors.toList()), null, quotaChargeCallback).get();
        assertEquals(expectedChargeCallbackCount, listenerCalledCount.get());
        retainingAsyncWritableChannel = new RetainingAsyncWritableChannel();
        router.getBlob(stitchedBlobId, new GetBlobOptionsBuilder().build(), null, quotaChargeCallback).get().getBlobDataChannel().readInto(retainingAsyncWritableChannel, null).get();
        // read out all the chunks to make sure all the chunks are consumed and accounted for.
        retainingAsyncWritableChannel.consumeContentAsInputStream().close();
        assertEquals(expectedChargeCallbackCount += (PUT_CONTENT_SIZE * stitchedBlobCount), listenerCalledCount.get());
        router.updateBlobTtl(stitchedBlobId, null, Utils.Infinite_Time, null, quotaChargeCallback).get();
        assertEquals(expectedChargeCallbackCount += quotaAccountingSize, listenerCalledCount.get());
        router.deleteBlob(stitchedBlobId, null, null, quotaChargeCallback).get();
        assertEquals(expectedChargeCallbackCount + quotaAccountingSize, listenerCalledCount.get());
    } finally {
        router.close();
        assertExpectedThreadCounts(0, 0);
        // submission after closing should return a future that is already done.
        assertClosed();
    }
}
Also used : GetOption(com.github.ambry.protocol.GetOption) Arrays(java.util.Arrays) RunWith(org.junit.runner.RunWith) LoggerFactory(org.slf4j.LoggerFactory) AccountService(com.github.ambry.account.AccountService) QuotaManager(com.github.ambry.quota.QuotaManager) ArrayList(java.util.ArrayList) QuotaConfig(com.github.ambry.config.QuotaConfig) QuotaMode(com.github.ambry.quota.QuotaMode) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) QuotaResource(com.github.ambry.quota.QuotaResource) TestUtils(com.github.ambry.utils.TestUtils) Map(java.util.Map) QuotaAction(com.github.ambry.quota.QuotaAction) RetainingAsyncWritableChannel(com.github.ambry.commons.RetainingAsyncWritableChannel) QuotaMethod(com.github.ambry.quota.QuotaMethod) Parameterized(org.junit.runners.Parameterized) MetricRegistry(com.codahale.metrics.MetricRegistry) Properties(java.util.Properties) Logger(org.slf4j.Logger) VerifiableProperties(com.github.ambry.config.VerifiableProperties) QuotaChargeCallback(com.github.ambry.quota.QuotaChargeCallback) Utils(com.github.ambry.utils.Utils) Test(org.junit.Test) Collectors(java.util.stream.Collectors) AccountStatsStore(com.github.ambry.accountstats.AccountStatsStore) QuotaUtils(com.github.ambry.quota.QuotaUtils) ExecutionException(java.util.concurrent.ExecutionException) AmbryQuotaManager(com.github.ambry.quota.AmbryQuotaManager) AtomicLong(java.util.concurrent.atomic.AtomicLong) List(java.util.List) QuotaException(com.github.ambry.quota.QuotaException) QuotaMetrics(com.github.ambry.quota.QuotaMetrics) QuotaRecommendationMergePolicy(com.github.ambry.quota.QuotaRecommendationMergePolicy) QuotaName(com.github.ambry.quota.QuotaName) SimpleQuotaRecommendationMergePolicy(com.github.ambry.quota.SimpleQuotaRecommendationMergePolicy) MessageFormatRecord(com.github.ambry.messageformat.MessageFormatRecord) Assert(org.junit.Assert) RestRequest(com.github.ambry.rest.RestRequest) RetainingAsyncWritableChannel(com.github.ambry.commons.RetainingAsyncWritableChannel) ArrayList(java.util.ArrayList) AtomicLong(java.util.concurrent.atomic.AtomicLong) QuotaChargeCallback(com.github.ambry.quota.QuotaChargeCallback) QuotaException(com.github.ambry.quota.QuotaException) ExecutionException(java.util.concurrent.ExecutionException) Test(org.junit.Test)

Aggregations

RetainingAsyncWritableChannel (com.github.ambry.commons.RetainingAsyncWritableChannel)9 MetricRegistry (com.codahale.metrics.MetricRegistry)5 Test (org.junit.Test)5 RestRequest (com.github.ambry.rest.RestRequest)4 ReadableStreamChannel (com.github.ambry.router.ReadableStreamChannel)4 TestUtils (com.github.ambry.utils.TestUtils)4 Account (com.github.ambry.account.Account)3 AccountCollectionSerde (com.github.ambry.account.AccountCollectionSerde)3 Container (com.github.ambry.account.Container)3 InMemAccountService (com.github.ambry.account.InMemAccountService)3 VerifiableProperties (com.github.ambry.config.VerifiableProperties)3 MockRestRequest (com.github.ambry.rest.MockRestRequest)3 MockRestResponseChannel (com.github.ambry.rest.MockRestResponseChannel)3 RequestPath (com.github.ambry.rest.RequestPath)3 RestMethod (com.github.ambry.rest.RestMethod)3 RestResponseChannel (com.github.ambry.rest.RestResponseChannel)3 RestServiceErrorCode (com.github.ambry.rest.RestServiceErrorCode)3 RestServiceException (com.github.ambry.rest.RestServiceException)3 RestUtils (com.github.ambry.rest.RestUtils)3 FutureResult (com.github.ambry.router.FutureResult)3