Package org.apache.jmeter.protocol.jdbc.config

Source Code of org.apache.jmeter.protocol.jdbc.config.DataSourceElement$DataSourceComponentImpl

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jmeter.protocol.jdbc.config;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.avalon.excalibur.datasource.DataSourceComponent;
import org.apache.avalon.excalibur.datasource.ResourceLimitingJdbcDataSource;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.configuration.DefaultConfiguration;
import org.apache.avalon.framework.logger.LogKitLogger;
import org.apache.jmeter.config.ConfigElement;
import org.apache.jmeter.engine.event.LoopIterationEvent;
import org.apache.jmeter.testbeans.TestBean;
import org.apache.jmeter.testbeans.TestBeanHelper;
import org.apache.jmeter.testelement.AbstractTestElement;
import org.apache.jmeter.testelement.TestListener;
import org.apache.jmeter.threads.JMeterContextService;
import org.apache.jmeter.threads.JMeterVariables;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;

public class DataSourceElement extends AbstractTestElement
    implements ConfigElement, TestListener, TestBean
    {
  private static final Logger log = LoggingManager.getLoggerForClass();

  transient String dataSource, driver, dbUrl, username, password, checkQuery, poolMax, connectionAge, timeout,
      trimInterval;

  transient boolean keepAlive, autocommit;

  /*
   *  The datasource is set up by testStarted and cleared by testEnded.
   *  These are called from different threads, so access must be synchronized.
   *  The same instance is called in each case.
  */
  transient ResourceLimitingJdbcDataSource excaliburSource;

  // Keep a record of the pre-thread pools so that they can be disposed of at the end of a test
  private transient Set perThreadPoolSet = Collections.synchronizedSet(new HashSet());
 
  public DataSourceElement() {
  }

  public void testEnded() {
    synchronized (this) {
      if (excaliburSource != null) {
        excaliburSource.dispose();
      }
        excaliburSource = null;
    }
    if (perThreadPoolSet != null) {// in case
      Iterator it = perThreadPoolSet.iterator();
      while(it.hasNext()){
        ResourceLimitingJdbcDataSource dsc = (ResourceLimitingJdbcDataSource)it.next();
        log.debug("Disposing pool: "+dsc.getInstrumentableName()+" @"+System.identityHashCode(dsc));
        dsc.dispose();
      }
      perThreadPoolSet.clear();
    }
  }

  public void testEnded(String host) {
    testEnded();
  }

  public void testIterationStart(LoopIterationEvent event) {
  }

  public void testStarted() {
        this.setRunningVersion(true);
        TestBeanHelper.prepare(this);
    JMeterVariables variables = getThreadContext().getVariables();
    String poolName = getDataSource();
    if (variables.getObject(poolName) != null) {
      log.error("JDBC data source already defined for: "+poolName);
    } else {
      String maxPool = getPoolMax();
      if (maxPool.equals("0")){ // i.e. if we want per thread pooling
        variables.putObject(poolName, new DataSourceComponentImpl()); // pool will be created later
      } else {
        ResourceLimitingJdbcDataSource src=initPool(maxPool);
        synchronized(this){
          excaliburSource = src;
            variables.putObject(poolName, new DataSourceComponentImpl(excaliburSource));
        }
      }
    }
  }

  public void testStarted(String host) {
    testStarted();
  }

  public Object clone() {
    DataSourceElement el = (DataSourceElement) super.clone();
    el.excaliburSource = excaliburSource;
    el.perThreadPoolSet = perThreadPoolSet;
    return el;
  }

  /*
   * Utility routine to get the connection from the pool.
   * Purpose:
   * - allows JDBCSampler to be entirely independent of the pooling classes
   * - allows the pool storage mechanism to be changed if necessary
   */
  public static Connection getConnection(String poolName) throws SQLException{
    DataSourceComponent pool = (DataSourceComponent)
        JMeterContextService.getContext().getVariables().getObject(poolName);
    if (pool == null) {
      throw new SQLException("No pool found named: '" + poolName + "'");
    }
    return pool.getConnection();
  }

  /*
   * Set up the DataSource - maxPool is a parameter, so the same code can
   * also be used for setting up the per-thread pools.
  */
  private ResourceLimitingJdbcDataSource initPool(String maxPool) {
    ResourceLimitingJdbcDataSource source = null;
    source = new ResourceLimitingJdbcDataSource();
    DefaultConfiguration config = new DefaultConfiguration("rl-jdbc"); // $NON-NLS-1$

    if (log.isDebugEnabled()) {
      StringBuffer sb = new StringBuffer(40);
      sb.append("MaxPool: ");
      sb.append(maxPool);
      sb.append(" Timeout: ");
      sb.append(getTimeout());
      sb.append(" TrimInt: ");
      sb.append(getTrimInterval());
      sb.append(" Auto-Commit: ");
      sb.append(isAutocommit());
      log.debug(sb.toString());
    }
    DefaultConfiguration poolController = new DefaultConfiguration("pool-controller"); // $NON-NLS-1$
    poolController.setAttribute("max", maxPool); // $NON-NLS-1$
    poolController.setAttribute("max-strict", "true"); // $NON-NLS-1$ $NON-NLS-2$
    poolController.setAttribute("blocking", "true"); // $NON-NLS-1$ $NON-NLS-2$
    poolController.setAttribute("timeout", getTimeout()); // $NON-NLS-1$
    poolController.setAttribute("trim-interval", getTrimInterval()); // $NON-NLS-1$
    config.addChild(poolController);

    DefaultConfiguration autoCommit = new DefaultConfiguration("auto-commit"); // $NON-NLS-1$
    autoCommit.setValue(String.valueOf(isAutocommit()));
    config.addChild(autoCommit);
   
    if (log.isDebugEnabled()) {
      StringBuffer sb = new StringBuffer(40);
      sb.append("KeepAlive: ");
      sb.append(isKeepAlive());
      sb.append(" Age: ");
      sb.append(getConnectionAge());
      sb.append(" CheckQuery: ");
      sb.append(getCheckQuery());
      log.debug(sb.toString());
    }
    DefaultConfiguration cfgKeepAlive = new DefaultConfiguration("keep-alive"); // $NON-NLS-1$
    cfgKeepAlive.setAttribute("disable", String.valueOf(!isKeepAlive())); // $NON-NLS-1$
    cfgKeepAlive.setAttribute("age", getConnectionAge()); // $NON-NLS-1$
    cfgKeepAlive.setValue(getCheckQuery());
    poolController.addChild(cfgKeepAlive);

    String _username = getUsername();
    if (log.isDebugEnabled()) {
      StringBuffer sb = new StringBuffer(40);
      sb.append("Driver: ");
      sb.append(getDriver());
      sb.append(" DbUrl: ");
      sb.append(getDbUrl());
      sb.append(" User: ");
      sb.append(_username);
      log.debug(sb.toString());
    }
    DefaultConfiguration cfgDriver = new DefaultConfiguration("driver"); // $NON-NLS-1$
    cfgDriver.setValue(getDriver());
    config.addChild(cfgDriver);
    DefaultConfiguration cfgDbUrl = new DefaultConfiguration("dburl"); // $NON-NLS-1$
    cfgDbUrl.setValue(getDbUrl());
    config.addChild(cfgDbUrl);

    if (_username.length() > 0){
      DefaultConfiguration cfgUsername = new DefaultConfiguration("user"); // $NON-NLS-1$
      cfgUsername.setValue(_username);
      config.addChild(cfgUsername);
      DefaultConfiguration cfgPassword = new DefaultConfiguration("password"); // $NON-NLS-1$
      cfgPassword.setValue(getPassword());
      config.addChild(cfgPassword);
    }

    // log is required to ensure errors are available
    source.enableLogging(new LogKitLogger(log));
    try {
      source.configure(config);
      source.setInstrumentableName(getDataSource());
    } catch (ConfigurationException e) {
      log.error("Could not configure datasource for pool: "+getDataSource(),e);
    }
    return source;
  }

  // used to hold per-thread singleton connection pools
  private static final ThreadLocal perThreadPoolMap = new ThreadLocal(){
    protected synchronized Object initialValue() {
            return new HashMap();
        }
  };
 
  /*
   * Wrapper class to allow getConnection() to be implemented for both shared
   * and per-thread pools.
   *
   */
  private class DataSourceComponentImpl implements DataSourceComponent{

    private final ResourceLimitingJdbcDataSource sharedDSC;
   
    DataSourceComponentImpl(){
      sharedDSC=null;
    }
   
    DataSourceComponentImpl(ResourceLimitingJdbcDataSource p_dsc){
      sharedDSC=p_dsc;
    }

    public Connection getConnection() throws SQLException {
      Connection conn = null;
      ResourceLimitingJdbcDataSource dsc = null;
      if (sharedDSC != null){ // i.e. shared pool
        dsc = sharedDSC;
      } else {
        Map poolMap = (Map) perThreadPoolMap.get();
        dsc = (ResourceLimitingJdbcDataSource) poolMap.get(getDataSource());
        if (dsc == null){
          dsc = initPool("1");
          poolMap.put(getDataSource(),dsc);
          log.debug("Storing pool: "+dsc.getInstrumentableName()+" @"+System.identityHashCode(dsc));
          perThreadPoolSet.add(dsc);
        }
      }
      if (dsc != null) {
          conn=dsc.getConnection();
      }
      return conn;
    }

    public void configure(Configuration arg0) throws ConfigurationException {
    }
   
  }

  public void addConfigElement(ConfigElement config) {
  }

  public boolean expectsModification() {
    return false;
  }

  /**
   * @return Returns the checkQuery.
   */
  public String getCheckQuery() {
    return checkQuery;
  }

  /**
   * @param checkQuery
   *            The checkQuery to set.
   */
  public void setCheckQuery(String checkQuery) {
    this.checkQuery = checkQuery;
  }

  /**
   * @return Returns the connectionAge.
   */
  public String getConnectionAge() {
    return connectionAge;
  }

  /**
   * @param connectionAge
   *            The connectionAge to set.
   */
  public void setConnectionAge(String connectionAge) {
    this.connectionAge = connectionAge;
  }

  /**
   * @return Returns the poolname.
   */
  public String getDataSource() {
    return dataSource;
  }

  /**
   * @param dataSource
   *            The poolname to set.
   */
  public void setDataSource(String dataSource) {
    this.dataSource = dataSource;
  }

  /**
   * @return Returns the dbUrl.
   */
  public String getDbUrl() {
    return dbUrl;
  }

  /**
   * @param dbUrl
   *            The dbUrl to set.
   */
  public void setDbUrl(String dbUrl) {
    this.dbUrl = dbUrl;
  }

  /**
   * @return Returns the driver.
   */
  public String getDriver() {
    return driver;
  }

  /**
   * @param driver
   *            The driver to set.
   */
  public void setDriver(String driver) {
    this.driver = driver;
  }

  /**
   * @return Returns the password.
   */
  public String getPassword() {
    return password;
  }

  /**
   * @param password
   *            The password to set.
   */
  public void setPassword(String password) {
    this.password = password;
  }

  /**
   * @return Returns the poolMax.
   */
  public String getPoolMax() {
    return poolMax;
  }

  /**
   * @param poolMax
   *            The poolMax to set.
   */
  public void setPoolMax(String poolMax) {
    this.poolMax = poolMax;
  }

  /**
   * @return Returns the timeout.
   */
  public String getTimeout() {
    return timeout;
  }

  /**
   * @param timeout
   *            The timeout to set.
   */
  public void setTimeout(String timeout) {
    this.timeout = timeout;
  }

  /**
   * @return Returns the trimInterval.
   */
  public String getTrimInterval() {
    return trimInterval;
  }

  /**
   * @param trimInterval
   *            The trimInterval to set.
   */
  public void setTrimInterval(String trimInterval) {
    this.trimInterval = trimInterval;
  }

  /**
   * @return Returns the username.
   */
  public String getUsername() {
    return username;
  }

  /**
   * @param username
   *            The username to set.
   */
  public void setUsername(String username) {
    this.username = username;
  }

  /**
   * @return Returns the autocommit.
   */
  public boolean isAutocommit() {
    return autocommit;
  }

  /**
   * @param autocommit
   *            The autocommit to set.
   */
  public void setAutocommit(boolean autocommit) {
    this.autocommit = autocommit;
  }

  /**
   * @return Returns the keepAlive.
   */
  public boolean isKeepAlive() {
    return keepAlive;
  }

  /**
   * @param keepAlive
   *            The keepAlive to set.
   */
  public void setKeepAlive(boolean keepAlive) {
    this.keepAlive = keepAlive;
  }
}
TOP

Related Classes of org.apache.jmeter.protocol.jdbc.config.DataSourceElement$DataSourceComponentImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.