001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     * 
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     * 
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    package org.apache.commons.performance.dbcp;
019    
020    import java.sql.Connection;
021    import java.sql.ResultSet;
022    import java.sql.Statement;
023    import java.util.logging.Logger;
024    import javax.sql.DataSource;
025    
026    import org.apache.commons.performance.ClientThread;
027    import org.apache.commons.performance.Statistics;
028    
029    /**
030     * Client thread that executes requests in a loop using a configured
031     * DataSource, with the number of requests, time between requests and 
032     * query strings governed by constructor parameters. See 
033     * {@link ClientThread ClientThread javadoc} for a description
034     * of how times between requests are computed.
035     *
036     */
037    public class DBCPClientThread extends ClientThread {
038        /** Initial segment of query string */
039        private String queryString = null;
040        /** Whether or not the query is on the text column */
041        private boolean textQuery = false;
042        /** DataSource used to connect */
043        private DataSource dataSource = null;
044        /** Database connection */
045        Connection conn = null;
046        /** Current query */
047        String currentQuery = null;
048         
049        /**
050         * Create a dbcp client thread.
051         * 
052         * @param iterations number of iterations
053         * @param minDelay minimum delay time between client requests
054         * @param maxDelay maximum delay time between client requests
055         * @param sigma standard deviation of delay times between client requests
056         * @param delayType distribution of time between client requests
057         * @param queryType type of query 
058         * @param rampPeriod rampup, rampdown period for cyclic load
059         * @param peakPeriod period of sustained peak for cyclic load
060         * @param troughPeriod period of sustained minimum load
061         * @param cycleType type of cycle for mean delay
062         * @param rampType type of ramp (linear or random jumps)
063         * @param logger common logger shared by all clients
064         * @param dataSource DataSource for connections
065         * @param stats Statistics container
066         */
067        public DBCPClientThread(long iterations, long minDelay, long maxDelay,
068                double sigma, String delayType, String queryType, long rampPeriod,
069                long peakPeriod, long troughPeriod, String cycleType,
070                String rampType, Logger logger, DataSource dataSource,
071                Statistics stats) {
072            
073            super(iterations, minDelay, maxDelay, sigma, delayType, rampPeriod,
074                    peakPeriod, troughPeriod, cycleType, rampType, logger,
075                    stats);
076            
077            this.dataSource = dataSource;
078            
079            if (queryType.equals("no-op")) {
080                return;
081            }
082            
083            if (queryType.equals("integerIndexed")) {
084                queryString = "select * from test_table WHERE indexed=";
085            } else if (queryType.equals("integerScan")) {
086                queryString = "select * from test_table WHERE not_indexed=";  
087            } else {
088                queryString = "select * from test_table WHERE text='"; 
089                textQuery = true;
090            }
091        }
092        
093        /** Generate a random query */
094        public void setUp() throws Exception {
095            if (queryString == null) {
096                return;
097            }
098            if (textQuery) {
099                currentQuery = queryString +
100                    randomData.nextHexString(20) + "';";
101            } else {
102                currentQuery = queryString +
103                    randomData.nextInt(0, 100) + ";";
104            }
105        }
106        
107        /** Execute query */
108        public void execute() throws Exception {
109            conn = dataSource.getConnection();
110            if (queryString == null) {
111                return;
112            }
113            Statement stmt = conn.createStatement();
114            stmt.execute(currentQuery);
115            ResultSet rs = stmt.getResultSet();
116            if (!rs.isAfterLast()) {
117                rs.next();
118            }
119            rs.close();
120            stmt.close();
121        }
122        
123        /** Close connection */
124        public void cleanUp() throws Exception {
125            if (conn != null) {
126                try {
127                    conn.close();
128                } finally {
129                    conn = null;
130                } 
131            }
132        }
133    
134    }