Search in sources :

Example 1 with RunOnce

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

the class IndexShard method bumpPrimaryTerm.

private <E extends Exception> void bumpPrimaryTerm(long newPrimaryTerm, final CheckedRunnable<E> onBlocked, @Nullable ActionListener<Releasable> combineWithAction) {
    assert Thread.holdsLock(mutex);
    assert newPrimaryTerm > pendingPrimaryTerm || (newPrimaryTerm >= pendingPrimaryTerm && combineWithAction != null);
    assert getOperationPrimaryTerm() <= pendingPrimaryTerm;
    final CountDownLatch termUpdated = new CountDownLatch(1);
    asyncBlockOperations(new ActionListener<Releasable>() {

        @Override
        public void onFailure(final Exception e) {
            try {
                innerFail(e);
            } finally {
                if (combineWithAction != null) {
                    combineWithAction.onFailure(e);
                }
            }
        }

        private void innerFail(final Exception e) {
            try {
                failShard("exception during primary term transition", e);
            } catch (AlreadyClosedException ace) {
            // ignore, shard is already closed
            }
        }

        @Override
        public void onResponse(final Releasable releasable) {
            final RunOnce releaseOnce = new RunOnce(releasable::close);
            try {
                assert getOperationPrimaryTerm() <= pendingPrimaryTerm;
                termUpdated.await();
                // in the order submitted. We need to guard against another term bump
                if (getOperationPrimaryTerm() < newPrimaryTerm) {
                    replicationTracker.setOperationPrimaryTerm(newPrimaryTerm);
                    onBlocked.run();
                }
            } catch (final Exception e) {
                if (combineWithAction == null) {
                    // otherwise leave it to combineWithAction to release the permit
                    releaseOnce.run();
                }
                innerFail(e);
            } finally {
                if (combineWithAction != null) {
                    combineWithAction.onResponse(releasable);
                } else {
                    releaseOnce.run();
                }
            }
        }
    }, 30, TimeUnit.MINUTES);
    pendingPrimaryTerm = newPrimaryTerm;
    termUpdated.countDown();
}
Also used : RunOnce(org.elasticsearch.common.util.concurrent.RunOnce) Releasable(org.elasticsearch.common.lease.Releasable) AlreadyClosedException(org.apache.lucene.store.AlreadyClosedException) CountDownLatch(java.util.concurrent.CountDownLatch) AlreadyClosedException(org.apache.lucene.store.AlreadyClosedException) WriteStateException(org.elasticsearch.gateway.WriteStateException) IndexNotFoundException(org.elasticsearch.index.IndexNotFoundException) ClosedByInterruptException(java.nio.channels.ClosedByInterruptException) ThreadInterruptedException(org.apache.lucene.util.ThreadInterruptedException) RecoveryFailedException(org.elasticsearch.indices.recovery.RecoveryFailedException) EngineException(org.elasticsearch.index.engine.EngineException) IOException(java.io.IOException) ElasticsearchException(org.elasticsearch.ElasticsearchException) TimeoutException(java.util.concurrent.TimeoutException) RefreshFailedEngineException(org.elasticsearch.index.engine.RefreshFailedEngineException)

Example 2 with RunOnce

use of org.elasticsearch.common.util.concurrent.RunOnce 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

CountDownLatch (java.util.concurrent.CountDownLatch)2 RunOnce (org.elasticsearch.common.util.concurrent.RunOnce)2 IOUtils (io.crate.common.io.IOUtils)1 Closeable (java.io.Closeable)1 IOException (java.io.IOException)1 ClosedByInterruptException (java.nio.channels.ClosedByInterruptException)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 TimeoutException (java.util.concurrent.TimeoutException)1 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)1 LogManager (org.apache.logging.log4j.LogManager)1 Logger (org.apache.logging.log4j.Logger)1 AlreadyClosedException (org.apache.lucene.store.AlreadyClosedException)1 ThreadInterruptedException (org.apache.lucene.util.ThreadInterruptedException)1 ElasticsearchException (org.elasticsearch.ElasticsearchException)1 ActionListener (org.elasticsearch.action.ActionListener)1