use of com.github.ambry.server.ServerErrorCode in project ambry by linkedin.
the class StoredBlob method updateBlobMap.
/**
* Updates the blob map based on the {@code undeleteRequest}.
* @param undeleteRequest the {@link TtlUpdateRequest} that needs to be processed
*/
private ServerErrorCode updateBlobMap(UndeleteRequest undeleteRequest) {
ServerErrorCode errorCode = ServerErrorCode.No_Error;
StoredBlob blob = blobs.get(undeleteRequest.getBlobId().getID());
if (blob == null) {
errorCode = ServerErrorCode.Blob_Not_Found;
} else if (blob.isUndeleted()) {
errorCode = ServerErrorCode.Blob_Already_Undeleted;
} else if (!blob.isDeleted()) {
errorCode = ServerErrorCode.Blob_Not_Deleted;
} else if (blob.hasExpired()) {
errorCode = ServerErrorCode.Blob_Expired;
} else {
blob.updateLifeVersion();
}
return errorCode;
}
use of com.github.ambry.server.ServerErrorCode in project ambry by linkedin.
the class DeleteManagerTest method testSelectorError.
/**
* Test the case when the {@link com.github.ambry.network.Selector} of {@link SocketNetworkClient}
* experiences various exceptions. The order of received responses is the same as defined in {@code serverErrorCodes}.
*/
@Test
public void testSelectorError() throws Exception {
ServerErrorCode[] serverErrorCodes = new ServerErrorCode[9];
Arrays.fill(serverErrorCodes, ServerErrorCode.No_Error);
HashMap<MockSelectorState, RouterErrorCode> errorCodeHashMap = new HashMap<>();
errorCodeHashMap.put(MockSelectorState.DisconnectOnSend, RouterErrorCode.OperationTimedOut);
errorCodeHashMap.put(MockSelectorState.ThrowExceptionOnAllPoll, RouterErrorCode.OperationTimedOut);
errorCodeHashMap.put(MockSelectorState.ThrowExceptionOnConnect, RouterErrorCode.OperationTimedOut);
errorCodeHashMap.put(MockSelectorState.ThrowExceptionOnSend, RouterErrorCode.OperationTimedOut);
errorCodeHashMap.put(MockSelectorState.ThrowThrowableOnSend, RouterErrorCode.RouterClosed);
for (MockSelectorState state : MockSelectorState.values()) {
if (state == MockSelectorState.Good || state == MockSelectorState.FailConnectionInitiationOnPoll) {
// FailConnectionInitiationOnPoll is temporarily used for warm up failure test, skip it here
continue;
}
mockSelectorState.set(state);
setServerErrorCodes(serverErrorCodes, partition, serverLayout);
CountDownLatch operationCompleteLatch = new CountDownLatch(1);
future = router.deleteBlob(blobIdString, null, new ClientCallback(operationCompleteLatch), quotaChargeCallback);
do {
// increment mock time
mockTime.sleep(1000);
} while (!operationCompleteLatch.await(10, TimeUnit.MILLISECONDS));
assertFailureAndCheckErrorCode(future, errorCodeHashMap.get(state));
}
}
use of com.github.ambry.server.ServerErrorCode in project ambry by linkedin.
the class MockRouterCallback method testFailureOnServerErrors.
/**
* Tests the case where all servers return the same server level error code
* @throws Exception
*/
@Test
public void testFailureOnServerErrors() throws Exception {
// set the status to various server level errors (remove all partition level errors or non errors)
EnumSet<ServerErrorCode> serverErrors = EnumSet.complementOf(EnumSet.of(ServerErrorCode.Blob_Deleted, ServerErrorCode.Blob_Expired, ServerErrorCode.No_Error, ServerErrorCode.Blob_Authorization_Failure, ServerErrorCode.Blob_Not_Found));
for (ServerErrorCode serverErrorCode : serverErrors) {
mockServerLayout.getMockServers().forEach(server -> server.setServerErrorForAllRequests(serverErrorCode));
RouterErrorCode expectedRouterError;
switch(serverErrorCode) {
case Replica_Unavailable:
expectedRouterError = RouterErrorCode.AmbryUnavailable;
break;
case Disk_Unavailable:
// if all the disks are unavailable (which should be extremely rare), after replacing these disks, the blob is
// definitely not present.
expectedRouterError = RouterErrorCode.BlobDoesNotExist;
break;
default:
expectedRouterError = RouterErrorCode.UnexpectedInternalError;
}
assertOperationFailure(expectedRouterError);
}
}
use of com.github.ambry.server.ServerErrorCode in project ambry by linkedin.
the class MockRouterCallback method testBlobAuthorizationFailureOverrideAll.
/**
* Test the case where servers return different {@link ServerErrorCode} or success, and the {@link GetBlobInfoOperation}
* is able to resolve and conclude the correct {@link RouterErrorCode}. The get blob operation should be able
* to resolve the router error code as {@code Blob_Authorization_Failure}.
* @throws Exception
*/
@Test
public void testBlobAuthorizationFailureOverrideAll() throws Exception {
// set it to 2 for more coverage
successTarget = 2;
Properties props = getNonBlockingRouterProperties(true);
routerConfig = new RouterConfig(new VerifiableProperties(props));
ServerErrorCode[] serverErrorCodes = new ServerErrorCode[9];
serverErrorCodes[0] = ServerErrorCode.Blob_Not_Found;
serverErrorCodes[1] = ServerErrorCode.Data_Corrupt;
serverErrorCodes[2] = ServerErrorCode.IO_Error;
serverErrorCodes[3] = ServerErrorCode.Partition_Unknown;
serverErrorCodes[4] = ServerErrorCode.Disk_Unavailable;
serverErrorCodes[5] = ServerErrorCode.Blob_Authorization_Failure;
serverErrorCodes[6] = ServerErrorCode.Unknown_Error;
serverErrorCodes[7] = ServerErrorCode.Unknown_Error;
serverErrorCodes[8] = ServerErrorCode.No_Error;
testErrorPrecedence(serverErrorCodes, RouterErrorCode.BlobAuthorizationFailure);
}
use of com.github.ambry.server.ServerErrorCode in project ambry by linkedin.
the class TtlUpdateOperation method handleResponse.
/**
* Handles a response for a TTL update 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 ttlUpdateResponse The {@link TtlUpdateResponse} associated with this response.
*/
void handleResponse(ResponseInfo responseInfo, TtlUpdateResponse ttlUpdateResponse) {
TtlUpdateRequest ttlUpdateRequest = (TtlUpdateRequest) responseInfo.getRequestInfo().getRequest();
TtlUpdateRequestInfo ttlUpdateRequestInfo = ttlUpdateRequestInfos.remove(ttlUpdateRequest.getCorrelationId());
// metric is updated here, as corresponding metrics have been updated when the request was timed out.
if (ttlUpdateRequestInfo == null) {
return;
}
ReplicaId replica = ttlUpdateRequestInfo.replica;
long requestLatencyMs = time.milliseconds() - ttlUpdateRequestInfo.startTimeMs;
routerMetrics.routerRequestLatencyMs.update(requestLatencyMs);
routerMetrics.getDataNodeBasedMetrics(replica.getDataNodeId()).ttlUpdateRequestLatencyMs.update(requestLatencyMs);
// Check the error code from NetworkClient.
if (responseInfo.getError() != null) {
LOGGER.debug("TtlUpdateRequest with response correlationId {} timed out for replica {} ", ttlUpdateRequest.getCorrelationId(), replica.getDataNodeId());
onErrorResponse(replica, new RouterException("Operation timed out because of " + responseInfo.getError() + " at DataNode " + responseInfo.getDataNode(), RouterErrorCode.OperationTimedOut));
} else {
if (ttlUpdateResponse == null) {
LOGGER.debug("TtlUpdateRequest with response correlationId {} received UnexpectedInternalError on response deserialization for replica {} ", ttlUpdateRequest.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 (ttlUpdateResponse.getCorrelationId() != ttlUpdateRequest.getCorrelationId()) {
LOGGER.error("The correlation id in the TtlUpdateResponse {} is not the same as the correlation id in the associated TtlUpdateRequest: {}", ttlUpdateResponse.getCorrelationId(), ttlUpdateRequest.getCorrelationId());
routerMetrics.unknownReplicaResponseError.inc();
onErrorResponse(replica, new RouterException("Received wrong response that is not for the corresponding request.", RouterErrorCode.UnexpectedInternalError));
} else {
ServerErrorCode serverError = ttlUpdateResponse.getError();
if (serverError == ServerErrorCode.No_Error || serverError == ServerErrorCode.Blob_Already_Updated) {
operationTracker.onResponse(replica, TrackedRequestFinalState.SUCCESS);
if (RouterUtils.isRemoteReplica(routerConfig, replica)) {
LOGGER.trace("Cross colo request successful for remote replica {} in {} ", replica.getDataNodeId(), replica.getDataNodeId().getDatacenterName());
routerMetrics.crossColoSuccessCount.inc();
}
} else if (serverError == ServerErrorCode.Disk_Unavailable) {
LOGGER.debug("Replica {} returned Disk_Unavailable for a Ttl update request with response correlationId : {} ", replica.getDataNodeId(), ttlUpdateResponse.getCorrelationId());
operationTracker.onResponse(replica, TrackedRequestFinalState.DISK_DOWN);
setOperationException(new RouterException("Server returned: " + serverError, RouterErrorCode.AmbryUnavailable));
routerMetrics.getDataNodeBasedMetrics(replica.getDataNodeId()).ttlUpdateRequestErrorCount.inc();
} else {
LOGGER.debug("Replica {} returned an error {} for a Ttl update request with response correlationId : {} ", replica.getDataNodeId(), serverError, ttlUpdateResponse.getCorrelationId());
RouterErrorCode routerErrorCode = processServerError(serverError);
if (ttlUpdateResponse.getError() == 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
// because the operation itself doesn't succeed although the response in some cases is successful (i.e. Blob_Deleted)
onErrorResponse(replica, new RouterException("Server returned: " + serverError, routerErrorCode));
}
}
}
}
checkAndMaybeComplete();
}
Aggregations