Search in sources :

Example 21 with ReadableStreamChannel

use of com.github.ambry.router.ReadableStreamChannel in project ambry by linkedin.

the class PostAccountsHandlerTest method sendRequestGetResponse.

// helpers
// general
/**
 * Sends a request to the {@link PostAccountsHandler} and waits for the response.
 * @param requestBody body of the request in string form.
 * @param restResponseChannel the {@link RestResponseChannel} where headers will be set.
 * @throws Exception
 */
private void sendRequestGetResponse(String requestBody, RestResponseChannel restResponseChannel) throws Exception {
    JSONObject data = new JSONObject();
    data.put(MockRestRequest.REST_METHOD_KEY, RestMethod.POST.name());
    data.put(MockRestRequest.URI_KEY, Operations.ACCOUNTS);
    List<ByteBuffer> body = new LinkedList<>();
    body.add(ByteBuffer.wrap(requestBody.getBytes(StandardCharsets.UTF_8)));
    body.add(null);
    RestRequest restRequest = new MockRestRequest(data, body);
    restRequest.setArg(RestUtils.InternalKeys.REQUEST_PATH, RequestPath.parse(restRequest, null, null));
    FutureResult<ReadableStreamChannel> future = new FutureResult<>();
    handler.handle(restRequest, restResponseChannel, future::done);
    try {
        future.get(1, TimeUnit.SECONDS);
    } catch (ExecutionException e) {
        throw e.getCause() instanceof Exception ? (Exception) e.getCause() : new Exception(e.getCause());
    }
}
Also used : MockRestRequest(com.github.ambry.rest.MockRestRequest) RestRequest(com.github.ambry.rest.RestRequest) JSONObject(org.json.JSONObject) FutureResult(com.github.ambry.router.FutureResult) ReadableStreamChannel(com.github.ambry.router.ReadableStreamChannel) MockRestRequest(com.github.ambry.rest.MockRestRequest) ExecutionException(java.util.concurrent.ExecutionException) ByteBuffer(java.nio.ByteBuffer) LinkedList(java.util.LinkedList) ExecutionException(java.util.concurrent.ExecutionException) RestServiceException(com.github.ambry.rest.RestServiceException)

Example 22 with ReadableStreamChannel

use of com.github.ambry.router.ReadableStreamChannel in project ambry by linkedin.

the class FrontendRestRequestService method securityPostProcessRequestCallback.

/**
 * Build a callback to use for {@link SecurityService#postProcessRequest}. This callback forwards request to the
 * {@link Router} once ID conversion is completed. In the case of some sub-resources
 * (e.g., {@link SubResource#Replicas}), the request is completed and not forwarded to the {@link Router}.
 * @param convertedId the converted blob ID to use in router requests.
 * @param restRequest the {@link RestRequest}.
 * @param restResponseChannel the {@link RestResponseChannel}.
 * @param getCallback the {@link GetCallback} to use if this is a {@link RestMethod#GET} request, or null for other
 *                    request types.
 * @param headCallback the {@link HeadCallback} to use if this is a {@link RestMethod#HEAD} request, or null for other
 *                    request types.
 * @param deleteCallback the {@link DeleteCallback} to use if this is a {@link RestMethod#DELETE} request, or null for
 *                       other request types.
 * @return the {@link Callback} to use.
 */
private Callback<Void> securityPostProcessRequestCallback(String convertedId, RestRequest restRequest, RestResponseChannel restResponseChannel, GetCallback getCallback, HeadCallback headCallback, DeleteCallback deleteCallback) {
    Callback<ReadableStreamChannel> completionCallback = (result, exception) -> submitResponse(restRequest, restResponseChannel, result, exception);
    RestMethod restMethod = restRequest.getRestMethod();
    AsyncOperationTracker.Metrics metrics;
    switch(restMethod) {
        case GET:
            metrics = frontendMetrics.getSecurityPostProcessRequestMetrics;
            break;
        case HEAD:
            metrics = frontendMetrics.headSecurityPostProcessRequestMetrics;
            break;
        case DELETE:
            metrics = frontendMetrics.deleteSecurityPostProcessRequestMetrics;
            break;
        default:
            throw new IllegalStateException("Unrecognized RestMethod: " + restMethod);
    }
    return FrontendUtils.buildCallback(metrics, result -> {
        ReadableStreamChannel response = null;
        switch(restMethod) {
            case GET:
                SubResource subResource = getRequestPath(restRequest).getSubResource();
                // inject encryption metrics if need be
                if (BlobId.isEncrypted(convertedId)) {
                    RestRequestMetrics restRequestMetrics = getMetricsGroupForGet(frontendMetrics, subResource).getRestRequestMetrics(restRequest.isSslUsed(), true);
                    restRequest.getMetricsTracker().injectMetrics(restRequestMetrics);
                }
                if (subResource == null) {
                    getCallback.markStartTime();
                    router.getBlob(convertedId, getCallback.options, getCallback, QuotaUtils.buildQuotaChargeCallback(restRequest, quotaManager, true));
                } else {
                    switch(subResource) {
                        case BlobInfo:
                        case UserMetadata:
                        case Segment:
                            getCallback.markStartTime();
                            router.getBlob(convertedId, getCallback.options, getCallback, QuotaUtils.buildQuotaChargeCallback(restRequest, quotaManager, true));
                            break;
                        case Replicas:
                            response = getReplicasHandler.getReplicas(convertedId, restResponseChannel);
                            break;
                    }
                }
                break;
            case HEAD:
                GetOption getOption = getGetOption(restRequest, frontendConfig.defaultRouterGetOption);
                // inject encryption metrics if need be
                if (BlobId.isEncrypted(convertedId)) {
                    RestRequestMetrics requestMetrics = frontendMetrics.headBlobMetricsGroup.getRestRequestMetrics(restRequest.isSslUsed(), true);
                    restRequest.getMetricsTracker().injectMetrics(requestMetrics);
                }
                headCallback.markStartTime();
                router.getBlob(convertedId, new GetBlobOptionsBuilder().operationType(GetBlobOptions.OperationType.BlobInfo).getOption(getOption).restRequest(restRequest).build(), headCallback, QuotaUtils.buildQuotaChargeCallback(restRequest, quotaManager, false));
                break;
            case DELETE:
                deleteCallback.markStartTime();
                router.deleteBlob(convertedId, getHeader(restRequest.getArgs(), Headers.SERVICE_ID, false), deleteCallback, QuotaUtils.buildQuotaChargeCallback(restRequest, quotaManager, false));
                break;
            default:
                throw new IllegalStateException("Unrecognized RestMethod: " + restMethod);
        }
        if (response != null) {
            completionCallback.onCompletion(response, null);
        }
    }, restRequest.getUri(), logger, completionCallback);
}
Also used : Histogram(com.codahale.metrics.Histogram) GetOption(com.github.ambry.protocol.GetOption) FrontendConfig(com.github.ambry.config.FrontendConfig) ResponseStatus(com.github.ambry.rest.ResponseStatus) LoggerFactory(org.slf4j.LoggerFactory) ByteBufferReadableStreamChannel(com.github.ambry.commons.ByteBufferReadableStreamChannel) AccountService(com.github.ambry.account.AccountService) QuotaManager(com.github.ambry.quota.QuotaManager) ByteBuffer(java.nio.ByteBuffer) ThrowingConsumer(com.github.ambry.utils.ThrowingConsumer) RequestPath(com.github.ambry.rest.RequestPath) NamedBlobDb(com.github.ambry.named.NamedBlobDb) RestRequestService(com.github.ambry.rest.RestRequestService) RestRequestMetrics(com.github.ambry.rest.RestRequestMetrics) SystemTime(com.github.ambry.utils.SystemTime) Router(com.github.ambry.router.Router) RouterErrorCode(com.github.ambry.router.RouterErrorCode) RestResponseHandler(com.github.ambry.rest.RestResponseHandler) ReadableStreamChannel(com.github.ambry.router.ReadableStreamChannel) Logger(org.slf4j.Logger) GregorianCalendar(java.util.GregorianCalendar) RestMethod(com.github.ambry.rest.RestMethod) RestResponseChannel(com.github.ambry.rest.RestResponseChannel) RestServiceErrorCode(com.github.ambry.rest.RestServiceErrorCode) InternalKeys(com.github.ambry.rest.RestUtils.InternalKeys) ClusterMap(com.github.ambry.clustermap.ClusterMap) Utils(com.github.ambry.utils.Utils) IOException(java.io.IOException) GetBlobOptions(com.github.ambry.router.GetBlobOptions) RouterException(com.github.ambry.router.RouterException) BlobInfo(com.github.ambry.messageformat.BlobInfo) QuotaUtils(com.github.ambry.quota.QuotaUtils) AccountStatsStore(com.github.ambry.accountstats.AccountStatsStore) RestServiceException(com.github.ambry.rest.RestServiceException) GetBlobResult(com.github.ambry.router.GetBlobResult) Callback(com.github.ambry.commons.Callback) RestUtils(com.github.ambry.rest.RestUtils) AsyncOperationTracker(com.github.ambry.utils.AsyncOperationTracker) RestRequest(com.github.ambry.rest.RestRequest) GetBlobOptionsBuilder(com.github.ambry.router.GetBlobOptionsBuilder) BlobId(com.github.ambry.commons.BlobId) GetBlobOptionsBuilder(com.github.ambry.router.GetBlobOptionsBuilder) ByteBufferReadableStreamChannel(com.github.ambry.commons.ByteBufferReadableStreamChannel) ReadableStreamChannel(com.github.ambry.router.ReadableStreamChannel) RestRequestMetrics(com.github.ambry.rest.RestRequestMetrics) GetOption(com.github.ambry.protocol.GetOption) AsyncOperationTracker(com.github.ambry.utils.AsyncOperationTracker) RestMethod(com.github.ambry.rest.RestMethod)

Example 23 with ReadableStreamChannel

use of com.github.ambry.router.ReadableStreamChannel in project ambry by linkedin.

the class GetReplicasHandler method getReplicas.

/**
 * Handles {@link RestUtils.SubResource#Replicas} operations by obtaining the replicas of the blob ID from the cluster
 * map and returning a serialized JSON object in the response.
 * @param blobId the blob ID whose replicas are required.
 * @param restResponseChannel the {@link RestResponseChannel} to set headers in.
 * @return a {@link ReadableStreamChannel} that contains the getReplicas response.
 * @throws RestServiceException if there was any problem constructing the response.
 */
ReadableStreamChannel getReplicas(String blobId, RestResponseChannel restResponseChannel) throws RestServiceException {
    logger.trace("Getting replicas of blob ID - {}", blobId);
    long startTime = System.currentTimeMillis();
    ReadableStreamChannel channel = null;
    try {
        channel = FrontendUtils.serializeJsonToChannel(getReplicas(blobId));
        restResponseChannel.setHeader(RestUtils.Headers.CONTENT_TYPE, RestUtils.JSON_CONTENT_TYPE);
        restResponseChannel.setHeader(RestUtils.Headers.CONTENT_LENGTH, channel.getSize());
    } finally {
        metrics.getReplicasProcessingTimeInMs.update(System.currentTimeMillis() - startTime);
    }
    return channel;
}
Also used : ReadableStreamChannel(com.github.ambry.router.ReadableStreamChannel) ByteBufferReadableStreamChannel(com.github.ambry.commons.ByteBufferReadableStreamChannel)

Example 24 with ReadableStreamChannel

use of com.github.ambry.router.ReadableStreamChannel in project ambry by linkedin.

the class GetReplicasHandlerTest method getReplicasTest.

/**
 * Tests {@link GetReplicasHandler#getReplicas(String, RestResponseChannel)}
 * <p/>
 * For the each {@link PartitionId} in the {@link ClusterMap}, a {@link BlobId} is created. The replica list returned
 * from {@link GetReplicasHandler#getReplicas(String, RestResponseChannel)}is checked for equality against a locally
 * obtained replica list.
 * @throws Exception
 */
@Test
public void getReplicasTest() throws Exception {
    List<? extends PartitionId> partitionIds = CLUSTER_MAP.getWritablePartitionIds(null);
    for (PartitionId partitionId : partitionIds) {
        String originalReplicaStr = partitionId.getReplicaIds().toString().replace(", ", ",");
        BlobId blobId = new BlobId(CommonTestUtils.getCurrentBlobIdVersion(), BlobId.BlobIdType.NATIVE, ClusterMap.UNKNOWN_DATACENTER_ID, Account.UNKNOWN_ACCOUNT_ID, Container.UNKNOWN_CONTAINER_ID, partitionId, false, BlobId.BlobDataType.DATACHUNK);
        MockRestResponseChannel restResponseChannel = new MockRestResponseChannel();
        ReadableStreamChannel channel = getReplicasHandler.getReplicas(blobId.getID(), restResponseChannel);
        assertEquals("Unexpected response status", ResponseStatus.Ok, restResponseChannel.getStatus());
        assertEquals("Unexpected Content-Type", RestUtils.JSON_CONTENT_TYPE, restResponseChannel.getHeader(RestUtils.Headers.CONTENT_TYPE));
        String returnedReplicasStr = RestTestUtils.getJsonizedResponseBody(channel).get(GetReplicasHandler.REPLICAS_KEY).toString().replace("\"", "");
        assertEquals("Replica IDs returned for the BlobId do no match with the replicas IDs of partition", originalReplicaStr, returnedReplicasStr);
    }
}
Also used : ReadableStreamChannel(com.github.ambry.router.ReadableStreamChannel) PartitionId(com.github.ambry.clustermap.PartitionId) MockRestResponseChannel(com.github.ambry.rest.MockRestResponseChannel) BlobId(com.github.ambry.commons.BlobId) Test(org.junit.Test)

Example 25 with ReadableStreamChannel

use of com.github.ambry.router.ReadableStreamChannel in project ambry by linkedin.

the class GetStatsReportHandlerTest method handleGoodCaseTest.

@Test
public void handleGoodCaseTest() throws Exception {
    AggregatedAccountStorageStats aggregatedAccountStorageStats = new AggregatedAccountStorageStats(StorageStatsUtilTest.generateRandomAggregatedAccountStorageStats((short) 1, 10, 10, 1000L, 2, 100));
    doAnswer(invocation -> {
        String clusterName = invocation.getArgument(0);
        if (clusterName.equals(CLUSTER_NAME)) {
            return aggregatedAccountStorageStats;
        } else {
            return null;
        }
    }).when(accountStatsStore).queryAggregatedAccountStorageStatsByClusterName(anyString());
    RestRequest restRequest = createRestRequest(CLUSTER_NAME, StatsReportType.ACCOUNT_REPORT.name());
    RestResponseChannel restResponseChannel = new MockRestResponseChannel();
    ReadableStreamChannel channel = sendRequestGetResponse(restRequest, restResponseChannel);
    assertNotNull("There should be a response", channel);
    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)));
    assertEquals("Storage stats mismatch", aggregatedAccountStorageStats.getStorageStats(), mapper.readValue(RestTestUtils.getResponseBody(channel), AggregatedAccountStorageStats.class).getStorageStats());
    AggregatedPartitionClassStorageStats aggregatedPartitionClassStorageStats = new AggregatedPartitionClassStorageStats(StorageStatsUtilTest.generateRandomAggregatedPartitionClassStorageStats(new String[] { "default", "newClass" }, (short) 1, 10, 10, 1000L, 2, 100));
    doAnswer(invocation -> {
        String clusterName = invocation.getArgument(0);
        if (clusterName.equals(CLUSTER_NAME)) {
            return aggregatedPartitionClassStorageStats;
        } else {
            return null;
        }
    }).when(accountStatsStore).queryAggregatedPartitionClassStorageStatsByClusterName(anyString());
    restRequest = createRestRequest(CLUSTER_NAME, StatsReportType.PARTITION_CLASS_REPORT.name());
    restResponseChannel = new MockRestResponseChannel();
    channel = sendRequestGetResponse(restRequest, restResponseChannel);
    assertNotNull("There should be a response", channel);
    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)));
    assertEquals("Storage stats mismatch", aggregatedPartitionClassStorageStats.getStorageStats(), mapper.readValue(RestTestUtils.getResponseBody(channel), AggregatedPartitionClassStorageStats.class).getStorageStats());
}
Also used : MockRestRequest(com.github.ambry.rest.MockRestRequest) RestRequest(com.github.ambry.rest.RestRequest) ReadableStreamChannel(com.github.ambry.router.ReadableStreamChannel) AggregatedAccountStorageStats(com.github.ambry.server.storagestats.AggregatedAccountStorageStats) RestResponseChannel(com.github.ambry.rest.RestResponseChannel) MockRestResponseChannel(com.github.ambry.rest.MockRestResponseChannel) AggregatedPartitionClassStorageStats(com.github.ambry.server.storagestats.AggregatedPartitionClassStorageStats) MockRestResponseChannel(com.github.ambry.rest.MockRestResponseChannel) Test(org.junit.Test) StorageStatsUtilTest(com.github.ambry.server.StorageStatsUtilTest)

Aggregations

ReadableStreamChannel (com.github.ambry.router.ReadableStreamChannel)29 Test (org.junit.Test)14 MockRestRequest (com.github.ambry.rest.MockRestRequest)13 ByteBufferReadableStreamChannel (com.github.ambry.commons.ByteBufferReadableStreamChannel)11 RestRequest (com.github.ambry.rest.RestRequest)10 MockRestResponseChannel (com.github.ambry.rest.MockRestResponseChannel)9 IOException (java.io.IOException)8 ByteBuffer (java.nio.ByteBuffer)8 RestResponseChannel (com.github.ambry.rest.RestResponseChannel)7 InputStream (java.io.InputStream)7 RestServiceException (com.github.ambry.rest.RestServiceException)6 JSONObject (org.json.JSONObject)6 FutureResult (com.github.ambry.router.FutureResult)5 RetainingAsyncWritableChannel (com.github.ambry.commons.RetainingAsyncWritableChannel)4 RequestPath (com.github.ambry.rest.RequestPath)4 RestMethod (com.github.ambry.rest.RestMethod)4 RestServiceErrorCode (com.github.ambry.rest.RestServiceErrorCode)4 RestUtils (com.github.ambry.rest.RestUtils)4 RouterException (com.github.ambry.router.RouterException)4 ThrowingConsumer (com.github.ambry.utils.ThrowingConsumer)4