/*
 * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.jndi.ldap.pool;

import java.util.ArrayList; // JDK 1.2
import java.util.List;
import java.util.Iterator;

import java.lang.ref.Reference;
import java.lang.ref.SoftReference;

import javax.naming.NamingException;
import javax.naming.InterruptedNamingException;
import javax.naming.CommunicationException;

/**
 * Represents a list of PooledConnections (actually, ConnectionDescs) with the
 * same pool id.
 * The list starts out with an initial number of connections.
 * Additional PooledConnections are created lazily upon demand.
 * The list has a maximum size. When the number of connections
 * reaches the maximum size, a request for a PooledConnection blocks until
 * a connection is returned to the list. A maximum size of zero means that
 * there is no maximum: connection creation will be attempted when
 * no idle connection is available.
 *
 * The list may also have a preferred size. If the current list size
 * is less than the preferred size, a request for a connection will result in
 * a PooledConnection being created (even if an idle connection is available).
 * If the current list size is greater than the preferred size,
 * a connection being returned to the list will be closed and removed from
 * the list. A preferred size of zero means that there is no preferred size:
 * connections are created only when no idle connection is available and
 * a connection being returned to the list is not closed. Regardless of the
 * preferred size, connection creation always observes the maximum size:
 * a connection won't be created if the list size is at or exceeds the
 * maximum size.
 *
 * @author Rosanna Lee
 */

// Package private: accessed only by Pool
final class Connections implements PoolCallback {
    private static final boolean debug = Pool.debug;
    private static final boolean trace =
        com.sun.jndi.ldap.LdapPoolManager.trace;
    private static final int DEFAULT_SIZE = 10;

    final private int maxSize;
    final private int prefSize;
    final private List conns;

    private boolean closed = false;   // Closed for business
    private Reference ref; // maintains reference to id to prevent premature GC

    /**
     * @param id the identity (connection request) of the connections in the list
     * @param initSize the number of connections to create initially
     * @param prefSize the preferred size of the pool. The pool will try
     * to maintain a pool of this size by creating and closing connections
     * as needed.
     * @param maxSize the maximum size of the pool. The pool will not exceed
     * this size. If the pool is at this size, a request for a connection
     * will block until an idle connection is released to the pool or
     * when one is removed.
     * @param factory The factory responsible for creating a connection
     */
    Connections(Object id, int initSize, int prefSize, int maxSize,
        PooledConnectionFactory factory) throws NamingException {

        this.maxSize = maxSize;
        if (maxSize > 0) {
            // prefSize and initSize cannot exceed specified maxSize
            this.prefSize = Math.min(prefSize, maxSize);
            initSize = Math.min(initSize, maxSize);
        } else {
            this.prefSize = prefSize;
        }
        conns = new ArrayList(maxSize > 0 ? maxSize : DEFAULT_SIZE);

        // Maintain soft ref to id so that this Connections' entry in
        // Pool doesn't get GC'ed prematurely
        ref = new SoftReference(id);

        d("init size=", initSize);
        d("max size=", maxSize);
        d("preferred size=", prefSize);

        // Create initial connections
        PooledConnection conn;
        for (int i = 0; i < initSize; i++) {
            conn = factory.createPooledConnection(this);
            td("Create ", conn ,factory);
            conns.add(new ConnectionDesc(conn)); // Add new idle conn to pool
        }
    }

    /**
     * Retrieves a PooledConnection from this list of connections.
     * Use an existing one if one is idle, or create one if the list's
     * max size hasn't been reached. If max size has been reached, wait
     * for a PooledConnection to be returned, or one to be removed (thus
     * not reaching the max size any longer).
     *
     * @param timeout if > 0, msec to wait until connection is available
     * @param factory creates the PooledConnection if one needs to be created
     *
     * @return A non-null PooledConnection
     * @throws NamingException PooledConnection cannot be created, because this
     * thread was interrupted while it waited for an available connection,
     * or if it timed out while waiting, or the creation of a connection
     * resulted in an error.
     */
    synchronized PooledConnection get(long timeout,
        PooledConnectionFactory factory) throws NamingException {
        PooledConnection conn;
        long start = (timeout > 0 ? System.currentTimeMillis() : 0);
        long waittime = timeout;

        d("get(): before");
        while ((conn = getOrCreateConnection(factory)) == null) {
            if (timeout > 0 && waittime <= 0) {
                throw new CommunicationException(
                    "Timeout exceeded while waiting for a connection: " +
                    timeout + "ms");
            }
            try {
                d("get(): waiting");
                if (waittime > 0) {
                    wait(waittime);  // Wait until one is released or removed
                } else {
                    wait();
                }
            } catch (InterruptedException e) {
                throw new InterruptedNamingException(
                    "Interrupted while waiting for a connection");
            }
            // Check whether we timed out
            if (timeout > 0) {
                long now = System.currentTimeMillis();
                waittime = timeout - (now - start);
            }
        }

        d("get(): after");
        return conn;
    }

    /**
     * Retrieves an idle connection from this list if one is available.
     * If none is available, create a new one if maxSize hasn't been reached.
     * If maxSize has been reached, return null.
     * Always called from a synchronized method.
     */
    private PooledConnection getOrCreateConnection(
        PooledConnectionFactory factory) throws NamingException {

        int size = conns.size(); // Current number of idle/nonidle conns
        PooledConnection conn = null;

        if (prefSize <= 0 || size >= prefSize) {
            // If no prefSize specified, or list size already meets or
            // exceeds prefSize, then first look for an idle connection
            ConnectionDesc entry;
            for (int i = 0; i < size; i++) {
                entry = (ConnectionDesc) conns.get(i);
                if ((conn = entry.tryUse()) != null) {
                    d("get(): use ", conn);
                    td("Use ", conn);
                    return conn;
                }
            }
        }

        // Check if list size already at maxSize specified
        if (maxSize > 0 && size >= maxSize) {
            return null;   // List size is at limit; cannot create any more
        }

        conn = factory.createPooledConnection(this);
        td("Create and use ", conn, factory);
        conns.add(new ConnectionDesc(conn, true)); // Add new conn to pool

        return conn;
    }

    /**
     * Releases connection back into list.
     * If the list size is below prefSize, the connection may be reused.
     * If the list size exceeds prefSize, then the connection is closed
     * and removed from the list.
     *
     * public because implemented as part of PoolCallback.
     */
    public synchronized boolean releasePooledConnection(PooledConnection conn) {
        ConnectionDesc entry;
        int loc = conns.indexOf(entry=new ConnectionDesc(conn));

        d("release(): ", conn);

        if (loc >= 0) {
            // Found entry

            if (closed || (prefSize > 0 && conns.size() > prefSize)) {
                // If list size exceeds prefSize, close connection

                d("release(): closing ", conn);
                td("Close ", conn);

                // size must be >= 2 so don't worry about empty list
                conns.remove(entry);
                conn.closeConnection();

            } else {
                d("release(): release ", conn);
                td("Release ", conn);

                // Get ConnectionDesc from list to get correct state info
                entry = (ConnectionDesc) conns.get(loc);
                // Return connection to list, ready for reuse
                entry.release();
            }
            notifyAll();
            d("release(): notify");
            return true;
        } else {
            return false;
        }
    }

    /**
     * Removes PooledConnection from list of connections.
     * The closing of the connection is separate from this method.
     * This method is called usually when the caller encouters an error
     * when using the connection and wants it removed from the pool.
     *
     * @return true if conn removed; false if it was not in pool
     *
     * public because implemented as part of PoolCallback.
     */
    public synchronized boolean removePooledConnection(PooledConnection conn) {
        if (conns.remove(new ConnectionDesc(conn))) {
            d("remove(): ", conn);

            notifyAll();

            d("remove(): notify");
            td("Remove ", conn);

            if (conns.isEmpty()) {
                // Remove softref to make pool entry eligible for GC.
                // Once ref has been removed, it cannot be reinstated.
                ref = null;
            }

            return true;
        } else {
            d("remove(): not found ", conn);
            return false;
        }
    }

    /**
     * Goes through all entries in list, removes and closes ones that have been
     * idle before threshold.
     *
     * @param threshold an entry idle since this time has expired.
     * @return true if no more connections in list
     */
    synchronized boolean expire(long threshold) {
        Iterator iter = conns.iterator();
        ConnectionDesc entry;
        while (iter.hasNext()) {
            entry = (ConnectionDesc) iter.next();
            if (entry.expire(threshold)) {
                d("expire(): removing ", entry);
                td("Expired ", entry);

                iter.remove();  // remove from pool

                // Don't need to call notify() because we're
                // removing only idle connections. If there were
                // idle connections, then there should be no waiters.
            }
        }
        return conns.isEmpty();  // whether whole list has 'expired'
    }

    /**
     * Called when this instance of Connections has been removed from Pool.
     * This means that no one can get any pooled connections from this
     * Connections any longer. Expire all idle connections as of 'now'
     * and leave indicator so that any in-use connections will be closed upon
     * their return.
     */
    synchronized void close() {
        expire(System.currentTimeMillis());     // Expire idle connections
        closed = true;   // Close in-use connections when they are returned
    }

    String getStats() {
        int idle = 0;
        int busy = 0;
        int expired = 0;
        long use = 0;
        int len;

        synchronized (this) {
            len = conns.size();

            ConnectionDesc entry;
            for (int i = 0; i < len; i++) {
                entry = (ConnectionDesc) conns.get(i);
                use += entry.getUseCount();
                switch (entry.getState()) {
                case ConnectionDesc.BUSY:
                    ++busy;
                    break;
                case ConnectionDesc.IDLE:
                    ++idle;
                    break;
                case ConnectionDesc.EXPIRED:
                    ++expired;
                }
            }
        }
        return "size=" + len + "; use=" + use + "; busy=" + busy
            + "; idle=" + idle + "; expired=" + expired;
    }

    private void d(String msg, Object o1) {
        if (debug) {
            d(msg + o1);
        }
    }

    private void d(String msg, int i) {
        if (debug) {
            d(msg + i);
        }
    }

    private void d(String msg) {
        if (debug) {
            System.err.println(this + "." + msg + "; size: " + conns.size());
        }
    }

    private void td(String msg, Object o1, Object o2) {
        if (trace) { // redo test to avoid object creation
            td(msg + o1 + "[" + o2 + "]");
        }
    }
    private void td(String msg, Object o1) {
        if (trace) { // redo test to avoid object creation
            td(msg + o1);
        }
    }
    private void td(String msg) {
        if (trace) {
            System.err.println(msg);
        }
    }
}
