Hi,
     The commit to which i am replying contains a fix for OPENEJB-786 .

1) Stateless Ejb Pooling  :-
              The issue here is that the getInstance method of
StatelessInstanceManager is not properly synchronized and so the pool
size always exceeds the set poolLimit even when strictpooling is
enabled. Consider the scenario where you have say a 100 parallel
requests to an ejb A hitting the server and say a 100 threads are
created. Say the pool size is set to 10 and strict pooling is true.
Initially there are no beans of type A in the pool for A. So pool.pop
will be null. Since the check we do is

while(strictPooling && bean == null && pool.size >= poolLimit){
}
 and its not synchronized many threads will execute in parallel and
skip this altogether as the pool size is not incremented until we
release. Thus as many beans are usually created as there are parallel
threads in some cases.

The approach that I took was to have a HashMap of Semaphores with keys
as deployment ids i.e one for each ejb. The no of threads that the
semaphores would allow simultaneously would be equivalent to pool
limit and so that many no of instances are created and thereafter
used.

Regards
Manu

On Fri, Apr 25, 2008 at 4:25 AM,  <[EMAIL PROTECTED]> wrote:
> Author: manugeorge
>  Date: Thu Apr 24 15:55:03 2008
>  New Revision: 651451
>
>  URL: http://svn.apache.org/viewvc?rev=651451&view=rev
>  Log:
>  OPENEJB-786 -- Stateless Container StrictPooling option ignored -- Use 
> Semaphores provided in java 5 for enforcing StrictPooling
>
>  Modified:
>     
> openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java
>
>  Modified: 
> openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java
>  URL: 
> http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java?rev=651451&r1=651450&r2=651451&view=diff
>  
> ==============================================================================
>  --- 
> openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java
>  (original)
>  +++ 
> openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java
>  Thu Apr 24 15:55:03 2008
>  @@ -22,6 +22,7 @@
>   import java.util.HashMap;
>   import java.util.List;
>   import java.util.Map;
>  +import java.util.concurrent.Semaphore;
>
>   import javax.ejb.SessionBean;
>   import javax.ejb.SessionContext;
>  @@ -57,7 +58,7 @@
>      protected int beanCount = 0;
>      protected boolean strictPooling = false;
>
>  -    protected PoolQueue poolQueue = null;
>  +    protected HashMap<Object,Semaphore> semaphores;
>
>      protected final SafeToolkit toolkit = 
> SafeToolkit.getToolkit("StatefulInstanceManager");
>      private TransactionManager transactionManager;
>  @@ -74,7 +75,7 @@
>          }
>
>          if (this.strictPooling) {
>  -            poolQueue = new PoolQueue(timeout);
>  +            this.semaphores = new HashMap();
>          }
>      }
>
>  @@ -98,12 +99,14 @@
>          CoreDeploymentInfo deploymentInfo = callContext.getDeploymentInfo();
>          Data data = (Data) deploymentInfo.getContainerData();
>          Stack pool = data.getPool();
>  -        Object bean = pool.pop();
>  -
>  -        while (strictPooling && bean == null && pool.size() >= poolLimit) {
>  -            poolQueue.waitForAvailableInstance();
>  -            bean = pool.pop();
>  +        if(strictPooling){
>  +            try {
>  +                semaphores.get(deploymentInfo.getDeploymentID()).acquire();
>  +            } catch (InterruptedException e2) {
>  +                throw new OpenEJBException("Unexpected Interruption of 
> current thread: ",e2);
>  +            }
>          }
>  +        Object bean = pool.pop();
>
>          if (bean == null) {
>
>  @@ -278,7 +281,7 @@
>
>          if (strictPooling) {
>              pool.push(bean);
>  -            poolQueue.notifyWaitingThreads();
>  +            semaphores.get(deploymentInfo.getDeploymentID()).release();
>          } else {
>              if (pool.size() >= poolLimit) {
>                  freeInstance(callContext, (Instance)bean);
>  @@ -320,37 +323,23 @@
>
>      public void deploy(CoreDeploymentInfo deploymentInfo) {
>          Data data = new Data(poolLimit);
>  -        deploymentInfo.setContainerData(data);
>  +        deploymentInfo.setContainerData(data);
>  +        if (this.strictPooling) {
>  +            this.semaphores.put(deploymentInfo.getDeploymentID(), new 
> Semaphore(poolLimit));
>  +        }
>  +
>      }
>
>      public void undeploy(CoreDeploymentInfo deploymentInfo) {
>          Data data = (Data) deploymentInfo.getContainerData();
>  +        if (this.strictPooling) {
>  +            semaphores.remove(deploymentInfo.getDeploymentID());
>  +        }
>          if (data == null) return;
>          Stack pool = data.getPool();
>          //TODO ejbRemove on each bean in pool.
>          //clean pool
>          deploymentInfo.setContainerData(null);
>  -    }
>  -
>  -    static class PoolQueue {
>  -        private final long waitPeriod;
>  -
>  -        public PoolQueue(long time) {
>  -            waitPeriod = time;
>  -        }
>  -
>  -        public synchronized void waitForAvailableInstance()
>  -                throws org.apache.openejb.InvalidateReferenceException {
>  -            try {
>  -                wait(waitPeriod);
>  -            } catch (InterruptedException ie) {
>  -                throw new 
> org.apache.openejb.InvalidateReferenceException(new RemoteException("No 
> instance available to service request", ie));
>  -            }
>  -        }
>  -
>  -        public synchronized void notifyWaitingThreads() {
>  -            notify();
>  -        }
>      }
>
>      private static final class Data {
>
>
>

Reply via email to