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); }
/// <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)); } }
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)); }