ConnectionAccessQueue.java :  » Web-Framework » anvil » anvil » database » Java Open Source

Java Open Source » Web Framework » anvil 
anvil » anvil » database » ConnectionAccessQueue.java
/*
 * $Id: ConnectionAccessQueue.java,v 1.7 2002/09/16 08:05:03 jkl Exp $
 *
 * Copyright (c) 2002 Njet Communications Ltd. All Rights Reserved.
 *
 * Use is subject to license terms, as defined in
 * Anvil Sofware License, Version 1.1. See LICENSE 
 * file, or http://njet.org/license-1.1.txt
 */
package anvil.database;

import java.util.ArrayList;

/**
 * <code>ConnectionAccessQueue</code> is used by <code>ConnectionManager</code> 
 * when acquiring connections from the pool. Queue handles the situations when connections
 * are not immediately available by letting threads to wait 
 * for certain (limited) amount of time. Queue implements 
 * <code>ConnectionObserver</code> through which the notifications 
 * of available are made by the pool.
 *
 * @see ConnectionManager
 * @see ConnectionManager#acquire(String)
 * @see ConnectionPool
 * @see ConnectionPool#acquire
 * @see ConnectionObserver
 * @see PooledConnection
 * @version $Revision: 1.7 $
 * @author Jani Lehtimki
 */
public class ConnectionAccessQueue implements ConnectionObserver 
{

    /**
     * Maximum time to wait for connections, in milliseconds.
     */
    private int acquireTimeout;

    /**
     * ConnectionPool.
     */ 
    private ConnectionPool pool;

    /**
     * Vector of waiting threads.
     */
    private ArrayList queue = new ArrayList();

    /**
     * System still running?
     */
    private boolean running = true;

    /** 
     * Constructs the queue.
     *
     * @param pool    Connection pool
     * @param timeout Acquire timeout
     */
    public ConnectionAccessQueue(ConnectionPool pool) 
    {
        this.pool = pool;
        this.acquireTimeout = pool.getConnectionAcquireTimeout();
        pool.setObserver(this);
    }


    /**
     * Gets the connection pool of this queue.
     *
     * @return Connection pool
     */
    public ConnectionPool getPool() 
    {
        return pool;
    }

    /**
     * Acquire the connection from the pool, waiting for only specified
     * amount of time.
     *
     * @param timeout Timeout override (if > 0)
     * @return Connection
     * @throws CannotReturnPooledConnectionException If acquire timed out
     */
    public PooledConnection acquire(int timeout) 
      throws CannotReturnPooledConnectionException 
    {
        PooledConnection conn          = null;
        Thread         currentThread = Thread.currentThread();
        long           started       = System.currentTimeMillis();
        long           bailout       = acquireTimeout;
        Exception      lastException = null;

        while (running) {

            /*
             * Thread need to be added to queue first before ConnectionPool.acquire()
             * in order to ensure that connectionsAvailable() notifications
             * aren't missed at any point.
             */
            synchronized (queue) {
                if (queue.contains(currentThread) == false) {
                    queue.add(currentThread);
                }
            }

            /*
             * Try to acquire connection and break from the loop
             * if we got one.
             */
            try {
              conn = pool.acquire(timeout);
            } catch (Exception e) {
              lastException = e;
            }

            if (conn != null) {
                break;
            }

            /*
             * Do we still have time left?
             */
            bailout = bailout - (System.currentTimeMillis() - started);

            if (bailout <= 0) {
                break;
            }

            /*
             * Wait for connectionsAvailable() notification
             */
            try {
                currentThread.sleep(bailout);
            } catch (InterruptedException exception) {} 
        }

        /*
         * Clear the interrupted status of thread in case Thread.sleep()
         * was missed.
         */
        currentThread.interrupted();

        synchronized (queue) {
            queue.remove(currentThread);
        }

        /*
         * Are we shutting down? Pool will take care about
         * the connection we possibly just received.
         */
        if (running == false) {
            throw new CannotReturnPooledConnectionException("System is shutting down");
        }

        /*
         * Do we have timeout?
         */
        long duration = System.currentTimeMillis() - started;

        if (conn == null) {
            pool.connectionAcquireTimedout(pool, duration);
            if (lastException == null) {
              throw new CannotReturnPooledConnectionException("Acquire timed out");
            } else {
              throw new CannotReturnPooledConnectionException(
                "Acquire timed out: "+lastException.getMessage());
            }
        }

        pool.connectionReserved(conn, duration);
        return conn;
    }

    /**
     * Notification from connection observer interface. Interrupt the first
     * thread waiting in queue.
     */
    public void connectionsAvailable() 
    {
        synchronized(queue) {
            if (queue.size()>0) {
                Thread sleepingThread = (Thread)queue.remove(0);
                sleepingThread.interrupt();
            }
        }
    }


    /**
     * Shuts down the queue, delegating the request to connection pool and
     * interrupting all threads waiting for connection.
     */
    void stop() 
    {
        running = false;
        pool.stop();
        synchronized(queue) {
           int n = queue.size();
           for (int i = 0; i < n; i++) {
                Thread sleepingThread = (Thread)queue.get(i);
                sleepingThread.interrupt();  
            }
            queue.clear();
        }
    }

}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.