use of com.github.ambry.network.ResponseInfo in project ambry by linkedin.
the class NonBlockingRouterTestBase method testResponseDeserializationError.
/**
* Test that operations succeed even in the presence of responses that are corrupt and fail to deserialize.
* @param opHelper the {@link OperationHelper}
* @param networkClient the {@link SocketNetworkClient}
* @param blobId the id of the blob to get/delete. For puts, this will be null.
* @throws Exception
*/
protected void testResponseDeserializationError(OperationHelper opHelper, SocketNetworkClient networkClient, BlobId blobId) throws Exception {
mockSelectorState.set(MockSelectorState.Good);
FutureResult futureResult = opHelper.submitOperation(blobId);
int requestParallelism = opHelper.requestParallelism;
List<RequestInfo> allRequests = new ArrayList<>();
Set<Integer> allDropped = new HashSet<>();
long loopStartTimeMs = SystemTime.getInstance().milliseconds();
while (allRequests.size() < requestParallelism) {
if (loopStartTimeMs + AWAIT_TIMEOUT_MS < SystemTime.getInstance().milliseconds()) {
Assert.fail("Waited too long for requests.");
}
opHelper.pollOpManager(allRequests, allDropped);
}
List<ResponseInfo> responseInfoList = new ArrayList<>();
loopStartTimeMs = SystemTime.getInstance().milliseconds();
do {
if (loopStartTimeMs + AWAIT_TIMEOUT_MS < SystemTime.getInstance().milliseconds()) {
Assert.fail("Waited too long for the response.");
}
responseInfoList.addAll(networkClient.sendAndPoll(allRequests, allDropped, 10));
allRequests.clear();
} while (responseInfoList.size() < requestParallelism);
// corrupt the first response.
ByteBuf response = responseInfoList.get(0).content();
byte b = response.getByte(response.writerIndex() - 1);
response.setByte(response.writerIndex() - 1, (byte) ~b);
for (ResponseInfo responseInfo : responseInfoList) {
opHelper.handleResponse(responseInfo);
}
responseInfoList.forEach(ResponseInfo::release);
allRequests.clear();
if (testEncryption) {
opHelper.awaitOpCompletionOrTimeOut(futureResult);
} else {
opHelper.pollOpManager(allRequests, allDropped);
}
try {
futureResult.get(AWAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
} catch (ExecutionException e) {
Assert.fail("Operation should have succeeded with one corrupt response");
}
}
use of com.github.ambry.network.ResponseInfo in project ambry by linkedin.
the class UndeleteManagerTest method sendRequestsGetResponse.
private void sendRequestsGetResponse(FutureResult<Void> future, UndeleteManager undeleteManager, boolean advanceTime) {
List<RequestInfo> requestInfoList = new ArrayList<>();
Set<Integer> requestsToDrop = new HashSet<>();
Set<RequestInfo> requestAcks = new HashSet<>();
List<RequestInfo> referenceRequestInfos = new ArrayList<>();
while (!future.isDone()) {
undeleteManager.poll(requestInfoList, requestsToDrop);
referenceRequestInfos.addAll(requestInfoList);
List<ResponseInfo> responseInfoList = new ArrayList<>();
try {
responseInfoList = networkClient.sendAndPoll(requestInfoList, requestsToDrop, AWAIT_TIMEOUT_MS);
} catch (RuntimeException | Error e) {
if (!advanceTime) {
throw e;
}
}
for (ResponseInfo responseInfo : responseInfoList) {
RequestInfo requestInfo = responseInfo.getRequestInfo();
assertNotNull("Request is null", requestInfo);
if (!referenceRequestInfos.contains(requestInfo)) {
throw new IllegalStateException("Received Response for unrecognized request");
} else if (requestAcks.contains(requestInfo)) {
throw new IllegalStateException("Received response more than once for a request");
}
requestAcks.add(requestInfo);
RequestInfo routerRequestInfo = responseInfo.getRequestInfo();
RequestOrResponseType type = ((RequestOrResponse) routerRequestInfo.getRequest()).getRequestType();
switch(type) {
case UndeleteRequest:
undeleteManager.handleResponse(responseInfo);
break;
default:
throw new IllegalStateException("Unrecognized request type: " + type);
}
}
if (advanceTime) {
time.sleep(ADVANCE_TIME_INCREMENT_MS);
}
requestInfoList.clear();
}
}
use of com.github.ambry.network.ResponseInfo in project ambry by linkedin.
the class Http2NetworkClientTest method putGetTest.
@Test
public void putGetTest() throws Exception {
MockClusterMap clusterMap = http2Cluster.getClusterMap();
DataNodeId dataNodeId = http2Cluster.getGeneralDataNode();
BlobIdFactory blobIdFactory = new BlobIdFactory(clusterMap);
SSLFactory sslFactory = new NettySslHttp2Factory(clientSSLConfig);
Http2NetworkClient networkClient = new Http2NetworkClient(new Http2ClientMetrics(new MetricRegistry()), new Http2ClientConfig(new VerifiableProperties(new Properties())), sslFactory, eventLoopGroup);
// Put a blob
int blobSize = 1024 * 1024;
byte[] usermetadata = new byte[1000];
byte[] data = new byte[blobSize];
short accountId = Utils.getRandomShort(TestUtils.RANDOM);
short containerId = Utils.getRandomShort(TestUtils.RANDOM);
BlobProperties properties = new BlobProperties(blobSize, "serviceid1", accountId, containerId, false);
TestUtils.RANDOM.nextBytes(usermetadata);
TestUtils.RANDOM.nextBytes(data);
List<? extends PartitionId> partitionIds = clusterMap.getWritablePartitionIds(MockClusterMap.DEFAULT_PARTITION_CLASS);
short blobIdVersion = CommonTestUtils.getCurrentBlobIdVersion();
BlobId blobId1 = new BlobId(blobIdVersion, BlobId.BlobIdType.NATIVE, clusterMap.getLocalDatacenterId(), properties.getAccountId(), properties.getContainerId(), partitionIds.get(0), false, BlobId.BlobDataType.DATACHUNK);
// put blob 1
PutRequest putRequest = new PutRequest(1, "client1", blobId1, properties, ByteBuffer.wrap(usermetadata), Unpooled.wrappedBuffer(data), properties.getBlobSize(), BlobType.DataBlob, null);
RequestInfo request = new RequestInfo(dataNodeId.getHostname(), new Port(dataNodeId.getHttp2Port(), PortType.HTTP2), putRequest, clusterMap.getReplicaIds(dataNodeId).get(0), null);
List<ResponseInfo> responseInfos = networkClient.sendAndPoll(Collections.singletonList(request), new HashSet<>(), 300);
long startTime = SystemTime.getInstance().milliseconds();
while (responseInfos.size() == 0) {
responseInfos = networkClient.sendAndPoll(Collections.EMPTY_LIST, new HashSet<>(), 300);
if (SystemTime.getInstance().milliseconds() - startTime >= 6000) {
fail("Network Client no reponse and timeout.");
}
Thread.sleep(30);
}
assertEquals("Should be only one response", 1, responseInfos.size());
DataInputStream dis = new NettyByteBufDataInputStream(responseInfos.get(0).content());
PutResponse putResponse = PutResponse.readFrom(dis);
assertEquals("No error expected.", ServerErrorCode.No_Error, putResponse.getError());
// Get the blob
// get blob properties
ArrayList<BlobId> ids = new ArrayList<BlobId>();
MockPartitionId partition = (MockPartitionId) clusterMap.getWritablePartitionIds(MockClusterMap.DEFAULT_PARTITION_CLASS).get(0);
ids.add(blobId1);
ArrayList<PartitionRequestInfo> partitionRequestInfoList = new ArrayList<PartitionRequestInfo>();
PartitionRequestInfo partitionRequestInfo = new PartitionRequestInfo(partition, ids);
partitionRequestInfoList.add(partitionRequestInfo);
GetRequest getRequest = new GetRequest(1, "http2-clientid", MessageFormatFlags.All, partitionRequestInfoList, GetOption.None);
request = new RequestInfo(dataNodeId.getHostname(), new Port(dataNodeId.getHttp2Port(), PortType.HTTP2), getRequest, clusterMap.getReplicaIds(dataNodeId).get(0), null);
responseInfos = networkClient.sendAndPoll(Collections.singletonList(request), new HashSet<>(), 300);
startTime = SystemTime.getInstance().milliseconds();
while (responseInfos.size() == 0) {
responseInfos = networkClient.sendAndPoll(Collections.EMPTY_LIST, new HashSet<>(), 300);
if (SystemTime.getInstance().milliseconds() - startTime >= 3000) {
fail("Network Client no response and timeout.");
}
Thread.sleep(30);
}
assertEquals("Should be only one response", 1, responseInfos.size());
dis = new NettyByteBufDataInputStream(responseInfos.get(0).content());
GetResponse resp = GetResponse.readFrom(dis, clusterMap);
BlobAll blobAll = MessageFormatRecord.deserializeBlobAll(resp.getInputStream(), blobIdFactory);
// verify BlobProperties
BlobProperties propertyOutput = blobAll.getBlobInfo().getBlobProperties();
assertEquals(blobSize, propertyOutput.getBlobSize());
assertEquals("serviceid1", propertyOutput.getServiceId());
assertEquals("AccountId mismatch", accountId, propertyOutput.getAccountId());
assertEquals("ContainerId mismatch", containerId, propertyOutput.getContainerId());
// verify UserMetadata
byte[] userMetadataOutput = blobAll.getBlobInfo().getUserMetadata();
assertArrayEquals(usermetadata, userMetadataOutput);
// verify content
byte[] actualBlobData = getBlobDataAndRelease(blobAll.getBlobData());
assertArrayEquals("Content mismatch.", data, actualBlobData);
}
use of com.github.ambry.network.ResponseInfo in project ambry by linkedin.
the class PutOperationTest method testSlippedPutsWithServerErrors.
/**
* Test PUT operation that handles ServerErrorCode = Temporarily_Disabled and Replica_Unavailable
* @throws Exception
*/
@Test
public void testSlippedPutsWithServerErrors() throws Exception {
Properties properties = new Properties();
properties.setProperty("router.hostname", "localhost");
properties.setProperty("router.datacenter.name", "DC1");
properties.setProperty("router.max.put.chunk.size.bytes", Integer.toString(chunkSize));
properties.setProperty("router.put.request.parallelism", Integer.toString(requestParallelism));
// Expect at least two successes so that you can create slipped puts.
properties.setProperty("router.put.success.target", Integer.toString(2));
VerifiableProperties vProps = new VerifiableProperties(properties);
RouterConfig routerConfig = new RouterConfig(vProps);
int numChunks = 1;
BlobProperties blobProperties = new BlobProperties(-1, "serviceId", "memberId", "contentType", false, Utils.Infinite_Time, Utils.getRandomShort(TestUtils.RANDOM), Utils.getRandomShort(TestUtils.RANDOM), false, null, null, null);
byte[] userMetadata = new byte[10];
byte[] content = new byte[chunkSize * numChunks];
random.nextBytes(content);
ReadableStreamChannel channel = new ByteBufferReadableStreamChannel(ByteBuffer.wrap(content));
MockNetworkClient mockNetworkClient = new MockNetworkClient();
PutOperation op = PutOperation.forUpload(routerConfig, routerMetrics, mockClusterMap, new LoggingNotificationSystem(), new InMemAccountService(true, false), userMetadata, channel, PutBlobOptions.DEFAULT, new FutureResult<>(), null, new RouterCallback(mockNetworkClient, new ArrayList<>()), null, null, null, null, time, blobProperties, MockClusterMap.DEFAULT_PARTITION_CLASS, quotaChargeCallback);
op.startOperation();
List<RequestInfo> requestInfos = new ArrayList<>();
requestRegistrationCallback.setRequestsToSend(requestInfos);
// fill chunks would end up filling the maximum number of PutChunks.
op.fillChunks();
Assert.assertTrue("ReadyForPollCallback should have been invoked as chunks were fully filled", mockNetworkClient.getAndClearWokenUpStatus());
// poll to populate request
op.poll(requestRegistrationCallback);
// Set up server errors such that put fails on 2 out 3 nodes, hence creating a slipped put on the succeeding node.
// Second attempts on all node succeed.
List<ServerErrorCode> serverErrorList = new ArrayList<>();
// Success on the first host, slipped put
serverErrorList.add(ServerErrorCode.No_Error);
// Fail on the second host
serverErrorList.add(ServerErrorCode.Unknown_Error);
// Fail on the third host
serverErrorList.add(ServerErrorCode.Unknown_Error);
// Success on the second attempts on all hosts
serverErrorList.add(ServerErrorCode.No_Error);
serverErrorList.add(ServerErrorCode.No_Error);
serverErrorList.add(ServerErrorCode.No_Error);
mockServer.setServerErrors(serverErrorList);
// Send all requests.
for (int i = 0; i < requestInfos.size(); i++) {
ResponseInfo responseInfo = getResponseInfo(requestInfos.get(i));
PutResponse putResponse = responseInfo.getError() == null ? PutResponse.readFrom(new NettyByteBufDataInputStream(responseInfo.content())) : null;
op.handleResponse(responseInfo, putResponse);
requestInfos.get(i).getRequest().release();
responseInfo.release();
}
Assert.assertEquals("Number of slipped puts should be 1", 1, op.getSlippedPutBlobIds().size());
// fill chunks again.
op.fillChunks();
requestInfos.clear();
// poll to populate request
op.poll(requestRegistrationCallback);
// Send all requests again.
for (int i = 0; i < requestInfos.size(); i++) {
ResponseInfo responseInfo = getResponseInfo(requestInfos.get(i));
PutResponse putResponse = responseInfo.getError() == null ? PutResponse.readFrom(new NettyByteBufDataInputStream(responseInfo.content())) : null;
op.handleResponse(responseInfo, putResponse);
requestInfos.get(i).getRequest().release();
responseInfo.release();
}
Assert.assertEquals("Number of slipped puts should be 1", 1, op.getSlippedPutBlobIds().size());
PutOperation.PutChunk putChunk = op.getPutChunks().get(0);
// Make sure the chunk blob id which has been put successfully is not part of the slipped puts.
Assert.assertFalse(op.getSlippedPutBlobIds().contains(putChunk.chunkBlobId));
}
use of com.github.ambry.network.ResponseInfo in project ambry by linkedin.
the class PutOperationTest method testHandleResponseWithServerErrors.
/**
* Test PUT operation that handles ServerErrorCode = Temporarily_Disabled and Replica_Unavailable
* @throws Exception
*/
@Test
public void testHandleResponseWithServerErrors() throws Exception {
int numChunks = routerConfig.routerMaxInMemPutChunks + 1;
BlobProperties blobProperties = new BlobProperties(-1, "serviceId", "memberId", "contentType", false, Utils.Infinite_Time, Utils.getRandomShort(TestUtils.RANDOM), Utils.getRandomShort(TestUtils.RANDOM), false, null, null, null);
byte[] userMetadata = new byte[10];
byte[] content = new byte[chunkSize * numChunks];
random.nextBytes(content);
ReadableStreamChannel channel = new ByteBufferReadableStreamChannel(ByteBuffer.wrap(content));
PutOperation op = PutOperation.forUpload(routerConfig, routerMetrics, mockClusterMap, new LoggingNotificationSystem(), new InMemAccountService(true, false), userMetadata, channel, PutBlobOptions.DEFAULT, new FutureResult<>(), null, new RouterCallback(new MockNetworkClient(), new ArrayList<>()), null, null, null, null, time, blobProperties, MockClusterMap.DEFAULT_PARTITION_CLASS, quotaChargeCallback);
op.startOperation();
List<RequestInfo> requestInfos = new ArrayList<>();
requestRegistrationCallback.setRequestsToSend(requestInfos);
// fill chunks would end up filling the maximum number of PutChunks.
op.fillChunks();
// poll to populate request
op.poll(requestRegistrationCallback);
// make 1st request of first chunk encounter Temporarily_Disabled
mockServer.setServerErrorForAllRequests(ServerErrorCode.Temporarily_Disabled);
ResponseInfo responseInfo = getResponseInfo(requestInfos.get(0));
PutResponse putResponse = responseInfo.getError() == null ? PutResponse.readFrom(new NettyByteBufDataInputStream(responseInfo.content())) : null;
op.handleResponse(responseInfo, putResponse);
responseInfo.release();
PutOperation.PutChunk putChunk = op.getPutChunks().get(0);
SimpleOperationTracker operationTracker = (SimpleOperationTracker) putChunk.getOperationTrackerInUse();
Assert.assertEquals("Disabled count should be 1", 1, operationTracker.getDisabledCount());
Assert.assertEquals("Disabled count should be 0", 0, operationTracker.getFailedCount());
// make 2nd request of first chunk encounter Replica_Unavailable
mockServer.setServerErrorForAllRequests(ServerErrorCode.Replica_Unavailable);
responseInfo = getResponseInfo(requestInfos.get(1));
putResponse = responseInfo.getError() == null ? PutResponse.readFrom(new NettyByteBufDataInputStream(responseInfo.content())) : null;
op.handleResponse(responseInfo, putResponse);
responseInfo.release();
putChunk = op.getPutChunks().get(0);
Assert.assertEquals("Failure count should be 1", 1, ((SimpleOperationTracker) putChunk.getOperationTrackerInUse()).getFailedCount());
mockServer.resetServerErrors();
// Release all the other requests
requestInfos.forEach(info -> info.getRequest().release());
}
Aggregations