use of io.pravega.client.connection.impl.ClientConnection in project pravega by pravega.
the class SegmentOutputStreamImpl method write.
/**
* @see SegmentOutputStream#write(PendingEvent)
*/
@Override
public void write(PendingEvent event) {
// State is set to sealed during a Transaction abort and the segment writer should not throw an {@link IllegalStateException} in such a case.
checkState(!state.isAlreadySealed() || NameUtils.isTransactionSegment(segmentName), "Segment: %s is already sealed", segmentName);
synchronized (writeOrderLock) {
ClientConnection connection;
try {
// if connection is null getConnection() establishes a connection and retransmits all events in inflight
// list.
connection = Futures.getThrowingException(getConnection());
} catch (SegmentSealedException | NoSuchSegmentException e) {
// Add the event to inflight, this will be resent to the successor during the execution of resendToSuccessorsCallback
state.addToInflight(event);
return;
} catch (RetriesExhaustedException e) {
event.getAckFuture().completeExceptionally(e);
log.error("Failed to write event to Pravega due connectivity error ", e);
return;
}
long eventNumber = state.addToInflight(event);
try {
Append append = new Append(segmentName, writerId, eventNumber, event.getEventCount(), event.getData(), null, requestId);
log.trace("Sending append request: {}", append);
connection.send(append);
} catch (ConnectionFailedException e) {
log.warn("Failed writing event through writer " + writerId + " due to: ", e);
// As the message is inflight, this will perform the retransmission.
reconnect();
}
}
}
use of io.pravega.client.connection.impl.ClientConnection in project pravega by pravega.
the class SegmentOutputStreamImpl method flush.
/**
* @see SegmentOutputStream#flush()
*/
@Override
public void flush() throws SegmentSealedException {
int numInflight = state.getNumInflight();
log.debug("Flushing writer: {} with {} inflight events", writerId, numInflight);
if (numInflight != 0) {
try {
ClientConnection connection = Futures.getThrowingException(getConnection());
connection.send(new KeepAlive());
} catch (SegmentSealedException | NoSuchSegmentException e) {
if (NameUtils.isTransactionSegment(segmentName)) {
log.warn("Exception observed during a flush on a transaction segment, this indicates that the transaction is " + "committed/aborted. Details: {}", e.getMessage());
failConnection(e);
} else {
log.info("Exception observed while obtaining connection during flush. Details: {} ", e.getMessage());
}
} catch (Exception e) {
failConnection(e);
if (e instanceof RetriesExhaustedException) {
log.error("Flush on segment {} by writer {} failed after all retries", segmentName, writerId);
// throw an exception to the external world that the flush failed due to RetriesExhaustedException
throw Exceptions.sneakyThrow(e);
}
}
state.waitForInflight();
Exceptions.checkNotClosed(state.isClosed(), this);
/* SegmentSealedException is thrown if either of the below conditions are true
- resendToSuccessorsCallback has been invoked.
- the segment corresponds to an aborted Transaction.
*/
if (state.needSuccessors.get() || (NameUtils.isTransactionSegment(segmentName) && state.isAlreadySealed())) {
throw new SegmentSealedException(segmentName + " sealed for writer " + writerId);
}
} else if (state.exception instanceof RetriesExhaustedException) {
// All attempts to connect with SSS have failed.
// The number of retry attempts is based on EventWriterConfig
log.error("Flush on segment {} by writer {} failed after all retries", segmentName, writerId);
throw Exceptions.sneakyThrow(state.exception);
}
}
use of io.pravega.client.connection.impl.ClientConnection in project pravega by pravega.
the class MockConnectionFactoryImpl method establishConnection.
@Override
@Synchronized
public CompletableFuture<ClientConnection> establishConnection(PravegaNodeUri location, ReplyProcessor rp) {
ClientConnection connection = connections.get(location);
Preconditions.checkState(connection != null, "Unexpected Endpoint");
ReplyProcessor previous = processors.put(location, rp);
assertNull("Mock connection factory does not support multiple concurrent connections to the same location", previous);
return CompletableFuture.completedFuture(new DelegateClientConnection(location, connection));
}
use of io.pravega.client.connection.impl.ClientConnection in project pravega by pravega.
the class LargeEventWriterTest method testPipelining.
@Test(timeout = 5000)
public void testPipelining() throws NoSuchSegmentException, AuthenticationException, SegmentSealedException, ConnectionFailedException {
Segment segment = Segment.fromScopedName("foo/bar/1");
MockConnectionFactoryImpl connectionFactory = new MockConnectionFactoryImpl();
MockController controller = new MockController("localhost", 0, connectionFactory, false);
ClientConnection connection = Mockito.mock(ClientConnection.class);
PravegaNodeUri location = new PravegaNodeUri("localhost", 0);
connectionFactory.provideConnection(location, connection);
ArrayList<ByteBuffer> buffers = new ArrayList<>();
buffers.add(ByteBuffer.allocate(Serializer.MAX_EVENT_SIZE - WireCommands.TYPE_PLUS_LENGTH_SIZE));
buffers.add(ByteBuffer.allocate(Serializer.MAX_EVENT_SIZE - WireCommands.TYPE_PLUS_LENGTH_SIZE));
buffers.add(ByteBuffer.allocate(Serializer.MAX_EVENT_SIZE - WireCommands.TYPE_PLUS_LENGTH_SIZE));
ArrayList<ConditionalBlockEnd> written = new ArrayList<>();
answerRequest(connectionFactory, connection, location, CreateTransientSegment.class, r -> new SegmentCreated(r.getRequestId(), "transient-segment"));
answerRequest(connectionFactory, connection, location, SetupAppend.class, r -> new AppendSetup(r.getRequestId(), segment.getScopedName(), r.getWriterId(), WireCommands.NULL_ATTRIBUTE_VALUE));
// If appends are not pipelined, the call to writeLargeEvents will stall waiting for the first reply.
Mockito.doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
ConditionalBlockEnd argument = (ConditionalBlockEnd) invocation.getArgument(0);
written.add(argument);
if (written.size() == buffers.size()) {
for (ConditionalBlockEnd append : written) {
connectionFactory.getProcessor(location).process(new DataAppended(append.getRequestId(), writerId, append.getEventNumber(), append.getEventNumber() - 1, append.getExpectedOffset() + append.getData().readableBytes()));
}
}
return null;
}
}).when(connection).send(any(ConditionalBlockEnd.class));
answerRequest(connectionFactory, connection, location, MergeSegments.class, r -> {
return new SegmentsMerged(r.getRequestId(), r.getSource(), r.getTarget(), -1);
});
LargeEventWriter writer = new LargeEventWriter(writerId, controller, connectionFactory);
EmptyTokenProviderImpl tokenProvider = new EmptyTokenProviderImpl();
writer.writeLargeEvent(segment, buffers, tokenProvider, EventWriterConfig.builder().build());
}
use of io.pravega.client.connection.impl.ClientConnection in project pravega by pravega.
the class LargeEventWriterTest method testRetries.
@Test(timeout = 5000)
public void testRetries() throws ConnectionFailedException, NoSuchSegmentException, AuthenticationException {
Segment segment = Segment.fromScopedName("foo/bar/1");
MockConnectionFactoryImpl connectionFactory = new MockConnectionFactoryImpl();
MockController controller = new MockController("localhost", 0, connectionFactory, false);
ClientConnection connection = Mockito.mock(ClientConnection.class);
PravegaNodeUri location = new PravegaNodeUri("localhost", 0);
connectionFactory.provideConnection(location, connection);
AtomicInteger count = new AtomicInteger(0);
answerRequest(connectionFactory, connection, location, CreateTransientSegment.class, r -> new SegmentCreated(r.getRequestId(), "transient-segment"));
answerRequest(connectionFactory, connection, location, SetupAppend.class, r -> new AppendSetup(r.getRequestId(), segment.getScopedName(), r.getWriterId(), WireCommands.NULL_ATTRIBUTE_VALUE));
answerRequest(connectionFactory, connection, location, ConditionalBlockEnd.class, r -> {
count.getAndIncrement();
return new WrongHost(r.getRequestId(), segment.getScopedName(), null, null);
});
LargeEventWriter writer = new LargeEventWriter(writerId, controller, connectionFactory);
EmptyTokenProviderImpl tokenProvider = new EmptyTokenProviderImpl();
ArrayList<ByteBuffer> buffers = new ArrayList<>();
buffers.add(ByteBuffer.allocate(5));
AssertExtensions.assertThrows(RetriesExhaustedException.class, () -> writer.writeLargeEvent(segment, buffers, tokenProvider, EventWriterConfig.builder().initialBackoffMillis(1).backoffMultiple(1).enableLargeEvents(true).retryAttempts(7).build()));
assertEquals(8, count.get());
}
Aggregations