public HostConnectionPool(Host host, HostDistance hostDistance, Configuration configuration) { this.Host = host; this.Host.Down += OnHostDown; this.HostDistance = hostDistance; this.Configuration = configuration; }
public HostConnectionPool(Host host, HostDistance hostDistance, byte protocolVersion, Configuration configuration) { this.Host = host; this.HostDistance = hostDistance; this.ProtocolVersion = protocolVersion; this.Configuration = configuration; }
public HostConnectionPool(Host host, HostDistance hostDistance, Configuration configuration) { Host = host; Host.Down += OnHostDown; HostDistance = hostDistance; Configuration = configuration; }
private void OnDistanceChanged(HostDistance previousDistance, HostDistance distance) { SetDistance(distance); if (previousDistance == HostDistance.Ignored) { _canCreateForeground = true; // Start immediate reconnection ScheduleReconnection(true); return; } if (distance != HostDistance.Ignored) { return; } // Host is now ignored var isClosing = Interlocked.CompareExchange(ref _state, PoolState.Closing, PoolState.Init) == PoolState.Init; if (!isClosing) { // Is already shutting down or shutdown, don't mind return; } Logger.Info("Host ignored. Closing pool #{0} to {1}", GetHashCode(), _host.Address); DrainConnections(() => { // After draining, set the pool back to init state Interlocked.CompareExchange(ref _state, PoolState.Init, PoolState.Closing); }); CancelNewConnectionTimeout(); }
/// <summary> /// Gets or creates the connection pool for a given host /// </summary> internal HostConnectionPool GetOrCreateConnectionPool(Host host, HostDistance distance) { var hostPool = _connectionPool.GetOrAdd(host.Address, address => new HostConnectionPool(host, distance, Configuration, _serializer)); return(hostPool); }
/// <summary> /// Gets the connection pool for a given host /// </summary> internal HostConnectionPool GetConnectionPool(Host host, HostDistance distance) { var hostPool = _connectionPool.GetOrAdd(host.Address, address => new HostConnectionPool(host, distance, Configuration)); //It can change from the last time, when trying lower protocol versions hostPool.ProtocolVersion = (byte)BinaryProtocolVersion; return(hostPool); }
public void SetDistance(HostDistance distance) { var poolingOptions = _config.GetPoolingOptions(_serializer.ProtocolVersion); _expectedConnectionLength = poolingOptions.GetCoreConnectionsPerHost(distance); _maxInflightThreshold = poolingOptions.GetMaxSimultaneousRequestsPerConnectionTreshold(distance); _maxConnectionLength = poolingOptions.GetMaxConnectionPerHost(distance); }
public HostConnectionPool(Host host, HostDistance distance, Configuration config) { _host = host; _host.Down += OnHostDown; _host.Up += OnHostUp; _distance = distance; _config = config; _timer = config.Timer; }
/// <summary> /// Updates the internal state representing the distance. /// </summary> internal void SetDistance(HostDistance distance) { var previousDistance = (HostDistance)Interlocked.Exchange(ref _distance, (int)distance); if (previousDistance != distance && DistanceChanged != null) { DistanceChanged(previousDistance, distance); } }
/// <summary> /// The core number of connections per host. <p> For the provided /// <c>distance</c>, this correspond to the number of connections initially /// created and kept open to each host of that distance.</p> /// </summary> /// <param name="distance"> the <c>HostDistance</c> for which to return this threshold. /// </param> /// /// <returns>the core number of connections per host at distance /// <c>distance</c>.</returns> public int GetCoreConnectionsPerHost(HostDistance distance) { switch (distance) { case HostDistance.Local: return _coreConnectionsForLocal; case HostDistance.Remote: return _coreConnectionsForRemote; default: return 0; } }
/// <summary> /// Number of simultaneous requests on a connection below which connections in /// excess are reclaimed. <p> If an opened connection to an host at distance /// <c>distance</c> handles less than this number of simultaneous requests /// and there is more than <link>#GetCoreConnectionsPerHost</link> connections /// open to this host, the connection is closed. </p><p> The default value for this /// option is 25 for <c>Local</c> and <c>Remote</c> hosts.</p> /// </summary> /// <param name="distance"> the <c>HostDistance</c> for which to return this threshold.</param> /// <returns>the configured threshold, or the default one if none have been set.</returns> public int GetMinSimultaneousRequestsPerConnectionTreshold(HostDistance distance) { switch (distance) { case HostDistance.Local: return _minSimultaneousRequestsForLocal; case HostDistance.Remote: return _minSimultaneousRequestsForRemote; default: return 0; } }
public HostConnectionPool(Host host, HostDistance distance, Configuration config, Serializer serializer) { _host = host; _host.CheckedAsDown += OnHostCheckedAsDown; _host.Down += OnHostDown; _host.Up += OnHostUp; _host.Remove += OnHostRemoved; _distance = distance; _config = config; _serializer = serializer; _timer = config.Timer; }
/// <summary> /// Gets or creates the connection pool for a given host /// </summary> internal HostConnectionPool GetOrCreateConnectionPool(Host host, HostDistance distance) { var hostPool = _connectionPool.GetOrAdd(host.Address, address => { var newPool = new HostConnectionPool(host, Configuration, _serializer); newPool.AllConnectionClosed += OnAllConnectionClosed; newPool.SetDistance(distance); return(newPool); }); return(hostPool); }
/// <summary> /// The maximum number of connections per host. <p> For the provided /// <c>distance</c>, this correspond to the maximum number of connections /// that can be created per host at that distance.</p> /// </summary> /// <param name="distance"> the <c>HostDistance</c> for which to return this threshold. /// </param> /// /// <returns>the maximum number of connections per host at distance /// <c>distance</c>.</returns> public int GetMaxConnectionPerHost(HostDistance distance) { switch (distance) { case HostDistance.Local: return _maxConnectionsForLocal; case HostDistance.Remote: return _maxConnectionsForRemote; default: return 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) { 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> /// Number of simultaneous requests on all connections to an host after which /// more connections are created. <p> If all the connections opened to an host at /// distance <code>* distance</code> connection are handling more than this /// number of simultaneous requests and there is less than /// <link>#getMaxConnectionPerHost</link> connections open to this host, a new /// connection is open. <p> Note that a given connection cannot handle more than /// 128 simultaneous requests (protocol limitation). <p> The default value for /// this option is 100 for <code>Local</code> and <code>Remote</code> hosts.</p> /// </summary> /// <param name="distance"> the <code>HostDistance</code> for which to return this threshold. /// </param> /// /// <returns>the configured threshold, or the default one if none have been /// set.</returns> public int GetMaxSimultaneousRequestsPerConnectionTreshold(HostDistance distance) { switch (distance) { case HostDistance.Local: return(_maxSimultaneousRequestsForLocal); case HostDistance.Remote: return(_maxSimultaneousRequestsForRemote); default: return(0); } }
/// <summary> /// The core number of connections per host. <p> For the provided /// <code>distance</code>, this correspond to the number of connections initially /// created and kept open to each host of that distance.</p> /// </summary> /// <param name="distance"> the <code>HostDistance</code> for which to return this threshold. /// </param> /// /// <returns>the core number of connections per host at distance /// <code>distance</code>.</returns> public int GetCoreConnectionsPerHost(HostDistance distance) { switch (distance) { case HostDistance.Local: return(_coreConnectionsForLocal); case HostDistance.Remote: return(_coreConnectionsForRemote); default: return(0); } }
/// <summary> /// Sets the number of simultaneous requests on a connection below which /// connections in excess are reclaimed. /// </summary> /// <param name="distance"> the <c>HostDistance</c> for which to configure this /// threshold. </param> /// <param name="minSimultaneousRequests"> the value to set. </param> /// /// <returns>this <c>PoolingOptions</c>. </returns> public PoolingOptions SetMinSimultaneousRequestsPerConnectionTreshold(HostDistance distance, int minSimultaneousRequests) { switch (distance) { case HostDistance.Local: _minSimultaneousRequestsForLocal = minSimultaneousRequests; break; case HostDistance.Remote: _minSimultaneousRequestsForRemote = minSimultaneousRequests; break; default: throw new ArgumentOutOfRangeException("Cannot set min streams per connection threshold for " + distance + " hosts"); } return this; }
/// <summary> /// Sets the maximum number of connections per host. /// </summary> /// <param name="distance"> the <c>HostDistance</c> for which to set this threshold. /// </param> /// <param name="maxConnections"> the value to set </param> /// /// <returns>this <c>PoolingOptions</c>. </returns> public PoolingOptions SetMaxConnectionsPerHost(HostDistance distance, int maxConnections) { switch (distance) { case HostDistance.Local: _maxConnectionsForLocal = maxConnections; break; case HostDistance.Remote: _maxConnectionsForRemote = maxConnections; break; default: throw new ArgumentOutOfRangeException("Cannot set max connections per host for " + distance + " hosts"); } return this; }
/// <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)); } }
/// <summary> /// Builds a <see cref="ValidHost"/> instance. /// </summary> /// <returns>Newly built instance if valid or <code>null</code> if not valid /// (e.g. the host is ignored or the driver sees it as down)</returns> public static ValidHost New(Host host, HostDistance distance) { if (distance == HostDistance.Ignored) { // We should not use an ignored host return(null); } if (!host.IsUp) { // The host is not considered UP by the driver. // We could have filtered earlier by hosts that are considered UP, but we must // check the host distance first. return(null); } return(new ValidHost(host, distance)); }
private Host GetNextHost(IEnumerator <Host> queryPlan, out HostDistance distance) { distance = HostDistance.Ignored; while (queryPlan.MoveNext()) { var host = queryPlan.Current; if (!host.IsUp) { continue; } distance = _cluster.RetrieveAndSetDistance(host); if (distance == HostDistance.Ignored) { continue; } return(host); } return(null); }
/// <summary> /// Gets a connection from a host or null if its not possible, filling the triedHosts map with the failures. /// </summary> internal static async Task <Connection> GetConnectionFromHost(Host host, HostDistance distance, Session session, IDictionary <IPEndPoint, Exception> triedHosts) { Connection 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 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 (Exception ex) { // Probably a SocketException/AuthenticationException, move along 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 GetConnectionFromHost(host, distance, session, triedHosts).ConfigureAwait(false)); } return(c); }
private Host GetNextHost(ILoadBalancingPolicy lbp, out HostDistance distance) { distance = HostDistance.Ignored; while (_queryPlan.MoveNext()) { var host = _queryPlan.Current; if (!host.IsUp) { continue; } distance = Cluster.RetrieveDistance(host, lbp); if (distance == HostDistance.Ignored) { continue; } return(host); } return(null); }
public void SetDistance(HostDistance distance) { _expectedConnectionLength = _poolingOptions.GetCoreConnectionsPerHost(distance); _maxInflightThresholdToConsiderResizing = _poolingOptions.GetMaxSimultaneousRequestsPerConnectionTreshold(distance); _maxConnectionLength = _poolingOptions.GetMaxConnectionPerHost(distance); }
CassandraConnection AllocateConnection(IPAddress endPoint, HostDistance hostDistance, out Exception outExc) { CassandraConnection nconn = null; outExc = null; try { int no = 1; if (!_allocatedConnections.TryAdd(endPoint, new AtomicValue <int>(1))) { AtomicValue <int> val; _allocatedConnections.TryGetValue(endPoint, out val); no = Interlocked.Increment(ref val.RawValue); if (no > _poolingOptions.GetMaxConnectionPerHost(hostDistance)) { Interlocked.Decrement(ref val.RawValue); outExc = new ToManyConnectionsPerHost(); return(null); } } RETRY: nconn = new CassandraConnection(this, endPoint, _protocolOptions, _socketOptions, _clientOptions, _authProvider, _authInfoProvider, _binaryProtocolVersion); var streamId = nconn.AllocateStreamId(); try { var options = ProcessExecuteOptions(nconn.ExecuteOptions(streamId)); } catch (CassandraConnectionBadProtocolVersionException) { if (_binaryProtocolVersion == 1) { throw; } else { _binaryProtocolVersion = 1; goto RETRY; } } if (!string.IsNullOrEmpty(_keyspace)) { nconn.SetKeyspace(_keyspace); } } catch (Exception ex) { if (nconn != null) { nconn.Dispose(); nconn = null; } AtomicValue <int> val; _allocatedConnections.TryGetValue(endPoint, out val); Interlocked.Decrement(ref val.RawValue); if (CassandraConnection.IsStreamRelatedException(ex)) { HostIsDown(endPoint); outExc = ex; return(null); } else { throw ex; } } _logger.Info("Allocated new connection"); return(nconn); }
private ValidHost(Host host, HostDistance distance) { Host = host; Distance = distance; }
/// <summary> /// Gets the connection pool for a given host /// </summary> internal HostConnectionPool GetConnectionPool(Host host, HostDistance distance) { return _connectionPool.GetOrAdd(host.Address, new HostConnectionPool(host, distance, (byte)BinaryProtocolVersion, Configuration)); }
/// <summary> /// Gets or creates the connection pool for a given host /// </summary> internal HostConnectionPool GetOrCreateConnectionPool(Host host, HostDistance distance) { var hostPool = _connectionPool.GetOrAdd(host.Address, address => new HostConnectionPool(host, distance, Configuration, _serializer)); return hostPool; }
/// <summary> /// Gets the connection pool for a given host /// </summary> internal HostConnectionPool GetConnectionPool(Host host, HostDistance distance) { var hostPool = _connectionPool.GetOrAdd(host.Address, address => new HostConnectionPool(host, distance, Configuration)); //It can change from the last time, when trying lower protocol versions hostPool.ProtocolVersion = (byte) BinaryProtocolVersion; return hostPool; }
public TestLoadBalancingPolicy(HostDistance distance = HostDistance.Local) { _distance = distance; }
/// <summary> /// Sets number of simultaneous requests on all connections to an host after /// which more connections are created. /// </summary> /// <param name="distance">The <see cref="HostDistance"/> for which to configure this /// threshold. </param> /// <param name="maxSimultaneousRequests"> the value to set. </param> /// <returns>this <c>PoolingOptions</c>. </returns> /// <throws name="IllegalArgumentException"> if <c>distance == HostDistance.Ignore</c>.</throws> public PoolingOptions SetMaxSimultaneousRequestsPerConnectionTreshold(HostDistance distance, int maxSimultaneousRequests) { switch (distance) { case HostDistance.Local: _maxSimultaneousRequestsForLocal = maxSimultaneousRequests; break; case HostDistance.Remote: _maxSimultaneousRequestsForRemote = maxSimultaneousRequests; break; default: throw new ArgumentOutOfRangeException("Cannot set max streams per connection threshold for " + distance + " hosts"); } return this; }
CassandraConnection AllocateConnection(IPAddress endPoint, HostDistance hostDistance, out Exception outExc) { CassandraConnection nconn = null; outExc = null; try { int no = 1; if (!_allocatedConnections.TryAdd(endPoint, new AtomicValue<int>(1))) { AtomicValue<int> val; _allocatedConnections.TryGetValue(endPoint, out val); no = Interlocked.Increment(ref val.RawValue); if (no > _poolingOptions.GetMaxConnectionPerHost(hostDistance)) { Interlocked.Decrement(ref val.RawValue); outExc = new ToManyConnectionsPerHost(); return null; } } nconn = new CassandraConnection(this, endPoint, _protocolOptions, _socketOptions, _clientOptions, _authProvider); var streamId = nconn.AllocateStreamId(); var options = ProcessExecuteOptions(nconn.ExecuteOptions(streamId)); if (!string.IsNullOrEmpty(_keyspace)) nconn.SetKeyspace(_keyspace); } catch (Exception ex) { if (nconn != null) { nconn.Dispose(); nconn = null; } AtomicValue<int> val; _allocatedConnections.TryGetValue(endPoint, out val); Interlocked.Decrement(ref val.RawValue); if (CassandraConnection.IsStreamRelatedException(ex)) { HostIsDown(endPoint); outExc = ex; return null; } else throw ex; } _logger.Info("Allocated new connection"); return nconn; }