Exemplo n.º 1
0
        /// <summary>
        /// Gets a connection from the next host according to the load balancing policy
        /// </summary>
        /// <exception cref="NoHostAvailableException"/>
        /// <exception cref="InvalidQueryException">When keyspace does not exist</exception>
        /// <exception cref="UnsupportedProtocolVersionException"/>
        internal Connection GetNextConnection(IStatement statement, bool isLastChance = false)
        {
            var  hostEnumerable = _session.Policies.LoadBalancingPolicy.NewQueryPlan(statement);
            Host lastChanceHost = null;

            //hostEnumerable GetEnumerator will return a NEW enumerator, making this call thread safe
            foreach (var host in hostEnumerable)
            {
                if (!host.IsConsiderablyUp)
                {
                    if (!isLastChance && host.Resurrect)
                    {
                        lastChanceHost = host;
                    }
                    continue;
                }
                _currentHost = host;
                _triedHosts[host.Address] = null;
                Connection connection = null;
                try
                {
                    var distance = _session.Policies.LoadBalancingPolicy.Distance(host);
                    var hostPool = _session.GetConnectionPool(host, distance);
                    connection = hostPool.BorrowConnection();
                    if (connection == null)
                    {
                        continue;
                    }
                    connection.Keyspace = _session.Keyspace;
                    return(connection);
                }
                catch (SocketException ex)
                {
                    _session.SetHostDown(host, connection);
                    _triedHosts[host.Address] = ex;
                    host.Resurrect            = CanBeResurrected(ex, connection);
                    if (!isLastChance && host.Resurrect)
                    {
                        lastChanceHost = host;
                    }
                }
                catch (InvalidQueryException)
                {
                    //The keyspace does not exist
                    throw;
                }
                catch (UnsupportedProtocolVersionException)
                {
                    //The version of the protocol is not supported
                    throw;
                }
                catch (Exception ex)
                {
                    _logger.Error(ex);
                    _triedHosts[host.Address] = ex;
                }
            }
            _currentHost = null;
            if (lastChanceHost != null)
            {
                //There are no host available and some of them are due to network events.
                //Probably there was a network event that reset all connections and it does not mean the connection
                _logger.Warning("Suspected network reset. Getting one host up and retrying for a last chance");
                lastChanceHost.BringUpIfDown();
                return(GetNextConnection(statement, true));
            }
            throw new NoHostAvailableException(_triedHosts);
        }