void ExecConn(RequestHandler handler, bool moveNext) { while (true) { try { int streamId; handler.Connect(this, moveNext, out streamId); handler.Begin(this, streamId); return; } catch (Exception ex) { if (!CassandraConnection.IsStreamRelatedException(ex)) { handler.Complete(this, null, ex); return; } else if (_alreadyDisposed.IsTaken()) { return; } } } }
internal bool RefreshHosts() { lock (this) { try { if (!_isDiconnected) { RefreshNodeListAndTokenMap(); return(true); } return(false); } catch (NoHostAvailableException) { _logger.Error("ControlConnection is lost now."); return(false); } catch (Exception ex) { if (CassandraConnection.IsStreamRelatedException(ex)) { _logger.Error("ControlConnection is lost now."); return(false); } else { _logger.Error("Unexpected error occurred during forced ControlConnection refresh.", ex); throw; } } } }
virtual public void Connect(Session owner, bool moveNext, out int streamId) { if (_hostsIter == null) { _hostsIter = owner._policies.LoadBalancingPolicy.NewQueryPlan(Query).GetEnumerator(); if (!_hostsIter.MoveNext()) { var ex = new NoHostAvailableException(new Dictionary <IPAddress, List <Exception> >()); _logger.Error(ex); throw ex; } } else { if (moveNext) { if (!_hostsIter.MoveNext()) { var ex = new NoHostAvailableException(InnerExceptions); _logger.Error(ex); throw ex; } } } Connection = owner.Connect(Query, _hostsIter, TriedHosts, InnerExceptions, out streamId); }
void FreeConnection(CassandraConnection connection) { connection.Dispose(); AtomicValue <int> val; _allocatedConnections.TryGetValue(connection.GetHostAdress(), out val); var no = Interlocked.Decrement(ref val.RawValue); }
void ClbNoQuery(IAsyncResult ar) { var token = ar.AsyncState as LongToken; try { try { object value; token.Process(this, ar, out value); token.Complete(this, value); } catch (QueryValidationException exc) { var decision = GetRetryDecision(token.Query, exc, _policies.RetryPolicy, token.QueryRetries); if (decision == null) { token.InnerExceptions[token.Connection.GetHostAdress()] = exc; ExecConn(token, true); } else { switch (decision.DecisionType) { case RetryDecision.RetryDecisionType.Rethrow: token.Complete(this, null, exc); return; case RetryDecision.RetryDecisionType.Retry: token.Consistency = decision.RetryConsistencyLevel ?? token.Consistency; token.QueryRetries++; token.InnerExceptions[token.Connection.GetHostAdress()] = exc; ExecConn(token, false); return; default: token.Complete(this, null); return; } } } } catch (Exception ex) { if (CassandraConnection.IsStreamRelatedException(ex)) { token.InnerExceptions[token.Connection.GetHostAdress()] = ex; ExecConn(token, true); } else { token.Complete(this, null, ex); } } }
private void SetupControlConnection(bool refreshOnly = false) { lock (this) { try { _reconnectionTimer.Change(Timeout.Infinite, Timeout.Infinite); _logger.Info("Refreshing ControlConnection..."); if (!refreshOnly) { Monitor.Exit(this); try { SetupEventListener(); } finally { Monitor.Enter(this); } } RefreshNodeListAndTokenMap(); _isDiconnected = false; _logger.Info("ControlConnection is fresh!"); } catch (NoHostAvailableException) { _isDiconnected = true; if (!shotDown.IsTaken()) { _logger.Error("ControlConnection is lost. Retrying.."); _reconnectionTimer.Change(_reconnectionSchedule.NextDelayMs(), Timeout.Infinite); } } catch (Exception ex) { _isDiconnected = true; if (CassandraConnection.IsStreamRelatedException(ex)) { if (!shotDown.IsTaken()) { _logger.Error("ControlConnection is lost. Retrying.."); _reconnectionTimer.Change(_reconnectionSchedule.NextDelayMs(), Timeout.Infinite); } } else { _logger.Error("Unexpected error occurred during ControlConnection refresh.", ex); // throw; } } } }
CassandraConnection AllocateConnection(IPAddress endPoint, out Exception outExc) { CassandraConnection nconn = null; outExc = null; try { 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(); } if (CassandraConnection.IsStreamRelatedException(ex)) { HostIsDown(endPoint); outExc = ex; return(null); } else { throw ex; } } _logger.Info("Allocated new connection"); return(nconn); }
void TrashcanPut(CassandraConnection conn) { RETRY: if (!_trashcan.ContainsKey(conn.GetHostAdress())) { _trashcan.TryAdd(conn.GetHostAdress(), new ConcurrentDictionary <Guid, CassandraConnection>()); } ConcurrentDictionary <Guid, CassandraConnection> trashes; if (_trashcan.TryGetValue(conn.GetHostAdress(), out trashes)) { trashes.TryAdd(conn.Guid, conn); } else { goto RETRY; } _trashcanCleaner.Change(10000, Timeout.Infinite); }
void ExecConn(LongToken token, bool moveNext) { while (true) { try { token.Connect(this, moveNext); token.Begin(this); return; } catch (Exception ex) { if (!CassandraConnection.IsStreamRelatedException(ex)) { token.Complete(this, null, ex); return; } //else //retry } } }
public virtual void Connect(Session owner, bool moveNext, out int streamId) { if (_hostsIter == null) { _hostsIter = owner._policies.LoadBalancingPolicy.NewQueryPlan(Query).GetEnumerator(); if (!_hostsIter.MoveNext()) { var ex = new NoHostAvailableException(new Dictionary<IPAddress, List<Exception>>()); _logger.Error(ex); throw ex; } } else { if (moveNext) if (!_hostsIter.MoveNext()) { var ex = new NoHostAvailableException(InnerExceptions); _logger.Error(ex); throw ex; } } Connection = owner.Connect(_hostsIter, TriedHosts, InnerExceptions, out streamId); }
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 void SetupEventListeners(CassandraConnection nconn) { Exception theExc = null; nconn.CassandraEvent += new CassandraEventHandler(conn_CassandraEvent); using (var ret = nconn.RegisterForCassandraEvent( CassandraEventType.TopologyChange | CassandraEventType.StatusChange | CassandraEventType.SchemaChange)) { if (!(ret is OutputVoid)) { if (ret is OutputError) theExc = (ret as OutputError).CreateException(); else theExc = new DriverInternalError("Expected Error on Output"); } } if (theExc != null) { _logger.Error(theExc); throw theExc; } }
private void RefreshNodeListAndTokenMap(CassandraConnection connection) { _logger.Info("Refreshing NodeList and TokenMap.."); // Make sure we're up to date on nodes and tokens var tokenMap = new Dictionary<IPAddress, DictSet<string>>(); string partitioner = null; using (var rowset = _session.Query(SelectLocal, ConsistencyLevel.Default)) { // Update cluster name, DC and rack for the one node we are connected to foreach (var localRow in rowset.GetRows()) { var clusterName = localRow.GetValue<string>("cluster_name"); if (clusterName != null) _cluster.Metadata.ClusterName = clusterName; var host = _cluster.Metadata.GetHost(connection.GetHostAdress()); // In theory host can't be null. However there is no point in risking a NPE in case we // have a race between a node removal and this. if (host != null) { host.SetLocationInfo(localRow.GetValue<string>("data_center"), localRow.GetValue<string>("rack")); partitioner = localRow.GetValue<string>("partitioner"); var tokens = localRow.GetValue<IList<string>>("tokens"); if (partitioner != null && tokens.Count > 0) { if (!tokenMap.ContainsKey(host.Address)) tokenMap.Add(host.Address, new DictSet<string>()); tokenMap[host.Address].AddRange(tokens); } } break; } } var foundHosts = new List<IPAddress>(); var dcs = new List<string>(); var racks = new List<string>(); var allTokens = new List<DictSet<string>>(); using (var rowset = _session.Query(SelectPeers, ConsistencyLevel.Default)) { foreach (var row in rowset.GetRows()) { var hstip = row.GetValue<IPEndPoint>("peer").Address; if (hstip != null) { foundHosts.Add(hstip); dcs.Add(row.GetValue<string>("data_center")); racks.Add(row.GetValue<string>("rack")); allTokens.Add(new DictSet<string>(row.GetValue<IEnumerable<string>>("tokens"))); } } } for (int i = 0; i < foundHosts.Count; i++) { var host = _cluster.Metadata.GetHost(foundHosts[i]); if (host == null) { // We don't know that node, add it. host = _cluster.Metadata.AddHost(foundHosts[i], _session._policies.ReconnectionPolicy); } host.SetLocationInfo(dcs[i], racks[i]); if (partitioner != null && !allTokens[i].IsEmpty) tokenMap.Add(host.Address, allTokens[i]); } // Removes all those that seems to have been removed (since we lost the control connection) var foundHostsSet = new DictSet<IPAddress>(foundHosts); foreach (var host in _cluster.Metadata.AllReplicas()) if (!host.Equals(connection.GetHostAdress()) && !foundHostsSet.Contains(host)) _cluster.Metadata.RemoveHost(host); if (partitioner != null) _cluster.Metadata.RebuildTokenMap(partitioner, tokenMap); _logger.Info("NodeList and TokenMap have been successfully refreshed!"); }
private void Go(bool refresh) { lock (this) { try { if (_hostsIter == null) { _logger.Info("Retrieving hosts list."); _hostsIter = _session._policies.LoadBalancingPolicy.NewQueryPlan(null).GetEnumerator(); } if (!_hostsIter.MoveNext()) { _isDiconnected = true; _hostsIter = null; _reconnectionTimer.Change(_reconnectionSchedule.NextDelayMs(), Timeout.Infinite); } else { _logger.Info("Establishing ControlConnection..."); _reconnectionTimer.Change(Timeout.Infinite, Timeout.Infinite); var triedHosts = new List<IPAddress>(); var innerExceptions = new Dictionary<IPAddress, Exception>(); _connection = _session.Connect(null, _hostsIter, triedHosts, innerExceptions); SetupEventListeners(_connection); if (refresh) RefreshNodeListAndTokenMap(_connection); _logger.Info("ControlConnection has been established!"); } } catch (NoHostAvailableException) { _logger.Error("Cannot connect to any host. Retrying.."); _isDiconnected = true; _hostsIter = null; _reconnectionTimer.Change(_reconnectionSchedule.NextDelayMs(), Timeout.Infinite); } catch (Exception ex) { if (CassandraConnection.IsStreamRelatedException(ex)) { _isDiconnected = true; _hostsIter = null; _reconnectionTimer.Change(_reconnectionSchedule.NextDelayMs(), Timeout.Infinite); } else { _logger.Error("Unexpected error occurred during ControlConnection establishment.", ex); throw; } } } }
internal void RequestCallback(IAsyncResult ar) { var handler = ar.AsyncState as RequestHandler; try { try { object value; handler.Process(this, ar, out value); handler.Complete(this, value); } catch (QueryValidationException exc) { var decision = GetRetryDecision(handler.Statement, exc, handler.Statement != null ? (handler.Statement.RetryPolicy ?? Policies.RetryPolicy) : Policies.RetryPolicy, handler.QueryRetries); if (decision == null) { if (!handler.InnerExceptions.ContainsKey(handler.Connection.GetHostAdress())) { handler.InnerExceptions.Add(handler.Connection.GetHostAdress(), new List <Exception>()); } handler.InnerExceptions[handler.Connection.GetHostAdress()].Add(exc); ExecConn(handler, true); } else { switch (decision.DecisionType) { case RetryDecision.RetryDecisionType.Rethrow: handler.Complete(this, null, exc); return; case RetryDecision.RetryDecisionType.Retry: if (handler.LongActionAc.IsCompleted) { return; } handler.Consistency = (decision.RetryConsistencyLevel.HasValue && (decision.RetryConsistencyLevel.Value < ConsistencyLevel.Serial)) ? decision.RetryConsistencyLevel.Value : handler.Consistency; handler.QueryRetries++; if (!handler.InnerExceptions.ContainsKey(handler.Connection.GetHostAdress())) { handler.InnerExceptions.Add(handler.Connection.GetHostAdress(), new List <Exception>()); } handler.InnerExceptions[handler.Connection.GetHostAdress()].Add(exc); ExecConn(handler, exc is UnavailableException); return; default: handler.Complete(this, null); return; } } } } catch (Exception ex) { if (CassandraConnection.IsStreamRelatedException(ex)) { if (!handler.InnerExceptions.ContainsKey(handler.Connection.GetHostAdress())) { handler.InnerExceptions.Add(handler.Connection.GetHostAdress(), new List <Exception>()); } handler.InnerExceptions[handler.Connection.GetHostAdress()].Add(ex); ExecConn(handler, true); } else { handler.Complete(this, null, ex); } } }
public void Connect(string username, string password, string apiKey) { if (Config.Settings.ContainsKey("PUBLISHING_START_TIME")) _startTime = Config.ParseDateTimeLocal(Config.Settings["PUBLISHING_START_TIME"]); if (Config.Settings.ContainsKey("PUBLISHING_STOP_TIME")) _stopTime = Config.ParseDateTimeLocal(Config.Settings["PUBLISHING_STOP_TIME"]); if (Config.Settings.ContainsKey("SAMPLING_MS")) _samplingMs = int.Parse(Config.Settings["SAMPLING_MS"]); _testReplayFiles.Clear(); if (Config.Settings.ContainsKey("DELETEDB")) { _deleteDB = true; _testReplayFiles.Add(null); // Add a fake element to trigger the replay from db _deleter = new CassandraConnection(); _reader = _deleter; _readerExpectedResults = _deleter; _hasExpectedResults = true; } else { if (Config.Settings["REPLAY_MODE"] == "DB") { _testReplayFiles.Add(null); // Add a fake element to trigger the replay from db _reader = new CassandraConnection(); } else if (Config.Settings["REPLAY_MODE"] == "CSV") { if (Config.Settings.ContainsKey("REPLAY_CSV")) { _testReplayFiles = Config.Settings["REPLAY_CSV"].Split(';').ToList(); if (_reader != null) _reader.CloseConnection(); _reader = new CsvReader(_testReplayFiles[0]); } else _reader = new CsvReader(null); } else _reader = null; _hasExpectedResults = Config.TestReplayEnabled || Config.CalibratorEnabled; if (_hasExpectedResults) { if (Config.Settings.ContainsKey("EXPECTEDRESULTS_CSV")) _readerExpectedResults = new CsvReader(Config.Settings["EXPECTEDRESULTS_CSV"]); else _readerExpectedResults = new CsvReader(_testReplayFiles[0]); } } _numId = 1; _numRef = 1; }
void TrashcanPut(CassandraConnection conn) { RETRY: if (!_trashcan.ContainsKey(conn.GetHostAdress())) _trashcan.TryAdd(conn.GetHostAdress(), new ConcurrentDictionary<Guid, CassandraConnection>()); ConcurrentDictionary<Guid, CassandraConnection> trashes; if (_trashcan.TryGetValue(conn.GetHostAdress(), out trashes)) trashes.TryAdd(conn.Guid,conn); else goto RETRY; _trashcanCleaner.Change(10000, Timeout.Infinite); }
void FreeConnection(CassandraConnection connection) { connection.Dispose(); AtomicValue<int> val; _allocatedConnections.TryGetValue(connection.GetHostAdress(), out val); var no = Interlocked.Decrement(ref val.RawValue); }
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; } } }
void ClbNoQuery(IAsyncResult ar) { var token = ar.AsyncState as LongToken; try { try { object value; token.Process(this, ar, out value); token.Complete(this, value); } catch (QueryValidationException exc) { var decision = GetRetryDecision(token.Query, exc, token.Query != null ? (token.Query.RetryPolicy ?? _policies.RetryPolicy) : _policies.RetryPolicy, token.QueryRetries); if (decision == null) { if (!token.InnerExceptions.ContainsKey(token.Connection.GetHostAdress())) { token.InnerExceptions.Add(token.Connection.GetHostAdress(), new List <Exception>()); } token.InnerExceptions[token.Connection.GetHostAdress()].Add(exc); ExecConn(token, true); } else { switch (decision.DecisionType) { case RetryDecision.RetryDecisionType.Rethrow: token.Complete(this, null, exc); return; case RetryDecision.RetryDecisionType.Retry: if (token.LongActionAc.IsCompleted) { return; } token.Consistency = decision.RetryConsistencyLevel.HasValue ? decision.RetryConsistencyLevel.Value : token.Consistency; token.QueryRetries++; if (!token.InnerExceptions.ContainsKey(token.Connection.GetHostAdress())) { token.InnerExceptions.Add(token.Connection.GetHostAdress(), new List <Exception>()); } token.InnerExceptions[token.Connection.GetHostAdress()].Add(exc); ExecConn(token, false); return; default: token.Complete(this, null); return; } } } } catch (Exception ex) { if (CassandraConnection.IsStreamRelatedException(ex)) { if (!token.InnerExceptions.ContainsKey(token.Connection.GetHostAdress())) { token.InnerExceptions.Add(token.Connection.GetHostAdress(), new List <Exception>()); } token.InnerExceptions[token.Connection.GetHostAdress()].Add(ex); ExecConn(token, true); } else { token.Complete(this, null, ex); } } }
CassandraConnection AllocateConnection(IPAddress endPoint, out Exception outExc) { CassandraConnection nconn = null; outExc = null; try { nconn = new CassandraConnection(this, endPoint, _protocolOptions, _socketOptions, _clientOptions, _authProvider); var options = nconn.ExecuteOptions(); if (!string.IsNullOrEmpty(_keyspace)) { nconn.SetKeyspace(_keyspace); } } catch (Exception ex) { if (nconn != null) nconn.Dispose(); if (CassandraConnection.IsStreamRelatedException(ex)) { HostIsDown(endPoint); outExc = ex; return null; } else throw ex; } _logger.Info("Allocated new connection"); return nconn; }
CassandraConnection AllocateConnection(IPAddress endPoint, out Exception outExc) { CassandraConnection nconn = null; outExc = null; try { nconn = new CassandraConnection(this, endPoint, _protocolOptions, _socketOptions, _clientOptions, _authProvider); var options = nconn.ExecuteOptions(); if (!string.IsNullOrEmpty(_keyspace)) { var keyspaceId = CqlQueryTools.CqlIdentifier(_keyspace); string retKeyspaceId; try { retKeyspaceId = ProcessSetKeyspace(nconn.Query(GetUseKeyspaceCQL(keyspaceId), ConsistencyLevel.Ignore,false)); } catch (InvalidException) { throw; } catch (QueryValidationException) { return null; } if (CqlQueryTools.CqlIdentifier(retKeyspaceId) != CqlQueryTools.CqlIdentifier(keyspaceId)) { var ex = new DriverInternalError("USE query returned " + retKeyspaceId + ". We expected " + keyspaceId + "."); _logger.Error(ex); throw ex; } lock(_preparedQueries) foreach (var prepQ in _preparedQueries) { try { byte[] queryid; RowSetMetadata metadata; ProcessPrepareQuery(nconn.PrepareQuery(prepQ.Key), out metadata, out queryid); } catch (QueryValidationException) { return null; } //TODO: makesure that ids are equal; } } } catch (Exception ex) { if (nconn != null) nconn.Dispose(); if (CassandraConnection.IsStreamRelatedException(ex)) { outExc = ex; return null; } else throw ex; } _logger.Info("Allocated new connection"); return nconn; }
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; } } } }
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; }