You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by ma...@apache.org on 2008/04/25 00:55:16 UTC

svn commit: r651451 - /openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java

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 {



Re: svn commit: r651451 - /openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java

Posted by Manu George <ma...@gmail.com>.
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,  <ma...@apache.org> 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 {
>
>
>