Hello -

I recently observed in my prod system a case of GenericObjectPool not 
respecting its limits.  I had a pool of maxActive 10 that ultimately served out 
objects to every single thread in my app server, ultimately bringing it down 
when the pooled resource stopped responding.  I have reproduced a small test 
case that shows a pool with max size one that serves out more than one object 
when hit by 5 concurrent threads.  Hopefully I'm just doing something obviously 
wrong.  Any thoughts?

Ken





import org.apache.commons.pool.impl.GenericObjectPool;
import org.apache.commons.pool.PoolableObjectFactory;
import java.util.List;
import java.util.ArrayList;
import java.util.Random;


public class MaxActiveExceeded {
    public static void main(String[] args) {
        Pool pool = new Pool();  //just to instantiate

        List<DoSomething> tlist = new ArrayList<DoSomething>();
        for(int i = 0; i < 5; i++) {
            DoSomething x = new DoSomething("" + i);
            tlist.add(x);
        }

        for(DoSomething x : tlist) {
            x.start();
            try {
                Thread.sleep(100);
            } catch(InterruptedException e) {
                e.printStackTrace();  //To change body of catch statement use 
File | Settings | File Templates.
            }
        }
    }

    public static Object testBorrow() {
        Object ctx = null;
        try {
            System.out.println("---Idle " + ImageNowConnectionPool.getNumIdle() 
+ " Active " + ImageNowConnectionPool.getNumActive() + " : " + 
System.currentTimeMillis());
            ctx = Pool.getConnection();
            Pool.releaseConnection(ctx);
        } catch (Exception e) {
            System.out.println("msg " + ctx + " -- " + e.getLocalizedMessage() 
+ " : " + System.currentTimeMillis());
        }
        return ctx;
    }

    private static class DoSomething extends Thread {

        private DoSomething(String name) {
            super(name);
        }

        public void run() {
            System.out.println("Thread running " + getName());
            Object o = testBorrow();
            System.out.println("Thread stopping " + getName() + ", object 
returned - " + o);
        }
    }

    private static class Pool {
        private static final int MAXACTIVE = 1;
        private static final long MAXWAIT = 500;
        private static final int MAXIDLE = -1;
        private static final int MINIDLE = 0;
        private static final boolean TESTONBORROW = false;
        private static final boolean TESTWHILEIDLE = false;
        private static final boolean TESTONRETURN = false;
        private static final long TIMEBETWEENEVICTRUNS = -1;
        private static final int NUMTESTSPEREVICTRUN = 2;
        private static final long MINEVICTABLEIDLETIME = -1;

        private static final GenericObjectPool<Object> POOL = new 
GenericObjectPool<Object>(new ObjectFactory(),
            MAXACTIVE, GenericObjectPool.WHEN_EXHAUSTED_BLOCK, MAXWAIT, 
MAXIDLE, MINIDLE,
            TESTONBORROW, TESTONRETURN, TIMEBETWEENEVICTRUNS, 
NUMTESTSPEREVICTRUN, MINEVICTABLEIDLETIME,
            TESTWHILEIDLE);

        public static Object getConnection(){
            Object o = null;
            try {
                System.out.println("pre-borrow " + Thread.currentThread() + ": 
Idle" + POOL.getNumIdle() + " Active " + POOL.getNumActive() + " : " + 
System.currentTimeMillis());
                o = POOL.borrowObject();
                System.out.println("post-borrow " + Thread.currentThread() + ": 
Idle" + POOL.getNumIdle() + " Active " + POOL.getNumActive() + " : " + 
System.currentTimeMillis());
            } catch (Exception e) {
                System.out.println("****Error trying to borow - " + 
Thread.currentThread() + ":" + e.getMessage() );
//                System.out.println("borrow exception " + 
Thread.currentThread() + ": Idle" + POOL.getNumIdle() + " Active " + 
POOL.getNumActive() + " : " + System.currentTimeMillis());
    //            e.printStackTrace();
            }
            return o;
        }

        public static void releaseConnection(Object o){
            try {
                System.out.println("pre-release " + Thread.currentThread() + ": 
Idle" + POOL.getNumIdle() + " Active " + POOL.getNumActive() + " : " + 
System.currentTimeMillis());
                POOL.returnObject(o);
                System.out.println("post-release " + Thread.currentThread() + 
": Idle" + POOL.getNumIdle() + " Active " + POOL.getNumActive() + " : " + 
System.currentTimeMillis());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private static class ObjectFactory implements PoolableObjectFactory<Object> 
{
        // returns a new connection to imagenow
        public Object makeObject() {
            Object retObj = null;
            try {
                retObj = login();
                System.out.println("make obj" + retObj + " : " + 
System.currentTimeMillis() + Thread.currentThread());
            } catch (Exception e) {
                e.printStackTrace();
            }
            return retObj;
        }

        public void destroyObject(Object obj) {
            System.out.println("destroy obj" + obj + " : " + 
System.currentTimeMillis() + Thread.currentThread());
        }

        public boolean validateObject(Object obj) {
            boolean isValid = false;
            if(obj == null) {
                System.out.println("validation obj is null " + 
Thread.currentThread());
            } else {
                try {
                    System.out.println("about to validate " + 
Thread.currentThread());
                    Random r = new Random();
                    Thread.sleep(5000 + r.nextInt(20000));
                    isValid = true;
                    System.out.println("validate obj " + obj + " valid = " + 
isValid + " : " + System.currentTimeMillis() + Thread.currentThread());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return isValid;
        }

        public void activateObject(Object obj) {
            System.out.println("activate" + obj + " : " + 
System.currentTimeMillis() + Thread.currentThread());
        }

        public void passivateObject(Object obj) {
            System.out.println("passivate" + obj + " : " + 
System.currentTimeMillis() + Thread.currentThread());
        }


        /*-----------------------------------*/
        private static Object login() throws Exception {
            System.out.println("about to login " + Thread.currentThread());
            Random r = new Random();
            Thread.sleep(5000 + r.nextInt(20000));
            System.out.println("login complete " + Thread.currentThread());
            return new Object();
        }
    }
}

----------------------------------------------------------------------
CONFIDENTIALITY NOTICE: This email and any files transmitted with it are 
confidential and intended solely for the use of the individual or entity to 
which they are addressed.  If you are not the intended recipient, you may not 
review, copy or distribute this message.  If you have received this email in 
error, please notify the sender immediately and delete the original message.  
Neither the sender nor the company for which he or she works accepts any 
liability for any damage caused by any virus transmitted by this email.

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscr...@commons.apache.org
For additional commands, e-mail: user-h...@commons.apache.org

Reply via email to