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());
}
}
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);
}
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;
}
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);
}
}
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());
}
Aggregations