/// <summary> /// Get a socket connection from connection pool to the server node. /// </summary> /// <param name="timeoutMillis">connection timeout value in milliseconds if a new connection is created</param> /// <exception cref="AerospikeException">if a connection could not be provided</exception> public Connection GetConnection(int timeoutMillis) { uint max = (uint)cluster.connPoolsPerNode; uint initialIndex; bool backward; if (max == 1) { initialIndex = 0; backward = false; } else { uint iter = connectionIter++; // not atomic by design initialIndex = iter % max; backward = true; } Pool <Connection> pool = connectionPools[initialIndex]; uint queueIndex = initialIndex; Connection conn; while (true) { if (pool.TryDequeue(out conn)) { // Found socket. // Verify that socket is active and receive buffer is empty. if (cluster.IsConnCurrentTran(conn.LastUsed) && conn.IsValid()) { try { conn.SetTimeout(timeoutMillis); return(conn); } catch (Exception e) { // Set timeout failed. Something is probably wrong with timeout // value itself, so don't empty queue retrying. Just get out. CloseConnection(conn); throw new AerospikeException.Connection(e); } } CloseConnection(conn); } else if (pool.IncrementTotal() <= pool.Capacity) { // Socket not found and queue has available slot. // Create new connection. try { conn = CreateConnection(host.tlsName, address, timeoutMillis, pool); } catch (Exception) { pool.DecrementTotal(); throw; } if (cluster.user != null) { try { AdminCommand command = new AdminCommand(ThreadLocalData.GetBuffer(), 0); if (!command.Authenticate(cluster, conn, sessionToken)) { SignalLogin(); throw new AerospikeException("Authentication failed"); } } catch (Exception) { // Socket not authenticated. Do not put back into pool. CloseConnection(conn); throw; } } return(conn); } else { // Socket not found and queue is full. Try another queue. pool.DecrementTotal(); if (backward) { if (queueIndex > 0) { queueIndex--; } else { queueIndex = initialIndex; if (++queueIndex >= max) { break; } backward = false; } } else if (++queueIndex >= max) { break; } pool = connectionPools[queueIndex]; } } throw new AerospikeException.Connection(ResultCode.NO_MORE_CONNECTIONS, "Node " + this + " max connections " + cluster.maxConnsPerNode + " would be exceeded."); }