/[Apache-SVN]/commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/dbcp/DBCPSoak.java
ViewVC logotype

Contents of /commons/sandbox/performance/trunk/src/java/org/apache/commons/performance/dbcp/DBCPSoak.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 668357 - (show annotations)
Tue Jun 17 00:17:33 2008 UTC (17 months, 1 week ago) by psteitz
File size: 15874 byte(s)
Added cleanUp to LoadGenerator.
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.dbcp;
19
20
21 import java.sql.Connection;
22 import java.sql.Driver;
23 import java.sql.DriverManager;
24 import java.sql.Statement;
25 import java.util.Properties;
26 import java.util.logging.Logger;
27 import org.apache.commons.dbcp.AbandonedConfig;
28 import org.apache.commons.dbcp.AbandonedObjectPool;
29 import org.apache.commons.dbcp.ConnectionFactory;
30 import org.apache.commons.dbcp.DriverConnectionFactory;
31 import org.apache.commons.dbcp.DriverManagerConnectionFactory;
32 import org.apache.commons.dbcp.PoolableConnectionFactory;
33 import org.apache.commons.dbcp.PoolingDataSource;
34 import org.apache.commons.pool.KeyedObjectPoolFactory;
35 import org.apache.commons.pool.PoolableObjectFactory;
36 import org.apache.commons.pool.impl.GenericKeyedObjectPool;
37 import org.apache.commons.pool.impl.GenericKeyedObjectPoolFactory;
38 import org.apache.commons.pool.impl.GenericObjectPool;
39 import org.apache.commons.math.random.RandomData;
40 import org.apache.commons.math.random.RandomDataImpl;
41 import org.apache.commons.performance.ConfigurationException;
42 import org.apache.commons.performance.ClientThread;
43 import org.apache.commons.performance.LoadGenerator;
44 import org.apache.commons.performance.Statistics;
45
46 /**
47 * Configurable load / performance tester for commons dbcp.
48 * Uses Commons Digester to parse and load configuration and spawns
49 * DBCPClientThread instances to generate load and gather statistics.
50 *
51 */
52 public class DBCPSoak extends LoadGenerator {
53 // Connection properties
54 private String driverClass;
55 private String connectUrl;
56 private String connectUser;
57 private String connectPassword;
58 private String queryType;
59
60 // Connection pool properties
61 private String poolType;
62 private String driverType;
63 private String factoryType;
64 private boolean autocommit;
65 private boolean readOnly;
66 private byte exhaustedAction;
67 private boolean testOnBorrow;
68 private boolean testOnReturn;
69 private long timeBetweenEvictions;
70 private int testsPerEviction;
71 private long idleTimeout;
72 private boolean testWhileIdle;
73 private String validationQuery;
74 private AbandonedConfig abandonedConfig = new AbandonedConfig();
75 private boolean poolPreparedStatements;
76 private int maxOpenStatements;
77 private int maxActive;
78 private int maxIdle;
79 private int minIdle;
80 private long maxWait;
81
82 // Instance variables
83 private GenericObjectPool connectionPool;
84 private PoolingDataSource dataSource;
85
86 /**
87 * Create connection pool and, if necessary, test table.
88 */
89 protected void init() throws Exception {
90 Class.forName(driverClass);
91
92 // Create object pool
93 if (poolType.equals("GenericObjectPool")) {
94 connectionPool = new GenericObjectPool(
95 null, maxActive, exhaustedAction,
96 maxWait, maxIdle, minIdle, testOnBorrow, testOnReturn,
97 timeBetweenEvictions, testsPerEviction, idleTimeout,
98 testWhileIdle);
99 } else if (poolType.equals("AbandonedObjectPool")) {
100 connectionPool = new AbandonedObjectPool(null,abandonedConfig);
101 } else {
102 throw new ConfigurationException(
103 "invalid pool type configuration: " + poolType);
104 }
105
106 // Create raw connection factory
107 ConnectionFactory connectionFactory = null;
108 if (driverType.equals("DriverManager")) {
109 connectionFactory = new DriverManagerConnectionFactory(
110 connectUrl,connectUser,
111 connectPassword);
112 } else if (driverType.equals("Driver")) {
113 Properties props = new Properties();
114 props.put("user", connectUser);
115 props.put("password", connectPassword);
116 connectionFactory = new DriverConnectionFactory(
117 (Driver) Class.forName(driverClass).newInstance(),
118 connectUrl, props);
119 } else {
120 throw new ConfigurationException(
121 "Bad config setting for driver type");
122 }
123
124 // Create object factory
125 PoolableObjectFactory poolableConnectionFactory = null;
126 KeyedObjectPoolFactory statementPoolFactory = null;
127 if (poolPreparedStatements) { // Use same defaults as BasicDataSource
128 statementPoolFactory = new GenericKeyedObjectPoolFactory(null,
129 -1, // unlimited maxActive (per key)
130 GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL,
131 0, // maxWait
132 1, // maxIdle (per key)
133 maxOpenStatements); //TODO: make all configurable
134 }
135 if (factoryType.equals("PoolableConnectionFactory")) {
136 poolableConnectionFactory =
137 new PoolableConnectionFactory(
138 connectionFactory,connectionPool, statementPoolFactory,
139 validationQuery, readOnly, autocommit);
140 } else if (factoryType.equals("CPDSConnectionFactory")) {
141 throw new ConfigurationException(
142 "CPDSConnectionFactory not implemented yet");
143 } else {
144 throw new ConfigurationException(
145 "Invalid factory type: " + factoryType);
146 }
147
148 // Create DataSource
149 dataSource = new PoolingDataSource(connectionPool);
150
151 // Try to connect and query test_table. If "test_table" appears in
152 // exception message, assume table needs to be created.
153 Connection conn = dataSource.getConnection();
154 try {
155 Statement stmnt = conn.createStatement();
156 stmnt.execute("select * from test_table where indexed=1;");
157 stmnt.close();
158 } catch (Exception ex) {
159 if (ex.getMessage().indexOf("test_table") > 0) {
160 logger.info("Creating test_table");
161 makeTable();
162 logger.info("test_table created successfully");
163 } else {
164 throw ex;
165 }
166 } finally {
167 conn.close();
168 }
169 }
170
171 /**
172 * Close connection pool
173 */
174 protected void cleanUp() throws Exception {
175 connectionPool.close();
176 }
177
178 protected ClientThread makeClientThread(
179 long iterations, long minDelay, long maxDelay, double sigma,
180 String delayType, long rampPeriod, long peakPeriod,
181 long troughPeriod, String cycleType, String rampType,
182 Logger logger, Statistics stats) {
183
184 return new DBCPClientThread(iterations, minDelay, maxDelay,
185 sigma, delayType, queryType, rampPeriod, peakPeriod,
186 troughPeriod, cycleType, rampType, logger, dataSource,
187 stats);
188 }
189
190 // ------------------------------------------------------------------------
191 // Configuration methods specific to this LoadGenerator invoked by Digester
192 // when superclass execute calls digester.parse.
193 // ------------------------------------------------------------------------
194 public void configureDataBase(String driver, String url,
195 String username, String password, String queryType) {
196 this.driverClass = driver;
197 this.connectUrl = url;
198 this.connectUser = username;
199 this.connectPassword = password;
200 this.queryType = queryType;
201 }
202
203 public void configureConnectionFactory(String type,
204 String autoCommit, String readOnly, String validationQuery) {
205 this.driverType = type;
206 this.autocommit = Boolean.parseBoolean(autoCommit);
207 this.readOnly = Boolean.parseBoolean(readOnly);
208 this.validationQuery = validationQuery;
209 }
210
211 public void configurePoolableConnectionFactory(String type,
212 String poolPreparedStatements, String maxOpenStatements) {
213 this.factoryType = type;
214 this.poolPreparedStatements =
215 Boolean.parseBoolean(poolPreparedStatements);
216 this.maxOpenStatements = Integer.parseInt(maxOpenStatements);
217 }
218
219 public void configurePool(String maxActive, String maxIdle, String minIdle,
220 String maxWait, String exhaustedAction, String testOnBorrow,
221 String testOnReturn, String timeBetweenEvictions,
222 String testsPerEviction, String idleTimeout,
223 String testWhileIdle, String type) throws ConfigurationException {
224 this.maxActive = Integer.parseInt(maxActive);
225 this.maxIdle = Integer.parseInt(maxIdle);
226 this.minIdle = Integer.parseInt(minIdle);
227 this.maxWait = Long.parseLong(maxWait);
228 this.testOnBorrow = Boolean.parseBoolean(testOnBorrow);
229 this.testOnReturn = Boolean.parseBoolean(testOnReturn);
230 this.timeBetweenEvictions = Long.parseLong(timeBetweenEvictions);
231 this.testsPerEviction = Integer.parseInt(testsPerEviction);
232 this.idleTimeout = Long.parseLong(idleTimeout);
233 this.testWhileIdle = Boolean.parseBoolean(testWhileIdle);
234 this.poolType = type;
235 if (exhaustedAction.equals("block")) {
236 this.exhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_BLOCK;
237 } else if (exhaustedAction.equals("fail")) {
238 this.exhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_FAIL;
239 } else if (exhaustedAction.equals("grow")) {
240 this.exhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
241 } else {
242 throw new ConfigurationException(
243 "Bad configuration setting for exhausted action: "
244 + exhaustedAction);
245 }
246 }
247
248 public void configureAbandonedConfig(String logAbandoned,
249 String removeAbandoned, String abandonedTimeout) {
250 abandonedConfig.setLogAbandoned(Boolean.parseBoolean(logAbandoned));
251 abandonedConfig.setRemoveAbandoned(
252 Boolean.parseBoolean(removeAbandoned));
253 abandonedConfig.setRemoveAbandonedTimeout(
254 Integer.parseInt(abandonedTimeout));
255 }
256
257 /**
258 * Creates and populates the test table (test_table) used in the
259 * load tests. The created table will have 10,000 rows and 3 columns,
260 * populated with random data: <ul>
261 * <li> indexed (indexed integer column) </li>
262 * <li> not_indexed (non-indexed integer column) </li>
263 * <li> text (non-indexed varchar column) </li>
264 * </ul>
265 *
266 * @throws Exception
267 */
268 protected void makeTable() throws Exception {
269 Class.forName(driverClass);
270 Connection db = DriverManager.getConnection(connectUrl,connectUser,
271 connectPassword);
272 try {
273 Statement sql = db.createStatement();
274 String sqlText =
275 "create table test_table (indexed int, text varchar(20)," +
276 " not_indexed int)";
277 sql.executeUpdate(sqlText);
278 sqlText = "CREATE INDEX test1_id_index ON test_table (indexed);";
279 sql.executeUpdate(sqlText);
280 RandomData randomData = new RandomDataImpl();
281 for (int i = 0; i < 10000; i++) {
282 int indexed = randomData.nextInt(0, 100);
283 int not_indexed = randomData.nextInt(0, 1000);
284 String text = randomData.nextHexString(20);
285 sqlText =
286 "INSERT INTO test_table (indexed, text, not_indexed)" +
287 "VALUES (" + indexed + "," + "'"+ text + "'," +
288 not_indexed + ");";
289 sql.executeUpdate(sqlText);
290 }
291 sql.close();
292 } finally {
293 db.close();
294 }
295 }
296
297 /**
298 * Add dbcp configuration to parameters loaded by super.
299 * Also set config file name.
300 */
301 protected void configure() throws Exception {
302
303 super.configure();
304
305 digester.addCallMethod("configuration/database",
306 "configureDataBase", 5);
307 digester.addCallParam("configuration/database/driver", 0);
308 digester.addCallParam("configuration/database/url", 1);
309 digester.addCallParam("configuration/database/username", 2);
310 digester.addCallParam("configuration/database/password", 3);
311 digester.addCallParam("configuration/database/query-type", 4);
312
313 digester.addCallMethod("configuration/connection-factory",
314 "configureConnectionFactory", 4);
315 digester.addCallParam(
316 "configuration/connection-factory/type", 0);
317 digester.addCallParam(
318 "configuration/connection-factory/auto-commit", 1);
319 digester.addCallParam(
320 "configuration/connection-factory/read-only", 2);
321 digester.addCallParam(
322 "configuration/connection-factory/validation-query", 3);
323
324 digester.addCallMethod("configuration/poolable-connection-factory",
325 "configurePoolableConnectionFactory", 3);
326 digester.addCallParam(
327 "configuration/poolable-connection-factory/type", 0);
328 digester.addCallParam(
329 "configuration/poolable-connection-factory/pool-prepared-statements", 1);
330 digester.addCallParam(
331 "configuration/poolable-connection-factory/max-open-statements", 2);
332
333 digester.addCallMethod("configuration/pool",
334 "configurePool", 12);
335 digester.addCallParam(
336 "configuration/pool/max-active", 0);
337 digester.addCallParam(
338 "configuration/pool/max-idle", 1);
339 digester.addCallParam(
340 "configuration/pool/min-idle", 2);
341 digester.addCallParam(
342 "configuration/pool/max-wait", 3);
343 digester.addCallParam(
344 "configuration/pool/exhausted-action", 4);
345 digester.addCallParam(
346 "configuration/pool/test-on-borrow", 5);
347 digester.addCallParam(
348 "configuration/pool/test-on-return", 6);
349 digester.addCallParam(
350 "configuration/pool/time-between-evictions", 7);
351 digester.addCallParam(
352 "configuration/pool/tests-per-eviction", 8);
353 digester.addCallParam(
354 "configuration/pool/idle-timeout", 9);
355 digester.addCallParam(
356 "configuration/pool/test-while-idle", 10);
357 digester.addCallParam(
358 "configuration/pool/type", 11);
359
360 digester.addCallMethod("configuration/abandoned-config",
361 "configureAbandonedConfig", 3);
362 digester.addCallParam(
363 "configuration/abandoned-config/log-abandoned", 0);
364 digester.addCallParam(
365 "configuration/abandoned-config/remove-abandoned", 1);
366 digester.addCallParam(
367 "configuration/abandoned-config/abandoned-timeout", 2);
368
369 this.configFile = "config-dbcp.xml";
370 }
371
372 public GenericObjectPool getConnectionPool() {
373 return connectionPool;
374 }
375 }

Properties

Name Value
svn:eol-style native

apache@apache.org
ViewVC Help
Powered by ViewVC 1.1.2