@Override public CompletableFuture<SegmentRead> read(long offset, int length) { Exceptions.checkNotClosed(closed.get(), this); WireCommands.ReadSegment request = new WireCommands.ReadSegment(segmentId.getScopedName(), offset, length, this.delegationToken); return backoffSchedule.retryWhen(t -> { Throwable ex = Exceptions.unwrap(t); if (closed.get()) { log.debug("Exception while reading from Segment : {}", segmentId, ex); } else { log.warn("Exception while reading from Segment : {}", segmentId, ex); } return ex instanceof Exception && !(ex instanceof ConnectionClosedException) && !(ex instanceof SegmentTruncatedException); }).runAsync(() -> { return getConnection() .whenComplete((connection, ex) -> { if (ex != null) { log.warn("Exception while establishing connection with Pravega " + "node", ex); closeConnection(new ConnectionFailedException(ex)); } }).thenCompose(c -> sendRequestOverConnection(request, c)); }, connectionFactory.getInternalExecutor()); }
private CompletableFuture<SegmentRead> sendRequestOverConnection(WireCommands.ReadSegment request, ClientConnection c) { CompletableFuture<WireCommands.SegmentRead> result = new CompletableFuture<>(); if (closed.get()) { result.completeExceptionally(new ConnectionClosedException()); return result; } synchronized (lock) { outstandingRequests.put(request.getOffset(), result); } log.trace("Sending read request {}", request); c.sendAsync(request, cfe -> { if (cfe != null) { log.error("Error while sending request {}", request, cfe); synchronized (lock) { outstandingRequests.remove(request.getOffset()); } result.completeExceptionally(cfe); } }); return result; }
String segment = request.getSegment(); ArrayList<ReadResultEntryContents> cachedEntries = new ArrayList<>(); ReadResultEntry nonCachedEntry = collectCachedEntries(request.getOffset(), result, cachedEntries); final String operation = "readSegment"; SegmentRead reply = new SegmentRead(segment, request.getOffset(), atTail, endOfSegment, data); connection.send(reply); dynamicLogger.incCounterValue(globalMetricName(SEGMENT_READ_BYTES), reply.getData().array().length);
assertEquals(segmentRead, readFuture.join()); assertTrue(Futures.isSuccessful(readFuture)); inOrder.verify(c).sendAsync(Mockito.eq(new WireCommands.ReadSegment(segment.getScopedName(), 1234, 5678, "")), Mockito.any(ClientConnection.CompletedCallback.class)); inOrder.verify(c).close(); inOrder.verify(c).sendAsync(Mockito.eq(new WireCommands.ReadSegment(segment.getScopedName(), 1234, 5678, "")), Mockito.any(ClientConnection.CompletedCallback.class)); inOrder.verify(c).close(); inOrder.verify(c).sendAsync(Mockito.eq(new WireCommands.ReadSegment(segment.getScopedName(), 1234, 5678, "")), Mockito.any(ClientConnection.CompletedCallback.class)); verifyNoMoreInteractions(c);
processor.segmentIsTruncated(segmentIsTruncated); }); verify(c).sendAsync(Mockito.eq(new WireCommands.ReadSegment(segment.getScopedName(), 1234, 5678, "")), Mockito.any(ClientConnection.CompletedCallback.class)); processor.segmentRead(segmentRead); }); verify(c).sendAsync(Mockito.eq(new WireCommands.ReadSegment(segment.getScopedName(), 5656, 5678, "")), Mockito.any(ClientConnection.CompletedCallback.class)); assertTrue(Futures.isSuccessful(readFuture2));
SegmentRead result = (SegmentRead) AppendTest.sendRequest(channel, new ReadSegment(segmentName, actual.position(), 10000, ""));
@Test(timeout = 20000) public void testReadSegmentTruncated() { // Set up PravegaRequestProcessor instance to execute read segment request against String streamSegmentName = "testReadSegment"; int readLength = 1000; StreamSegmentStore store = mock(StreamSegmentStore.class); ServerConnection connection = mock(ServerConnection.class); PravegaRequestProcessor processor = new PravegaRequestProcessor(store, mock(TableStore.class), connection); TestReadResultEntry entry1 = new TestReadResultEntry(ReadResultEntryType.Truncated, 0, readLength); List<ReadResultEntry> results = new ArrayList<>(); results.add(entry1); CompletableFuture<ReadResult> readResult = new CompletableFuture<>(); readResult.complete(new TestReadResult(0, readLength, results)); when(store.read(streamSegmentName, 0, readLength, PravegaRequestProcessor.TIMEOUT)).thenReturn(readResult); StreamSegmentInformation info = StreamSegmentInformation.builder() .name(streamSegmentName) .length(1234) .startOffset(123) .build(); when(store.getStreamSegmentInfo(streamSegmentName, PravegaRequestProcessor.TIMEOUT)) .thenReturn(CompletableFuture.completedFuture(info)); // Execute and Verify readSegment calling stack in connection and store is executed as design. processor.readSegment(new WireCommands.ReadSegment(streamSegmentName, 0, readLength, "")); verify(store).read(streamSegmentName, 0, readLength, PravegaRequestProcessor.TIMEOUT); verify(store).getStreamSegmentInfo(streamSegmentName, PravegaRequestProcessor.TIMEOUT); verify(connection).send(new WireCommands.SegmentIsTruncated(0, streamSegmentName, info.getStartOffset(), "")); verifyNoMoreInteractions(connection); verifyNoMoreInteractions(store); }
@Test(timeout = 20000) public void testReadSegment() { // Set up PravegaRequestProcessor instance to execute read segment request against String streamSegmentName = "testReadSegment"; byte[] data = new byte[]{1, 2, 3, 4, 6, 7, 8, 9}; int readLength = 1000; StreamSegmentStore store = mock(StreamSegmentStore.class); ServerConnection connection = mock(ServerConnection.class); PravegaRequestProcessor processor = new PravegaRequestProcessor(store, mock(TableStore.class), connection); TestReadResultEntry entry1 = new TestReadResultEntry(ReadResultEntryType.Cache, 0, readLength); entry1.complete(new ReadResultEntryContents(new ByteArrayInputStream(data), data.length)); TestReadResultEntry entry2 = new TestReadResultEntry(ReadResultEntryType.Future, data.length, readLength); List<ReadResultEntry> results = new ArrayList<>(); results.add(entry1); results.add(entry2); CompletableFuture<ReadResult> readResult = new CompletableFuture<>(); readResult.complete(new TestReadResult(0, readLength, results)); when(store.read(streamSegmentName, 0, readLength, PravegaRequestProcessor.TIMEOUT)).thenReturn(readResult); // Execute and Verify readSegment calling stack in connection and store is executed as design. processor.readSegment(new WireCommands.ReadSegment(streamSegmentName, 0, readLength, "")); verify(store).read(streamSegmentName, 0, readLength, PravegaRequestProcessor.TIMEOUT); verify(connection).send(new WireCommands.SegmentRead(streamSegmentName, 0, true, false, ByteBuffer.wrap(data))); verifyNoMoreInteractions(connection); verifyNoMoreInteractions(store); entry2.complete(new ReadResultEntryContents(new ByteArrayInputStream(data), data.length)); verifyNoMoreInteractions(connection); verifyNoMoreInteractions(store); }
@Test(timeout = 10000) public void testWrongOffsetReturned() throws ConnectionFailedException { Segment segment = new Segment("scope", "testWrongOffsetReturned", 0); byte[] good = new byte[] { 0, 1, 2, 3, 4 }; byte[] bad = new byte[] { 9, 8, 7, 6 }; PravegaNodeUri endpoint = new PravegaNodeUri("localhost", SERVICE_PORT); MockConnectionFactoryImpl connectionFactory = new MockConnectionFactoryImpl(); MockController controller = new MockController(endpoint.getEndpoint(), endpoint.getPort(), connectionFactory); @Cleanup AsyncSegmentInputStreamImpl in = new AsyncSegmentInputStreamImpl(controller, connectionFactory, segment, ""); ClientConnection c = mock(ClientConnection.class); connectionFactory.provideConnection(endpoint, c); CompletableFuture<SegmentRead> readFuture = in.read(1234, 5678); AssertExtensions.assertBlocks(() -> readFuture.get(), () -> { ReplyProcessor processor = connectionFactory.getProcessor(endpoint); processor.segmentRead(new WireCommands.SegmentRead(segment.getScopedName(), 1235, false, false, ByteBuffer.wrap(bad))); processor.segmentRead(new WireCommands.SegmentRead(segment.getScopedName(), 1234, false, false, ByteBuffer.wrap(good))); }); verify(c).sendAsync(Mockito.eq(new WireCommands.ReadSegment(segment.getScopedName(), 1234, 5678, "")), Mockito.any(ClientConnection.CompletedCallback.class)); assertTrue(Futures.isSuccessful(readFuture)); assertEquals(ByteBuffer.wrap(good), readFuture.join().getData()); verifyNoMoreInteractions(c); }
@Test(timeout = 10000) public void testRead() throws ConnectionFailedException { Segment segment = new Segment("scope", "testRead", 1); PravegaNodeUri endpoint = new PravegaNodeUri("localhost", SERVICE_PORT); MockConnectionFactoryImpl connectionFactory = new MockConnectionFactoryImpl(); MockController controller = new MockController(endpoint.getEndpoint(), endpoint.getPort(), connectionFactory); @Cleanup AsyncSegmentInputStreamImpl in = new AsyncSegmentInputStreamImpl(controller, connectionFactory, segment, ""); ClientConnection c = mock(ClientConnection.class); connectionFactory.provideConnection(endpoint, c); WireCommands.SegmentRead segmentRead = new WireCommands.SegmentRead(segment.getScopedName(), 1234, false, false, ByteBuffer.allocate(0)); CompletableFuture<SegmentRead> readFuture = in.read(1234, 5678); AssertExtensions.assertBlocks(() -> readFuture.get(), () -> { ReplyProcessor processor = connectionFactory.getProcessor(endpoint); processor.segmentRead(segmentRead); }); verify(c).sendAsync(Mockito.eq(new WireCommands.ReadSegment(segment.getScopedName(), 1234, 5678, "")), Mockito.any(ClientConnection.CompletedCallback.class)); assertTrue(Futures.isSuccessful(readFuture)); assertEquals(segmentRead, readFuture.join()); verifyNoMoreInteractions(c); }
@Test(timeout = 20000) public void testReadSegmentEmptySealed() { // Set up PravegaRequestProcessor instance to execute read segment request against String streamSegmentName = "testReadSegment"; int readLength = 1000; StreamSegmentStore store = mock(StreamSegmentStore.class); ServerConnection connection = mock(ServerConnection.class); PravegaRequestProcessor processor = new PravegaRequestProcessor(store, mock(TableStore.class), connection); TestReadResultEntry entry1 = new TestReadResultEntry(ReadResultEntryType.EndOfStreamSegment, 0, readLength); List<ReadResultEntry> results = new ArrayList<>(); results.add(entry1); CompletableFuture<ReadResult> readResult = new CompletableFuture<>(); readResult.complete(new TestReadResult(0, readLength, results)); when(store.read(streamSegmentName, 0, readLength, PravegaRequestProcessor.TIMEOUT)).thenReturn(readResult); // Execute and Verify readSegment calling stack in connection and store is executed as design. processor.readSegment(new WireCommands.ReadSegment(streamSegmentName, 0, readLength, "")); verify(store).read(streamSegmentName, 0, readLength, PravegaRequestProcessor.TIMEOUT); verify(connection).send(new WireCommands.SegmentRead(streamSegmentName, 0, false, true, ByteBuffer.wrap(new byte[0]))); verifyNoMoreInteractions(connection); verifyNoMoreInteractions(store); }
@Test(timeout = 20000) public void testReadSegmentWithCancellationException() { // Set up PravegaRequestProcessor instance to execute read segment request against String streamSegmentName = "testReadSegment"; int readLength = 1000; StreamSegmentStore store = mock(StreamSegmentStore.class); ServerConnection connection = mock(ServerConnection.class); PravegaRequestProcessor processor = new PravegaRequestProcessor(store, mock(TableStore.class), connection); CompletableFuture<ReadResult> readResult = new CompletableFuture<>(); readResult.completeExceptionally(new CancellationException("cancel read")); // Simulate a CancellationException for a Read Segment. when(store.read(streamSegmentName, 0, readLength, PravegaRequestProcessor.TIMEOUT)).thenReturn(readResult); // Execute and Verify readSegment is calling stack in connection and store is executed as design. processor.readSegment(new WireCommands.ReadSegment(streamSegmentName, 0, readLength, "")); verify(store).read(streamSegmentName, 0, readLength, PravegaRequestProcessor.TIMEOUT); // Since the underlying store cancels the read request verify if an empty SegmentRead Wirecommand is sent as a response. verify(connection).send(new WireCommands.SegmentRead(streamSegmentName, 0, true, false, ByteBuffer.wrap(new byte[0]))); verifyNoMoreInteractions(connection); verifyNoMoreInteractions(store); }
@Override public void readSegment(ReadSegment readSegment) { Timer timer = new Timer(); final String segment = readSegment.getSegment(); final String operation = "readSegment"; if (!verifyToken(segment, readSegment.getOffset(), readSegment.getDelegationToken(), operation)) { return; } final int readSize = min(MAX_READ_SIZE, max(TYPE_PLUS_LENGTH_SIZE, readSegment.getSuggestedLength())); long trace = LoggerHelpers.traceEnter(log, operation, readSegment); segmentStore.read(segment, readSegment.getOffset(), readSize, TIMEOUT) .thenAccept(readResult -> { LoggerHelpers.traceLeave(log, operation, trace, readResult); handleReadResult(readSegment, readResult); readStreamSegment.reportSuccessEvent(timer.getElapsed()); }) .exceptionally(ex -> handleException(readSegment.getOffset(), segment, operation, wrapCancellationException(ex))); }
@Test public void testReadSegment() throws IOException { testCommand(new WireCommands.ReadSegment(testString1, l, i, "")); }
public static WireCommand readFrom(DataInput in, int length) throws IOException { String segment = in.readUTF(); long offset = in.readLong(); int suggestedLength = in.readInt(); String delegationToken = in.readUTF(); return new ReadSegment(segment, offset, suggestedLength, delegationToken); }
@Test public void readSegment() { processor.readSegment(new WireCommands.ReadSegment("segment", 0, 10, "")); verify(connection).send(new WireCommands.AuthTokenCheckFailed(0, "")); }