private async Task PrepareOnTheRestOfTheNodes(PrepareRequest request, IInternalSession session)
        {
            Host         host;
            HostDistance distance;
            var          lbp        = session.Cluster.Configuration.Policies.LoadBalancingPolicy;
            var          tasks      = new List <Task>();
            var          triedHosts = new Dictionary <IPEndPoint, Exception>();

            while ((host = GetNextHost(lbp, out distance)) != null)
            {
                var connection = await RequestHandler
                                 .GetConnectionFromHostAsync(host, distance, session, triedHosts).ConfigureAwait(false);

                if (connection == null)
                {
                    continue;
                }
                // For each valid connection, send a the request in parallel
                tasks.Add(connection.Send(request));
            }
            try
            {
                await Task.WhenAll(tasks).ConfigureAwait(false);
            }
            catch
            {
                // Don't consider individual failures
            }
        }
        /// <summary>
        /// Gets a connection from a host or null if its not possible, filling the triedHosts map with the failures.
        /// </summary>
        /// <param name="host">Host to which a connection will be obtained.</param>
        /// <param name="distance">Output parameter that will contain the <see cref="HostDistance"/> associated with
        /// <paramref name="host"/>. It is retrieved from the current <see cref="ILoadBalancingPolicy"/>.</param>
        /// <param name="session">Session from where a connection will be obtained (or created).</param>
        /// <param name="triedHosts">Hosts for which there were attempts to connect and send the request.</param>
        /// <exception cref="InvalidQueryException">When the keyspace is not valid</exception>
        internal static async Task <IConnection> GetConnectionFromHostAsync(
            Host host, HostDistance distance, IInternalSession session, IDictionary <IPEndPoint, Exception> triedHosts)
        {
            IConnection c        = null;
            var         hostPool = session.GetOrCreateConnectionPool(host, distance);

            try
            {
                c = await hostPool.BorrowConnection().ConfigureAwait(false);
            }
            catch (UnsupportedProtocolVersionException ex)
            {
                // The version of the protocol is not supported on this host
                // Most likely, we are using a higher protocol version than the host supports
                RequestHandler.Logger.Error("Host {0} does not support protocol version {1}. You should use a fixed protocol " +
                                            "version during rolling upgrades of the cluster. Setting the host as DOWN to " +
                                            "avoid hitting this node as part of the query plan for a while", host.Address, ex.ProtocolVersion);
                triedHosts[host.Address] = ex;
                session.MarkAsDownAndScheduleReconnection(host, hostPool);
            }
            catch (BusyPoolException ex)
            {
                RequestHandler.Logger.Warning(
                    "All connections to host {0} are busy ({1} requests are in-flight on {2} connection(s))," +
                    " consider lowering the pressure or make more nodes available to the client", host.Address,
                    ex.MaxRequestsPerConnection, ex.ConnectionLength);
                triedHosts[host.Address] = ex;
            }
            catch (Exception ex)
            {
                // Probably a SocketException/AuthenticationException, move along
                RequestHandler.Logger.Error("Exception while trying borrow a connection from a pool", ex);
                triedHosts[host.Address] = ex;
            }

            if (c == null)
            {
                return(null);
            }
            try
            {
                await c.SetKeyspace(session.Keyspace).ConfigureAwait(false);
            }
            catch (SocketException)
            {
                hostPool.Remove(c);
                // A socket exception on the current connection does not mean that all the pool is closed:
                // Retry on the same host
                return(await RequestHandler.GetConnectionFromHostAsync(host, distance, session, triedHosts).ConfigureAwait(false));
            }
            return(c);
        }
Beispiel #3
0
        /// <summary>
        /// Gets a connection from a host or null if its not possible, filling the triedHosts map with the failures.
        /// </summary>
        /// <param name="host">Host to which a connection will be obtained.</param>
        /// <param name="distance">Output parameter that will contain the <see cref="HostDistance"/> associated with
        /// <paramref name="host"/>. It is retrieved from the current <see cref="ILoadBalancingPolicy"/>.</param>
        /// <param name="session">Session from where a connection will be obtained (or created).</param>
        /// <param name="triedHosts">Hosts for which there were attempts to connect and send the request.</param>
        /// <exception cref="InvalidQueryException">When the keyspace is not valid</exception>
        internal static async Task <IConnection> GetConnectionFromHostAsync(
            Host host, HostDistance distance, IInternalSession session, IDictionary <IPEndPoint, Exception> triedHosts)
        {
            var hostPool = session.GetOrCreateConnectionPool(host, distance);

            try
            {
                return(await hostPool.GetConnectionFromHostAsync(triedHosts, () => session.Keyspace).ConfigureAwait(false));
            }
            catch (SocketException)
            {
                // A socket exception on the current connection does not mean that all the pool is closed:
                // Retry on the same host
                return(await RequestHandler.GetConnectionFromHostAsync(host, distance, session, triedHosts).ConfigureAwait(false));
            }
        }
Beispiel #4
0
        private async Task <Tuple <Host, IConnection> > GetNextConnection(
            IInternalSession session, IEnumerator <Host> queryPlan, Dictionary <IPEndPoint, Exception> triedHosts)
        {
            Host host;

            while ((host = GetNextHost(queryPlan, out HostDistance distance)) != null)
            {
                var connection = await RequestHandler.GetConnectionFromHostAsync(host, distance, session, triedHosts).ConfigureAwait(false);

                if (connection != null)
                {
                    return(Tuple.Create(host, connection));
                }
            }
            throw new NoHostAvailableException(triedHosts);
        }
        private async Task <IConnection> GetNextConnection(IInternalSession session, IEnumerator <Host> queryPlan, Dictionary <IPEndPoint, Exception> triedHosts)
        {
            Host         host;
            HostDistance distance;
            var          lbp = session.Cluster.Configuration.DefaultRequestOptions.LoadBalancingPolicy;

            while ((host = GetNextHost(lbp, queryPlan, out distance)) != null)
            {
                var connection = await RequestHandler.GetConnectionFromHostAsync(host, distance, session, triedHosts).ConfigureAwait(false);

                if (connection != null)
                {
                    return(connection);
                }
            }
            throw new NoHostAvailableException(triedHosts);
        }
 /// <inheritdoc />
 public Task <IConnection> GetConnectionToValidHostAsync(ValidHost validHost, IDictionary <IPEndPoint, Exception> triedHosts)
 {
     return(RequestHandler.GetConnectionFromHostAsync(validHost.Host, validHost.Distance, _session, triedHosts));
 }