KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > ejb > plugins > AbstractInstancePool


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.ejb.plugins;
23
24 import java.rmi.RemoteException JavaDoc;
25 import java.util.LinkedList JavaDoc;
26 import java.lang.reflect.UndeclaredThrowableException JavaDoc;
27 import javax.ejb.EJBException JavaDoc;
28 import javax.ejb.CreateException JavaDoc;
29
30 import org.jboss.ejb.Container;
31 import org.jboss.ejb.InstancePool;
32 import org.jboss.ejb.EnterpriseContext;
33
34 import org.jboss.deployment.DeploymentException;
35 import org.jboss.metadata.MetaData;
36 import org.jboss.metadata.XmlLoadable;
37 import org.jboss.system.ServiceMBeanSupport;
38
39 import org.w3c.dom.Element JavaDoc;
40 import EDU.oswego.cs.dl.util.concurrent.FIFOSemaphore;
41
42 /**
43  * Abstract Instance Pool class containing the basic logic to create
44  * an EJB Instance Pool.
45  *
46  * @author <a HREF="mailto:rickard.oberg@telkel.com">Rickard Oberg</a>
47  * @author <a HREF="mailto:marc.fleury@jboss.org">Marc Fleury</a>
48  * @author <a HREF="mailto:andreas.schaefer@madplanet.com">Andreas Schaefer</a>
49  * @author <a HREF="mailto:sacha.labourey@cogito-info.ch">Sacha Labourey</a>
50  * @author <a HREF="mailto:scott.stark@jboss.org">Scott Stark/a>
51  * @author <a HREF="mailto:dimitris@jboss.org">Dimitris Andreadis</a>
52  * @version $Revision: 38303 $
53  *
54  * @jmx:mbean extends="org.jboss.system.ServiceMBean"
55  */

56 public abstract class AbstractInstancePool
57    extends ServiceMBeanSupport
58    implements AbstractInstancePoolMBean, InstancePool, XmlLoadable
59 {
60    // Constants -----------------------------------------------------
61

62    // Attributes ----------------------------------------------------
63
/** A FIFO semaphore that is set when the strict max size behavior is in effect.
64     When set, only maxSize instances may be active and any attempt to get an
65     instance will block until an instance is freed.
66     */

67    private FIFOSemaphore strictMaxSize;
68    /** The time in milliseconds to wait for the strictMaxSize semaphore.
69     */

70    private long strictTimeout = Long.MAX_VALUE;
71    /** The Container the instance pool is associated with */
72    protected Container container;
73    /** The pool data structure */
74    protected LinkedList JavaDoc pool = new LinkedList JavaDoc();
75    /** The maximum number of instances allowed in the pool */
76    protected int maxSize = 30;
77    /** determine if we reuse EnterpriseContext objects i.e. if we actually do pooling */
78    protected boolean reclaim = false;
79
80
81    // Static --------------------------------------------------------
82

83    // Constructors --------------------------------------------------
84

85    // Public --------------------------------------------------------
86

87    /**
88     * Set the callback to the container. This is for initialization.
89     * The IM may extract the configuration from the container.
90     *
91     * @param c
92     */

93    public void setContainer(Container c)
94    {
95       this.container = c;
96    }
97
98    /**
99     * @return Callback to the container which can be null if not set proviously
100     */

101    public Container getContainer()
102    {
103       return container;
104    }
105
106    /**
107     * @jmx:managed-attribute
108     * @return the current pool size
109     */

110    public int getCurrentSize()
111    {
112       synchronized (pool)
113       {
114          return this.pool.size();
115       }
116    }
117
118    /**
119     * @jmx:managed-attribute
120     * @return the current pool size
121     */

122    public int getMaxSize()
123    {
124       return this.maxSize;
125    }
126
127    /** Get the current avaiable count from the strict max view. If there is
128     * no strict max then this will be Long.MAX_VALUE to indicate there is no
129     * restriction.
130     * @jmx:managed-attribute
131     * @return the current avaiable count from the strict max view
132     */

133    public long getAvailableCount()
134    {
135       long size = Long.MAX_VALUE;
136       if( strictMaxSize != null )
137          size = strictMaxSize.permits();
138       return size;
139    }
140
141    /**
142     * Get an instance without identity.
143     * Can be used by finders,create-methods, and activation
144     *
145     * @return Context /w instance
146     * @exception RemoteException
147     */

148    public EnterpriseContext get()
149       throws Exception JavaDoc
150    {
151       boolean trace = log.isTraceEnabled();
152       if( trace )
153          log.trace("Get instance "+this+"#"+pool.size()+"#"+getContainer().getBeanClass());
154
155       if( strictMaxSize != null )
156       {
157          // Block until an instance is available
158
boolean acquired = strictMaxSize.attempt(strictTimeout);
159          if( trace )
160             log.trace("Acquired("+acquired+") strictMaxSize semaphore, remaining="+strictMaxSize.permits());
161          if( acquired == false )
162             throw new EJBException JavaDoc("Failed to acquire the pool semaphore, strictTimeout="+strictTimeout);
163       }
164
165       synchronized (pool)
166       {
167          if ( pool.isEmpty() == false )
168          {
169             return (EnterpriseContext) pool.removeFirst();
170          }
171       }
172
173       // Pool is empty, create an instance
174
try
175       {
176          Object JavaDoc instance = container.createBeanClassInstance();
177          return create(instance);
178       }
179       catch (Throwable JavaDoc e)
180       {
181          // Release the strict max size mutex if it exists
182
if( strictMaxSize != null )
183          {
184             strictMaxSize.release();
185          }
186          // Don't wrap CreateExceptions
187
if( e instanceof CreateException JavaDoc )
188             throw (CreateException JavaDoc) e;
189
190          // Wrap e in an Exception if needed
191
Exception JavaDoc ex = null;
192          if(e instanceof Exception JavaDoc)
193          {
194             ex = (Exception JavaDoc)e;
195          } else
196          {
197             ex = new UndeclaredThrowableException JavaDoc(e);
198          }
199          throw new EJBException JavaDoc("Could not instantiate bean", ex);
200       }
201    }
202
203    /**
204     * Return an instance after invocation.
205     *
206     * Called in 2 cases:
207     * a) Done with finder method
208     * b) Just removed
209     *
210     * @param ctx
211     */

212    public void free(EnterpriseContext ctx)
213    {
214       if( log.isTraceEnabled() )
215       {
216          String JavaDoc msg = pool.size() + "/" + maxSize+" Free instance:"+this
217             +"#"+ctx.getId()
218             +"#"+ctx.getTransaction()
219             +"#"+reclaim
220             +"#"+getContainer().getBeanClass();
221          log.trace(msg);
222       }
223
224       ctx.clear();
225
226       try
227       {
228          // If the pool is not full, add the unused context back into the pool,
229
// otherwise, just discard the extraneous context and leave it for GC
230
boolean addedToPool = false;
231          
232          synchronized (pool)
233          {
234             if (pool.size() < maxSize)
235             {
236                pool.addFirst(ctx);
237                addedToPool = true;
238             }
239          }
240          
241          if (addedToPool)
242          {
243             // If we block when maxSize instances are in use, invoke release on strictMaxSize
244
if(strictMaxSize != null)
245             {
246                strictMaxSize.release();
247             }
248          }
249          else
250          {
251             // Get rid of the extraneous instance; strictMaxSize should be null
252
// (otherwise we wouldn't have gotten the extra instance)
253
discard(ctx);
254          }
255       }
256       catch (Exception JavaDoc ignored)
257       {
258       }
259    }
260
261    public void discard(EnterpriseContext ctx)
262    {
263       if( log.isTraceEnabled() )
264       {
265          String JavaDoc msg = "Discard instance:"+this+"#"+ctx
266             +"#"+ctx.getTransaction()
267             +"#"+reclaim
268             +"#"+getContainer().getBeanClass();
269          log.trace(msg);
270       }
271
272       // If we block when maxSize instances are in use, invoke release on strictMaxSize
273
if( strictMaxSize != null )
274          strictMaxSize.release();
275
276       // Throw away, unsetContext()
277
try
278       {
279          ctx.discard();
280       }
281       catch (RemoteException JavaDoc e)
282       {
283          if( log.isTraceEnabled() )
284             log.trace("Ctx.discard error", e);
285       }
286    }
287
288    public void clear()
289    {
290       synchronized (pool)
291       {
292          freeAll();
293       }
294    }
295
296    /**
297     * XmlLoadable implementation
298     */

299    public void importXml(Element JavaDoc element) throws DeploymentException
300    {
301       String JavaDoc maximumSize = MetaData.getElementContent(MetaData.getUniqueChild(element, "MaximumSize"));
302       try
303       {
304          this.maxSize = Integer.parseInt(maximumSize);
305       }
306       catch (NumberFormatException JavaDoc e)
307       {
308          throw new DeploymentException("Invalid MaximumSize value for instance pool configuration");
309       }
310
311       // Get whether the pool will block when MaximumSize instances are active
312
String JavaDoc strictValue = MetaData.getElementContent(MetaData.getOptionalChild(element, "strictMaximumSize"));
313       Boolean JavaDoc strictFlag = Boolean.valueOf(strictValue);
314       if( strictFlag == Boolean.TRUE )
315          this.strictMaxSize = new FIFOSemaphore(this.maxSize);
316       String JavaDoc delay = MetaData.getElementContent(MetaData.getOptionalChild(element, "strictTimeout"));
317       try
318       {
319          if( delay != null )
320             this.strictTimeout = Long.parseLong(delay);
321       }
322       catch (NumberFormatException JavaDoc e)
323       {
324          throw new DeploymentException("Invalid strictTimeout value for instance pool configuration");
325       }
326    }
327
328    // Package protected ---------------------------------------------
329

330    // Protected -----------------------------------------------------
331
protected abstract EnterpriseContext create(Object JavaDoc instance)
332    throws Exception JavaDoc;
333
334    protected void destroyService() throws Exception JavaDoc
335    {
336      freeAll();
337      this.container = null;
338    }
339
340    // Private -------------------------------------------------------
341

342    /**
343     * At undeployment we want to free completely the pool.
344     */

345    private void freeAll()
346    {
347       LinkedList JavaDoc clone = (LinkedList JavaDoc)pool.clone();
348       for (int i = 0; i < clone.size(); i++)
349       {
350          EnterpriseContext ec = (EnterpriseContext)clone.get(i);
351          // Clear TX so that still TX entity pools get killed as well
352
ec.clear();
353          discard(ec);
354       }
355       pool.clear();
356    }
357
358    // Inner classes -------------------------------------------------
359

360 }
361
Popular Tags