use of com.github.ambry.protocol.GetResponse in project ambry by linkedin.
the class ReplicaThread method getMessagesForMissingKeys.
/**
* Gets the messages for the keys that are missing from the local store by issuing a {@link GetRequest} to the remote
* node, if there are any missing keys. If there are no missing keys to be fetched, then no request is issued and a
* null response is returned.
* @param connectedChannel The connection channel to the remote node
* @param exchangeMetadataResponseList The list of metadata response from the remote node
* @param replicasToReplicatePerNode The list of remote replicas for the remote node
* @param remoteNode The remote node from which replication needs to happen
* @return The response that contains the missing messages; or null if no request was issued because there were no
* keys missing.
* @throws ReplicationException
* @throws IOException
*/
private GetResponse getMessagesForMissingKeys(ConnectedChannel connectedChannel, List<ExchangeMetadataResponse> exchangeMetadataResponseList, List<RemoteReplicaInfo> replicasToReplicatePerNode, DataNodeId remoteNode) throws ReplicationException, IOException {
List<PartitionRequestInfo> partitionRequestInfoList = new ArrayList<PartitionRequestInfo>();
for (int i = 0; i < exchangeMetadataResponseList.size(); i++) {
ExchangeMetadataResponse exchangeMetadataResponse = exchangeMetadataResponseList.get(i);
RemoteReplicaInfo remoteReplicaInfo = replicasToReplicatePerNode.get(i);
if (exchangeMetadataResponse.serverErrorCode == ServerErrorCode.No_Error) {
Set<StoreKey> missingStoreKeys = exchangeMetadataResponse.missingStoreKeys;
if (missingStoreKeys.size() > 0) {
ArrayList<BlobId> keysToFetch = new ArrayList<BlobId>();
for (StoreKey storeKey : missingStoreKeys) {
keysToFetch.add((BlobId) storeKey);
}
PartitionRequestInfo partitionRequestInfo = new PartitionRequestInfo(remoteReplicaInfo.getReplicaId().getPartitionId(), keysToFetch);
partitionRequestInfoList.add(partitionRequestInfo);
}
}
}
GetResponse getResponse = null;
if (!partitionRequestInfoList.isEmpty()) {
GetRequest getRequest = new GetRequest(correlationIdGenerator.incrementAndGet(), "replication-fetch-" + dataNodeId.getHostname(), MessageFormatFlags.All, partitionRequestInfoList, GetOption.None);
long startTime = SystemTime.getInstance().milliseconds();
try {
connectedChannel.send(getRequest);
ChannelOutput channelOutput = connectedChannel.receive();
getResponse = GetResponse.readFrom(new DataInputStream(channelOutput.getInputStream()), clusterMap);
long getRequestTime = SystemTime.getInstance().milliseconds() - startTime;
replicationMetrics.updateGetRequestTime(getRequestTime, replicatingFromRemoteColo, replicatingOverSsl, datacenterName);
if (getResponse.getError() != ServerErrorCode.No_Error) {
logger.error("Remote node: " + remoteNode + " Thread name: " + threadName + " Remote replicas: " + replicasToReplicatePerNode + " GetResponse from replication: " + getResponse.getError());
throw new ReplicationException(" Get Request returned error when trying to get missing keys " + getResponse.getError());
}
} catch (IOException e) {
responseHandler.onEvent(replicasToReplicatePerNode.get(0).getReplicaId(), e);
throw e;
}
}
return getResponse;
}
use of com.github.ambry.protocol.GetResponse in project ambry by linkedin.
the class GetBlobResultInternal method extractGetResponseAndNotifyResponseHandler.
/**
* Extract the {@link GetResponse} from the given {@link ResponseInfo}
* @param responseInfo the {@link ResponseInfo} from which the {@link GetResponse} is to be extracted.
* @return the extracted {@link GetResponse} if there is one; null otherwise.
*/
private GetResponse extractGetResponseAndNotifyResponseHandler(ResponseInfo responseInfo) {
GetResponse getResponse = null;
ReplicaId replicaId = ((RouterRequestInfo) responseInfo.getRequestInfo()).getReplicaId();
NetworkClientErrorCode networkClientErrorCode = responseInfo.getError();
if (networkClientErrorCode == null) {
try {
getResponse = GetResponse.readFrom(new DataInputStream(new ByteBufferInputStream(responseInfo.getResponse())), clusterMap);
ServerErrorCode serverError = getResponse.getError();
if (serverError == ServerErrorCode.No_Error) {
serverError = getResponse.getPartitionResponseInfoList().get(0).getErrorCode();
}
responseHandler.onEvent(replicaId, serverError);
} catch (Exception e) {
// Ignore. There is no value in notifying the response handler.
logger.error("Response deserialization received unexpected error", e);
routerMetrics.responseDeserializationErrorCount.inc();
}
} else {
responseHandler.onEvent(replicaId, networkClientErrorCode);
}
return getResponse;
}
use of com.github.ambry.protocol.GetResponse in project ambry by linkedin.
the class MockRouterCallback method assertOperationFailure.
/**
* Assert that operation fails with the expected error code
* @param errorCode expected error code on failure
* @throws RouterException
*/
private void assertOperationFailure(RouterErrorCode errorCode) throws RouterException, IOException, InterruptedException {
NonBlockingRouter.currentOperationsCount.incrementAndGet();
GetBlobInfoOperation op = new GetBlobInfoOperation(routerConfig, routerMetrics, mockClusterMap, responseHandler, blobId, options, null, routerCallback, kms, cryptoService, cryptoJobHandler, time);
ArrayList<RequestInfo> requestListToFill = new ArrayList<>();
requestRegistrationCallback.requestListToFill = requestListToFill;
op.poll(requestRegistrationCallback);
Assert.assertEquals("There should only be as many requests at this point as requestParallelism", requestParallelism, correlationIdToGetOperation.size());
CountDownLatch onPollLatch = new CountDownLatch(1);
routerCallback.setOnPollLatch(onPollLatch);
List<ResponseInfo> responses = sendAndWaitForResponses(requestListToFill);
for (ResponseInfo responseInfo : responses) {
GetResponse getResponse = responseInfo.getError() == null ? GetResponse.readFrom(new DataInputStream(new ByteBufferInputStream(responseInfo.getResponse())), mockClusterMap) : null;
op.handleResponse(responseInfo, getResponse);
if (op.isOperationComplete()) {
break;
}
}
if (!op.isOperationComplete()) {
Assert.assertTrue("Latch should have been zeroed ", onPollLatch.await(500, TimeUnit.MILLISECONDS));
op.poll(requestRegistrationCallback);
}
Assert.assertTrue("Operation should be complete at this time", op.isOperationComplete());
RouterException routerException = (RouterException) op.getOperationException();
Assert.assertEquals(errorCode, routerException.getErrorCode());
}
use of com.github.ambry.protocol.GetResponse in project ambry by linkedin.
the class MockRouterCallback method testBlobNotFoundCase.
/**
* Test the case where every server returns Blob_Not_Found. All servers must have been contacted,
* due to cross-colo proxying.
* @throws Exception
*/
@Test
public void testBlobNotFoundCase() throws Exception {
NonBlockingRouter.currentOperationsCount.incrementAndGet();
GetBlobInfoOperation op = new GetBlobInfoOperation(routerConfig, routerMetrics, mockClusterMap, responseHandler, blobId, options, null, routerCallback, kms, cryptoService, cryptoJobHandler, time);
ArrayList<RequestInfo> requestListToFill = new ArrayList<>();
requestRegistrationCallback.requestListToFill = requestListToFill;
for (MockServer server : mockServerLayout.getMockServers()) {
server.setServerErrorForAllRequests(ServerErrorCode.Blob_Not_Found);
}
while (!op.isOperationComplete()) {
op.poll(requestRegistrationCallback);
List<ResponseInfo> responses = sendAndWaitForResponses(requestListToFill);
for (ResponseInfo responseInfo : responses) {
GetResponse getResponse = responseInfo.getError() == null ? GetResponse.readFrom(new DataInputStream(new ByteBufferInputStream(responseInfo.getResponse())), mockClusterMap) : null;
op.handleResponse(responseInfo, getResponse);
if (op.isOperationComplete()) {
break;
}
}
}
Assert.assertEquals("Must have attempted sending requests to all replicas", replicasCount, correlationIdToGetOperation.size());
Assert.assertTrue("Operation should be complete at this time", op.isOperationComplete());
RouterException routerException = (RouterException) op.getOperationException();
Assert.assertEquals(RouterErrorCode.BlobDoesNotExist, routerException.getErrorCode());
}
use of com.github.ambry.protocol.GetResponse in project ambry by linkedin.
the class MockRouterCallback method testVariousErrors.
private void testVariousErrors(String dcWherePutHappened) throws Exception {
NonBlockingRouter.currentOperationsCount.incrementAndGet();
GetBlobInfoOperation op = new GetBlobInfoOperation(routerConfig, routerMetrics, mockClusterMap, responseHandler, blobId, options, null, routerCallback, kms, cryptoService, cryptoJobHandler, time);
ArrayList<RequestInfo> requestListToFill = new ArrayList<>();
requestRegistrationCallback.requestListToFill = requestListToFill;
ArrayList<MockServer> mockServers = new ArrayList<>(mockServerLayout.getMockServers());
// set the status to various server level or partition level errors (not Blob_Deleted or Blob_Expired).
mockServers.get(0).setServerErrorForAllRequests(ServerErrorCode.Unknown_Error);
mockServers.get(1).setServerErrorForAllRequests(ServerErrorCode.Unknown_Error);
mockServers.get(2).setServerErrorForAllRequests(ServerErrorCode.IO_Error);
mockServers.get(3).setServerErrorForAllRequests(ServerErrorCode.Blob_Not_Found);
mockServers.get(4).setServerErrorForAllRequests(ServerErrorCode.Data_Corrupt);
mockServers.get(5).setServerErrorForAllRequests(ServerErrorCode.Blob_Not_Found);
mockServers.get(6).setServerErrorForAllRequests(ServerErrorCode.Blob_Not_Found);
mockServers.get(7).setServerErrorForAllRequests(ServerErrorCode.Disk_Unavailable);
mockServers.get(8).setServerErrorForAllRequests(ServerErrorCode.Unknown_Error);
// clear the hard error in one of the servers in the datacenter where the put happened.
for (int i = 0; i < mockServers.size(); i++) {
MockServer mockServer = mockServers.get(i);
if (mockServer.getDataCenter().equals(dcWherePutHappened)) {
mockServer.setServerErrorForAllRequests(ServerErrorCode.No_Error);
break;
}
}
while (!op.isOperationComplete()) {
op.poll(requestRegistrationCallback);
List<ResponseInfo> responses = sendAndWaitForResponses(requestListToFill);
for (ResponseInfo responseInfo : responses) {
GetResponse getResponse = responseInfo.getError() == null ? GetResponse.readFrom(new DataInputStream(new ByteBufferInputStream(responseInfo.getResponse())), mockClusterMap) : null;
op.handleResponse(responseInfo, getResponse);
if (op.isOperationComplete()) {
break;
}
}
}
Assert.assertTrue("Operation should be complete at this time", op.isOperationComplete());
assertSuccess(op);
}
Aggregations