Search in sources :

Example 6 with UndeleteRequest

use of com.github.ambry.protocol.UndeleteRequest in project ambry by linkedin.

the class AmbryServerRequestsTest method sendAndVerifyOperationRequest.

/**
 * Sends and verifies that an operation specific request works correctly.
 * @param requestType the type of the request to send.
 * @param ids the partitionIds to send requests for.
 * @param expectedErrorCode the {@link ServerErrorCode} expected in the response. For some requests this is the
 *                          response in the constituents rather than the actual response ({@link GetResponse} and
 *                          {@link ReplicaMetadataResponse}).
 * @param forceCheckOpReceived if {@code true}, checks the operation received at the {@link Store} even if
 *                             there is an error expected. Always checks op received if {@code expectedErrorCode} is
 *                             {@link ServerErrorCode#No_Error}. Skips the check otherwise.
 * @param clientIdStr the clientId string to construct request. if null, generate a random string as clientId.
 * @throws InterruptedException
 * @throws IOException
 * @return a list of {@link Response}(s) associated with given partition ids.
 */
private List<Response> sendAndVerifyOperationRequest(RequestOrResponseType requestType, List<? extends PartitionId> ids, ServerErrorCode expectedErrorCode, Boolean forceCheckOpReceived, String clientIdStr) throws InterruptedException, IOException {
    List<Response> responses = new ArrayList<>();
    for (PartitionId id : ids) {
        int correlationId = TestUtils.RANDOM.nextInt();
        String clientId = clientIdStr == null ? TestUtils.getRandomString(10) : clientIdStr;
        BlobId originalBlobId = new BlobId(CommonTestUtils.getCurrentBlobIdVersion(), BlobId.BlobIdType.NATIVE, ClusterMap.UNKNOWN_DATACENTER_ID, Utils.getRandomShort(TestUtils.RANDOM), Utils.getRandomShort(TestUtils.RANDOM), id, false, BlobId.BlobDataType.DATACHUNK);
        BlobId convertedBlobId = new BlobId(CommonTestUtils.getCurrentBlobIdVersion(), BlobId.BlobIdType.CRAFTED, ClusterMap.UNKNOWN_DATACENTER_ID, originalBlobId.getAccountId(), originalBlobId.getContainerId(), id, false, BlobId.BlobDataType.DATACHUNK);
        conversionMap.put(originalBlobId, convertedBlobId);
        validKeysInStore.add(convertedBlobId);
        RequestOrResponse request;
        switch(requestType) {
            case PutRequest:
                BlobProperties properties = new BlobProperties(0, "serviceId", originalBlobId.getAccountId(), originalBlobId.getAccountId(), false);
                request = new PutRequest(correlationId, clientId, originalBlobId, properties, ByteBuffer.allocate(0), Unpooled.wrappedBuffer(ByteBuffer.allocate(0)), 0, BlobType.DataBlob, null);
                break;
            case DeleteRequest:
                request = new DeleteRequest(correlationId, clientId, originalBlobId, SystemTime.getInstance().milliseconds());
                break;
            case UndeleteRequest:
                request = new UndeleteRequest(correlationId, clientId, originalBlobId, SystemTime.getInstance().milliseconds());
                break;
            case GetRequest:
                PartitionRequestInfo pRequestInfo = new PartitionRequestInfo(id, Collections.singletonList(originalBlobId));
                request = new GetRequest(correlationId, clientId, MessageFormatFlags.All, Collections.singletonList(pRequestInfo), GetOption.Include_All);
                break;
            case ReplicaMetadataRequest:
                ReplicaMetadataRequestInfo rRequestInfo = new ReplicaMetadataRequestInfo(id, findTokenHelper.getFindTokenFactoryFromReplicaType(ReplicaType.DISK_BACKED).getNewFindToken(), "localhost", "/tmp", ReplicaType.DISK_BACKED, replicationConfig.replicaMetadataRequestVersion);
                request = new ReplicaMetadataRequest(correlationId, clientId, Collections.singletonList(rRequestInfo), Long.MAX_VALUE, replicationConfig.replicaMetadataRequestVersion);
                break;
            case TtlUpdateRequest:
                request = new TtlUpdateRequest(correlationId, clientId, originalBlobId, Utils.Infinite_Time, SystemTime.getInstance().milliseconds());
                break;
            default:
                throw new IllegalArgumentException(requestType + " not supported by this function");
        }
        responses.add(sendAndVerifyOperationRequest(request, expectedErrorCode, forceCheckOpReceived));
    }
    return responses;
}
Also used : TtlUpdateRequest(com.github.ambry.protocol.TtlUpdateRequest) ArrayList(java.util.ArrayList) PutRequest(com.github.ambry.protocol.PutRequest) UndeleteRequest(com.github.ambry.protocol.UndeleteRequest) MockPartitionId(com.github.ambry.clustermap.MockPartitionId) PartitionId(com.github.ambry.clustermap.PartitionId) PartitionRequestInfo(com.github.ambry.protocol.PartitionRequestInfo) CatchupStatusAdminResponse(com.github.ambry.protocol.CatchupStatusAdminResponse) Response(com.github.ambry.protocol.Response) GetResponse(com.github.ambry.protocol.GetResponse) ReplicaMetadataResponse(com.github.ambry.protocol.ReplicaMetadataResponse) AdminResponse(com.github.ambry.protocol.AdminResponse) RequestOrResponse(com.github.ambry.protocol.RequestOrResponse) RequestOrResponse(com.github.ambry.protocol.RequestOrResponse) ReplicaMetadataRequest(com.github.ambry.protocol.ReplicaMetadataRequest) ReplicaMetadataRequestInfo(com.github.ambry.protocol.ReplicaMetadataRequestInfo) BlobProperties(com.github.ambry.messageformat.BlobProperties) GetRequest(com.github.ambry.protocol.GetRequest) BlobId(com.github.ambry.commons.BlobId) DeleteRequest(com.github.ambry.protocol.DeleteRequest)

Example 7 with UndeleteRequest

use of com.github.ambry.protocol.UndeleteRequest in project ambry by linkedin.

the class AmbryServerRequestsTest method doUndelete.

/**
 * Does a UNDELETE and checks for success if {@code expectedErrorCode} is {@link ServerErrorCode#No_Error}. Else,
 * checks for failure with the code {@code expectedErrorCode}.
 * @param correlationId the correlation ID to use in the request
 * @param clientId the client ID to use in the request
 * @param blobId the blob ID to use in the request
 * @param opTimeMs the operation time (ms) to use in the request
 * @param expectedErrorCode the expected {@link ServerErrorCode}
 * @throws Exception
 */
private void doUndelete(int correlationId, String clientId, BlobId blobId, long opTimeMs, ServerErrorCode expectedErrorCode) throws Exception {
    UndeleteRequest request = new UndeleteRequest(correlationId, clientId, blobId, opTimeMs);
    sendAndVerifyOperationRequest(request, expectedErrorCode, true).release();
    if (expectedErrorCode == ServerErrorCode.No_Error) {
        verifyUndelete(request.getBlobId(), opTimeMs, MockStorageManager.messageWriteSetReceived);
    }
}
Also used : UndeleteRequest(com.github.ambry.protocol.UndeleteRequest)

Example 8 with UndeleteRequest

use of com.github.ambry.protocol.UndeleteRequest in project ambry by linkedin.

the class InMemoryCloudDestinationErrorSimulationTest method testUndeleteBlobErrorSimulation.

/**
 * test error simulation for UndeleteRequest
 * @throws Exception
 */
@Test
public void testUndeleteBlobErrorSimulation() throws Exception {
    BlobId blobId = doPut(partitionId);
    // Delete the blob first
    {
        DeleteRequest request = new DeleteRequest(1234, "clientId", blobId, SystemTime.getInstance().milliseconds());
        RequestInfo requestInfo = new RequestInfo(hostname, port, request, replica, null);
        ResponseInfo responseInfo = sendAndWaitForResponses(requestInfo);
        DeleteResponse response = responseInfo.getError() == null ? (DeleteResponse) RouterUtils.mapToReceivedResponse((Response) responseInfo.getResponse()) : null;
        Assert.assertEquals("DeleteRequest should succeed.", response.getError(), ServerErrorCode.No_Error);
    }
    UndeleteRequest request = new UndeleteRequest(1234, "clientId", blobId, SystemTime.getInstance().milliseconds());
    RequestInfo requestInfo = new RequestInfo(hostname, port, request, replica, null);
    ResponseInfo responseInfo = sendAndWaitForResponses(requestInfo);
    UndeleteResponse response = responseInfo.getError() == null ? (UndeleteResponse) RouterUtils.mapToReceivedResponse((UndeleteResponse) responseInfo.getResponse()) : null;
    Assert.assertEquals("UndeleteRequest should succeed.", response.getError(), ServerErrorCode.No_Error);
    response.release();
    // inject error for cloud colo.
    cloudDestination.setServerErrorForAllRequests(StoreErrorCodes.Unknown_Error);
    request = new UndeleteRequest(1234, "clientId", blobId, SystemTime.getInstance().milliseconds());
    requestInfo = new RequestInfo(hostname, port, request, replica, null);
    responseInfo = sendAndWaitForResponses(requestInfo);
    response = responseInfo.getError() == null ? (UndeleteResponse) RouterUtils.mapToReceivedResponse((UndeleteResponse) responseInfo.getResponse()) : null;
    Assert.assertEquals("UndeleteRequest should return Unknown_Error.", response.getError(), ServerErrorCode.Unknown_Error);
    response.release();
}
Also used : ResponseInfo(com.github.ambry.network.ResponseInfo) PartitionResponseInfo(com.github.ambry.protocol.PartitionResponseInfo) GetResponse(com.github.ambry.protocol.GetResponse) TtlUpdateResponse(com.github.ambry.protocol.TtlUpdateResponse) UndeleteResponse(com.github.ambry.protocol.UndeleteResponse) DeleteResponse(com.github.ambry.protocol.DeleteResponse) PutResponse(com.github.ambry.protocol.PutResponse) Response(com.github.ambry.protocol.Response) DeleteResponse(com.github.ambry.protocol.DeleteResponse) UndeleteRequest(com.github.ambry.protocol.UndeleteRequest) UndeleteResponse(com.github.ambry.protocol.UndeleteResponse) PartitionRequestInfo(com.github.ambry.protocol.PartitionRequestInfo) RequestInfo(com.github.ambry.network.RequestInfo) BlobId(com.github.ambry.commons.BlobId) DeleteRequest(com.github.ambry.protocol.DeleteRequest) Test(org.junit.Test)

Example 9 with UndeleteRequest

use of com.github.ambry.protocol.UndeleteRequest in project ambry by linkedin.

the class NonBlockingRouterTestBase method ensureUndeleteInAllServers.

/**
 * Ensure that Undelete request for given blob is reaches to all the  mock servers in the {@link MockServerLayout}.
 * @param blobId The blob id of which Undelete request will be created.
 * @param serverLayout The mock server layout.
 * @throws IOException
 */
protected void ensureUndeleteInAllServers(String blobId, MockServerLayout serverLayout) throws IOException {
    BlobId id = new BlobId(blobId, mockClusterMap);
    for (MockServer server : serverLayout.getMockServers()) {
        if (!server.getBlobs().get(blobId).isUndeleted()) {
            UndeleteRequest undeleteRequest = new UndeleteRequest(NonBlockingRouter.correlationIdGenerator.incrementAndGet(), routerConfig.routerHostname, id, mockTime.milliseconds());
            server.send(undeleteRequest).release();
            undeleteRequest.release();
        }
    }
}
Also used : UndeleteRequest(com.github.ambry.protocol.UndeleteRequest) BlobId(com.github.ambry.commons.BlobId)

Example 10 with UndeleteRequest

use of com.github.ambry.protocol.UndeleteRequest in project ambry by linkedin.

the class UndeleteOperation method handleResponse.

/**
 * Handles a response for a Undelete operation. It determines whether the request was successful and updates
 * operation tracker. For the same operation, it is possible that different {@link ServerErrorCode} are received from
 * different replicas. These error codes are eventually resolved to a single {@link RouterErrorCode}.
 * @param responseInfo The {@link ResponseInfo} to be handled.
 * @param undeleteResponse The {@link UndeleteResponse} associated with this response.
 */
void handleResponse(ResponseInfo responseInfo, UndeleteResponse undeleteResponse) {
    UndeleteRequest undeleteRequest = (UndeleteRequest) responseInfo.getRequestInfo().getRequest();
    UndeleteRequestInfo undeleteRequestInfo = undeleteRequestInfos.remove(undeleteRequest.getCorrelationId());
    // metric is updated here, as corresponding metrics have been updated when the request was timed out.
    if (undeleteRequestInfo == null) {
        return;
    }
    ReplicaId replica = undeleteRequestInfo.replica;
    long requestLatencyMs = time.milliseconds() - undeleteRequestInfo.startTimeMs;
    routerMetrics.routerRequestLatencyMs.update(requestLatencyMs);
    routerMetrics.getDataNodeBasedMetrics(replica.getDataNodeId()).undeleteRequestLatencyMs.update(requestLatencyMs);
    // Check the error code from NetworkClient.
    if (responseInfo.getError() != null) {
        LOGGER.trace("UndeleteRequest with response correlationId {} timed out for replica {} ", undeleteRequest.getCorrelationId(), replica.getDataNodeId());
        onErrorResponse(replica, new RouterException("Operation timed out because of " + responseInfo.getError() + " at DataNode " + responseInfo.getDataNode(), RouterErrorCode.OperationTimedOut));
    } else {
        if (undeleteResponse == null) {
            LOGGER.trace("UndeleteRequest with response correlationId {} received UnexpectedInternalError on response deserialization for replica {} ", undeleteRequest.getCorrelationId(), replica.getDataNodeId());
            onErrorResponse(replica, new RouterException("Response deserialization received an unexpected error", RouterErrorCode.UnexpectedInternalError));
        } else {
            // not for its original request. We will immediately fail this operation.
            if (undeleteResponse.getCorrelationId() != undeleteRequest.getCorrelationId()) {
                LOGGER.error("The correlation id in the DeleteResponse {} is not the same as the correlation id in the associated DeleteRequest: {}", undeleteResponse.getCorrelationId(), undeleteRequest.getCorrelationId());
                routerMetrics.unknownReplicaResponseError.inc();
                onErrorResponse(replica, new RouterException("Received wrong response that is not for the corresponding request.", RouterErrorCode.UnexpectedInternalError));
            } else {
                ServerErrorCode serverError = undeleteResponse.getError();
                if (serverError == ServerErrorCode.No_Error || (serverError == ServerErrorCode.Blob_Already_Undeleted && // LIFE_VERSION_FROM_FRONTEND is an invalid lifeVersion
                undeleteResponse.getLifeVersion() != MessageInfo.LIFE_VERSION_FROM_FRONTEND)) {
                    if (RouterUtils.isRemoteReplica(routerConfig, replica)) {
                        LOGGER.trace("Cross colo request successful for remote replica {} in {} ", replica.getDataNodeId(), replica.getDataNodeId().getDatacenterName());
                        routerMetrics.crossColoSuccessCount.inc();
                    }
                    if (lifeVersion == null) {
                        // This is first successful response.
                        lifeVersion = undeleteResponse.getLifeVersion();
                        firstResponseReplicaId = replica;
                        operationTracker.onResponse(replica, TrackedRequestFinalState.SUCCESS);
                    } else {
                        if (lifeVersion != undeleteResponse.getLifeVersion()) {
                            String message = "LifeVersion of " + blobId + " from Replica " + firstResponseReplicaId + " is different than the lifeVersion from replica " + replica + " " + lifeVersion + " != " + undeleteResponse.getLifeVersion();
                            LOGGER.error(message);
                            // this is a successful response and one that completes the operation regardless of whether the
                            // success target has been reached or not.
                            operationCompleted = true;
                            onErrorResponse(replica, new RouterException(message, RouterErrorCode.LifeVersionConflict));
                        } else {
                            operationTracker.onResponse(replica, TrackedRequestFinalState.SUCCESS);
                        }
                    }
                } else if (serverError == ServerErrorCode.Disk_Unavailable) {
                    LOGGER.trace("Replica {} returned Disk_Unavailable for an undelete request with correlationId : {} ", replica, undeleteRequest.getCorrelationId());
                    operationTracker.onResponse(replica, TrackedRequestFinalState.DISK_DOWN);
                    setOperationException(new RouterException("Server returned: " + serverError, RouterErrorCode.AmbryUnavailable));
                    routerMetrics.routerRequestErrorCount.inc();
                    routerMetrics.getDataNodeBasedMetrics(replica.getDataNodeId()).undeleteRequestErrorCount.inc();
                } else {
                    LOGGER.trace("Replica {} returned an error {} for an undelete request with response correlationId : {} ", replica, serverError, undeleteRequest.getCorrelationId());
                    RouterErrorCode routerErrorCode = processServerError(serverError);
                    if (serverError == ServerErrorCode.Blob_Authorization_Failure) {
                        // this is a successful response and one that completes the operation regardless of whether the
                        // success target has been reached or not.
                        operationCompleted = true;
                    }
                    // any server error code that is not equal to ServerErrorCode.No_Error, the onErrorResponse should be invoked
                    onErrorResponse(replica, new RouterException("Server returned: " + serverError, routerErrorCode));
                }
            }
        }
    }
    checkAndMaybeComplete();
}
Also used : UndeleteRequest(com.github.ambry.protocol.UndeleteRequest) ReplicaId(com.github.ambry.clustermap.ReplicaId) ServerErrorCode(com.github.ambry.server.ServerErrorCode)

Aggregations

UndeleteRequest (com.github.ambry.protocol.UndeleteRequest)12 UndeleteResponse (com.github.ambry.protocol.UndeleteResponse)7 BlobId (com.github.ambry.commons.BlobId)6 DeleteRequest (com.github.ambry.protocol.DeleteRequest)6 GetResponse (com.github.ambry.protocol.GetResponse)6 PartitionRequestInfo (com.github.ambry.protocol.PartitionRequestInfo)6 BlobProperties (com.github.ambry.messageformat.BlobProperties)5 DeleteResponse (com.github.ambry.protocol.DeleteResponse)5 GetRequest (com.github.ambry.protocol.GetRequest)5 PutRequest (com.github.ambry.protocol.PutRequest)5 PutResponse (com.github.ambry.protocol.PutResponse)5 DataInputStream (java.io.DataInputStream)5 ArrayList (java.util.ArrayList)5 MockPartitionId (com.github.ambry.clustermap.MockPartitionId)4 PartitionId (com.github.ambry.clustermap.PartitionId)4 ReplicaId (com.github.ambry.clustermap.ReplicaId)4 MessageFormatException (com.github.ambry.messageformat.MessageFormatException)4 NettyByteBufDataInputStream (com.github.ambry.utils.NettyByteBufDataInputStream)4 IOException (java.io.IOException)4 AccountService (com.github.ambry.account.AccountService)3