Search in sources :

Example 11 with ByteBufferAsyncWritableChannel

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());
    }
}
Also used : AtomicReference(java.util.concurrent.atomic.AtomicReference) BlobInfo(com.github.ambry.messageformat.BlobInfo) CountDownLatch(java.util.concurrent.CountDownLatch) ByteBufferAsyncWritableChannel(com.github.ambry.commons.ByteBufferAsyncWritableChannel) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) AtomicLong(java.util.concurrent.atomic.AtomicLong) AtomicLong(java.util.concurrent.atomic.AtomicLong)

Example 12 with ByteBufferAsyncWritableChannel

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));
}
Also used : ByteBuffer(java.nio.ByteBuffer) ByteBufferAsyncWritableChannel(com.github.ambry.commons.ByteBufferAsyncWritableChannel)

Example 13 with ByteBufferAsyncWritableChannel

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);
    }
}
Also used : RetainingAsyncWritableChannel(com.github.ambry.commons.RetainingAsyncWritableChannel) ByteBufferAsyncWritableChannel(com.github.ambry.commons.ByteBufferAsyncWritableChannel) AsyncWritableChannel(com.github.ambry.router.AsyncWritableChannel) ByteBufferAsyncWritableChannel(com.github.ambry.commons.ByteBufferAsyncWritableChannel) Test(org.junit.Test)

Example 14 with ByteBufferAsyncWritableChannel

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());
    }
}
Also used : ClosedChannelException(java.nio.channels.ClosedChannelException) DefaultLastHttpContent(io.netty.handler.codec.http.DefaultLastHttpContent) AsyncWritableChannel(com.github.ambry.router.AsyncWritableChannel) ByteBufferAsyncWritableChannel(com.github.ambry.commons.ByteBufferAsyncWritableChannel) EmbeddedChannel(io.netty.channel.embedded.EmbeddedChannel) Channel(io.netty.channel.Channel) AsyncWritableChannel(com.github.ambry.router.AsyncWritableChannel) ByteBufferAsyncWritableChannel(com.github.ambry.commons.ByteBufferAsyncWritableChannel) ExecutionException(java.util.concurrent.ExecutionException) ByteBufferAsyncWritableChannel(com.github.ambry.commons.ByteBufferAsyncWritableChannel) TimeoutException(java.util.concurrent.TimeoutException) SSLException(javax.net.ssl.SSLException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) ClosedChannelException(java.nio.channels.ClosedChannelException) IOException(java.io.IOException) CertificateException(java.security.cert.CertificateException) ExecutionException(java.util.concurrent.ExecutionException) Test(org.junit.Test)

Example 15 with ByteBufferAsyncWritableChannel

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);
}
Also used : DefaultLastHttpContent(io.netty.handler.codec.http.DefaultLastHttpContent) AsyncWritableChannel(com.github.ambry.router.AsyncWritableChannel) ByteBufferAsyncWritableChannel(com.github.ambry.commons.ByteBufferAsyncWritableChannel) EmbeddedChannel(io.netty.channel.embedded.EmbeddedChannel) Channel(io.netty.channel.Channel) ByteBufferAsyncWritableChannel(com.github.ambry.commons.ByteBufferAsyncWritableChannel) LastHttpContent(io.netty.handler.codec.http.LastHttpContent) HttpContent(io.netty.handler.codec.http.HttpContent) DefaultHttpContent(io.netty.handler.codec.http.DefaultHttpContent) DefaultLastHttpContent(io.netty.handler.codec.http.DefaultLastHttpContent) Test(org.junit.Test)

Aggregations

ByteBufferAsyncWritableChannel (com.github.ambry.commons.ByteBufferAsyncWritableChannel)20 ExecutionException (java.util.concurrent.ExecutionException)11 AsyncWritableChannel (com.github.ambry.router.AsyncWritableChannel)9 DefaultHttpContent (io.netty.handler.codec.http.DefaultHttpContent)9 DefaultLastHttpContent (io.netty.handler.codec.http.DefaultLastHttpContent)9 Channel (io.netty.channel.Channel)8 EmbeddedChannel (io.netty.channel.embedded.EmbeddedChannel)8 HttpContent (io.netty.handler.codec.http.HttpContent)8 LastHttpContent (io.netty.handler.codec.http.LastHttpContent)8 IOException (java.io.IOException)8 Test (org.junit.Test)8 ArrayList (java.util.ArrayList)7 ByteBuffer (java.nio.ByteBuffer)6 CountDownLatch (java.util.concurrent.CountDownLatch)6 AtomicReference (java.util.concurrent.atomic.AtomicReference)6 Callback (com.github.ambry.commons.Callback)5 AtomicLong (java.util.concurrent.atomic.AtomicLong)5 InMemAccountService (com.github.ambry.account.InMemAccountService)3 MockClusterMap (com.github.ambry.clustermap.MockClusterMap)3 PartitionId (com.github.ambry.clustermap.PartitionId)3