internal CassandraConnection Connect(Query query, IEnumerator <Host> hostsIter, List <IPAddress> triedHosts, Dictionary <IPAddress, List <Exception> > innerExceptions, out int streamId) { CheckDisposed(); lock (_connectionPool) { List <CassandraConnection> toDel = null; foreach (var conn in _trashcan) { if (conn.IsEmpty()) { _logger.Info("Connection trashed"); conn.Dispose(); if (toDel == null) { toDel = new List <CassandraConnection>(); } toDel.Add(conn); } } if (toDel != null) { foreach (var d in toDel) { _trashcan.Remove(d); } } while (true) { var currentHost = hostsIter.Current; if (currentHost == null) { var ex = new NoHostAvailableException(innerExceptions); _logger.Error("All hosts are not responding.", ex); throw ex; } if (currentHost.IsConsiderablyUp) { triedHosts.Add(currentHost.Address); var hostDistance = _policies.LoadBalancingPolicy.Distance(currentHost); if (!_connectionPool.ContainsKey(currentHost.Address)) { _connectionPool.Add(currentHost.Address, new List <CassandraConnection>()); } var pool = _connectionPool[currentHost.Address]; var poolCpy = new List <CassandraConnection>(pool); CassandraCounters.SetConnectionsCount(currentHost.Address, poolCpy.Count); CassandraConnection toReturn = null; foreach (var conn in poolCpy) { if (!conn.IsHealthy) { pool.Remove(conn); conn.Dispose(); } else { if (toReturn == null) { if (!conn.IsBusy(_poolingOptions.GetMaxSimultaneousRequestsPerConnectionTreshold(hostDistance))) { toReturn = conn; } } else { if (pool.Count > _poolingOptions.GetCoreConnectionsPerHost(hostDistance)) { if (conn.IsFree(_poolingOptions.GetMinSimultaneousRequestsPerConnectionTreshold(hostDistance))) { _trashcan.Add(conn); pool.Remove(conn); } } } } } if (toReturn != null) { streamId = toReturn.AllocateStreamId(); return(toReturn); } if (pool.Count < _poolingOptions.GetMaxConnectionPerHost(hostDistance) - 1) { bool error = false; CassandraConnection conn = null; do { Exception outExc; conn = AllocateConnection(currentHost.Address, out outExc); if (conn != null) { if (_cluster.Metadata != null) { _cluster.Metadata.BringUpHost(currentHost.Address, this); } pool.Add(conn); } else { if (!innerExceptions.ContainsKey(currentHost.Address)) { innerExceptions.Add(currentHost.Address, new List <Exception>()); } innerExceptions[currentHost.Address].Add(outExc); _logger.Info("New connection attempt failed - goto another host."); error = true; break; } }while (pool.Count < _poolingOptions.GetCoreConnectionsPerHost(hostDistance)); if (!error) { streamId = conn.AllocateStreamId(); return(conn); } } } _logger.Verbose(string.Format("Currently tried host: {0} have all of connections busy. Switching to the next host.", currentHost.Address)); if (!hostsIter.MoveNext()) { var ex = new NoHostAvailableException(innerExceptions); _logger.Error("Cannot connect to any host from pool.", ex); throw ex; } } } }
internal CassandraConnection Connect(IEnumerator <Host> hostsIter, List <IPAddress> triedHosts, Dictionary <IPAddress, List <Exception> > innerExceptions, out int streamId) { CheckDisposed(); while (true) { var currentHost = hostsIter.Current; if (currentHost == null) { var ex = new NoHostAvailableException(innerExceptions); _logger.Error("All hosts are not responding.", ex); throw ex; } if (currentHost.IsConsiderablyUp) { triedHosts.Add(currentHost.Address); var hostDistance = Policies.LoadBalancingPolicy.Distance(currentHost); RETRY_GET_POOL: if (!_connectionPool.ContainsKey(currentHost.Address)) { _connectionPool.TryAdd(currentHost.Address, new ConcurrentDictionary <Guid, CassandraConnection>()); } ConcurrentDictionary <Guid, CassandraConnection> pool; if (!_connectionPool.TryGetValue(currentHost.Address, out pool)) { goto RETRY_GET_POOL; } // CassandraCounters.SetConnectionsCount(currentHost.Address, pool.Count); foreach (var kv in pool) { CassandraConnection conn = kv.Value; if (!conn.IsHealthy) { CassandraConnection cc; if (pool.TryRemove(conn.Guid, out cc)) { FreeConnection(cc); } } else { if (!conn.IsBusy(_poolingOptions.GetMaxSimultaneousRequestsPerConnectionTreshold(hostDistance))) { streamId = conn.AllocateStreamId(); return(conn); } else { if (pool.Count > _poolingOptions.GetCoreConnectionsPerHost(hostDistance)) { if (conn.IsFree(_poolingOptions.GetMinSimultaneousRequestsPerConnectionTreshold(hostDistance))) { CassandraConnection cc; if (pool.TryRemove(conn.Guid, out cc)) { TrashcanPut(cc); } } } } } } { var conn = TrashcanRecycle(currentHost.Address); if (conn != null) { if (!conn.IsHealthy) { FreeConnection(conn); } else { pool.TryAdd(conn.Guid, conn); streamId = conn.AllocateStreamId(); return(conn); } } // if not recycled { Exception outExc; conn = AllocateConnection(currentHost.Address, hostDistance, out outExc); if (conn != null) { if (_cluster.Metadata != null) { _cluster.Metadata.BringUpHost(currentHost.Address, this); } pool.TryAdd(conn.Guid, conn); streamId = conn.AllocateStreamId(); return(conn); } else { if (!innerExceptions.ContainsKey(currentHost.Address)) { innerExceptions.Add(currentHost.Address, new List <Exception>()); } innerExceptions[currentHost.Address].Add(outExc); _logger.Info("New connection attempt failed - goto another host."); } } } } _logger.Verbose(string.Format("Currently tried host: {0} have all of connections busy. Switching to the next host.", currentHost.Address)); if (!hostsIter.MoveNext()) { var ex = new NoHostAvailableException(innerExceptions); _logger.Error("Cannot connect to any host from pool.", ex); throw ex; } } }