View | Details | Raw Unified | Return to bug 60085
Collapse All | Expand All

(-)a/bin/jmeter.properties (-4 / +1 lines)
Lines 821-829 wmlParser.types=text/vnd.wap.wml Link Here
821
# JDBC Request configuration
821
# JDBC Request configuration
822
#---------------------------------------------------------------------------
822
#---------------------------------------------------------------------------
823
823
824
# Max number of PreparedStatements per Connection for PreparedStatement cache
825
#jdbcsampler.maxopenpreparedstatements=100
826
827
# String used to indicate a null value
824
# String used to indicate a null value
828
#jdbcsampler.nullmarker=]NULL[
825
#jdbcsampler.nullmarker=]NULL[
829
826
Lines 1245-1248 system.properties=system.properties Link Here
1245
1242
1246
# Force throuput controllers that work in percentage mode to be a 100%
1243
# Force throuput controllers that work in percentage mode to be a 100%
1247
# Disabled by default
1244
# Disabled by default
1248
#testplan_validation.tpc_force_100_pct=false
1245
#testplan_validation.tpc_force_100_pct=false
(-)a/src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/AbstractJDBCTestElement.java (-65 / +5 lines)
Lines 36-48 import java.sql.Timestamp; Link Here
36
import java.sql.Types;
36
import java.sql.Types;
37
import java.util.ArrayList;
37
import java.util.ArrayList;
38
import java.util.Collection;
38
import java.util.Collection;
39
import java.util.Collections;
40
import java.util.HashMap;
39
import java.util.HashMap;
41
import java.util.List;
40
import java.util.List;
42
import java.util.Map;
41
import java.util.Map;
43
import java.util.concurrent.ConcurrentHashMap;
44
42
45
import org.apache.commons.collections.map.LRUMap;
46
import org.apache.jmeter.samplers.SampleResult;
43
import org.apache.jmeter.samplers.SampleResult;
47
import org.apache.jmeter.save.CSVSaveService;
44
import org.apache.jmeter.save.CSVSaveService;
48
import org.apache.jmeter.testelement.AbstractTestElement;
45
import org.apache.jmeter.testelement.AbstractTestElement;
Lines 69-77 public abstract class AbstractJDBCTestElement extends AbstractTestElement implem Link Here
69
    // String used to indicate a null value
66
    // String used to indicate a null value
70
    private static final String NULL_MARKER =
67
    private static final String NULL_MARKER =
71
        JMeterUtils.getPropDefault("jdbcsampler.nullmarker","]NULL["); // $NON-NLS-1$
68
        JMeterUtils.getPropDefault("jdbcsampler.nullmarker","]NULL["); // $NON-NLS-1$
72
    
73
    private static final int MAX_OPEN_PREPARED_STATEMENTS =
74
        JMeterUtils.getPropDefault("jdbcsampler.maxopenpreparedstatements", 100); 
75
69
76
    private static final String INOUT = "INOUT"; // $NON-NLS-1$
70
    private static final String INOUT = "INOUT"; // $NON-NLS-1$
77
71
Lines 131-144 public abstract class AbstractJDBCTestElement extends AbstractTestElement implem Link Here
131
    private String queryTimeout = ""; // $NON-NLS-1$
125
    private String queryTimeout = ""; // $NON-NLS-1$
132
126
133
    /**
127
    /**
134
     *  Cache of PreparedStatements stored in a per-connection basis. Each entry of this
135
     *  cache is another Map mapping the statement string to the actual PreparedStatement.
136
     *  At one time a Connection is only held by one thread
137
     */
138
    private static final Map<Connection, Map<String, PreparedStatement>> perConnCache =
139
            new ConcurrentHashMap<>();
140
141
    /**
142
     * Creates a JDBCSampler.
128
     * Creates a JDBCSampler.
143
     */
129
     */
144
    protected AbstractJDBCTestElement() {
130
    protected AbstractJDBCTestElement() {
Lines 446-495 public abstract class AbstractJDBCTestElement extends AbstractTestElement implem Link Here
446
    }
432
    }
447
433
448
    private PreparedStatement getPreparedStatement(Connection conn, boolean callable) throws SQLException {
434
    private PreparedStatement getPreparedStatement(Connection conn, boolean callable) throws SQLException {
449
        Map<String, PreparedStatement> preparedStatementMap = perConnCache.get(conn);
435
        PreparedStatement pstmt;
450
        if (null == preparedStatementMap ) {
436
        if (callable) {
451
            @SuppressWarnings("unchecked") // LRUMap is not generic
437
            pstmt = conn.prepareCall(getQuery());
452
            Map<String, PreparedStatement> lruMap = new LRUMap(MAX_OPEN_PREPARED_STATEMENTS) {
453
                private static final long serialVersionUID = 1L;
454
                @Override
455
                protected boolean removeLRU(LinkEntry entry) {
456
                    PreparedStatement preparedStatement = (PreparedStatement)entry.getValue();
457
                    close(preparedStatement);
458
                    return true;
459
                }
460
            };
461
            preparedStatementMap = Collections.<String, PreparedStatement>synchronizedMap(lruMap);
462
            // As a connection is held by only one thread, we cannot already have a 
463
            // preparedStatementMap put by another thread
464
            perConnCache.put(conn, preparedStatementMap);
465
        }
466
        PreparedStatement pstmt = preparedStatementMap.get(getQuery());
467
        if (null == pstmt) {
468
            if (callable) {
469
                pstmt = conn.prepareCall(getQuery());
470
            } else {
471
                pstmt = conn.prepareStatement(getQuery());
472
            }
473
            pstmt.setQueryTimeout(getIntegerQueryTimeout());
474
            // PreparedStatementMap is associated to one connection so 
475
            //  2 threads cannot use the same PreparedStatement map at the same time
476
            preparedStatementMap.put(getQuery(), pstmt);
477
        } else {
438
        } else {
478
            int timeoutInS = getIntegerQueryTimeout();
439
            pstmt = conn.prepareStatement(getQuery());
479
            if(pstmt.getQueryTimeout() != timeoutInS) {
480
                pstmt.setQueryTimeout(getIntegerQueryTimeout());
481
            }
482
        }
440
        }
483
        pstmt.clearParameters();
441
        pstmt.setQueryTimeout(getIntegerQueryTimeout());
484
        return pstmt;
442
        return pstmt;
485
    }
443
    }
486
444
487
    private static void closeAllStatements(Collection<PreparedStatement> collection) {
488
        for (PreparedStatement pstmt : collection) {
489
            close(pstmt);
490
        }
491
    }
492
493
    /**
445
    /**
494
     * Gets a Data object from a ResultSet.
446
     * Gets a Data object from a ResultSet.
495
     *
447
     *
Lines 759-765 public abstract class AbstractJDBCTestElement extends AbstractTestElement implem Link Here
759
     */
711
     */
760
    @Override
712
    @Override
761
    public void testStarted(String host) {
713
    public void testStarted(String host) {
762
        cleanCache();
763
    }
714
    }
764
715
765
    /**
716
    /**
Lines 777-793 public abstract class AbstractJDBCTestElement extends AbstractTestElement implem Link Here
777
     */
728
     */
778
    @Override
729
    @Override
779
    public void testEnded(String host) {
730
    public void testEnded(String host) {
780
        cleanCache();
781
    }
782
    
783
    /**
784
     * Clean cache of PreparedStatements
785
     */
786
    private static void cleanCache() {
787
        for (Map<String, PreparedStatement> element : perConnCache.values()) {
788
            closeAllStatements(element.values());
789
        }
790
        perConnCache.clear();
791
    }
731
    }
792
732
793
}
733
}
(-)a/xdocs/usermanual/properties_reference.xml (-2 lines)
Lines 487-493 Other parsers:<br/> Link Here
487
</section>
487
</section>
488
<section name="&sect-num;.26 JDBC Request configuration" anchor="jdbc_request">
488
<section name="&sect-num;.26 JDBC Request configuration" anchor="jdbc_request">
489
<properties>
489
<properties>
490
<property name="jdbcsampler.maxopenpreparedstatements"> Max number of PreparedStatements per Connection for PreparedStatement cache<br/>, defaults to:100</property>
491
<property name="jdbcsampler.nullmarker"> String used to indicate a null value<br/>, defaults to:]NULL[</property>
490
<property name="jdbcsampler.nullmarker"> String used to indicate a null value<br/>, defaults to:]NULL[</property>
492
</properties>
491
</properties>
493
</section>
492
</section>
494
- 

Return to bug 60085