예제 #1
0
        /// <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.");
        }