Search in sources :

Example 1 with ListenableFuture

use of org.elasticsearch.common.util.concurrent.ListenableFuture in project crate by crate.

the class ConnectionManager method connectToNode.

/**
 * Connects to a node with the given connection profile. If the node is already connected this method has no effect.
 * Once a successful is established, it can be validated before being exposed.
 * The ActionListener will be called on the calling thread or the generic thread pool.
 */
public void connectToNode(DiscoveryNode node, ConnectionProfile connectionProfile, ConnectionValidator connectionValidator, ActionListener<Void> listener) throws ConnectTransportException {
    if (node == null) {
        listener.onFailure(new ConnectTransportException(null, "can't connect to a null node"));
        return;
    }
    if (connectingRefCounter.tryIncRef() == false) {
        listener.onFailure(new IllegalStateException("connection manager is closed"));
        return;
    }
    if (connectedNodes.containsKey(node)) {
        connectingRefCounter.decRef();
        listener.onResponse(null);
        return;
    }
    final ListenableFuture<Void> currentListener = new ListenableFuture<>();
    final ListenableFuture<Void> existingListener = pendingConnections.putIfAbsent(node, currentListener);
    if (existingListener != null) {
        try {
            // wait on previous entry to complete connection attempt
            existingListener.addListener(listener, EsExecutors.directExecutor());
        } finally {
            connectingRefCounter.decRef();
        }
        return;
    }
    currentListener.addListener(listener, EsExecutors.directExecutor());
    final RunOnce releaseOnce = new RunOnce(connectingRefCounter::decRef);
    ConnectionProfile resolvedProfile = ConnectionProfile.resolveConnectionProfile(connectionProfile, defaultProfile);
    internalOpenConnection(node, resolvedProfile, ActionListener.wrap(conn -> {
        connectionValidator.validate(conn, resolvedProfile, ActionListener.wrap(ignored -> {
            assert Transports.assertNotTransportThread("connection validator success");
            try {
                if (connectedNodes.putIfAbsent(node, conn) != null) {
                    LOGGER.debug("existing connection to node [{}], closing new redundant connection", node);
                    IOUtils.closeWhileHandlingException(conn);
                } else {
                    LOGGER.debug("connected to node [{}]", node);
                    try {
                        connectionListener.onNodeConnected(node, conn);
                    } finally {
                        final Transport.Connection finalConnection = conn;
                        conn.addCloseListener(ActionListener.wrap(() -> {
                            LOGGER.trace("unregistering {} after connection close and marking as disconnected", node);
                            connectedNodes.remove(node, finalConnection);
                            connectionListener.onNodeDisconnected(node, conn);
                        }));
                    }
                }
            } finally {
                ListenableFuture<Void> future = pendingConnections.remove(node);
                assert future == currentListener : "Listener in pending map is different than the expected listener";
                releaseOnce.run();
                future.onResponse(null);
            }
        }, e -> {
            assert Transports.assertNotTransportThread("connection validator failure");
            IOUtils.closeWhileHandlingException(conn);
            failConnectionListeners(node, releaseOnce, e, currentListener);
        }));
    }, e -> {
        assert Transports.assertNotTransportThread("internalOpenConnection failure");
        failConnectionListeners(node, releaseOnce, e, currentListener);
    }));
}
Also used : EsExecutors(org.elasticsearch.common.util.concurrent.EsExecutors) Iterator(java.util.Iterator) AbstractRefCounted(org.elasticsearch.common.util.concurrent.AbstractRefCounted) ConcurrentCollections(org.elasticsearch.common.util.concurrent.ConcurrentCollections) IOUtils(io.crate.common.io.IOUtils) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ListenableFuture(org.elasticsearch.common.util.concurrent.ListenableFuture) Set(java.util.Set) ConcurrentMap(java.util.concurrent.ConcurrentMap) Lifecycle(org.elasticsearch.common.component.Lifecycle) CountDownLatch(java.util.concurrent.CountDownLatch) DiscoveryNode(org.elasticsearch.cluster.node.DiscoveryNode) Logger(org.apache.logging.log4j.Logger) Settings(org.elasticsearch.common.settings.Settings) Closeable(java.io.Closeable) Map(java.util.Map) LogManager(org.apache.logging.log4j.LogManager) Collections(java.util.Collections) ActionListener(org.elasticsearch.action.ActionListener) RunOnce(org.elasticsearch.common.util.concurrent.RunOnce) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) RunOnce(org.elasticsearch.common.util.concurrent.RunOnce) ListenableFuture(org.elasticsearch.common.util.concurrent.ListenableFuture)

Aggregations

IOUtils (io.crate.common.io.IOUtils)1 Closeable (java.io.Closeable)1 Collections (java.util.Collections)1 Iterator (java.util.Iterator)1 Map (java.util.Map)1 Set (java.util.Set)1 ConcurrentMap (java.util.concurrent.ConcurrentMap)1 CopyOnWriteArrayList (java.util.concurrent.CopyOnWriteArrayList)1 CountDownLatch (java.util.concurrent.CountDownLatch)1 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)1 LogManager (org.apache.logging.log4j.LogManager)1 Logger (org.apache.logging.log4j.Logger)1 ActionListener (org.elasticsearch.action.ActionListener)1 DiscoveryNode (org.elasticsearch.cluster.node.DiscoveryNode)1 Lifecycle (org.elasticsearch.common.component.Lifecycle)1 Settings (org.elasticsearch.common.settings.Settings)1 AbstractRefCounted (org.elasticsearch.common.util.concurrent.AbstractRefCounted)1 ConcurrentCollections (org.elasticsearch.common.util.concurrent.ConcurrentCollections)1 EsExecutors (org.elasticsearch.common.util.concurrent.EsExecutors)1 ListenableFuture (org.elasticsearch.common.util.concurrent.ListenableFuture)1