You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jmeter.apache.org by pm...@apache.org on 2019/07/22 19:49:55 UTC
[jmeter] branch master updated: implemented preinit of jdbc
connection pool (#477)
This is an automated email from the ASF dual-hosted git repository.
pmouawad pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/jmeter.git
The following commit(s) were added to refs/heads/master by this push:
new 031807a implemented preinit of jdbc connection pool (#477)
031807a is described below
commit 031807aed3d8365513b9e0689ce599bc5d97ddc1
Author: Franz Schwab <fr...@users.noreply.github.com>
AuthorDate: Mon Jul 22 21:49:47 2019 +0200
implemented preinit of jdbc connection pool (#477)
* implemented pre-init of jdbc connection pool
Former-commit-id: f742eff6f3d7ad699610599890360eb9c00216ff
* added french translation, used JMeter built-in logging mechanism for sql exception, default value for pr-einit changed to FALSE to not break existing behavior
* removed whitespace due to checkstyle ant target error
* added documentation to the user manual
* changed screenshot of jdbc connection configuration dialogue
* add Exasol jdbc driver to documentation
* added a detailed comment about what we do exactly and why, and sorrounded the log output with is...Enabled() checks
* added assertion for pre-init of pool in batchtest JDBC_TESTS
* better assertion message for the pre-init test
---
bin/jmeter.properties | 4 +--
bin/testfiles/JDBC_TESTS.csv | 1 +
bin/testfiles/JDBC_TESTS.jmx | 37 +++++++++++++++++++++
bin/testfiles/JDBC_TESTS.xml | 7 ++++
.../protocol/jdbc/config/DataSourceElement.java | 35 +++++++++++++++++++
.../jdbc/config/DataSourceElementBeanInfo.java | 5 ++-
.../config/DataSourceElementResources.properties | 2 ++
.../DataSourceElementResources_fr.properties | 2 ++
.../screenshots/jdbc-config/jdbc-conn-config.png | Bin 14933 -> 26380 bytes
xdocs/usermanual/component_reference.xml | 16 +++++++--
xdocs/usermanual/properties_reference.xml | 2 +-
11 files changed, 105 insertions(+), 6 deletions(-)
diff --git a/bin/jmeter.properties b/bin/jmeter.properties
index 6fa7808..f5753f4 100644
--- a/bin/jmeter.properties
+++ b/bin/jmeter.properties
@@ -793,7 +793,7 @@ wmlParser.types=text/vnd.wap.wml
# Database validation query
# based in https://stackoverflow.com/questions/10684244/dbcp-validationquery-for-different-databases list
jdbc.config.check.query=select 1 from INFORMATION_SCHEMA.SYSTEM_USERS|select 1 from dual|select 1 from sysibm.sysdummy1|select 1|select 1 from rdb$database
-jdbc.config.jdbc.driver.class=com.mysql.jdbc.Driver|org.postgresql.Driver|oracle.jdbc.OracleDriver|com.ingres.jdbc.IngresDriver|com.microsoft.sqlserver.jdbc.SQLServerDriver|com.microsoft.jdbc.sqlserver.SQLServerDriver|org.apache.derby.jdbc.ClientDriver|org.hsqldb.jdbc.JDBCDriver|com.ibm.db2.jcc.DB2Driver|org.apache.derby.jdbc.ClientDriver|org.h2.Driver|org.firebirdsql.jdbc.FBDriver|org.mariadb.jdbc.Driver|org.sqlite.JDBC|net.sourceforge.jtds.jdbc.Driver
+jdbc.config.jdbc.driver.class=com.mysql.jdbc.Driver|org.postgresql.Driver|oracle.jdbc.OracleDriver|com.ingres.jdbc.IngresDriver|com.microsoft.sqlserver.jdbc.SQLServerDriver|com.microsoft.jdbc.sqlserver.SQLServerDriver|org.apache.derby.jdbc.ClientDriver|org.hsqldb.jdbc.JDBCDriver|com.ibm.db2.jcc.DB2Driver|org.apache.derby.jdbc.ClientDriver|org.h2.Driver|org.firebirdsql.jdbc.FBDriver|org.mariadb.jdbc.Driver|org.sqlite.JDBC|net.sourceforge.jtds.jdbc.Driver|com.exasol.jdbc.EXADriver
#---------------------------------------------------------------------------
# OS Process Sampler configuration
@@ -1343,4 +1343,4 @@ jmeter.reportgenerator.apdex_tolerated_threshold=1500
# Path to XSL file used to generate Schematic View of Test Plan
# When empty, JMeter will use the embedded one in src/core/org/apache/jmeter/gui/action/schematic.xsl
-#docgeneration.schematic_xsl=
\ No newline at end of file
+#docgeneration.schematic_xsl=
diff --git a/bin/testfiles/JDBC_TESTS.csv b/bin/testfiles/JDBC_TESTS.csv
index c7d06a6..d405c8f 100644
--- a/bin/testfiles/JDBC_TESTS.csv
+++ b/bin/testfiles/JDBC_TESTS.csv
@@ -1,4 +1,5 @@
label,responseCode,responseMessage,threadName,dataType,success,grpThreads,allThreads,SampleCount,ErrorCount
+JSR223_CHECK_POOL_PREINIT,200,OK,setUp Thread Group 1-1,text,true,1,1,1,0
JDBC_DROP_PROCEDURE,200,OK,setUp Thread Group 1-1,text,true,1,1,1,0
JDBC_DROP_PROCEDURE,200,OK,setUp Thread Group 1-1,text,true,1,1,1,0
JDBC_DROP_TABLE,200,OK,setUp Thread Group 1-1,text,true,1,1,1,0
diff --git a/bin/testfiles/JDBC_TESTS.jmx b/bin/testfiles/JDBC_TESTS.jmx
index 2ead07b..6f35336 100644
--- a/bin/testfiles/JDBC_TESTS.jmx
+++ b/bin/testfiles/JDBC_TESTS.jmx
@@ -25,6 +25,7 @@
<stringProp name="transactionIsolation">DEFAULT</stringProp>
<stringProp name="trimInterval">60000</stringProp>
<stringProp name="username">SA</stringProp>
+ <boolProp name="preinit">true</boolProp>
</JDBCDataSource>
<hashTree/>
<SetupThreadGroup guiclass="SetupThreadGroupGui" testclass="SetupThreadGroup" testname="setUp Thread Group" enabled="true">
@@ -42,6 +43,42 @@
<stringProp name="ThreadGroup.delay"></stringProp>
</SetupThreadGroup>
<hashTree>
+ <JSR223Sampler guiclass="TestBeanGUI" testclass="JSR223Sampler" testname="JSR223_CHECK_POOL_PREINIT" enabled="true">
+ <stringProp name="scriptLanguage">groovy</stringProp>
+ <stringProp name="parameters"></stringProp>
+ <stringProp name="filename"></stringProp>
+ <stringProp name="cacheKey">true</stringProp>
+ <stringProp name="script">//dummy sampler, just needed for the assertion</stringProp>
+ </JSR223Sampler>
+ <hashTree>
+ <JSR223Assertion guiclass="TestBeanGUI" testclass="JSR223Assertion" testname="JSR223_CHECK_POOL_PREINIT_ASSERTION" enabled="true">
+ <stringProp name="scriptLanguage">groovy</stringProp>
+ <stringProp name="parameters"></stringProp>
+ <stringProp name="filename"></stringProp>
+ <stringProp name="cacheKey">true</stringProp>
+ <stringProp name="script">
+import groovy.sql.Sql
+
+def url = 'jdbc:hsqldb:mem:mymemdb'
+def user = 'SA'
+def password = ''
+def driver = 'org.hsqldb.jdbcDriver'
+def sql = Sql.newInstance(url, user, password, driver)
+def row = sql.firstRow('select count(*) from INFORMATION_SCHEMA.system_sessions')
+def sessionNum = row[0]
+
+try {
+ assert sessionNum == 2
+} catch (Error err) {
+ AssertionResult.setFailure(true)
+ AssertionResult.setFailureMessage("Got " + sessionNum + " sessions on the database, but expected 2 sessions. (1 preinitialized session from the connection pool, and 1 from the above jdbc call.)");
+}
+
+sql.close()
+</stringProp>
+ </JSR223Assertion>
+ <hashTree/>
+ </hashTree>
<JDBCSampler guiclass="TestBeanGUI" testclass="JDBCSampler" testname="JDBC_DROP_PROCEDURE" enabled="true">
<stringProp name="dataSource">dbConfig</stringProp>
<stringProp name="query">drop PROCEDURE new_user IF EXISTS;
diff --git a/bin/testfiles/JDBC_TESTS.xml b/bin/testfiles/JDBC_TESTS.xml
index 62eb164..27b0726 100644
--- a/bin/testfiles/JDBC_TESTS.xml
+++ b/bin/testfiles/JDBC_TESTS.xml
@@ -1,5 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<testResults version="1.2">
+<sample s="true" lb="JSR223_CHECK_POOL_PREINIT" rc="200" rm="OK" tn="setUp Thread Group 1-1" dt="text" sc="1" ec="0" ng="1" na="1">
+ <assertionResult>
+ <name>JSR223_CHECK_POOL_PREINIT_ASSERTION</name>
+ <failure>false</failure>
+ <error>false</error>
+ </assertionResult>
+</sample>
<sample s="true" lb="JDBC_DROP_PROCEDURE" rc="200" rm="OK" tn="setUp Thread Group 1-1" dt="text" sc="1" ec="0" ng="1" na="1">
<assertionResult>
<name>RA</name>
diff --git a/src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/config/DataSourceElement.java b/src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/config/DataSourceElement.java
index 35ec44a..8887dcb 100644
--- a/src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/config/DataSourceElement.java
+++ b/src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/config/DataSourceElement.java
@@ -59,6 +59,7 @@ public class DataSourceElement extends AbstractTestElement
private transient boolean keepAlive;
private transient boolean autocommit;
+ private transient boolean preinit;
/*
* The datasource is set up by testStarted and cleared by testEnded.
@@ -218,6 +219,8 @@ public class DataSourceElement extends AbstractTestElement
sb.append(getTrimInterval());
sb.append(" Auto-Commit: ");
sb.append(isAutocommit());
+ sb.append(" Preinit: ");
+ sb.append(isPreinit());
log.debug(sb.toString());
}
int poolSize = Integer.parseInt(maxPool);
@@ -288,6 +291,23 @@ public class DataSourceElement extends AbstractTestElement
dataSource.setPassword(getPassword());
}
+ if(isPreinit()) {
+ // side effect - connection pool init - that is what we want
+ // see also https://commons.apache.org/proper/commons-dbcp/apidocs/org/apache/commons/dbcp2/BasicDataSource.html#setInitialSize-int-
+ // it says: "The pool is initialized the first time one of the following methods is invoked: getConnection, setLogwriter, setLoginTimeout, getLoginTimeout, getLogWriter."
+ // so we get a connection and close it - which releases it back to the pool (but stays open)
+ try {
+ dataSource.getConnection().close();
+ if (log.isDebugEnabled()) {
+ log.debug("Preinitializing the connection pool: {}@{}", getDataSourceName(), System.identityHashCode(dataSource));
+ }
+ } catch (SQLException ex) {
+ if (log.isErrorEnabled()) {
+ log.error("Error preinitializing the connection pool: {}@{}", getDataSourceName(), System.identityHashCode(dataSource), ex);
+ }
+ }
+ }
+
log.debug("PoolConfiguration:{}", this.dataSource);
return dataSource;
}
@@ -544,6 +564,21 @@ public class DataSourceElement extends AbstractTestElement
}
/**
+ * @return Returns the preinit.
+ */
+ public boolean isPreinit() {
+ return preinit;
+ }
+
+ /**
+ * @param preinit
+ * The preinit to set.
+ */
+ public void setPreinit(boolean preinit) {
+ this.preinit = preinit;
+ }
+
+ /**
* @return Returns the keepAlive.
*/
public boolean isKeepAlive() {
diff --git a/src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/config/DataSourceElementBeanInfo.java b/src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/config/DataSourceElementBeanInfo.java
index c3a5a7d..2474cf1 100644
--- a/src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/config/DataSourceElementBeanInfo.java
+++ b/src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/config/DataSourceElementBeanInfo.java
@@ -54,7 +54,7 @@ public class DataSourceElementBeanInfo extends BeanInfoSupport {
createPropertyGroup("varName", new String[] { "dataSource" });
createPropertyGroup("pool", new String[] { "poolMax", "timeout",
- "trimInterval", "autocommit", "transactionIsolation", "initQuery" });
+ "trimInterval", "autocommit", "transactionIsolation", "preinit", "initQuery" });
createPropertyGroup("keep-alive", new String[] { "keepAlive", "connectionAge", "checkQuery" });
@@ -82,6 +82,9 @@ public class DataSourceElementBeanInfo extends BeanInfoSupport {
Set<String> modesSet = TRANSACTION_ISOLATION_MAP.keySet();
String[] modes = modesSet.toArray(new String[modesSet.size()]);
p.setValue(TAGS, modes);
+ p = property("preinit");
+ p.setValue(NOT_UNDEFINED, Boolean.TRUE);
+ p.setValue(DEFAULT, Boolean.FALSE);
p = property("initQuery", TypeEditor.TextAreaEditor);
p.setValue(NOT_UNDEFINED, Boolean.TRUE);
p.setValue(DEFAULT, "");
diff --git a/src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/config/DataSourceElementResources.properties b/src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/config/DataSourceElementResources.properties
index d5acb59..16571c0 100644
--- a/src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/config/DataSourceElementResources.properties
+++ b/src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/config/DataSourceElementResources.properties
@@ -46,3 +46,5 @@ keepAlive.displayName=Test While Idle
keepAlive.shortDescription=Whether the pool should validate connections while they are idle in Pool. If no, Soft Min Evictable Idle Time and Validation Query are ignored.
transactionIsolation.displayName=Transaction Isolation
transactionIsolation.shortDescription=Transaction Isolation Level
+preinit.displayName=Preinit Pool
+preinit.shortDescription=Preinitialize the whole connection pool by requesting one connection from it.
diff --git a/src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/config/DataSourceElementResources_fr.properties b/src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/config/DataSourceElementResources_fr.properties
index fb2d2f1..0ff2a48 100644
--- a/src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/config/DataSourceElementResources_fr.properties
+++ b/src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/config/DataSourceElementResources_fr.properties
@@ -47,3 +47,5 @@ username.shortDescription=L'identifiant à utiliser pour la connexion à la base
varName.displayName=Nom de liaison du pool
transactionIsolation.displayName=Isolation de la Transaction
transactionIsolation.shortDescription=Niveau d'isolation de la transaction
+preinit.displayName=Préinit Pool
+preinit.shortDescription=Préinitialise l'ensemble du pool de connexions en lui demandant une connexion.
diff --git a/xdocs/images/screenshots/jdbc-config/jdbc-conn-config.png b/xdocs/images/screenshots/jdbc-config/jdbc-conn-config.png
index b31811b..7834bce 100644
Binary files a/xdocs/images/screenshots/jdbc-config/jdbc-conn-config.png and b/xdocs/images/screenshots/jdbc-config/jdbc-conn-config.png differ
diff --git a/xdocs/usermanual/component_reference.xml b/xdocs/usermanual/component_reference.xml
index 1003901..49f5f05 100644
--- a/xdocs/usermanual/component_reference.xml
+++ b/xdocs/usermanual/component_reference.xml
@@ -3910,7 +3910,7 @@ instead. (see figures 12 and 13).</p>
</component>
<component name="JDBC Connection Configuration" index="§-num;.4.10"
- width="697" height="656" screenshot="jdbc-config/jdbc-conn-config.png">
+ width="687" height="669" screenshot="jdbc-config/jdbc-conn-config.png">
<description>Creates a database connection (used by <complink name="JDBC Request"/>Sampler)
from the supplied JDBC Connection settings. The connection may be optionally pooled between threads.
Otherwise each thread gets its own connection.
@@ -3941,6 +3941,7 @@ instead. (see figures 12 and 13).</p>
See <a href="https://commons.apache.org/proper/commons-dbcp/api-2.1.1/org/apache/commons/dbcp2/BasicDataSource.html#getTimeBetweenEvictionRunsMillis--" >BasicDataSource.html#getTimeBetweenEvictionRunsMillis</a></property>
<property name="Auto Commit" required="Yes">Turn auto commit on or off for the connections.</property>
<property name="Transaction isolation" required="Yes">Transaction isolation level</property>
+ <property name="Preinit Pool" required="No">The connection pool can be intialized instantly. If set to <code>False</code> (default), the JDBC request samplers using this pool might measure higher response times for the first queries – as the connection establishment time for the whole pool is included.</property>
<property name="Init SQL statements separated by new line" required="No">A Collection of SQL statements that will be used to initialize physical connections when they are first created. These statements are executed only once - when the configured connection factory creates the connection. </property>
<property name="Test While Idle" required="Yes">Test idle connections of the pool, see <a href="https://commons.apache.org/proper/commons-dbcp/api-2.1.1/org/apache/commons/dbcp2/BasicDataSource.html#getTestWhileIdle--">BasicDataSource.html#getTestWhileIdle</a>.
Validation Query will be used to test it.</property>
@@ -3963,6 +3964,7 @@ instead. (see figures 12 and 13).</p>
<dt>Derby</dt><dd><code>values 1</code></dd>
<dt>H2</dt><dd><code>select 1</code></dd>
<dt>Firebird</dt><dd><code>select 1 from rdb$database</code></dd>
+ <dt>Exasol</dt><dd><code>select 1</code></dd>
</dl>
<note>The list come from <a href="https://stackoverflow.com/questions/10684244/dbcp-validationquery-for-different-databases">stackoverflow entry on different database validation queries</a> and it can be incorrect</note>
<note>Note this validation query is used on pool creation to validate it even if "<code>Test While Idle</code>" suggests query would only be used on idle connections.
@@ -3971,7 +3973,7 @@ instead. (see figures 12 and 13).</p>
<property name="Database URL" required="Yes">JDBC Connection string for the database.</property>
<property name="JDBC Driver class" required="Yes">Fully qualified name of driver class. (Must be in
JMeter's classpath - easiest to copy <code>.jar</code> file into JMeter's <code>/lib</code> directory).
- <p>The list of the validation queries can be configured with <code>jdbc.config.jdbc.driver.class</code> property and are by default:</p>
+ <p>The list of the preconfigured jdbc driver classes can be configured with <code>jdbc.config.jdbc.driver.class</code> property and are by default:</p>
<dl>
<dt>hsqldb</dt><dd>org.hsqldb.jdbc.JDBCDriver</dd>
<dt>Oracle</dt><dd>oracle.jdbc.OracleDriver</dd>
@@ -3987,6 +3989,7 @@ instead. (see figures 12 and 13).</p>
<dt>MariaDB</dt><dd>org.mariadb.jdbc.Driver</dd>
<dt>SQLite</dt><dd>org.sqlite.JDBC</dd>
<dt>Sybase AES</dt><dd>net.sourceforge.jtds.jdbc.Driver</dd>
+ <dt>Exasol</dt><dd>com.exasol.jdbc.EXADriver</dd>
</dl>
</property>
<property name="Username" required="No">Name of user to connect as.</property>
@@ -4071,6 +4074,15 @@ If the database server is not running or is not accessible, then JMeter will rep
<dd><code>jdbc:mariadb://host[:port]/dbname[;URLAttributes=value[;…]]</code></dd>
</dl>
</dd>
+ <dt>Exasol (see also <a href="https://docs.exasol.com/connect_exasol/drivers/jdbc.htm" >JDBC driver documentation</a>)</dt>
+ <dd>
+ <dl>
+ <dt>Driver class</dt>
+ <dd><code>com.exasol.jdbc.EXADriver</code></dd>
+ <dt>Database URL</dt>
+ <dd><code>jdbc:exa:host[:port][;schema=SCHEMA_NAME][;prop_x=value_x]</code></dd>
+ </dl>
+ </dd>
</dl>
<note>The above may not be correct - please check the relevant JDBC driver documentation.</note>
</component>
diff --git a/xdocs/usermanual/properties_reference.xml b/xdocs/usermanual/properties_reference.xml
index b0af6f3..87994c8 100644
--- a/xdocs/usermanual/properties_reference.xml
+++ b/xdocs/usermanual/properties_reference.xml
@@ -1026,7 +1026,7 @@ JMETER-SERVER</source>
</property>
<property name="jdbc.config.jdbc.driver.class">
List of JDBC driver class name<br/>
- Defaults to: <source>com.mysql.jdbc.Driver|org.postgresql.Driver|oracle.jdbc.OracleDriver|com.ingres.jdbc.IngresDriver|com.microsoft.sqlserver.jdbc.SQLServerDriver|com.microsoft.jdbc.sqlserver.SQLServerDriver|org.apache.derby.jdbc.ClientDriver|org.hsqldb.jdbc.JDBCDriver|com.ibm.db2.jcc.DB2Driver|org.apache.derby.jdbc.ClientDriver|org.h2.Driver|org.firebirdsql.jdbc.FBDriver|org.mariadb.jdbc.Driver|org.sqlite.JDBC|net.sourceforge.jtds.jdbc.Driver</source>
+ Defaults to: <source>com.mysql.jdbc.Driver|org.postgresql.Driver|oracle.jdbc.OracleDriver|com.ingres.jdbc.IngresDriver|com.microsoft.sqlserver.jdbc.SQLServerDriver|com.microsoft.jdbc.sqlserver.SQLServerDriver|org.apache.derby.jdbc.ClientDriver|org.hsqldb.jdbc.JDBCDriver|com.ibm.db2.jcc.DB2Driver|org.apache.derby.jdbc.ClientDriver|org.h2.Driver|org.firebirdsql.jdbc.FBDriver|org.mariadb.jdbc.Driver|org.sqlite.JDBC|net.sourceforge.jtds.jdbc.Driver|com.exasol.jdbc.EXADriver</source>
</property>
</properties>
</section>