KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > dbcp > TestAbandonedObjectPool


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

16
17 package org.apache.commons.dbcp;
18
19 import java.util.Vector JavaDoc;
20
21 import junit.framework.Test;
22 import junit.framework.TestCase;
23 import junit.framework.TestSuite;
24
25 import org.apache.commons.pool.PoolableObjectFactory;
26
27 /**
28  * TestCase for AbandonedObjectPool
29  *
30  * @author Wayne Woodfield
31  * @version $Revision: 1.2 $ $Date: 2004/05/04 17:56:10 $
32  */

33 public class TestAbandonedObjectPool extends TestCase {
34     private AbandonedObjectPool pool = null;
35     private AbandonedConfig config = null;
36     
37     public TestAbandonedObjectPool(String JavaDoc testName) {
38         super(testName);
39     }
40
41     public static Test suite() {
42         return new TestSuite(TestAbandonedObjectPool.class);
43     }
44
45     public void setUp() throws Exception JavaDoc {
46         super.setUp();
47         config = new AbandonedConfig();
48         
49         // -- Uncomment the following line to enable logging --
50
// config.setLogAbandoned(true);
51

52         config.setRemoveAbandoned(true);
53         config.setRemoveAbandonedTimeout(1);
54         pool = new AbandonedObjectPool(new SimpleFactory(), config);
55     }
56
57     public void tearDown() throws Exception JavaDoc {
58         super.tearDown();
59         pool.close();
60         pool = null;
61     }
62
63     /**
64     * Tests fix for Bug 28579, a bug in AbandonedObjectPool that causes numActive to go negative
65     * in GenericObjectPool
66     */

67     public void testConcurrentInvalidation() throws Exception JavaDoc {
68         final int POOL_SIZE = 30;
69         pool.setMaxActive(POOL_SIZE);
70         pool.setMaxIdle(POOL_SIZE);
71         pool.setWhenExhaustedAction(AbandonedObjectPool.WHEN_EXHAUSTED_FAIL);
72
73         // Exhaust the connection pool
74
Vector JavaDoc vec = new Vector JavaDoc();
75         for (int i = 0; i < POOL_SIZE; i++) {
76             vec.add(pool.borrowObject());
77         }
78         
79         // Abandon all borrowed objects
80
for (int i = 0; i < vec.size(); i++) {
81             ((PooledTestObject)vec.elementAt(i)).setAbandoned(true);
82         }
83
84         // Try launching a bunch of borrows concurrently. Abandoned sweep will be triggered for each.
85
final int CONCURRENT_BORROWS = 5;
86         Thread JavaDoc[] threads = new Thread JavaDoc[CONCURRENT_BORROWS];
87         for (int i = 0; i < CONCURRENT_BORROWS; i++) {
88             threads[i] = new ConcurrentBorrower(vec);
89             threads[i].start();
90         }
91
92         // Wait for all the threads to finish
93
for (int i = 0; i < CONCURRENT_BORROWS; i++) {
94             threads[i].join();
95         }
96         
97         // Return all objects that have not been destroyed
98
for (int i = 0; i < vec.size(); i++) {
99             PooledTestObject pto = (PooledTestObject)vec.elementAt(i);
100             if (pto.isActive()) {
101                 pool.returnObject(pto);
102             }
103         }
104         
105         // Now, the number of open connections should be 0
106
assertTrue("numActive should have been 0, was " + pool.getNumActive(), pool.getNumActive() == 0);
107     }
108     
109     class ConcurrentBorrower extends Thread JavaDoc {
110         private Vector JavaDoc _borrowed;
111         
112         public ConcurrentBorrower(Vector JavaDoc borrowed) {
113             _borrowed = borrowed;
114         }
115         
116         public void run() {
117             try {
118                 _borrowed.add(pool.borrowObject());
119             } catch (Exception JavaDoc e) {
120                 // expected in most cases
121
}
122         }
123     }
124     
125     class SimpleFactory implements PoolableObjectFactory {
126
127         public Object JavaDoc makeObject() {
128             return new PooledTestObject(config);
129         }
130         
131         public boolean validateObject(Object JavaDoc obj) { return true; }
132         
133         public void activateObject(Object JavaDoc obj) {
134             ((PooledTestObject)obj).setActive(true);
135         }
136         
137         public void passivateObject(Object JavaDoc obj) {
138             ((PooledTestObject)obj).setActive(false);
139         }
140
141         public void destroyObject(Object JavaDoc obj) {
142             ((PooledTestObject)obj).setActive(false);
143             // while destroying connections, yield control to other threads
144
// helps simulate threading errors
145
Thread.yield();
146         }
147     }
148 }
149
150 class PooledTestObject extends AbandonedTrace {
151     private boolean active = false;
152     private int _hash = 0;
153     private boolean _abandoned = false;
154
155     private static int hash = 1;
156     
157     public PooledTestObject(AbandonedConfig config) {
158         super(config);
159         _hash = hash++;
160     }
161     
162     public synchronized void setActive(boolean b) {
163         active = b;
164     }
165
166     public synchronized boolean isActive() {
167         return active;
168     }
169     
170     public int hashCode() {
171         return _hash;
172     }
173     
174     public void setAbandoned(boolean b) {
175         _abandoned = b;
176     }
177     
178     protected long getLastUsed() {
179         if (_abandoned) {
180             // Abandoned object sweep will occur no matter what the value of removeAbandonedTimeout,
181
// because this indicates that this object was last used decades ago
182
return 1;
183         } else {
184             // Abandoned object sweep won't clean up this object
185
return 0;
186         }
187     }
188     
189     public boolean equals(Object JavaDoc obj) {
190         if (!(obj instanceof PooledTestObject)) return false;
191         return obj.hashCode() == hashCode();
192     }
193 }
194
195
Popular Tags