use of com.github.ambry.commons.ByteBufferAsyncWritableChannel in project ambry by linkedin.
the class GetBlobOperationTest method getAndAssertSuccess.
/**
* Construct GetBlob operations with appropriate callbacks, then poll those operations until they complete,
* and ensure that the whole blob data is read out and the contents match.
* @param getChunksBeforeRead {@code true} if all chunks should be cached by the router before reading from the
* stream.
* @param initiateReadBeforeChunkGet Whether readInto() should be initiated immediately before data chunks are
* fetched by the router to simulate chunk arrival delay.
*/
private void getAndAssertSuccess(final boolean getChunksBeforeRead, final boolean initiateReadBeforeChunkGet) throws Exception {
final CountDownLatch readCompleteLatch = new CountDownLatch(1);
final AtomicReference<Exception> readCompleteException = new AtomicReference<>(null);
final AtomicLong readCompleteResult = new AtomicLong(0);
final AtomicReference<Exception> operationException = new AtomicReference<>(null);
final int numChunks = ((blobSize + maxChunkSize - 1) / maxChunkSize) + (blobSize > maxChunkSize ? 1 : 0);
mockNetworkClient.resetProcessedResponseCount();
Callback<GetBlobResultInternal> callback = new Callback<GetBlobResultInternal>() {
@Override
public void onCompletion(final GetBlobResultInternal result, final Exception exception) {
if (exception != null) {
operationException.set(exception);
readCompleteLatch.countDown();
} else {
try {
switch(options.getBlobOptions.getOperationType()) {
case All:
BlobInfo blobInfo = result.getBlobResult.getBlobInfo();
Assert.assertTrue("Blob properties must be the same", RouterTestHelpers.haveEquivalentFields(blobProperties, blobInfo.getBlobProperties()));
Assert.assertEquals("Blob size should in received blobProperties should be the same as actual", blobSize, blobInfo.getBlobProperties().getBlobSize());
Assert.assertArrayEquals("User metadata must be the same", userMetadata, blobInfo.getUserMetadata());
break;
case Data:
Assert.assertNull("Unexpected blob info in operation result", result.getBlobResult.getBlobInfo());
break;
}
} catch (Exception e) {
readCompleteException.set(e);
}
final ByteBufferAsyncWritableChannel asyncWritableChannel = new ByteBufferAsyncWritableChannel();
final Future<Long> preSetReadIntoFuture = initiateReadBeforeChunkGet ? result.getBlobResult.getBlobDataChannel().readInto(asyncWritableChannel, null) : null;
Utils.newThread(new Runnable() {
@Override
public void run() {
if (getChunksBeforeRead) {
// wait for all chunks (data + metadata) to be received
while (mockNetworkClient.getProcessedResponseCount() < numChunks * routerConfig.routerGetRequestParallelism) {
Thread.yield();
}
}
Future<Long> readIntoFuture = initiateReadBeforeChunkGet ? preSetReadIntoFuture : result.getBlobResult.getBlobDataChannel().readInto(asyncWritableChannel, null);
assertBlobReadSuccess(options.getBlobOptions, readIntoFuture, asyncWritableChannel, result.getBlobResult.getBlobDataChannel(), readCompleteLatch, readCompleteResult, readCompleteException);
}
}, false).start();
}
}
};
GetBlobOperation op = createOperationAndComplete(callback);
readCompleteLatch.await();
Assert.assertTrue("Operation should be complete at this time", op.isOperationComplete());
if (operationException.get() != null) {
throw operationException.get();
}
if (readCompleteException.get() != null) {
throw readCompleteException.get();
}
// Ensure that a ChannelClosed exception is not set when the ReadableStreamChannel is closed correctly.
Assert.assertNull("Callback operation exception should be null", op.getOperationException());
if (options.getBlobOptions.getOperationType() != GetBlobOptions.OperationType.BlobInfo) {
int sizeWritten = blobSize;
if (options.getBlobOptions.getRange() != null) {
ByteRange range = options.getBlobOptions.getRange().toResolvedByteRange(blobSize);
sizeWritten = (int) (range.getEndOffset() - range.getStartOffset() + 1);
}
Assert.assertEquals("Size read must equal size written", sizeWritten, readCompleteResult.get());
}
}
use of com.github.ambry.commons.ByteBufferAsyncWritableChannel in project ambry by linkedin.
the class GetManagerTest method compareContent.
/**
* Compare and assert that the content in the given {@link ReadableStreamChannel} is exactly the same as
* the original put content.
* @param readableStreamChannel the {@link ReadableStreamChannel} that is the candidate for comparison.
*/
private void compareContent(ReadableStreamChannel readableStreamChannel) throws Exception {
ByteBuffer putContentBuf = ByteBuffer.wrap(putContent);
// If a range is set, compare the result against the specified byte range.
if (options.getRange() != null) {
ByteRange range = options.getRange().toResolvedByteRange(putContent.length);
putContentBuf = ByteBuffer.wrap(putContent, (int) range.getStartOffset(), (int) range.getRangeSize());
}
ByteBufferAsyncWritableChannel getChannel = new ByteBufferAsyncWritableChannel();
Future<Long> readIntoFuture = readableStreamChannel.readInto(getChannel, null);
final int bytesToRead = putContentBuf.remaining();
int readBytes = 0;
do {
ByteBuffer buf = getChannel.getNextChunk();
int bufLength = buf.remaining();
Assert.assertTrue("total content read should not be greater than length of put content", readBytes + bufLength <= bytesToRead);
while (buf.hasRemaining()) {
Assert.assertEquals("Get and Put blob content should match", putContentBuf.get(), buf.get());
readBytes++;
}
getChannel.resolveOldestChunk(null);
} while (readBytes < bytesToRead);
Assert.assertEquals("the returned length in the future should be the length of data written", (long) readBytes, (long) readIntoFuture.get());
Assert.assertNull("There should be no more data in the channel", getChannel.getNextChunk(0));
}
use of com.github.ambry.commons.ByteBufferAsyncWritableChannel in project ambry by linkedin.
the class NettyMultipartRequestTest method readIntoExceptionsTest.
/**
* Tests exception scenarios of {@link NettyMultipartRequest#readInto(AsyncWritableChannel, Callback)}.
* @throws Exception
*/
@Test
public void readIntoExceptionsTest() throws Exception {
// most tests are in NettyRequest. Adding tests for differing code in NettyMultipartRequest
// try to call readInto twice.
NettyMultipartRequest request = createRequest(null, null);
AsyncWritableChannel writeChannel = new ByteBufferAsyncWritableChannel();
request.prepare();
request.readInto(writeChannel, null);
try {
request.readInto(writeChannel, null);
fail("Calling readInto twice should have failed");
} catch (IllegalStateException e) {
// expected. Nothing to do.
} finally {
closeRequestAndValidate(request);
}
// call readInto when not ready for read.
request = createRequest(null, null);
writeChannel = new ByteBufferAsyncWritableChannel();
try {
request.readInto(writeChannel, null);
fail("Calling readInto without calling prepare() should have failed");
} catch (IllegalStateException e) {
// expected. Nothing to do.
} finally {
closeRequestAndValidate(request);
}
}
use of com.github.ambry.commons.ByteBufferAsyncWritableChannel in project ambry by linkedin.
the class CopyForcingByteBuf method operationsAfterCloseTest.
/**
* Tests for behavior of multiple operations after {@link NettyRequest#close()} has been called. Some should be ok to
* do and some should throw exceptions.
* @throws Exception
*/
@Test
public void operationsAfterCloseTest() throws Exception {
Channel channel = new MockChannel();
NettyRequest nettyRequest = createNettyRequest(HttpMethod.POST, "/", null, channel);
closeRequestAndValidate(nettyRequest, channel);
// operations that should be ok to do (does not include all operations).
nettyRequest.close();
// operations that will throw exceptions.
AsyncWritableChannel writeChannel = new ByteBufferAsyncWritableChannel();
ReadIntoCallback callback = new ReadIntoCallback();
try {
nettyRequest.readInto(writeChannel, callback).get();
fail("Request channel has been closed, so read should have thrown ClosedChannelException");
} catch (ExecutionException e) {
Exception exception = (Exception) Utils.getRootCause(e);
assertTrue("Exception is not ClosedChannelException", exception instanceof ClosedChannelException);
callback.awaitCallback();
assertEquals("Exceptions of callback and future differ", exception.getMessage(), callback.exception.getMessage());
}
try {
byte[] content = TestUtils.getRandomBytes(1024);
nettyRequest.addContent(new DefaultLastHttpContent(Unpooled.wrappedBuffer(content)));
fail("Request channel has been closed, so addContent() should have thrown ClosedChannelException");
} catch (RestServiceException e) {
assertEquals("Unexpected RestServiceErrorCode", RestServiceErrorCode.RequestChannelClosed, e.getErrorCode());
}
}
use of com.github.ambry.commons.ByteBufferAsyncWritableChannel in project ambry by linkedin.
the class CopyForcingByteBuf method zeroSizeContentTest.
/**
* Tests for POST request that has no content.
* @throws Exception
*/
@Test
public void zeroSizeContentTest() throws Exception {
Channel channel = new MockChannel();
NettyRequest nettyRequest = createNettyRequest(HttpMethod.POST, "/", null, channel);
HttpContent httpContent = new DefaultLastHttpContent();
nettyRequest.addContent(httpContent);
assertEquals("Reference count is not as expected", 2, httpContent.refCnt());
ByteBufferAsyncWritableChannel writeChannel = new ByteBufferAsyncWritableChannel();
ReadIntoCallback callback = new ReadIntoCallback();
Future<Long> future = nettyRequest.readInto(writeChannel, callback);
assertEquals("There should be no content", 0, writeChannel.getNextChunk().remaining());
writeChannel.resolveOldestChunk(null);
closeRequestAndValidate(nettyRequest, channel);
writeChannel.close();
assertEquals("Reference count of http content has changed", 1, httpContent.refCnt());
callback.awaitCallback();
if (callback.exception != null) {
throw callback.exception;
}
long futureBytesRead = future.get();
assertEquals("Total bytes read does not match (callback)", 0, callback.bytesRead);
assertEquals("Total bytes read does not match (future)", 0, futureBytesRead);
}
Aggregations