Exemple #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;
                    }
                }
            }
        }
Exemple #2
0
        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);
        }