@Override public Releasable openConnection(DiscoveryNode node, ConnectionProfile profile, ActionListener<Transport.Connection> listener) { Objects.requireNonNull(profile, "connection profile cannot be null"); if (node == null) { throw new ConnectTransportException(null, "can't open connection to a null node"); } ConnectionProfile finalProfile = maybeOverrideConnectionProfile(profile); closeLock.readLock().lock(); // ensure we don't open connections while we are closing try { ensureOpen(); List<TcpChannel> pendingChannels = initiateConnection(node, finalProfile, listener); return () -> CloseableChannel.closeChannels(pendingChannels, false); } finally { closeLock.readLock().unlock(); } }
@Override public void onFailure(Exception ex) { if (countDown.fastForward()) { CloseableChannel.closeChannels(channels, false); listener.onFailure(new ConnectTransportException(node, "connect_exception", ex)); } }
@Override public void onFailure(Exception e) { CloseableChannel.closeChannels(channels, false); if (e instanceof ConnectTransportException) { listener.onFailure(e); } else { listener.onFailure(new ConnectTransportException(node, "general node connection failure", e)); } } });
public void onTimeout() { if (countDown.fastForward()) { CloseableChannel.closeChannels(channels, false); listener.onFailure(new ConnectTransportException(node, "connect_timeout[" + connectionProfile.getConnectTimeout() + "]")); } } }
public CheckedBiConsumer<Transport.Connection, ConnectionProfile, IOException> connectionValidator(DiscoveryNode node) { return (newConnection, actualProfile) -> { // We don't validate cluster names to allow for CCS connections. final DiscoveryNode remote = handshake(newConnection, actualProfile.getHandshakeTimeout().millis(), cn -> true).discoveryNode; if (validateConnections && node.equals(remote) == false) { throw new ConnectTransportException(node, "handshake failed. unexpected remote node " + remote); } }; }
ConnectionProfile resolvedProfile = ConnectionProfile.resolveConnectionProfile(connectionProfile, defaultProfile); if (node == null) { throw new ConnectTransportException(null, "can't connect to a null node"); throw e; } catch (Exception e) { throw new ConnectTransportException(node, "general node connection failure", e); } finally { if (success == false) { // close the connection if there is a failure
void sendHandshake(long requestId, DiscoveryNode node, TcpChannel channel, TimeValue timeout, ActionListener<Version> listener) { numHandshakes.inc(); final HandshakeResponseHandler handler = new HandshakeResponseHandler(requestId, version, listener); pendingHandshakes.put(requestId, handler); channel.addCloseListener(ActionListener.wrap( () -> handler.handleLocalException(new TransportException("handshake failed because connection reset")))); boolean success = false; try { // for the request we use the minCompatVersion since we don't know what's the version of the node we talk to // we also have no payload on the request but the response will contain the actual version of the node we talk // to as the payload. final Version minCompatVersion = version.minimumCompatibilityVersion(); handshakeRequestSender.sendRequest(node, channel, requestId, minCompatVersion); threadPool.schedule(timeout, ThreadPool.Names.GENERIC, () -> handler.handleLocalException(new ConnectTransportException(node, "handshake_timeout[" + timeout + "]"))); success = true; } catch (Exception e) { handler.handleLocalException(new ConnectTransportException(node, "failure to send " + HANDSHAKE_ACTION_NAME, e)); } finally { if (success == false) { TransportResponseHandler<?> removed = pendingHandshakes.remove(requestId); assert removed == null : "Handshake should not be pending if exception was thrown"; } } }
private List<TcpChannel> initiateConnection(DiscoveryNode node, ConnectionProfile connectionProfile, ActionListener<Transport.Connection> listener) { int numConnections = connectionProfile.getNumConnections(); assert numConnections > 0 : "A connection profile must be configured with at least one connection"; final List<TcpChannel> channels = new ArrayList<>(numConnections); for (int i = 0; i < numConnections; ++i) { try { TcpChannel channel = initiateChannel(node); logger.trace(() -> new ParameterizedMessage("Tcp transport client channel opened: {}", channel)); channels.add(channel); } catch (ConnectTransportException e) { CloseableChannel.closeChannels(channels, false); listener.onFailure(e); return channels; } catch (Exception e) { CloseableChannel.closeChannels(channels, false); listener.onFailure(new ConnectTransportException(node, "general node connection failure", e)); return channels; } } ChannelsConnectedListener channelsConnectedListener = new ChannelsConnectedListener(node, connectionProfile, channels, listener); for (TcpChannel channel : channels) { channel.addConnectListener(channelsConnectedListener); } TimeValue connectTimeout = connectionProfile.getConnectTimeout(); threadPool.schedule(connectTimeout, ThreadPool.Names.GENERIC, channelsConnectedListener::onTimeout); return channels; }
@Override public Connection openConnection(DiscoveryNode node, ConnectionProfile profile) throws IOException { throw new ConnectTransportException(node, "DISCONNECT: simulated"); }
@Override public Connection openConnection(DiscoveryNode node, ConnectionProfile profile) throws IOException { throw new ConnectTransportException(node, "UNRESPONSIVE: simulated"); }
private Transport.Connection internalOpenConnection(DiscoveryNode node, ConnectionProfile connectionProfile) { PlainActionFuture<Transport.Connection> future = PlainActionFuture.newFuture(); Releasable pendingConnection = transport.openConnection(node, connectionProfile, future); Transport.Connection connection; try { connection = future.actionGet(); } catch (IllegalStateException e) { // If the future was interrupted we must cancel the pending connection to avoid channels leaking if (e.getCause() instanceof InterruptedException) { pendingConnection.close(); } throw e; } try { connectionListener.onConnectionOpened(connection); } finally { connection.addCloseListener(ActionListener.wrap(() -> connectionListener.onConnectionClosed(connection))); } if (connection.isClosed()) { throw new ConnectTransportException(node, "a channel closed while connecting"); } return connection; }
@Override public void connectToNode(DiscoveryNode node, ConnectionProfile connectionProfile, CheckedBiConsumer<Connection, ConnectionProfile, IOException> connectionValidator) throws ConnectTransportException { if (original.nodeConnected(node) == false) { // connecting to an already connected node is a no-op throw new ConnectTransportException(node, "DISCONNECT: simulated"); } }
@Override public void connectToNode(DiscoveryNode node, ConnectionProfile connectionProfile, CheckedBiConsumer<Connection, ConnectionProfile, IOException> connectionValidator) throws ConnectTransportException { if (original.nodeConnected(node) == false) { // connecting to an already connected node is a no-op throw new ConnectTransportException(node, "UNRESPONSIVE: simulated"); } }
@Override public Connection openConnection(DiscoveryNode node, ConnectionProfile profile) throws IOException { final LocalTransport targetTransport = transports.get(node.getAddress()); if (targetTransport == null) { throw new ConnectTransportException(node, "Failed to connect"); } return getConnectionForTransport(targetTransport, node, false); }
@Override public void connectToNode(DiscoveryNode node) throws ConnectTransportException { synchronized (this) { if (connectedNodes.containsKey(node)) { return; } final LocalTransport targetTransport = transports.get(node.address()); if (targetTransport == null) { throw new ConnectTransportException(node, "Failed to connect"); } connectedNodes.put(node, targetTransport); transportServiceAdapter.raiseNodeConnected(node); } }
public CheckedBiConsumer<Transport.Connection, ConnectionProfile, IOException> connectionValidator(DiscoveryNode node) { return (newConnection, actualProfile) -> { // We don't validate cluster names to allow for CCS connections. final DiscoveryNode remote = handshake(newConnection, actualProfile.getHandshakeTimeout().millis(), cn -> true).discoveryNode; if (validateConnections && node.equals(remote) == false) { throw new ConnectTransportException(node, "handshake failed. unexpected remote node " + remote); } }; }
private Transport.Connection internalOpenConnection(DiscoveryNode node, ConnectionProfile connectionProfile) { Transport.Connection connection = transport.openConnection(node, connectionProfile); try { connectionListener.onConnectionOpened(connection); } finally { connection.addCloseListener(ActionListener.wrap(() -> connectionListener.onConnectionClosed(connection))); } if (connection.isClosed()) { throw new ConnectTransportException(node, "a channel closed while connecting"); } return connection; }
private Transport.Connection internalOpenConnection(DiscoveryNode node, ConnectionProfile connectionProfile) { Transport.Connection connection = transport.openConnection(node, connectionProfile); try { connectionListener.onConnectionOpened(connection); } finally { connection.addCloseListener(ActionListener.wrap(() -> connectionListener.onConnectionClosed(connection))); } if (connection.isClosed()) { throw new ConnectTransportException(node, "a channel closed while connecting"); } return connection; }
private NodeChannels connectToChannelsLight(DiscoveryNode node) { InetSocketAddress address = ((InetSocketTransportAddress) node.address()).address(); ChannelFuture connect = clientBootstrap.connect(address); connect.awaitUninterruptibly((long) (connectTimeout.millis() * 1.5)); if (!connect.isSuccess()) { throw new ConnectTransportException(node, "connect_timeout[" + connectTimeout + "]", connect.getCause()); } Channel[] channels = new Channel[1]; channels[0] = connect.getChannel(); channels[0].getCloseFuture().addListener(new ChannelCloseListener(node)); return new NodeChannels(channels, channels, channels, channels, channels); }
protected NodeChannels connectToChannelsLight(DiscoveryNode node) { InetSocketAddress address = ((InetSocketTransportAddress) node.address()).address(); ChannelFuture connect = clientBootstrap.connect(address); connect.awaitUninterruptibly((long) (connectTimeout.millis() * 1.5)); if (!connect.isSuccess()) { throw new ConnectTransportException(node, "connect_timeout[" + connectTimeout + "]", connect.getCause()); } Channel[] channels = new Channel[1]; channels[0] = connect.getChannel(); channels[0].getCloseFuture().addListener(new ChannelCloseListener(node)); return new NodeChannels(channels, channels, channels, channels, channels); }