KickJava   Java API By Example, From Geeks To Geeks.

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


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.Iterator JavaDoc;
22 import java.util.LinkedList JavaDoc;
23
24 import org.apache.avalon.framework.activity.Disposable;
25 import org.apache.avalon.framework.logger.AbstractLogEnabled;
26 import org.apache.avalon.framework.logger.LogEnabled;
27 import org.apache.avalon.framework.thread.ThreadSafe;
28
29 import org.apache.excalibur.instrument.CounterInstrument;
30 import org.apache.excalibur.instrument.Instrument;
31 import org.apache.excalibur.instrument.Instrumentable;
32 import org.apache.excalibur.instrument.ValueInstrument;
33
34 /**
35  * General Pool implementation which supports; weak and strong pool size limits,
36  * optional blocking gets when poolables are not available, and automatic pool
37  * trimming of unused poolables.
38  * <p>
39  * Whenever get() is called, the pool tests to see whether it is time to trim old
40  * poolables from the pool. If any old poolables exist then they are removed at
41  * this time. This means that old poolables will not be removed if get() is never
42  * called. Applications can optionally call trim() to force old objects to be
43  * trimmed. See the {@link #trim()} method for details of how trimming works.
44  *
45  * @author <a HREF="mailto:dev@avalon.apache.org">Avalon Development Team</a>
46  * @version CVS $Revision: 1.1 $ $Date: 2004/03/29 16:50:37 $
47  * @since 4.1
48  */

49 public class InstrumentedResourceLimitingPool
50     extends AbstractLogEnabled
51     implements Pool, LogEnabled, Disposable, ThreadSafe, Instrumentable
52 {
53     public static final String JavaDoc DEFAULT_INSTRUMENTABLE_NAME = "pool";
54     public static final String JavaDoc INSTRUMENT_SIZE_NAME = "size";
55     public static final String JavaDoc INSTRUMENT_READY_SIZE_NAME = "ready-size";
56     public static final String JavaDoc INSTRUMENT_GETS_NAME = "gets";
57     public static final String JavaDoc INSTRUMENT_PUTS_NAME = "puts";
58     public static final String JavaDoc INSTRUMENT_BLOCKS_NAME = "blocks";
59     public static final String JavaDoc INSTRUMENT_CREATES_NAME = "creates";
60     public static final String JavaDoc INSTRUMENT_DECOMMISSIONS_NAME = "decommissions";
61
62     /*---------------------------------------------------------------
63      * Protected Fields
64      *-------------------------------------------------------------*/

65     /**
66      * Object used to synchronize access to the get and put methods
67      */

68     protected final Object JavaDoc m_semaphore = new Object JavaDoc();
69
70     /*---------------------------------------------------------------
71      * Private Fields
72      *-------------------------------------------------------------*/

73     /**
74      * Keeps track of whether or not the Pool has been disposed.
75      */

76     private boolean m_disposed = false;
77
78     /**
79      * The Object Factory used to generate new Poolable instances for the pool.
80      */

81     private final ObjectFactory m_factory;
82
83     /**
84      * The maximum size of the pool.
85      */

86     private final int m_max;
87
88     /**
89      * Whether or not the pool allows for the creation of objects beyond the maximum pool size.
90      */

91     private final boolean m_maxStrict;
92
93     /**
94      * Whether or not the pool should cause threads requesting a Poolable to block when m_maxStrict
95      * is true, the pool size is equal to m_max and there are no Poolable instances available.
96      */

97     private final boolean m_blocking;
98
99     /**
100      * The maximum amount of time in milliseconds that the pool will block. If 0, blocking will
101      * wait indeffinately.
102      */

103     private final long m_blockTimeout;
104
105     /**
106      * The minimum interval with which old unused poolables will be removed from the pool.
107      */

108     private final long m_trimInterval;
109
110     /**
111      * The last time that the pool was trimmed.
112      */

113     private long m_lastTrim;
114
115     /**
116      * List of the Poolable instances which are available for use.
117      */

118     private LinkedList JavaDoc m_ready;
119
120     /**
121      * Store the size of the ready list to optimize operations which require this value.
122      */

123     private int m_readySize;
124
125     /**
126      * List of the Poolable instance which are available for use but have been idle for a while.
127      */

128     private LinkedList JavaDoc m_oldReady;
129
130     /**
131      * Store the size of the old ready list to optimize operations which require this value.
132      */

133     private int m_oldReadySize;
134
135     /**
136      * Total number of Poolable instances in the pool
137      */

138     private int m_size;
139
140     /** Instrumentable Name assigned to this Instrumentable */
141     private String JavaDoc m_instrumentableName = DEFAULT_INSTRUMENTABLE_NAME;
142
143     /** Instrument used to profile the size of the pool. */
144     private ValueInstrument m_sizeInstrument;
145
146     /** Instrument used to profile the number of available poolables. */
147     private ValueInstrument m_readySizeInstrument;
148
149     /** Instrument used to profile the number of gets. */
150     private CounterInstrument m_getsInstrument;
151
152     /** Instrument used to profile the number of puts. */
153     private CounterInstrument m_putsInstrument;
154
155     /** Instrument used to profile the number of blocks. */
156     private CounterInstrument m_blocksInstrument;
157
158     /** Instrument used to profile the number of created poolables. */
159     private CounterInstrument m_createsInstrument;
160
161     /** Instrument used to profile the number of decommissioned poolables. */
162     private CounterInstrument m_decommissionsInstrument;
163
164     /*---------------------------------------------------------------
165      * Constructors
166      *-------------------------------------------------------------*/

167     /**
168      * Creates a new InstrumentedResourceLimitingPool
169      *
170      * @param factory The ObjectFactory which will be used to create new Poolables as needed by
171      * the pool.
172      * @param max Maximum number of Poolables which can be stored in the pool, 0 implies no limit.
173      * @param maxStrict true if the pool should never allow more than max Poolable to be created.
174      * Will cause an exception to be thrown if more than max Poolables are requested and blocking
175      * is false.
176      * @param blocking true if the pool should cause a thread calling get() to block when Poolables
177      * are not currently available in the pool.
178      * @param blockTimeout The maximum amount of time, in milliseconds, that a call to get() will
179      * block before an exception is thrown. A value of 0 implies an indefinate wait.
180      * @param trimInterval The minimum interval with which old unused poolables will be removed
181      * from the pool. A value of 0 will cause the pool to never trim poolables.
182      */

183     public InstrumentedResourceLimitingPool( final ObjectFactory factory,
184                                  int max,
185                                  boolean maxStrict,
186                                  boolean blocking,
187                                  long blockTimeout,
188                                  long trimInterval )
189     {
190         m_factory = factory;
191         m_max = ( max <= 0 ? Integer.MAX_VALUE : max );
192         m_maxStrict = maxStrict;
193         m_blocking = blocking;
194         m_blockTimeout = blockTimeout;
195         m_trimInterval = trimInterval;
196
197         // Create the pool lists.
198
m_ready = new LinkedList JavaDoc();
199         if( m_trimInterval > 0 )
200         {
201             m_oldReady = new LinkedList JavaDoc();
202         }
203
204         // Initialize the Instrumentable elements.
205
m_sizeInstrument = new ValueInstrument( INSTRUMENT_SIZE_NAME );
206         m_readySizeInstrument = new ValueInstrument( INSTRUMENT_READY_SIZE_NAME );
207         m_getsInstrument = new CounterInstrument( INSTRUMENT_GETS_NAME );
208         m_putsInstrument = new CounterInstrument( INSTRUMENT_PUTS_NAME );
209         m_blocksInstrument = new CounterInstrument( INSTRUMENT_BLOCKS_NAME );
210         m_createsInstrument = new CounterInstrument( INSTRUMENT_CREATES_NAME );
211         m_decommissionsInstrument = new CounterInstrument( INSTRUMENT_DECOMMISSIONS_NAME );
212     }
213
214     /*---------------------------------------------------------------
215      * Pool Methods
216      *-------------------------------------------------------------*/

217     /**
218      * Gets a Poolable from the pool. If there is room in the pool, a new Poolable will be
219      * created. Depending on the parameters to the constructor, the method may block or throw
220      * an exception if a Poolable is not available on the pool.
221      *
222      * @return Always returns a Poolable. Contract requires that put must always be called with
223      * the Poolable returned.
224      * @throws Exception An exception may be thrown as described above or if there is an exception
225      * thrown by the ObjectFactory's newInstance() method.
226      */

227     public Poolable get() throws Exception JavaDoc
228     {
229         if( m_disposed ) throw new IllegalStateException JavaDoc( "Already Disposed" );
230
231         Poolable poolable;
232         int readySize;
233         synchronized( m_semaphore )
234         {
235             // If trimming is enabled then trim if it is time
236
if( ( m_oldReady != null ) &&
237                 ( System.currentTimeMillis() - m_lastTrim >= m_trimInterval ) )
238             {
239                 trimInner();
240             }
241
242             // Look for a Poolable at the end of the m_ready list
243
if( m_readySize > 0 )
244             {
245                 // A poolable is ready and waiting in the pool
246
poolable = (Poolable)m_ready.removeLast();
247                 m_readySize--;
248             }
249             else if( m_oldReadySize > 0 )
250             {
251                 // An old poolable is ready and waiting in the pool
252
poolable = (Poolable)m_oldReady.removeLast();
253                 m_oldReadySize--;
254             }
255             else
256             {
257                 // Are we allowed to create a new poolable here?
258
if( ( m_size >= m_max ) && m_maxStrict )
259                 {
260                     // The pool has as many active Poolables as it is allowed and
261
// we are not allowed to create any more.
262

263                     // Are we allowed to wait for a Poolable to become available?
264
if( m_blocking )
265                     {
266                         long blockStart = System.currentTimeMillis();
267
268                         if( getLogger().isDebugEnabled() )
269                         {
270                             getLogger().debug( "Blocking until a Poolable is available. "
271                                                + "Thread: " + Thread.currentThread().getName() );
272                         }
273
274                         // Notify the InstrumentManager
275
m_blocksInstrument.increment();
276
277                         if( m_blockTimeout > 0 )
278                         {
279                             // Wait for a limited amount of time for a poolable is made
280
// available.
281
// Other threads may grab a connection before this thread gets the
282
// semaphore, so be careful.
283
long blockWait = m_blockTimeout;
284                             do
285                             {
286                                 if( blockWait > 0 )
287                                 {
288                                     try
289                                     {
290                                         m_semaphore.wait( blockWait );
291                                     }
292                                     catch( InterruptedException JavaDoc e )
293                                     {
294                                     }
295
296                                     // The dispose() method might have woken us up.
297
if( m_disposed )
298                                     {
299                                         throw new IllegalStateException JavaDoc( "Already Disposed" );
300                                     }
301
302                                     if( m_readySize == 0 )
303                                     {
304                                         // Not available yet, calculate how much longer to wait.
305
long now = System.currentTimeMillis();
306                                         blockWait = m_blockTimeout - ( now - blockStart );
307                                     }
308                                 }
309                                 else
310                                 {
311                                     // We timed out waiting.
312
long now = System.currentTimeMillis();
313
314                                     if( getLogger().isDebugEnabled() )
315                                     {
316                                         getLogger().debug(
317                                             "Timed out waiting for a Poolable to become "
318                                             + "available. Blocked for " + ( now - blockStart )
319                                             + "ms. Thread: " + Thread.currentThread().getName() );
320                                     }
321                                     throw new Exception JavaDoc
322                                         ( "Could not create enough Components to service your "
323                                           + "request (Timed out)." );
324                                 }
325                             } while( m_readySize == 0 );
326                         }
327                         else
328                         {
329                             // Wait until we get a poolable no matter how long it takes.
330
// Other threads may grab a connection before this thread gets the
331
// semaphore, so be careful.
332
do
333                             {
334                                 try
335                                 {
336                                     m_semaphore.wait();
337                                 }
338                                 catch( InterruptedException JavaDoc e )
339                                 {
340                                 }
341
342                                 // The dispose() method might have woken us up.
343
if( m_disposed )
344                                 {
345                                     throw new IllegalStateException JavaDoc( "Already Disposed" );
346                                 }
347                             } while( m_readySize == 0 );
348                         }
349
350                         // A poolable is ready and waiting in the pool
351
poolable = (Poolable)m_ready.removeLast();
352                         m_readySize--;
353
354                         if( getLogger().isDebugEnabled() )
355                         {
356                             long now = System.currentTimeMillis();
357                             getLogger().debug( "Blocked for " + ( now - blockStart ) + "ms "
358                                                + "waiting for a Poolable to become available. "
359                                                + "Thread: " + Thread.currentThread().getName() );
360                         }
361                     }
362                     else
363                     {
364                         // We must fail.
365
throw new Exception JavaDoc
366                             ( "Could not create enough Components to service your request." );
367                     }
368                 }
369                 else
370                 {
371                     // Create a new poolable. May throw an exception if the poolable can not be
372
// instantiated.
373
poolable = newPoolable();
374                     m_size++;
375
376                     if( getLogger().isDebugEnabled() )
377                     {
378                         getLogger().debug( "Created a new " + poolable.getClass().getName()
379                                            + " from the object factory." );
380                     }
381                 }
382             }
383             
384             readySize = getReadySizeSync();
385         }
386
387         if( getLogger().isDebugEnabled() )
388         {
389             getLogger().debug( "Got a " + poolable.getClass().getName() + " from the pool." );
390         }
391
392         // Notify the InstrumentManager
393
m_getsInstrument.increment();
394         m_readySizeInstrument.setValue( readySize );
395
396         return poolable;
397     }
398
399     /**
400      * Returns a poolable to the pool and notifies any thread blocking.
401      *
402      * @param poolable Poolable to return to the pool.
403      */

404     public void put( Poolable poolable )
405     {
406         // Handle Recyclable objects
407
if( poolable instanceof Recyclable )
408         {
409             ( (Recyclable)poolable ).recycle();
410         }
411
412         int readySize;
413         synchronized( m_semaphore )
414         {
415             if( m_size <= m_max )
416             {
417                 if( m_disposed )
418                 {
419                     // The pool has already been disposed.
420
if( getLogger().isDebugEnabled() )
421                     {
422                         getLogger().debug( "Put called for a " + poolable.getClass().getName()
423                                            + " after the pool was disposed." );
424                     }
425
426                     permanentlyRemovePoolable( poolable );
427                 }
428                 else
429                 {
430                     // There is room in the pool to keep this poolable.
431
if( getLogger().isDebugEnabled() )
432                     {
433                         getLogger().debug( "Put a " + poolable.getClass().getName()
434                                            + " back into the pool." );
435                     }
436
437                     m_ready.addLast( poolable );
438                     m_readySize++;
439
440                     // Let any waiting threads know that a poolable has become available.
441
if( m_blocking )
442                     {
443                         m_semaphore.notify();
444                     }
445                 }
446             }
447             else
448             {
449                 // More Poolables were created than can be held in the pool, so remove.
450
if( getLogger().isDebugEnabled() )
451                 {
452                     getLogger().debug( "No room to put a " + poolable.getClass().getName()
453                                        + " back into the pool, so remove it." );
454                 }
455
456                 permanentlyRemovePoolable( poolable );
457             }
458             
459             readySize = getReadySizeSync();
460         }
461
462         // Notify the InstrumentManager
463
m_putsInstrument.increment();
464         m_readySizeInstrument.setValue( readySize );
465     }
466
467     /*---------------------------------------------------------------
468      * Disposable Methods
469      *-------------------------------------------------------------*/

470     /**
471      * The dispose operation is called at the end of a components lifecycle.
472      * This method will be called after Startable.stop() method (if implemented
473      * by component). Components use this method to release and destroy any
474      * resources that the Component owns.
475      */

476     public void dispose()
477     {
478         m_disposed = true;
479
480         // Any Poolables in the m_ready list need to be disposed of
481
int size;
482         int readySize;
483         synchronized( m_semaphore )
484         {
485             // Remove objects in the ready list.
486
for( Iterator JavaDoc iter = m_ready.iterator(); iter.hasNext(); )
487             {
488                 Poolable poolable = (Poolable)iter.next();
489                 iter.remove();
490                 m_readySize--;
491                 permanentlyRemovePoolable( poolable );
492             }
493
494             // Remove objects in the old ready list.
495
if( m_oldReady != null )
496             {
497                 for( Iterator JavaDoc iter = m_oldReady.iterator(); iter.hasNext(); )
498                 {
499                     Poolable poolable = (Poolable)iter.next();
500                     iter.remove();
501                     m_oldReadySize--;
502                     permanentlyRemovePoolable( poolable );
503                 }
504             }
505
506             // Notify any threads currently waiting for objects so they can abort
507
if( m_blocking )
508             {
509                 m_semaphore.notifyAll();
510             }
511
512             if( ( m_size > 0 ) && getLogger().isDebugEnabled() )
513             {
514                 getLogger().debug( "There were " + m_size
515                                    + " outstanding objects when the pool was disposed." );
516             }
517             
518             size = getSize();
519             readySize = getReadySizeSync();
520         }
521
522         // Notify the InstrumentManager
523
m_sizeInstrument.setValue( size );
524         m_readySizeInstrument.setValue( readySize );
525     }
526
527     /*---------------------------------------------------------------
528      * Instrumentable Methods
529      *-------------------------------------------------------------*/

530     /**
531      * Sets the name for the Instrumentable. The Instrumentable Name is used
532      * to uniquely identify the Instrumentable during the configuration of
533      * the InstrumentManager and to gain access to an InstrumentableDescriptor
534      * through the InstrumentManager. The value should be a string which does
535      * not contain spaces or periods.
536      * <p>
537      * This value may be set by a parent Instrumentable, or by the
538      * InstrumentManager using the value of the 'instrumentable' attribute in
539      * the configuration of the component.
540      *
541      * @param name The name used to identify a Instrumentable.
542      */

543     public void setInstrumentableName( String JavaDoc name )
544     {
545         m_instrumentableName = name;
546     }
547
548     /**
549      * Gets the name of the Instrumentable.
550      *
551      * @return The name used to identify a Instrumentable.
552      */

553     public String JavaDoc getInstrumentableName()
554     {
555         return m_instrumentableName;
556     }
557
558     /**
559      * Obtain a reference to all the Instruments that the Instrumentable object
560      * wishes to expose. All sampling is done directly through the
561      * Instruments as opposed to the Instrumentable interface.
562      *
563      * @return An array of the Instruments available for profiling. Should
564      * never be null. If there are no Instruments, then
565      * EMPTY_INSTRUMENT_ARRAY can be returned. This should never be
566      * the case though unless there are child Instrumentables with
567      * Instruments.
568      */

569     public Instrument[] getInstruments()
570     {
571         return new Instrument[]
572         {
573             m_sizeInstrument,
574             m_readySizeInstrument,
575             m_getsInstrument,
576             m_putsInstrument,
577             m_blocksInstrument,
578             m_createsInstrument,
579             m_decommissionsInstrument
580         };
581     }
582
583     /**
584      * Any Object which implements Instrumentable can also make use of other
585      * Instrumentable child objects. This method is used to tell the
586      * InstrumentManager about them.
587      *
588      * @return An array of child Instrumentables. This method should never
589      * return null. If there are no child Instrumentables, then
590      * EMPTY_INSTRUMENTABLE_ARRAY can be returned.
591      */

592     public Instrumentable[] getChildInstrumentables()
593     {
594         return Instrumentable.EMPTY_INSTRUMENTABLE_ARRAY;
595     }
596
597     /*---------------------------------------------------------------
598      * Methods
599      *-------------------------------------------------------------*/

600     /**
601      * Permanently removes a poolable from the pool's active list and
602      * destroys it so that it will not ever be reused.
603      * <p>
604      * This method is only called by threads that have m_semaphore locked.
605      */

606     protected void permanentlyRemovePoolable( Poolable poolable )
607     {
608         m_size--;
609         removePoolable( poolable );
610     }
611
612     /**
613      * Returns the total number of Poolables created by the pool. Includes active and ready.
614      *
615      * @return The total size.
616      */

617     public int getSize()
618     {
619         return m_size;
620     }
621
622     /**
623      * Returns the number of available Poolables waiting in the pool.
624      * Only called when synchronized.
625      *
626      * @return The ready size.
627      */

628     private int getReadySizeSync()
629     {
630         return m_readySize + m_oldReadySize;
631     }
632     
633     /**
634      * Returns the number of available Poolables waiting in the pool.
635      *
636      * @return The ready size.
637      */

638     public int getReadySize()
639     {
640         synchronized( m_semaphore )
641         {
642             return getReadySizeSync();
643         }
644     }
645
646     /**
647      * Create a new poolable instance by by calling the newInstance method
648      * on the pool's ObjectFactory.
649      * <p>
650      * This is the method to override when you need to enforce creational
651      * policies.
652      * <p>
653      * This method is only called by threads that have m_semaphore locked.
654      */

655     protected Poolable newPoolable() throws Exception JavaDoc
656     {
657         Object JavaDoc obj = m_factory.newInstance();
658
659         // Notify the InstrumentManager
660
m_createsInstrument.increment();
661         // The size is incremented after this call in case an error is thrown.
662
m_sizeInstrument.setValue( getSize() + 1 );
663
664         return (Poolable)obj;
665     }
666
667     /**
668      * Called when an object is being removed permanently from the pool.
669      * This is the method to override when you need to enforce destructional
670      * policies.
671      * <p>
672      * This method is only called by threads that have m_semaphore locked.
673      *
674      * @param poolable Poolable to be completely removed from the pool.
675      */

676     protected void removePoolable( Poolable poolable )
677     {
678         try
679         {
680             m_factory.decommission( poolable );
681
682             // Notify the InstrumentManager
683
m_decommissionsInstrument.increment();
684             m_sizeInstrument.setValue( getSize() );
685         }
686         catch( Exception JavaDoc e )
687         {
688             if( getLogger().isDebugEnabled() )
689             {
690                 getLogger().debug( "Error decommissioning object", e );
691             }
692         }
693     }
694
695     /**
696      * Forces the pool to trim, remove, old Poolables from the pool. If the Pool
697      * was created with a non-zero value for trimInterval, then this method will
698      * be called at that interval when get() is called. If get() is not called
699      * for long periods of time then if may be necessary to call this method
700      * manually.
701      * <p>
702      * Trimming is done by maintaining two lists of objects. The first is a ready list
703      * of new poolables. The second is a list of old poolables. Each time trim() is
704      * called, the contents of the old list are removed from the pool. Then the
705      * contents of the new list is moved into the old list.
706      * <p>
707      * Each time get() is called on the pool, the new list is checked first, then the
708      * old list is checked, finally a new poolable may be created if both lists are
709      * empty. Then whenever put() is called, the poolables are always returned to
710      * the new list. In this way, the need for maining time stamps for each poolable
711      * can be avoided while at the same time avoiding unnecessary removal and creation
712      * on poolables.
713      * <p>
714      * This works out to a poolable having a maximum idle time of two calls to trim() or
715      * twice the value of trimInterval.
716      * <p>
717      * NOTE - The trimming feature does not harm performance because pools with high
718      * load will not have old poolables to be trimmed, and the benefits to system
719      * resources from not keeping around unused poolables makes up for any hit.
720      *
721      * @return the number of Poolables that were trimmed.
722      */

723     public int trim()
724     {
725         if( m_oldReady != null )
726         {
727             synchronized( m_semaphore )
728             {
729                 return trimInner();
730             }
731         }
732         else
733         {
734             throw new IllegalStateException JavaDoc( "This pool is not configured to do trimming." );
735         }
736     }
737
738     /**
739      * See trim() for details.
740      *
741      * This method is only called by threads that have m_semaphore locked.
742      */

743     private int trimInner()
744     {
745         int trimCount = 0;
746
747         // Remove any poolables in the m_oldReady list.
748
if( m_oldReadySize > 0 )
749         {
750             if( getLogger().isDebugEnabled() )
751             {
752                 getLogger().debug( "Trimming " + m_oldReadySize + " idle objects from pool." );
753             }
754
755             trimCount = m_oldReadySize;
756
757             for( Iterator JavaDoc iter = m_oldReady.iterator(); iter.hasNext(); )
758             {
759                 Poolable poolable = (Poolable)iter.next();
760                 iter.remove();
761                 m_oldReadySize--;
762                 permanentlyRemovePoolable( poolable );
763             }
764         }
765
766         // Move the poolables in m_ready into m_oldReady (swap lists)
767
if( getLogger().isDebugEnabled() )
768         {
769             getLogger().debug( "Marking " + m_readySize + " objects as old in pool." );
770         }
771         LinkedList JavaDoc tempList = m_oldReady;
772         m_oldReady = m_ready;
773         m_oldReadySize = m_readySize;
774         m_ready = tempList;
775         m_readySize = 0;
776
777         m_lastTrim = System.currentTimeMillis();
778
779         return trimCount;
780     }
781 }
782
Popular Tags