Search in sources :

Example 36 with RestRequest

use of com.github.ambry.rest.RestRequest in project ambry by linkedin.

the class SimpleAmbryCostModelPolicyTest method testCalculateRequestCost.

@Test
public void testCalculateRequestCost() throws Exception {
    SimpleAmbryCostModelPolicy requestCostPolicy = new SimpleAmbryCostModelPolicy();
    RestResponseChannel restResponseChannel = mock(RestResponseChannel.class);
    when(restResponseChannel.getHeader(anyString())).thenReturn(0);
    String blobUri = "/AAYIAQSSAAgAAQAAAAAAABpFymbGwe7sRBWYa5OPlkcNHQ.bin";
    // test for a 4 MB GET request.
    BlobInfo blobInfo = getBlobInfo(4 * MB);
    RestRequest restRequest = createMockRequestWithMethod(RestMethod.GET, blobUri, -1);
    Map<String, Double> costMap = requestCostPolicy.calculateRequestCost(restRequest, restResponseChannel, blobInfo);
    verifyReadCost(costMap, 1);
    // test for a small GET request (fractional CU).
    blobInfo = getBlobInfo(6 * MB);
    costMap = requestCostPolicy.calculateRequestCost(restRequest, restResponseChannel, blobInfo);
    verifyReadCost(costMap, 2);
    // test for a GET request of blob of size 0.
    blobInfo = getBlobInfo(0);
    restRequest = createMockRequestWithMethod(RestMethod.GET, blobUri, -1);
    costMap = requestCostPolicy.calculateRequestCost(restRequest, restResponseChannel, blobInfo);
    verifyReadCost(costMap, 1);
    // test for a small POST request (fractional storage cost).
    blobInfo = getBlobInfo(8 * MB);
    restRequest = createMockRequestWithMethod(RestMethod.POST, blobUri, 8 * MB);
    costMap = requestCostPolicy.calculateRequestCost(restRequest, restResponseChannel, blobInfo);
    verifyWriteCost(costMap, 2, 8 * 1024 * 1024 / (double) QuotaUtils.BYTES_IN_GB);
    // test for a large POST request.
    blobInfo = getBlobInfo(4 * GB);
    restRequest = createMockRequestWithMethod(RestMethod.POST, blobUri, 4 * GB);
    costMap = requestCostPolicy.calculateRequestCost(restRequest, restResponseChannel, blobInfo);
    verifyWriteCost(costMap, 1024, 4);
    // test for a POST request of blob of size 0.
    blobInfo = getBlobInfo(0);
    restRequest = createMockRequestWithMethod(RestMethod.POST, blobUri, 0);
    costMap = requestCostPolicy.calculateRequestCost(restRequest, restResponseChannel, blobInfo);
    verifyWriteCost(costMap, 1, 0);
    // test for a HEAD request.
    restRequest = createMockRequestWithMethod(RestMethod.HEAD, blobUri, -1);
    costMap = requestCostPolicy.calculateRequestCost(restRequest, restResponseChannel, blobInfo);
    verifyReadCost(costMap, 1);
    // test for a DELETE request.
    restRequest = createMockRequestWithMethod(RestMethod.DELETE, blobUri, -1);
    costMap = requestCostPolicy.calculateRequestCost(restRequest, restResponseChannel, blobInfo);
    verifyWriteCost(costMap, 1, 0.0);
    // test for a PUT request.
    restRequest = createMockRequestWithMethod(RestMethod.PUT, blobUri, -1);
    costMap = requestCostPolicy.calculateRequestCost(restRequest, restResponseChannel, blobInfo);
    verifyWriteCost(costMap, 1, 0.0);
    // test for PUT with null blob info.
    costMap = requestCostPolicy.calculateRequestCost(restRequest, restResponseChannel, null);
    verifyWriteCost(costMap, 1, 0.0);
    // test BlobInfo and UserMetadata GET requests
    blobInfo = getBlobInfo(40 * GB);
    restRequest = createMockRequestWithMethod(RestMethod.GET, blobUri + "/BlobInfo", -1);
    costMap = requestCostPolicy.calculateRequestCost(restRequest, restResponseChannel, blobInfo);
    verifyReadCost(costMap, 1);
    restRequest = createMockRequestWithMethod(RestMethod.GET, blobUri + "/UserMetadata", -1);
    costMap = requestCostPolicy.calculateRequestCost(restRequest, restResponseChannel, blobInfo);
    verifyReadCost(costMap, 1);
    // Plain GET should use blob size
    restRequest = createMockRequestWithMethod(RestMethod.GET, blobUri, -1);
    costMap = requestCostPolicy.calculateRequestCost(restRequest, restResponseChannel, blobInfo);
    verifyReadCost(costMap, 10240);
// TODO add a range request case with large range
}
Also used : RestRequest(com.github.ambry.rest.RestRequest) RestResponseChannel(com.github.ambry.rest.RestResponseChannel) BlobInfo(com.github.ambry.messageformat.BlobInfo) Test(org.junit.Test)

Example 37 with RestRequest

use of com.github.ambry.rest.RestRequest in project ambry by linkedin.

the class TtlUpdateHandlerTest method badArgsTest.

/**
 * Tests for expected failures with bad arguments
 * @throws Exception
 */
private void badArgsTest() throws Exception {
    RestRequest restRequest = new MockRestRequest(MockRestRequest.DUMMY_DATA, null);
    restRequest.setArg(RestUtils.Headers.BLOB_ID, blobId);
    // no service ID
    verifyFailureWithErrorCode(restRequest, RestServiceErrorCode.MissingArgs);
    restRequest = new MockRestRequest(MockRestRequest.DUMMY_DATA, null);
    restRequest.setArg(RestUtils.Headers.SERVICE_ID, SERVICE_ID);
    // no blob ID
    verifyFailureWithErrorCode(restRequest, RestServiceErrorCode.MissingArgs);
    restRequest = new MockRestRequest(MockRestRequest.DUMMY_DATA, null);
    // not a valid blob ID
    restRequest.setArg(RestUtils.Headers.BLOB_ID, "abcd");
    idConverterFactory.translation = "abcd";
    restRequest.setArg(RestUtils.Headers.SERVICE_ID, SERVICE_ID);
    verifyFailureWithErrorCode(restRequest, RestServiceErrorCode.BadRequest);
}
Also used : MockRestRequest(com.github.ambry.rest.MockRestRequest) RestRequest(com.github.ambry.rest.RestRequest) MockRestRequest(com.github.ambry.rest.MockRestRequest)

Example 38 with RestRequest

use of com.github.ambry.rest.RestRequest in project ambry by linkedin.

the class HostLevelThrottlerTest method quotaTest.

/**
 * Test to make sure {@link HostLevelThrottler#shouldThrottle(RestRequest)} works as expected.
 */
@Test
public void quotaTest() throws Exception {
    Properties props = new Properties();
    props.setProperty(HostThrottleConfig.REST_REQUEST_QUOTA_STRING, "{\"PUT\": \"20\",\"GET\": \"20\",\"POST\": \"20\",\"HEAD\": \"20\",\"OPTIONS\": \"20\",\"DELETE\": \"20\"}");
    HostThrottleConfig hostThrottleConfig = new HostThrottleConfig(new VerifiableProperties(props));
    MockClock clock = new MockClock();
    HostLevelThrottler quotaManager = new HostLevelThrottler(createQuotaMock(hostThrottleConfig, clock), new HashMap<>(), null);
    // Issue new requests. Since MockClock tick doesn't change, rate is 0.
    for (int i = 0; i < 100; i++) {
        for (RestMethod restMethod : RestMethod.values()) {
            RestRequest restRequest = createRestRequest(restMethod, "http://www.linkedin.com/");
            Assert.assertFalse("Should not throttle", quotaManager.shouldThrottle(restRequest));
        }
    }
    // Move MockClock ahead to 5 seconds later. Rate = 20. New requests should be denied unless its quota is not defined.
    clock.tick(5);
    for (RestMethod restMethod : RestMethod.values()) {
        RestRequest restRequest = createRestRequest(restMethod, "http://www.linkedin.com/");
        if (restMethod == RestMethod.UNKNOWN) {
            Assert.assertFalse("Should not throttle.", quotaManager.shouldThrottle(restRequest));
        } else {
            Assert.assertTrue("Should throttle", quotaManager.shouldThrottle(restRequest));
        }
    }
    // Clock tick to another 5 seconds later, rate < 20. Accept new requests.
    clock.tick(5);
    for (RestMethod restMethod : RestMethod.values()) {
        RestRequest restRequest = createRestRequest(restMethod, "http://www.linkedin.com/");
        Assert.assertFalse("Should not throttle", quotaManager.shouldThrottle(restRequest));
    }
}
Also used : MockRestRequest(com.github.ambry.rest.MockRestRequest) RestRequest(com.github.ambry.rest.RestRequest) VerifiableProperties(com.github.ambry.config.VerifiableProperties) Properties(java.util.Properties) VerifiableProperties(com.github.ambry.config.VerifiableProperties) HostThrottleConfig(com.github.ambry.config.HostThrottleConfig) MockClock(com.github.ambry.utils.MockClock) RestMethod(com.github.ambry.rest.RestMethod) Test(org.junit.Test)

Example 39 with RestRequest

use of com.github.ambry.rest.RestRequest in project ambry by linkedin.

the class FrontendRestRequestService method handlePut.

@Override
public void handlePut(RestRequest restRequest, RestResponseChannel restResponseChannel) {
    ThrowingConsumer<RequestPath> routingAction = requestPath -> {
        if (requestPath.matchesOperation(Operations.UPDATE_TTL)) {
            ttlUpdateHandler.handle(restRequest, restResponseChannel, (r, e) -> {
                if (e instanceof RouterException && ((RouterException) e).getErrorCode() == RouterErrorCode.BlobUpdateNotAllowed) {
                    restResponseChannel.setHeader(Headers.ALLOW, TTL_UPDATE_REJECTED_ALLOW_HEADER_VALUE);
                }
                submitResponse(restRequest, restResponseChannel, null, e);
            });
        } else if (requestPath.matchesOperation(Operations.UNDELETE) && frontendConfig.enableUndelete) {
            // If the undelete is not enabled, then treat it as unrecognized operation.
            // And always send failure reason back to client for undelete
            restRequest.setArg(SEND_FAILURE_REASON, Boolean.TRUE);
            undeleteHandler.handle(restRequest, restResponseChannel, (r, e) -> {
                submitResponse(restRequest, restResponseChannel, null, e);
            });
        } else if (requestPath.matchesOperation(Operations.NAMED_BLOB)) {
            restRequest.setArg(SEND_FAILURE_REASON, Boolean.TRUE);
            namedBlobPutHandler.handle(restRequest, restResponseChannel, (r, e) -> submitResponse(restRequest, restResponseChannel, null, e));
        } else {
            throw new RestServiceException("Unrecognized operation: " + requestPath.getOperationOrBlobId(false), RestServiceErrorCode.BadRequest);
        }
    };
    preProcessAndRouteRequest(restRequest, restResponseChannel, frontendMetrics.putPreProcessingMetrics, routingAction);
}
Also used : RequestPath(com.github.ambry.rest.RequestPath) 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) RestServiceException(com.github.ambry.rest.RestServiceException) RouterException(com.github.ambry.router.RouterException)

Example 40 with RestRequest

use of com.github.ambry.rest.RestRequest in project ambry by linkedin.

the class AmbryCUQuotaEnforcerTest method testCharge.

@Test
public void testCharge() throws Exception {
    Container container = ACCOUNT.getAllContainers().iterator().next();
    Map<QuotaName, Double> readRequestCostMap = Collections.singletonMap(QuotaName.READ_CAPACITY_UNIT, 9.0);
    Map<QuotaName, Double> writeRequestCostMap = Collections.singletonMap(QuotaName.WRITE_CAPACITY_UNIT, 9.0);
    Map<String, CapacityUnit> usageMap = QUOTA_SOURCE.getAllQuotaUsage();
    // 1. Test that usage is updated and recommendation is serve when usage is within limit.
    RestRequest restRequest = QuotaTestUtils.createRestRequest(ACCOUNT, container, RestMethod.GET);
    AMBRY_QUOTA_ENFORCER.charge(restRequest, readRequestCostMap);
    QuotaRecommendation quotaRecommendation = AMBRY_QUOTA_ENFORCER.recommend(restRequest);
    assertEquals(quotaRecommendation.getQuotaName(), QuotaName.READ_CAPACITY_UNIT);
    assertEquals(quotaRecommendation.getQuotaUsagePercentage(), 90, 0.1);
    assertEquals(quotaRecommendation.getQuotaAction(), QuotaAction.ALLOW);
    // make sure that correct quota is charged.
    assertEquals(usageMap.get(String.valueOf(ACCOUNT.getId())).getWcu(), 0);
    restRequest = QuotaTestUtils.createRestRequest(ACCOUNT, container, RestMethod.POST);
    AMBRY_QUOTA_ENFORCER.charge(restRequest, writeRequestCostMap);
    quotaRecommendation = AMBRY_QUOTA_ENFORCER.recommend(restRequest);
    assertEquals(quotaRecommendation.getQuotaName(), QuotaName.WRITE_CAPACITY_UNIT);
    assertEquals(quotaRecommendation.getQuotaUsagePercentage(), 90, 0.1);
    assertEquals(quotaRecommendation.getQuotaAction(), QuotaAction.ALLOW);
    // make sure that correct quota is charged.
    assertEquals(usageMap.get(String.valueOf(ACCOUNT.getId())).getRcu(), 9);
    // 2. Test that retryable quota exception is thrown when quota not found.
    Account newAccount = ACCOUNT_SERVICE.generateRandomAccount(QuotaResourceType.ACCOUNT);
    restRequest = QuotaTestUtils.createRestRequest(newAccount, newAccount.getAllContainers().iterator().next(), RestMethod.GET);
    try {
        AMBRY_QUOTA_ENFORCER.charge(restRequest, readRequestCostMap);
        AMBRY_QUOTA_ENFORCER.recommend(restRequest);
        fail("if quota is not found we should see exception");
    } catch (QuotaException quotaException) {
        Assert.assertTrue(quotaException.isRetryable());
    }
    // 3. Test that retryable quota exception is thrown in case of any error.
    restRequest = QuotaTestUtils.createRestRequest(ACCOUNT, container, RestMethod.GET);
    QUOTA_SOURCE.throwException = true;
    try {
        AMBRY_QUOTA_ENFORCER.charge(restRequest, readRequestCostMap);
        fail("QuotaException should be thrown in case of any error.");
    } catch (QuotaException quotaException) {
        Assert.assertTrue(quotaException.isRetryable());
    }
    QUOTA_SOURCE.throwException = false;
    // 4. Test that usage is updated and recommendation is deny when usage >= quota.
    AMBRY_QUOTA_ENFORCER.charge(restRequest, readRequestCostMap);
    quotaRecommendation = AMBRY_QUOTA_ENFORCER.recommend(restRequest);
    assertEquals(QuotaName.READ_CAPACITY_UNIT, quotaRecommendation.getQuotaName());
    assertEquals(180, quotaRecommendation.getQuotaUsagePercentage(), 0.1);
    assertEquals(quotaRecommendation.getQuotaAction(), QuotaAction.DELAY);
    // make sure that correct quota is charged.
    assertEquals(9, usageMap.get(String.valueOf(ACCOUNT.getId())).getWcu());
    assertEquals(18, // make sure that correct quota is charged.
    usageMap.get(String.valueOf(ACCOUNT.getId())).getRcu());
    restRequest = QuotaTestUtils.createRestRequest(ACCOUNT, container, RestMethod.POST);
    AMBRY_QUOTA_ENFORCER.charge(restRequest, writeRequestCostMap);
    quotaRecommendation = AMBRY_QUOTA_ENFORCER.recommend(restRequest);
    assertEquals(QuotaName.WRITE_CAPACITY_UNIT, quotaRecommendation.getQuotaName());
    assertEquals(180, quotaRecommendation.getQuotaUsagePercentage(), 0.1);
    assertEquals(quotaRecommendation.getQuotaAction(), QuotaAction.DELAY);
    assertEquals(18, // make sure that correct quota is charged.
    usageMap.get(String.valueOf(ACCOUNT.getId())).getWcu());
    assertEquals(18, // make sure that correct quota is charged.
    usageMap.get(String.valueOf(ACCOUNT.getId())).getRcu());
    restRequest = QuotaTestUtils.createRestRequest(ACCOUNT, container, RestMethod.DELETE);
    AMBRY_QUOTA_ENFORCER.charge(restRequest, writeRequestCostMap);
    quotaRecommendation = AMBRY_QUOTA_ENFORCER.recommend(restRequest);
    assertEquals(QuotaName.WRITE_CAPACITY_UNIT, quotaRecommendation.getQuotaName());
    assertEquals(270, quotaRecommendation.getQuotaUsagePercentage(), 0.1);
    assertEquals(quotaRecommendation.getQuotaAction(), QuotaAction.DELAY);
    assertEquals(27, // make sure that correct quota is charged.
    usageMap.get(String.valueOf(ACCOUNT.getId())).getWcu());
    assertEquals(18, // make sure that correct quota is charged.
    usageMap.get(String.valueOf(ACCOUNT.getId())).getRcu());
    restRequest = QuotaTestUtils.createRestRequest(ACCOUNT, container, RestMethod.PUT);
    AMBRY_QUOTA_ENFORCER.charge(restRequest, writeRequestCostMap);
    quotaRecommendation = AMBRY_QUOTA_ENFORCER.recommend(restRequest);
    assertEquals(QuotaName.WRITE_CAPACITY_UNIT, quotaRecommendation.getQuotaName());
    assertEquals(360, quotaRecommendation.getQuotaUsagePercentage(), 0.1);
    assertEquals(quotaRecommendation.getQuotaAction(), QuotaAction.DELAY);
    assertEquals(36, // make sure that correct quota is charged.
    usageMap.get(String.valueOf(ACCOUNT.getId())).getWcu());
    assertEquals(18, // make sure that correct quota is charged.
    usageMap.get(String.valueOf(ACCOUNT.getId())).getRcu());
}
Also used : QuotaName(com.github.ambry.quota.QuotaName) Account(com.github.ambry.account.Account) Container(com.github.ambry.account.Container) RestRequest(com.github.ambry.rest.RestRequest) QuotaException(com.github.ambry.quota.QuotaException) QuotaRecommendation(com.github.ambry.quota.QuotaRecommendation) Test(org.junit.Test)

Aggregations

RestRequest (com.github.ambry.rest.RestRequest)102 MockRestRequest (com.github.ambry.rest.MockRestRequest)82 MockRestResponseChannel (com.github.ambry.rest.MockRestResponseChannel)54 JSONObject (org.json.JSONObject)50 Test (org.junit.Test)46 RestServiceException (com.github.ambry.rest.RestServiceException)34 RestResponseChannel (com.github.ambry.rest.RestResponseChannel)26 RestMethod (com.github.ambry.rest.RestMethod)23 Account (com.github.ambry.account.Account)18 StorageStatsUtilTest (com.github.ambry.server.StorageStatsUtilTest)18 ExecutionException (java.util.concurrent.ExecutionException)18 ByteBuffer (java.nio.ByteBuffer)17 RestUtils (com.github.ambry.rest.RestUtils)16 RestUtilsTest (com.github.ambry.rest.RestUtilsTest)16 ReadableStreamChannel (com.github.ambry.router.ReadableStreamChannel)16 RestServiceErrorCode (com.github.ambry.rest.RestServiceErrorCode)15 MetricRegistry (com.codahale.metrics.MetricRegistry)14 Container (com.github.ambry.account.Container)14 RequestPath (com.github.ambry.rest.RequestPath)14 FutureResult (com.github.ambry.router.FutureResult)14