org.quickserver.util.pool.BasicObjectPool.java Source code

Java tutorial

Introduction

Here is the source code for org.quickserver.util.pool.BasicObjectPool.java

Source

/*
 * This file is part of the QuickServer library 
 * Copyright (C) QuickServer.org
 *
 * Use, modification, copying and distribution of this software is subject to
 * the terms and conditions of the GNU Lesser General Public License. 
 * You should have received a copy of the GNU LGP License along with this 
 * library; if not, you can download a copy from <http://www.quickserver.org/>.
 *
 * For questions, suggestions, bug-reports, enhancement-requests etc.
 * visit http://www.quickserver.org
 *
 */

package org.quickserver.util.pool;

import java.util.*;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.commons.pool.*;
import java.util.logging.*;

/**
 * This class will maintain a simple pool of object instances.
 * It internally used a <code>HashSet</code>
 * @author Akshathkumar Shetty
 * @since 1.3
 */
public class BasicObjectPool implements QSObjectPool {
    private static final Logger logger = Logger.getLogger(BasicObjectPool.class.getName());

    private PoolableObjectFactory factory;
    private Config config;
    private final Set activeObjects, idleObjects;
    private volatile boolean inMaintain = false;
    protected AtomicLong activeCount = new AtomicLong();
    private long highestActiveCount;

    public BasicObjectPool() {
        activeObjects = Collections.synchronizedSet(new HashSet());
        idleObjects = Collections.synchronizedSet(new HashSet());
        config = new Config();
    }

    public BasicObjectPool(PoolableObjectFactory factory, BasicObjectPool.Config config) {
        this();
        this.factory = factory;
        if (config != null)
            this.config = config;
    }

    public void addObject() throws Exception {
        if (config.maxIdle == -1 || config.maxIdle > getNumIdle())
            idleObjects.add(factory.makeObject());
        else
            maintain();
    }

    public Object borrowObject() throws Exception {
        if (getNumIdle() <= 0 && (config.maxActive == -1 || config.maxActive > getNumActive())) {
            addObject();
        }
        if (getNumIdle() <= 0) {
            throw new NoSuchElementException(
                    "No free objects! MaxActive:" + config.maxActive + ", NumActive:" + getNumActive());
        }

        Object obj = null;
        synchronized (this) {
            obj = idleObjects.iterator().next();
            idleObjects.remove(obj);
            factory.activateObject(obj);
            activeObjects.add(obj);
        }
        if (getHighestActiveCount() < activeCount.incrementAndGet()) {
            setHighestActiveCount(activeCount.get());
        }
        return obj;
    }

    /**Clears any objects sitting idle in the pool*/
    public synchronized void clear() {
        Iterator iterator = idleObjects.iterator();
        while (iterator.hasNext()) {
            try {
                invalidateObject(iterator.next());
            } catch (Exception e) {
                logger.warning("Error in BasicObjectPool.clear : " + e);
            }
        }
        idleObjects.clear();
    }

    /**Close this pool, and free any resources associated with it.*/
    public void close() throws Exception {
        clear();
        /*
        Iterator iterator = activeObjects.iterator();
        while(iterator.hasNext()) {
           try {
        invalidateObject(iterator.next());
           } catch(Exception e) {
        logger.warning("Error in BasicObjectPool.close : "+e);
           }
        }
        */
        activeObjects.clear();
    }

    /**Return the number of instances currently borrowed from my pool */
    public int getNumActive() {
        return activeObjects.size();
    }

    /**Return the number of instances currently idle in my pool */
    public int getNumIdle() {
        return idleObjects.size();
    }

    /**Invalidates an object from the pool */
    public void invalidateObject(Object obj) throws Exception {
        factory.destroyObject(obj);
    }

    /**Return an instance to my pool*/
    public synchronized void returnObject(Object obj) throws Exception {
        if (activeObjects.remove(obj)) {
            activeCount.decrementAndGet();
        }
        if (factory.validateObject(obj) == false) {
            logger.log(Level.FINER, "Object not good for return: {0}", obj);
            return;
        }
        factory.passivateObject(obj);
        idleObjects.add(obj);
        if (config.maxIdle != -1 && config.maxIdle < getNumIdle()) {
            maintain();
        }
    }

    /**Sets the factory I use to create new instances */
    public void setFactory(PoolableObjectFactory factory) {
        this.factory = factory;
    }

    private void maintain() {
        if (inMaintain == true) {
            return;
        }
        inMaintain = true;
        logger.log(Level.FINEST, "Starting maintain: {0}", getNumIdle());
        while (getNumIdle() > config.maxIdle) {
            try {
                synchronized (idleObjects) {
                    Object obj = idleObjects.iterator().next();
                    idleObjects.remove(obj);
                    invalidateObject(obj);
                }
            } catch (Exception e) {
                logger.log(Level.WARNING, "Error in BasicObjectPool.maintain : {0}", e);
            }
        }
        inMaintain = false;
        logger.log(Level.FINEST, "Finished maintain: {0}", getNumIdle());
    }

    public static class Config {
        public int maxActive = -1;
        public int maxIdle = 10;
    }

    /**
     * Returns the iterator of all active objects
     * @since 1.3.1
     */
    public Iterator getAllActiveObjects() {
        List _list = new LinkedList();
        _list.addAll(activeObjects);
        return _list.iterator(); //*/activeObjects.iterator();
    }

    public Object getObjectToSynchronize() {
        return activeObjects;
    }

    /**
     * @return the highestActiveCount
     */
    public long getHighestActiveCount() {
        return highestActiveCount;
    }

    /**
     * @param highestActiveCount the highestActiveCount to set
     */
    public void setHighestActiveCount(long highestActiveCount) {
        this.highestActiveCount = highestActiveCount;
    }
}