Esempio n. 1
0
        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;
                    }
                }
            }
        }
Esempio n. 2
0
        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;
                }
            }
        }