View Javadoc

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 implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.performance.pool;
19  
20  import java.util.logging.Logger;
21  import org.apache.commons.dbcp.AbandonedConfig;
22  import org.apache.commons.dbcp.AbandonedObjectPool;
23  import org.apache.commons.pool.impl.GenericObjectPool;
24  import org.apache.commons.pool.impl.StackObjectPool;
25  import org.apache.commons.pool.impl.SoftReferenceObjectPool;
26  import org.apache.commons.pool.impl.GenericKeyedObjectPool;
27  import org.apache.commons.pool.impl.StackKeyedObjectPool;
28  import org.apache.commons.performance.ConfigurationException;
29  import org.apache.commons.performance.ClientThread;
30  import org.apache.commons.performance.LoadGenerator;
31  import org.apache.commons.performance.Statistics;
32   
33  /**
34   * Configurable load / performance tester for commons pool.
35   * Uses Commons Digester to parse and load configuration and spawns
36   * PoolClientThread instances to generate load and gather statistics.
37   *
38   */
39  public class PoolSoak extends LoadGenerator {
40      
41      // Pool instances
42      private GenericObjectPool genericObjectPool;
43      private GenericKeyedObjectPool genericKeyedObjectPool;
44      private StackObjectPool stackObjectPool;
45      private SoftReferenceObjectPool softReferenceObjectPool;
46      private StackKeyedObjectPool stackKeyedObjectPool;
47      
48      // Pool properties
49      private String poolType;
50      private int maxActive;       // maxActive for GOP, maxTotal for GKOP
51      private int maxActivePerKey; // maxActive for GKOP
52      private int maxIdle;
53      private int minIdle;
54      private long maxWait;
55      private byte exhaustedAction;
56      private boolean testOnBorrow;
57      private boolean testOnReturn;
58      private long timeBetweenEvictions;
59      private int testsPerEviction;
60      private long idleTimeout;
61      private boolean testWhileIdle;
62      private AbandonedConfig abandonedConfig = new AbandonedConfig();
63      private boolean lifo;
64      private double samplingRate;
65      
66      // WaiterFactory properties
67      private long activateLatency;
68      private long destroyLatency;
69      private long makeLatency;
70      private long passivateLatency;
71      private long validateLatency;
72      private long waiterLatency;
73      
74      /**
75       * Add pool configuration to parameters loaded by super.
76       * Also set config file name.
77       */
78      protected void configure() throws Exception {
79          super.configure();
80          digester.addCallMethod("configuration/factory", 
81                  "configureFactory", 6);
82          digester.addCallParam(
83                  "configuration/factory/activate-latency", 0);
84          digester.addCallParam(
85                  "configuration/factory/destroy-latency", 1);
86          digester.addCallParam(
87                  "configuration/factory/make-latency", 2);
88          digester.addCallParam(
89                  "configuration/factory/passivate-latency", 3);
90          digester.addCallParam(
91                  "configuration/factory/validate-latency", 4);
92          digester.addCallParam(
93                  "configuration/factory/waiter-latency", 5);   
94          digester.addCallMethod("configuration/pool", 
95                  "configurePool", 15);
96          digester.addCallParam(
97                  "configuration/pool/max-active", 0);
98          digester.addCallParam(
99                  "configuration/pool/max-active-per-key", 1);
100         digester.addCallParam(
101                 "configuration/pool/max-idle", 2);
102         digester.addCallParam(
103                 "configuration/pool/min-idle", 3);
104         digester.addCallParam(
105                 "configuration/pool/max-wait", 4);
106         digester.addCallParam(
107                 "configuration/pool/exhausted-action", 5);
108         digester.addCallParam(
109                 "configuration/pool/test-on-borrow", 6);
110         digester.addCallParam(
111                 "configuration/pool/test-on-return", 7);
112         digester.addCallParam(
113                 "configuration/pool/time-between-evictions", 8);
114         digester.addCallParam(
115                 "configuration/pool/tests-per-eviction", 9);
116         digester.addCallParam(
117                 "configuration/pool/idle-timeout", 10);
118         digester.addCallParam(
119                 "configuration/pool/test-while-idle", 11);
120         digester.addCallParam(
121                 "configuration/pool/lifo", 12);
122         digester.addCallParam(
123                 "configuration/pool/type", 13);
124         digester.addCallParam(
125                 "configuration/pool/sampling-rate", 14);
126         digester.addCallMethod("configuration/abandoned-config",
127                 "configureAbandonedConfig", 3);
128         digester.addCallParam(
129                 "configuration/abandoned-config/log-abandoned", 0);
130         digester.addCallParam(
131                 "configuration/abandoned-config/remove-abandoned", 1);
132         digester.addCallParam(
133                 "configuration/abandoned-config/abandoned-timeout", 2); 
134         
135         this.configFile = "config-pool.xml";
136         
137     }
138     
139     /**
140      * Create object pool and factory
141      */
142     protected void init() throws Exception {
143         // Create factory
144         WaiterFactory factory = new WaiterFactory(activateLatency, destroyLatency,
145                 makeLatency, passivateLatency, validateLatency, waiterLatency,
146                 maxActive, maxActivePerKey); 
147         
148         // Create object pool
149         if (poolType.equals("GenericObjectPool")) {
150             genericObjectPool = new GenericObjectPool(factory);
151             genericObjectPool.setMaxActive(maxActive);
152             genericObjectPool.setWhenExhaustedAction(exhaustedAction);
153             genericObjectPool.setMaxWait(maxWait);
154             genericObjectPool.setMaxIdle(maxIdle);
155             genericObjectPool.setMinIdle(minIdle);
156             genericObjectPool.setTestOnBorrow(testOnBorrow);
157             genericObjectPool.setTestOnReturn(testOnReturn);
158             genericObjectPool.setTimeBetweenEvictionRunsMillis(
159                     timeBetweenEvictions);
160             genericObjectPool.setNumTestsPerEvictionRun(testsPerEviction);
161             genericObjectPool.setMinEvictableIdleTimeMillis(idleTimeout);
162             genericObjectPool.setTestWhileIdle(testWhileIdle);
163             //genericObjectPool.setLifo(lifo);
164         } else if (poolType.equals("AbandonedObjectPool")) {
165             genericObjectPool = new AbandonedObjectPool(null,abandonedConfig);
166             genericObjectPool.setMaxActive(maxActive);
167             genericObjectPool.setWhenExhaustedAction(exhaustedAction);
168             genericObjectPool.setMaxWait(maxWait);
169             genericObjectPool.setMaxIdle(maxIdle);
170             genericObjectPool.setMinIdle(minIdle);
171             genericObjectPool.setTestOnBorrow(testOnBorrow);
172             genericObjectPool.setTestOnReturn(testOnReturn);
173             genericObjectPool.setTimeBetweenEvictionRunsMillis(
174                     timeBetweenEvictions);
175             genericObjectPool.setNumTestsPerEvictionRun(testsPerEviction);
176             genericObjectPool.setMinEvictableIdleTimeMillis(idleTimeout);
177             genericObjectPool.setTestWhileIdle(testWhileIdle);
178             //genericObjectPool.setLifo(lifo);
179             genericObjectPool.setFactory(factory);
180         } else if (poolType.equals("GenericKeyedObjectPool")) {
181             genericKeyedObjectPool = new GenericKeyedObjectPool();
182             genericKeyedObjectPool.setMaxActive(maxActivePerKey);
183             genericKeyedObjectPool.setMaxTotal(maxActive);
184             genericKeyedObjectPool.setWhenExhaustedAction(exhaustedAction);
185             genericKeyedObjectPool.setMaxWait(maxWait);
186             genericKeyedObjectPool.setMaxIdle(maxIdle);
187             genericKeyedObjectPool.setMinIdle(minIdle);
188             genericKeyedObjectPool.setTestOnBorrow(testOnBorrow);
189             genericKeyedObjectPool.setTestOnReturn(testOnReturn);
190             genericKeyedObjectPool.setTimeBetweenEvictionRunsMillis(
191                     timeBetweenEvictions);
192             genericKeyedObjectPool.setNumTestsPerEvictionRun(testsPerEviction);
193             genericKeyedObjectPool.setMinEvictableIdleTimeMillis(idleTimeout);
194             genericKeyedObjectPool.setTestWhileIdle(testWhileIdle);
195             //genericKeyedObjectPool.setLifo(lifo);
196             genericKeyedObjectPool.setFactory(factory);
197         } else if (poolType.equals("StackObjectPool")) {
198             stackObjectPool = new StackObjectPool();
199             stackObjectPool.setFactory(factory);
200         } else if (poolType.equals("SoftReferenceObjectPool")) {
201             softReferenceObjectPool = new SoftReferenceObjectPool();
202             softReferenceObjectPool.setFactory(factory);
203         } else if (poolType.equals("StackKeyedObjectPool")) {
204             stackKeyedObjectPool = new StackKeyedObjectPool();
205             stackKeyedObjectPool.setFactory(factory);
206         } else {
207             throw new ConfigurationException(
208                     "invalid pool type configuration: " + poolType);
209         }
210         
211         logger.info("Initialized pool with properties: ");
212         logger.info(" poolTypeT: " + poolType);
213         logger.info(" exhaustedAction: " + exhaustedAction);
214         logger.info(" maxActive: " + maxActive);
215         logger.info(" maxActivePerKey: " + maxActivePerKey);
216         logger.info(" maxIdle: " + maxIdle);
217         logger.info(" minIdle: " + minIdle);
218         logger.info(" testOnBorrow: " + testOnBorrow);
219         logger.info(" testWhileIdle: " + testWhileIdle);
220         logger.info(" timeBetweenEvictions: " + timeBetweenEvictions);
221         logger.info(" testsPerEviction: " + testsPerEviction);
222         logger.info(" idleTimeout: " + idleTimeout);
223         logger.info(" lifo: " + lifo);
224         logger.info(" abandonedConfig: ");
225         logger.info("  logAbandoned: " +
226                 abandonedConfig.getLogAbandoned());
227         logger.info("  removeAbandoned: " +
228                 abandonedConfig.getRemoveAbandoned());
229         logger.info("  abandonedTimeout: " + 
230                 abandonedConfig.getRemoveAbandonedTimeout()); 
231     }
232     
233     /**
234      * Close object pool
235      */
236     protected void cleanUp() throws Exception {
237         if (genericObjectPool != null) {
238             genericObjectPool.close();
239         }
240         if (genericKeyedObjectPool != null) {
241             genericKeyedObjectPool.close();
242         }
243         if (stackObjectPool != null) {
244             stackObjectPool.close();
245         }
246         if (softReferenceObjectPool != null) {
247             softReferenceObjectPool.close();
248         }
249         if (stackKeyedObjectPool != null) {
250             stackKeyedObjectPool.close();
251         }
252     }
253     
254     /**
255      * Create and return a PoolClientThread
256      */
257     protected ClientThread makeClientThread(long iterations, long minDelay,
258             long maxDelay, double sigma, String delayType, long rampPeriod,
259             long peakPeriod, long troughPeriod, String cycleType, 
260             String rampType, Logger logger, Statistics stats) {
261         if (poolType.equals("GenericObjectPool")) {
262             return new PoolClientThread(iterations, minDelay, maxDelay,
263                     sigma, delayType, rampPeriod, peakPeriod, troughPeriod,
264                     cycleType, rampType, logger, stats, genericObjectPool, 
265                     samplingRate);
266         }
267         if (poolType.equals("GenericKeyedObjectPool")) {
268             return new PoolClientThread(iterations, minDelay, maxDelay,
269                     sigma, delayType, rampPeriod, peakPeriod, troughPeriod,
270                     cycleType, rampType, logger, stats,
271                     genericKeyedObjectPool, samplingRate);
272         }
273         if (poolType.equals("StackKeyedObjectPool")) {
274             return new PoolClientThread(iterations, minDelay, maxDelay,
275                     sigma, delayType, rampPeriod, peakPeriod, troughPeriod,
276                     cycleType, rampType, logger, stats,
277                     stackKeyedObjectPool, samplingRate);
278         }
279         if (poolType.equals("StackObjectPool")) {
280             return new PoolClientThread(iterations, minDelay, maxDelay,
281                     sigma, delayType, rampPeriod, peakPeriod, troughPeriod,
282                     cycleType, rampType, logger, stats,
283                     stackObjectPool, samplingRate);
284         }
285         if (poolType.equals("SoftReferenceObjectPool")) {
286             return new PoolClientThread(iterations, minDelay, maxDelay,
287                     sigma, delayType, rampPeriod, peakPeriod, troughPeriod,
288                     cycleType, rampType, logger, stats,
289                     softReferenceObjectPool, samplingRate);
290         }
291         return null;
292     }
293     
294     // ------------------------------------------------------------------------
295     // Configuration methods specific to this LoadGenerator invoked by Digester
296     // when superclass execute calls digerster.parse.
297     // ------------------------------------------------------------------------       
298     public void configureFactory(String activateLatency, String destroyLatency,
299             String makeLatency, String passivateLatency, String validateLatency,
300             String waiterLatency) {
301        
302         this.activateLatency = Long.parseLong(activateLatency);
303         this.destroyLatency = Long.parseLong(destroyLatency);
304         this.makeLatency = Long.parseLong(makeLatency);
305         this.passivateLatency = Long.parseLong(passivateLatency);
306         this.validateLatency = Long.parseLong(validateLatency);
307         this.waiterLatency = Long.parseLong(waiterLatency);
308     }
309     
310     public void configurePool(String maxActive, String maxActivePerKey,
311             String maxIdle, String minIdle, String maxWait,
312             String exhaustedAction, String testOnBorrow,
313             String testOnReturn, String timeBetweenEvictions,
314             String testsPerEviction, String idleTimeout, 
315             String testWhileIdle, String lifo, String type, String samplingRate)
316         throws ConfigurationException { 
317         this.maxActive = Integer.parseInt(maxActive);
318         this.maxActivePerKey = Integer.parseInt(maxActivePerKey);
319         this.maxIdle = Integer.parseInt(maxIdle);
320         this.minIdle = Integer.parseInt(minIdle);
321         this.maxWait = Long.parseLong(maxWait);
322         this.testOnBorrow = Boolean.parseBoolean(testOnBorrow);
323         this.testOnReturn = Boolean.parseBoolean(testOnReturn);
324         this.timeBetweenEvictions = Long.parseLong(timeBetweenEvictions);
325         this.testsPerEviction = Integer.parseInt(testsPerEviction);
326         this.idleTimeout = Long.parseLong(idleTimeout);
327         this.testWhileIdle = Boolean.parseBoolean(testWhileIdle);
328         this.lifo = Boolean.parseBoolean(lifo);
329         this.poolType = type;
330         if (exhaustedAction.equals("block")) {
331             this.exhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_BLOCK;
332         } else if (exhaustedAction.equals("fail")) {
333             this.exhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_FAIL;
334         } else if (exhaustedAction.equals("grow")) {
335             this.exhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
336         } else { 
337             throw new ConfigurationException(
338             "Bad configuration setting for exhausted action: "
339                     + exhaustedAction); 
340         }  
341         this.samplingRate = Double.parseDouble(samplingRate);
342     }
343     
344     public void configureAbandonedConfig(String logAbandoned,
345             String removeAbandoned, String abandonedTimeout) {
346         abandonedConfig.setLogAbandoned(Boolean.parseBoolean(logAbandoned));
347         abandonedConfig.setRemoveAbandoned(
348                 Boolean.parseBoolean(removeAbandoned));
349         abandonedConfig.setRemoveAbandonedTimeout(
350                 Integer.parseInt(abandonedTimeout));
351     }
352     
353     // Pool getters for unit tests
354     protected GenericObjectPool getGenericObjectPool() {
355         return genericObjectPool;
356     }
357     
358     protected GenericKeyedObjectPool getGenericKeyedObjectPool() {
359         return genericKeyedObjectPool;
360     }
361     
362 }