KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > avalon > excalibur > pool > TraceableResourceLimitingPool


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14  * implied.
15  *
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */

19 package org.apache.avalon.excalibur.pool;
20
21 import java.util.HashMap JavaDoc;
22 import java.util.Iterator JavaDoc;
23 import java.util.Map JavaDoc;
24
25 /**
26  * A ResourceLimitingPool which can be configured so that it will trace the
27  * where get is being called fron. The pool can then be queried for its
28  * status.
29  *
30  * @author <a HREF="mailto:dev@avalon.apache.org">Avalon Development Team</a>
31  * @version CVS $Revision: 1.6 $ $Date: 2004/03/31 08:07:28 $
32  * @since 4.1
33  */

34 public class TraceableResourceLimitingPool
35     extends InstrumentedResourceLimitingPool
36 {
37     /*---------------------------------------------------------------
38      * Private Fields
39      *-------------------------------------------------------------*/

40     /** True if tracing is enabled for the pool. */
41     private boolean m_tracing;
42     
43     /** Map of elements describing each poolable. */
44     private Map JavaDoc m_elementMap;
45
46     /*---------------------------------------------------------------
47      * Constructors
48      *-------------------------------------------------------------*/

49     /**
50      * Creates a new TraceableResourceLimitingPool
51      *
52      * @param factory The ObjectFactory which will be used to create new Poolables as needed by
53      * the pool.
54      * @param max Maximum number of Poolables which can be stored in the pool, 0 implies no limit.
55      * @param maxStrict true if the pool should never allow more than max Poolable to be created.
56      * Will cause an exception to be thrown if more than max Poolables are requested and blocking
57      * is false.
58      * @param blocking true if the pool should cause a thread calling get() to block when Poolables
59      * are not currently available on the pool.
60      * @param blockTimeout The maximum amount of time, in milliseconds, that a call to get() will
61      * block before an exception is thrown. A value of 0 implies an indefinate wait.
62      * @param trimInterval The minimum interval with which old unused poolables will be removed
63      * from the pool. A value of 0 will cause the pool to never trim poolables.
64      * @param trace True if tracing of gets is enabled for the pool.
65      */

66     public TraceableResourceLimitingPool( final ObjectFactory factory,
67                                           int max,
68                                           boolean maxStrict,
69                                           boolean blocking,
70                                           long blockTimeout,
71                                           long trimInterval,
72                                           boolean trace )
73     {
74
75         super( factory, max, maxStrict, blocking, blockTimeout, trimInterval );
76         
77         m_tracing = trace;
78         if ( m_tracing )
79         {
80             m_elementMap = new HashMap JavaDoc();
81         }
82     }
83
84     /*---------------------------------------------------------------
85      * InstrumentedResourceLimitingPool Methods
86      *-------------------------------------------------------------*/

87     /**
88      * Gets a Poolable from the pool. If there is room in the pool, a new Poolable will be
89      * created. Depending on the parameters to the constructor, the method may block or throw
90      * an exception if a Poolable is not available on the pool.
91      *
92      * @return Always returns a Poolable. Contract requires that put must always be called with
93      * the Poolable returned.
94      * @throws Exception An exception may be thrown as described above or if there is an exception
95      * thrown by the ObjectFactory's newInstance() method.
96      */

97     public Poolable get() throws Exception JavaDoc
98     {
99         if ( m_tracing )
100         {
101             synchronized ( m_semaphore )
102             {
103                 Poolable poolable = (Poolable)super.get();
104                 
105                 PoolElement element = (PoolElement)m_elementMap.get( poolable );
106                 if ( element == null )
107                 {
108                     element = new PoolElement( poolable );
109                     m_elementMap.put( poolable, element );
110                 }
111                 element.trace();
112                 
113                 return poolable;
114             }
115         }
116         else
117         {
118             return super.get();
119         }
120     }
121
122     /**
123      * Returns a poolable to the pool and notifies any thread blocking.
124      *
125      * @param poolable Poolable to return to the pool.
126      */

127     public void put( Poolable poolable )
128     {
129         if ( m_tracing )
130         {
131             synchronized ( m_semaphore )
132             {
133                 PoolElement element = (PoolElement)m_elementMap.get( poolable );
134                 if ( element == null )
135                 {
136                     getLogger().error( "PoolElement not found in put for poolable: " + poolable );
137                 }
138                 else
139                 {
140                     element.clear();
141                 }
142                 
143                 super.put( poolable );
144             }
145         }
146         else
147         {
148             super.put( poolable );
149         }
150     }
151
152     /**
153      * Called when an object is being removed permanently from the pool.
154      * This is the method to override when you need to enforce destructional
155      * policies.
156      * <p>
157      * This method is only called by threads that have m_semaphore locked.
158      *
159      * @param poolable Poolable to be completely removed from the pool.
160      */

161     protected void removePoolable( Poolable poolable )
162     {
163         if ( m_tracing )
164         {
165             PoolElement element = (PoolElement)m_elementMap.remove( poolable );
166             if ( element == null )
167             {
168                 getLogger().error(
169                     "PoolElement not found in removePoolable for poolable: " + poolable );
170             }
171         }
172         
173         super.removePoolable( poolable );
174     }
175
176     /*---------------------------------------------------------------
177      * Public Methods
178      *-------------------------------------------------------------*/

179     /**
180      * Returns a snapshot of the current state of the pool.
181      *
182      * @return A snapshot of the current pool state.
183      */

184     public State getState()
185     {
186         if ( m_tracing )
187         {
188             synchronized ( m_semaphore )
189             {
190                 // Count how poolables are outstanding.
191
int count = 0;
192                 for ( Iterator JavaDoc iter = m_elementMap.values().iterator(); iter.hasNext(); )
193                 {
194                     PoolElement element = (PoolElement)iter.next();
195                     if ( element.m_thread != null )
196                     {
197                         count++;
198                     }
199                 }
200                 
201                 // Go back and extract the state.
202
Thread JavaDoc[] threads = new Thread JavaDoc[count];
203                 TraceException[] traceExceptions = new TraceException[count];
204                 long[] traceTimes = new long[count];
205                 if ( count > 0 )
206                 {
207                     int i = 0;
208                     for ( Iterator JavaDoc iter = m_elementMap.values().iterator(); iter.hasNext(); )
209                     {
210                         PoolElement element = (PoolElement)iter.next();
211                         if ( element.m_thread != null )
212                         {
213                             threads[i] = element.m_thread;
214                             traceExceptions[i] = element.m_traceException;
215                             traceTimes[i] = element.m_time;
216                             i++;
217                         }
218                     }
219                 }
220                 
221                 return new State( getSize(), getReadySize(), threads, traceExceptions, traceTimes );
222             }
223         }
224         else
225         {
226             throw new IllegalStateException JavaDoc( "Trace is disabled for this pool." );
227         }
228     }
229     
230     /*---------------------------------------------------------------
231      * Inner Classes
232      *-------------------------------------------------------------*/

233     public static class State
234     {
235         private int m_size;
236         private int m_readySize;
237         private Thread JavaDoc[] m_threads;
238         private TraceException[] m_traceExceptions;
239         private long[] m_traceTimes;
240         
241         private State( int size, int readySize,
242                        Thread JavaDoc[] threads,
243                        TraceException[] traceExceptions,
244                        long[] traceTimes )
245         {
246             m_size = size;
247             m_readySize = readySize;
248             m_threads = threads;
249             m_traceExceptions = traceExceptions;
250             m_traceTimes = traceTimes;
251         }
252         
253         public int getSize()
254         {
255             return m_size;
256         }
257         
258         public int getReadySize()
259         {
260             return m_readySize;
261         }
262         
263         public Thread JavaDoc[] getTraceThreads()
264         {
265             return m_threads;
266         }
267         
268         public TraceException[] getTraceExceptions()
269         {
270             return m_traceExceptions;
271         }
272         
273         public long[] getTraceTimes()
274         {
275             return m_traceTimes;
276         }
277     }
278     
279     private static class PoolElement
280     {
281         private Poolable m_poolable;
282         private Thread JavaDoc m_thread;
283         private TraceException m_traceException;
284         private long m_time;
285         
286         private PoolElement( Poolable poolable )
287         {
288             m_poolable = poolable;
289         }
290         
291         private void trace()
292         {
293             m_thread = Thread.currentThread();
294             m_traceException = new TraceException();
295             m_traceException.fillInStackTrace();
296             m_time = System.currentTimeMillis();
297         }
298         
299         private void clear()
300         {
301             m_thread = null;
302             m_traceException = null;
303         }
304     }
305     
306     public static class TraceException extends RuntimeException JavaDoc
307     {
308         private TraceException()
309         {
310         }
311     }
312 }
313
314
Popular Tags