use of io.pravega.shared.protocol.netty.ConnectionFailedException in project pravega by pravega.
the class ClientConnectionInboundHandler method sendAsync.
@Override
public void sendAsync(List<Append> appends, CompletedCallback callback) {
recentMessage.set(true);
Channel ch;
try {
ch = getChannel();
} catch (ConnectionFailedException e) {
callback.complete(new ConnectionFailedException("Connection to " + connectionName + " is not established."));
return;
}
PromiseCombiner combiner = new PromiseCombiner();
for (Append append : appends) {
batchSizeTracker.recordAppend(append.getEventNumber(), append.getData().readableBytes());
combiner.add(ch.write(append));
}
ch.flush();
ChannelPromise promise = ch.newPromise();
promise.addListener(new GenericFutureListener<Future<? super Void>>() {
@Override
public void operationComplete(Future<? super Void> future) throws Exception {
Throwable cause = future.cause();
callback.complete(cause == null ? null : new ConnectionFailedException(cause));
}
});
combiner.finish(promise);
}
use of io.pravega.shared.protocol.netty.ConnectionFailedException in project pravega by pravega.
the class ConnectionFactoryImpl method establishConnection.
@Override
public CompletableFuture<ClientConnection> establishConnection(PravegaNodeUri location, ReplyProcessor rp) {
Preconditions.checkNotNull(location);
Exceptions.checkNotClosed(closed.get(), this);
final SslContext sslCtx;
if (clientConfig.isEnableTls()) {
try {
SslContextBuilder sslCtxFactory = SslContextBuilder.forClient();
if (Strings.isNullOrEmpty(clientConfig.getTrustStore())) {
sslCtxFactory = sslCtxFactory.trustManager(FingerprintTrustManagerFactory.getInstance(FingerprintTrustManagerFactory.getDefaultAlgorithm()));
} else {
sslCtxFactory = SslContextBuilder.forClient().trustManager(new File(clientConfig.getTrustStore()));
}
sslCtx = sslCtxFactory.build();
} catch (SSLException | NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
} else {
sslCtx = null;
}
AppendBatchSizeTracker batchSizeTracker = new AppendBatchSizeTrackerImpl();
ClientConnectionInboundHandler handler = new ClientConnectionInboundHandler(location.getEndpoint(), rp, batchSizeTracker);
Bootstrap b = new Bootstrap();
b.group(group).channel(nio ? NioSocketChannel.class : EpollSocketChannel.class).option(ChannelOption.TCP_NODELAY, true).handler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
if (sslCtx != null) {
SslHandler sslHandler = sslCtx.newHandler(ch.alloc(), location.getEndpoint(), location.getPort());
if (clientConfig.isValidateHostName()) {
SSLEngine sslEngine = sslHandler.engine();
SSLParameters sslParameters = sslEngine.getSSLParameters();
sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
sslEngine.setSSLParameters(sslParameters);
}
p.addLast(sslHandler);
}
// p.addLast(new LoggingHandler(LogLevel.INFO));
p.addLast(new ExceptionLoggingHandler(location.getEndpoint()), new CommandEncoder(batchSizeTracker), new LengthFieldBasedFrameDecoder(WireCommands.MAX_WIRECOMMAND_SIZE, 4, 4), new CommandDecoder(), handler);
}
});
// Start the client.
CompletableFuture<ClientConnection> connectionComplete = new CompletableFuture<>();
try {
b.connect(location.getEndpoint(), location.getPort()).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) {
if (future.isSuccess()) {
// since ChannelFuture is complete future.channel() is not a blocking call.
Channel ch = future.channel();
log.debug("Connect operation completed for channel:{}, local address:{}, remote address:{}", ch.id(), ch.localAddress(), ch.remoteAddress());
// Once a channel is closed the channel group implementation removes it.
allChannels.add(ch);
connectionComplete.complete(handler);
} else {
connectionComplete.completeExceptionally(new ConnectionFailedException(future.cause()));
}
}
});
} catch (Exception e) {
connectionComplete.completeExceptionally(new ConnectionFailedException(e));
}
// check if channel is registered.
CompletableFuture<Void> channelRegisteredFuture = new CompletableFuture<>();
handler.completeWhenRegistered(channelRegisteredFuture);
return connectionComplete.thenCombine(channelRegisteredFuture, (clientConnection, v) -> clientConnection);
}
use of io.pravega.shared.protocol.netty.ConnectionFailedException in project pravega by pravega.
the class SegmentOutputStreamImpl method reconnect.
@VisibleForTesting
void reconnect() {
if (state.isClosed()) {
return;
}
log.debug("(Re)connect invoked, Segment: {}, writerID: {}", segmentName, writerId);
state.setupConnection.registerAndRunReleaser(() -> {
Retry.indefinitelyWithExpBackoff(retrySchedule.getInitialMillis(), retrySchedule.getMultiplier(), retrySchedule.getMaxDelay(), t -> log.warn(writerId + " Failed to connect: ", t)).runAsync(() -> {
log.debug("Running reconnect for segment:{} writerID: {}", segmentName, writerId);
if (state.isClosed() || state.isAlreadySealed()) {
return CompletableFuture.completedFuture(null);
}
Preconditions.checkState(state.getConnection() == null);
log.info("Fetching endpoint for segment {}, writerID: {}", segmentName, writerId);
return controller.getEndpointForSegment(segmentName).thenComposeAsync((PravegaNodeUri uri) -> {
log.info("Establishing connection to {} for {}, writerID: {}", uri, segmentName, writerId);
return connectionFactory.establishConnection(uri, responseProcessor);
}, connectionFactory.getInternalExecutor()).thenComposeAsync(connection -> {
CompletableFuture<Void> connectionSetupFuture = state.newConnection(connection);
SetupAppend cmd = new SetupAppend(requestIdGenerator.get(), writerId, segmentName, delegationToken);
try {
connection.send(cmd);
} catch (ConnectionFailedException e1) {
// This needs to be invoked here because call to failConnection from netty may occur before state.newConnection above.
state.failConnection(e1);
throw Lombok.sneakyThrow(e1);
}
return connectionSetupFuture.exceptionally(t -> {
if (Exceptions.unwrap(t) instanceof SegmentSealedException) {
log.info("Ending reconnect attempts to {} because segment is sealed", segmentName);
return null;
}
throw Lombok.sneakyThrow(t);
});
}, connectionFactory.getInternalExecutor());
}, connectionFactory.getInternalExecutor());
}, new CompletableFuture<ClientConnection>());
}
use of io.pravega.shared.protocol.netty.ConnectionFailedException in project pravega by pravega.
the class SegmentInputStreamTest method testExceptionRecovery.
@Test
public void testExceptionRecovery() throws EndOfSegmentException, SegmentTruncatedException {
byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
ByteBuffer wireData = createEventFromData(data);
TestAsyncSegmentInputStream fakeNetwork = new TestAsyncSegmentInputStream(segment, 7);
@Cleanup SegmentInputStreamImpl stream = new SegmentInputStreamImpl(fakeNetwork, 0);
fakeNetwork.complete(0, new WireCommands.SegmentRead(segment.getScopedName(), 0, false, false, ByteBufferUtils.slice(wireData, 0, 2)));
fakeNetwork.completeExceptionally(1, new ConnectionFailedException());
fakeNetwork.complete(2, new WireCommands.SegmentRead(segment.getScopedName(), 0, false, false, ByteBufferUtils.slice(wireData, 0, 2)));
fakeNetwork.complete(3, new WireCommands.SegmentRead(segment.getScopedName(), 2, false, false, ByteBufferUtils.slice(wireData, 2, 7)));
fakeNetwork.complete(4, new WireCommands.SegmentRead(segment.getScopedName(), 9, false, false, ByteBufferUtils.slice(wireData, 9, 2)));
fakeNetwork.complete(5, new WireCommands.SegmentRead(segment.getScopedName(), 11, false, false, ByteBufferUtils.slice(wireData, 11, wireData.capacity() - 11)));
AssertExtensions.assertThrows(ConnectionFailedException.class, () -> stream.read());
ByteBuffer read = stream.read();
assertEquals(ByteBuffer.wrap(data), read);
}
use of io.pravega.shared.protocol.netty.ConnectionFailedException in project pravega by pravega.
the class SegmentOutputStreamTest method testFailOnClose.
/**
* Verifies that if a exception is encountered while flushing data inside of close, the
* connection is reestablished and the data is retransmitted before close returns.
*/
@Test
public void testFailOnClose() throws ConnectionFailedException {
UUID cid = UUID.randomUUID();
PravegaNodeUri uri = new PravegaNodeUri("endpoint", SERVICE_PORT);
MockConnectionFactoryImpl cf = new MockConnectionFactoryImpl();
@Cleanup("shutdown") InlineExecutor inlineExecutor = new InlineExecutor();
cf.setExecutor(inlineExecutor);
MockController controller = new MockController(uri.getEndpoint(), uri.getPort(), cf);
ClientConnection connection = mock(ClientConnection.class);
cf.provideConnection(uri, connection);
SegmentOutputStreamImpl output = new SegmentOutputStreamImpl(SEGMENT, controller, cf, cid, segmentSealedCallback, RETRY_SCHEDULE, "");
output.reconnect();
InOrder inOrder = Mockito.inOrder(connection);
inOrder.verify(connection).send(new SetupAppend(1, cid, SEGMENT, ""));
cf.getProcessor(uri).appendSetup(new AppendSetup(1, SEGMENT, cid, 0));
ByteBuffer data = getBuffer("test");
// Prep mock: the mockito doAnswers setup below are triggered during the close inside of the testBlocking() call.
CompletableFuture<Boolean> acked = new CompletableFuture<>();
Append append = new Append(SEGMENT, cid, 1, Unpooled.wrappedBuffer(data), null);
doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
cf.getProcessor(uri).connectionDropped();
throw new ConnectionFailedException();
}
}).doNothing().when(connection).send(new WireCommands.KeepAlive());
doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
CompletedCallback callback = (CompletedCallback) invocation.getArgument(1);
callback.complete(null);
return null;
}
}).when(connection).sendAsync(Mockito.eq(Collections.singletonList(append)), Mockito.any());
// Queue up event.
output.write(new PendingEvent(null, data, acked, null));
inOrder.verify(connection).send(append);
// Verify behavior
Async.testBlocking(() -> {
output.close();
}, () -> {
cf.getProcessor(uri).appendSetup(new AppendSetup(2, SEGMENT, cid, 0));
cf.getProcessor(uri).dataAppended(new WireCommands.DataAppended(cid, 1, 0));
});
inOrder.verify(connection).send(new WireCommands.KeepAlive());
inOrder.verify(connection).send(new SetupAppend(2, cid, SEGMENT, ""));
inOrder.verify(connection).sendAsync(Mockito.eq(Collections.singletonList(append)), Mockito.any());
inOrder.verify(connection).close();
assertEquals(true, acked.isDone());
inOrder.verifyNoMoreInteractions();
}
Aggregations