You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by ka...@apache.org on 2008/02/07 14:25:27 UTC

svn commit: r619404 - in /db/derby/code/trunk/java/testing/org/apache/derbyTesting: functionTests/tests/lang/ perf/clients/

Author: kahatlen
Date: Thu Feb  7 05:25:24 2008
New Revision: 619404

URL: http://svn.apache.org/viewvc?rev=619404&view=rev
Log:
Checked in the performance tests used in DERBY-1961 and DERBY-2911.

The following command prints information on how to run the tests:

    java org.apache.derbyTesting.perf.clients.Runner

Added:
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/BackToBackLoadGenerator.java   (with props)
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/Client.java   (with props)
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/DBFiller.java   (with props)
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/IndexJoinClient.java   (with props)
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/LoadGenerator.java   (with props)
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/PoissonLoadGenerator.java   (with props)
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/Runner.java   (with props)
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordFiller.java   (with props)
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordSelectClient.java   (with props)
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordUpdateClient.java   (with props)
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/WisconsinFiller.java   (with props)
Modified:
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/wisconsin.java

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/wisconsin.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/wisconsin.java?rev=619404&r1=619403&r2=619404&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/wisconsin.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/wisconsin.java Thu Feb  7 05:25:24 2008
@@ -40,7 +40,7 @@
         conn.setAutoCommit(false);
         conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
         
-        createTables(conn);
+        createTables(conn, true);
         
         BufferedInputStream inStream;
         
@@ -62,7 +62,9 @@
 		conn.commit();
 	}
 	
-	private static void createTables(Connection conn) throws SQLException{
+	public static void createTables(Connection conn, boolean compress)
+			throws SQLException {
+
 		Statement stmt = conn.createStatement();
 		
 		stmt.execute("create table TENKTUP1 ( unique1 int not null, " +
@@ -166,7 +168,11 @@
 		stmt.execute("insert into BPRIME select * from TENKTUP2 where TENKTUP2.unique2 < 1000");
 
 		conn.commit();
-		
+
+		if (!compress) {
+			return;
+		}
+
 		PreparedStatement ps2 = conn.prepareStatement
 			("call SYSCS_UTIL.SYSCS_COMPRESS_TABLE(?, ?, ?)");
 		ps2.setString(1, "APP");

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/BackToBackLoadGenerator.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/BackToBackLoadGenerator.java?rev=619404&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/BackToBackLoadGenerator.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/BackToBackLoadGenerator.java Thu Feb  7 05:25:24 2008
@@ -0,0 +1,132 @@
+/*
+
+Derby - Class org.apache.derbyTesting.perf.clients.BackToBackLoadGenerator
+
+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.derbyTesting.perf.clients;
+
+import java.io.PrintStream;
+import java.sql.SQLException;
+
+/**
+ * Load generator which creates back-to-back load. This means that you have a
+ * number of threads running in parallel, where each thread continuously
+ * performs operations with no pauses in between.
+ */
+public class BackToBackLoadGenerator implements LoadGenerator {
+    /** The threads executing. */
+    private ClientThread[] threads;
+    /** Flag which tells the generator to stop. */
+    private volatile boolean stop;
+    /** Flag which tells the generator to collect results. */
+    private volatile boolean collect;
+    /** Start time for steady-state phase. */
+    private long startTime;
+    /** Stop time for steady-state phase. */
+    private long stopTime;
+
+    /**
+     * Thread class which runs a single client and collects results.
+     */
+    private class ClientThread extends Thread {
+        private final Client client;
+        private long count;
+
+        ClientThread(Client c) {
+            client = c;
+        }
+
+        public void run() {
+            try {
+                while (!stop) {
+                    client.doWork();
+                    if (collect) {
+                        count++;
+                    }
+                }
+            } catch (SQLException sqle) {
+                sqle.printStackTrace();
+            }
+        }
+    }
+
+    /**
+     * Initialize the load generator.
+     *
+     * @param clients the test clients to use
+     */
+    public void init(Client[] clients) {
+        threads = new ClientThread[clients.length];
+        for (int i = 0; i < clients.length; i++) {
+            threads[i] = new ClientThread(clients[i]);
+        }
+    }
+
+    /**
+     * Start warmup.
+     */
+    public void startWarmup() {
+        for (int i = 0; i < threads.length; i++) {
+            threads[i].start();
+        }
+    }
+
+    /**
+     * Start steady state.
+     */
+    public void startSteadyState() {
+        startTime = System.currentTimeMillis();
+        collect = true;
+    }
+
+    /**
+     * Stop the load generator.
+     */
+    public void stop() {
+        stopTime = System.currentTimeMillis();
+        collect = false;
+        stop = true;
+        for (int i = 0; i < threads.length; i++) {
+            try {
+                threads[i].join();
+            } catch (InterruptedException ie) {
+                ie.printStackTrace();
+            }
+        }
+    }
+
+    /**
+     * Print average number of transactions per second.
+     */
+    public void printReport(PrintStream out) {
+        long time = stopTime - startTime;
+
+        long count = 0;
+        for (int i = 0; i < threads.length; i++) {
+            count += threads[i].count;
+        }
+
+        double tps = (double) count * 1000 / time;
+
+        out.println("Number of threads:\t" + threads.length);
+        out.println("Test duration (s):\t" + ((double) time / 1000));
+        out.println("Number of transactions:\t" + count);
+        out.println("Average throughput (tx/s):\t" + tps);
+    }
+}

Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/BackToBackLoadGenerator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/Client.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/Client.java?rev=619404&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/Client.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/Client.java Thu Feb  7 05:25:24 2008
@@ -0,0 +1,50 @@
+/*
+
+Derby - Class org.apache.derbyTesting.perf.clients.Client
+
+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.derbyTesting.perf.clients;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+
+/**
+ * Interface that must be implemented by performance clients. The
+ * implementations of this interface normally perform a single operation, and
+ * the selected implementation of {@code LoadGenerator} repeatedly invokes this
+ * operation in order to get the desired distribution.
+ */
+public interface Client {
+    /**
+     * Initialize this client (typically prepare the statements needed in the
+     * {@code doWork()} method).
+     *
+     * @param c a connection which can be used by this client
+     * @throws SQLException if a database error occurs
+     */
+    void init(Connection c) throws SQLException;
+
+    /**
+     * Perform the work for a single iteration of the test (typically a single
+     * transaction).
+     *
+     * @throws SQLException if a database error occurs
+     */
+    void doWork() throws SQLException;
+}

Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/Client.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/DBFiller.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/DBFiller.java?rev=619404&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/DBFiller.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/DBFiller.java Thu Feb  7 05:25:24 2008
@@ -0,0 +1,38 @@
+/*
+
+Derby - Class org.apache.derbyTesting.perf.clients.DBFiller
+
+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.derbyTesting.perf.clients;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+
+/**
+ * Interface for classes that populate a database for a certain test.
+ */
+public interface DBFiller {
+    /**
+     * Populate the database with the data needed by a test.
+     *
+     * @param c the connection to use
+     * @throws SQLException if a database error occurs
+     */
+    void fill(Connection c) throws SQLException;
+}

Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/DBFiller.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/IndexJoinClient.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/IndexJoinClient.java?rev=619404&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/IndexJoinClient.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/IndexJoinClient.java Thu Feb  7 05:25:24 2008
@@ -0,0 +1,55 @@
+/*
+
+Derby - Class org.apache.derbyTesting.perf.clients.IndexJoinClient
+
+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.derbyTesting.perf.clients;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.ResultSet;
+
+/**
+ * Test client which performs an index join between the {@code TENKTUP1} and
+ * {@code ONEKTUP} tables generated by {@code WisconsinFiller}.
+ */
+public class IndexJoinClient implements Client {
+
+    private Connection conn;
+    private PreparedStatement ps;
+
+    public void init(Connection c) throws SQLException {
+        conn = c;
+        ps = c.prepareStatement(
+            "SELECT TENKTUP1.UNIQUE1 FROM TENKTUP1, ONEKTUP WHERE " +
+            "TENKTUP1.UNIQUE1 = ONEKTUP.UNIQUE1");
+        c.setAutoCommit(false);
+    }
+
+    public void doWork() throws SQLException {
+        ResultSet rs = ps.executeQuery();
+        while (rs.next()) {
+            rs.getInt(1);
+        }
+        rs.close();
+        conn.commit();
+    }
+
+}

Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/IndexJoinClient.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/LoadGenerator.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/LoadGenerator.java?rev=619404&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/LoadGenerator.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/LoadGenerator.java Thu Feb  7 05:25:24 2008
@@ -0,0 +1,64 @@
+/*
+
+Derby - Class org.apache.derbyTesting.perf.clients.LoadGenerator
+
+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.derbyTesting.perf.clients;
+
+import java.io.PrintStream;
+
+/**
+ * Interface implemented by load generators. A load generator generates the
+ * test load on the DBMS by invoking the clients' {@code doWork()} methods.
+ * Different load generators may generate load with different characteristics.
+ * The actual database operations performed are decided by the clients passed
+ * in to the load generator's {@code init()} method.
+ */
+public interface LoadGenerator {
+    /**
+     * Initialize the load generator.
+     * @param clients tells the load generator which clients it should use
+     * to generate load with
+     */
+    void init(Client[] clients);
+
+    /**
+     * Start the warmup phase. This means that the load generator is started,
+     * but the results are not collected.
+     */
+    void startWarmup();
+
+    /**
+     * Move from the warmup phase to the steady-state phase. Start collecting
+     * results.
+     */
+    void startSteadyState();
+
+    /**
+     * Stop the load generator.
+     */
+    void stop();
+
+    /**
+     * Print a report from the test run.
+     *
+     * @param out stream to print the report to
+     */
+    void printReport(PrintStream out);
+}

Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/LoadGenerator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/PoissonLoadGenerator.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/PoissonLoadGenerator.java?rev=619404&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/PoissonLoadGenerator.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/PoissonLoadGenerator.java Thu Feb  7 05:25:24 2008
@@ -0,0 +1,199 @@
+/*
+
+Derby - Class org.apache.derbyTesting.perf.clients.PoissonLoadGenerator
+
+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.derbyTesting.perf.clients;
+
+import java.io.PrintStream;
+import java.sql.SQLException;
+import java.util.Random;
+
+/**
+ * Load generator which generates Poisson distributed requests.
+ */
+public class PoissonLoadGenerator implements LoadGenerator {
+
+    /**
+     * The average time (in milliseconds) between each request from a client.
+     */
+    private final double avgWaitTime;
+
+    /** The client threads used to generate load. */
+    private ClientThread[] threads;
+    /** Flag which tells the generator to stop. */
+    private volatile boolean stop;
+    /** Flag which tells the generator to collect results. */
+    private volatile boolean collect;
+    /** Start time for steady-state phase. */
+    private long startTime;
+    /** Stop time for steady-state phase. */
+    private long stopTime;
+
+    /**
+     * Construct a {@code PoissonLoadGenerator} instance.
+     *
+     * @param avgWaitTime the time (in millisecond) between each request from
+     * a client
+     */
+    public PoissonLoadGenerator(double avgWaitTime) {
+        this.avgWaitTime = avgWaitTime;
+    }
+
+    /**
+     * Thread class which runs a single client and collects results.
+     */
+    private class ClientThread extends Thread {
+        private final Client client;
+        private long count;
+        private long totalTime;
+        private long min = Long.MAX_VALUE;
+        private long max = 0;
+
+        ClientThread(Client c) {
+            client = c;
+        }
+
+        /**
+         * Tell the client to stop waiting.
+         */
+        synchronized void wakeup() {
+            ClientThread.this.notifyAll();
+        }
+
+        public void run() {
+            try {
+                runClient();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+
+        private void runClient() throws SQLException, InterruptedException {
+            final Random r = new Random();
+            final long start = System.currentTimeMillis();
+            // use a double to prevent too short average wait time because
+            // of truncation
+            double timeOffset = 0d;
+            long now = start;
+            while (!stop) {
+                // Increase the timeOffset by a random value picked from an
+                // exponential distribution (exponentially distributed wait
+                // times give Poisson distributed requests, see
+                // http://en.wikipedia.org/wiki/Exponential_distribution)
+                timeOffset += -Math.log(r.nextDouble()) * avgWaitTime;
+                final long nextWakeup = start + (long) timeOffset;
+                while (now < nextWakeup) {
+                    synchronized (ClientThread.this) {
+                        if (stop) {
+                            return;
+                        }
+                        ClientThread.this.wait(nextWakeup - now);
+                    }
+                    now = System.currentTimeMillis();
+                }
+
+                final long t0 = now;
+                client.doWork();
+                final long t1 = System.currentTimeMillis();
+                if (collect) {
+                    final long time = t1 - t0;
+                    count++;
+                    totalTime += time;
+                    if (time > max) max = time;
+                    if (time < min) min = time;
+                }
+                now = t1;
+            }
+        }
+    }
+
+    /**
+     * Initialize the load generator.
+     *
+     * @param clients the test clients to use
+     */
+    public void init(Client[] clients) {
+        threads = new ClientThread[clients.length];
+        for (int i = 0; i < clients.length; i++) {
+            threads[i] = new ClientThread(clients[i]);
+        }
+    }
+
+    /**
+     * Start warmup phase.
+     */
+    public void startWarmup() {
+        for (int i = 0; i < threads.length; i++) {
+            threads[i].start();
+        }
+    }
+
+    /**
+     * Start steady-state phase.
+     */
+    public void startSteadyState() {
+        startTime = System.currentTimeMillis();
+        collect = true;
+    }
+
+    /**
+     * Stop the load generator.
+     */
+    public void stop() {
+        stopTime = System.currentTimeMillis();
+        collect = false;
+        stop = true;
+        for (int i = 0; i < threads.length; i++) {
+            try {
+                threads[i].wakeup();
+                threads[i].join();
+            } catch (InterruptedException ie) {
+                ie.printStackTrace();
+            }
+        }
+    }
+
+    /**
+     * Print average transaction injection rate and response times.
+     */
+    public void printReport(PrintStream out) {
+        long time = stopTime - startTime;
+
+        long count = 0;
+        long totalTime = 0;
+        long min = Long.MAX_VALUE;
+        long max = 0;
+        for (int i = 0; i < threads.length; i++) {
+            count += threads[i].count;
+            totalTime += threads[i].totalTime;
+            min = Math.min(min, threads[i].min);
+            max = Math.max(max, threads[i].max);
+        }
+
+        double tps = (double) count * 1000 / time;
+        double avgResp = (double) totalTime / count;
+
+        out.println("Number of threads:\t" + threads.length);
+        out.println("Average injection rate (tx/s):\t" + tps);
+        out.println("Average response time (ms):\t" + avgResp);
+        out.println("Minimum response time (ms):\t" + min);
+        out.println("Maximum response time (ms):\t" + max);
+    }
+}

Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/PoissonLoadGenerator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/Runner.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/Runner.java?rev=619404&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/Runner.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/Runner.java Thu Feb  7 05:25:24 2008
@@ -0,0 +1,286 @@
+/*
+
+Derby - Class org.apache.derbyTesting.perf.clients.Runner
+
+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.derbyTesting.perf.clients;
+
+import java.io.PrintStream;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
+/**
+ * Class used for running a performance test from the command line. To learn
+ * how to run the tests, invoke this command:
+ * <pre>
+ * java org.apache.derbyTesting.perf.clients.Runner
+ * </pre>
+ */
+public class Runner {
+
+    private static final String DERBY_EMBEDDED_DRIVER =
+            "org.apache.derby.jdbc.EmbeddedDriver";
+
+    private static final String DEFAULT_URL = "jdbc:derby:db;create=true";
+
+    /** The JDBC driver class to use in the test. */
+    private static String driver = DERBY_EMBEDDED_DRIVER;
+    /** The JDBC connection URL to use in the test. */
+    private static String url = DEFAULT_URL;
+    /** Username for connecting to the database. */
+    private static String user = "test";
+    /** Password for connecting to the database. */
+    private static String password = "test";
+    /**
+     * Flag which tells whether the data needed by this test should be
+     * (re)created.
+     */
+    private static boolean init = false;
+    /** The name of the type of load to use in the test. */
+    private static String load; // required argument
+    /** The name of the load generator to use in the test. */
+    private static String generator = "b2b";
+    /** The number of client threads to use in the test. */
+    private static int threads = 1;
+    /**
+     * The number of requests to issue to the database per second (for the
+     * load generators that take that as an argument).
+     */
+    private static int requestsPerSecond = 100;
+    /** The number of seconds to spend in the warmup phase. */
+    private static int warmupSec = 30;
+    /** The number of seconds to collect results. */
+    private static int steadySec = 60;
+
+    /**
+     * Main method which starts the Runner application.
+     *
+     * @param args the command line arguments
+     */
+    public static void main(String[] args) throws Exception {
+        try {
+            parseArgs(args);
+        } catch (Exception e) {
+            System.err.println(e);
+            printUsage(System.err);
+            System.exit(1);
+        }
+
+        Class.forName(driver).newInstance();
+
+        if (init) {
+            DBFiller filler = getDBFiller();
+            Connection conn = DriverManager.getConnection(url, user, password);
+            System.out.println("initializing database...");
+            filler.fill(conn);
+            conn.close();
+        }
+
+        Client[] clients = new Client[threads];
+        for (int i = 0; i < clients.length; i++) {
+            Connection c = DriverManager.getConnection(url, user, password);
+            c.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
+            clients[i] = newClient();
+            clients[i].init(c);
+        }
+
+        LoadGenerator gen = getLoadGenerator();
+        gen.init(clients);
+        System.out.println("starting warmup...");
+        gen.startWarmup();
+        Thread.sleep(1000L * warmupSec);
+        System.out.println("entering steady state...");
+        gen.startSteadyState();
+        Thread.sleep(1000L * steadySec);
+        System.out.println("stopping threads...");
+        gen.stop();
+        gen.printReport(System.out);
+
+        shutdownDatabase();
+    }
+
+    /**
+     * Parse the command line arguments and set the state variables to
+     * reflect the arguments.
+     *
+     * @param args the command line arguments
+     */
+    private static void parseArgs(String[] args) throws Exception {
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("-driver")) {
+                driver = args[++i];
+            } else if (args[i].equals("-url")) {
+                url = args[++i];
+            } else if (args[i].equals("-user")) {
+                user = args[++i];
+            } else if (args[i].equals("-pass")) {
+                password = args[++i];
+            } else if (args[i].equals("-init")) {
+                init = true;
+            } else if (args[i].equals("-load")) {
+                load = args[++i];
+            } else if (args[i].equals("-gen")) {
+                generator = args[++i];
+            } else if (args[i].equals("-threads")) {
+                threads = Integer.parseInt(args[++i]);
+            } else if (args[i].equals("-rate")) {
+                requestsPerSecond = Integer.parseInt(args[++i]);
+            } else if (args[i].equals("-wt")) {
+                warmupSec = Integer.parseInt(args[++i]);
+            } else if (args[i].equals("-rt")) {
+                steadySec = Integer.parseInt(args[++i]);
+            } else {
+                throw new Exception("invalid argument: " + args[i]);
+            }
+        }
+        if (load == null) {
+            throw new Exception("required parameter -load not specified");
+        }
+    }
+
+    /** String to print when there are errors in the command line arguments. */
+    private static final String USAGE =
+
+"Valid parameters:\n" +
+"  -driver: JDBC driver class, default: " + DERBY_EMBEDDED_DRIVER + "\n" +
+"  -url: JDBC connection url, default: " +  DEFAULT_URL + "\n" +
+"  -user: JDBC user name, default: test\n" +
+"  -pass: JDBC user password, default: test\n" +
+"  -init: initialize database (otherwise, reuse database)\n" +
+"  -load: type of load, required argument, valid types:\n" +
+"      * sr_select - single-record (primary key) select from table with\n" +
+"                    100 000 rows\n" +
+"      * sr_update - single-record (primary key) update on table with\n" +
+"                    100 000 rows\n" +
+"      * sr_select_big - single-record (primary key) select from table with\n" +
+"                    100 000 000 rows\n" +
+"      * sr_update_big - single-record (primary key) update on table with\n" +
+"                    100 000 000 rows\n" +
+"      * sr_select_multi - single-record select from a random table\n" +
+"                    (32 tables with a single row each)\n" +
+"      * sr_update_multi - single-record update on a random table\n" +
+"                    (32 tables with a single row each)\n" +
+"      * index_join - join of two tables (using indexed columns)\n" +
+"  -gen: load generator, default: b2b, valid types:\n" +
+"      * b2b - clients perform operations back-to-back\n" +
+"      * poisson - load is Poisson distributed\n" +
+"  -threads: number of threads performing operations, default: 1\n" +
+"  -rate: average number of transactions per second to inject when\n" +
+"         load generator is \"poisson\", default: 100\n" +
+"  -wt: warmup time in seconds, default: 30\n" +
+"  -rt: time in seconds to collect results, default: 60";
+
+    /**
+     * Print the usage string.
+     *
+     * @param out the stream to print the usage string to
+     */
+    private static void printUsage(PrintStream out) {
+        out.println(USAGE);
+    }
+
+    /**
+     * Find the {@code DBFiller} instance for the load specified on the
+     * command line.
+     *
+     * @return a {@code DBFiller} instance
+     */
+    private static DBFiller getDBFiller() {
+        if (load.equals("sr_select") || load.equals("sr_update")) {
+            return new SingleRecordFiller(100000, 1);
+        } else if (load.equals("sr_select_big") ||
+                       load.equals("sr_update_big")) {
+            return new SingleRecordFiller(100000000, 1);
+        } else if (load.equals("sr_select_multi") ||
+                       load.equals("sr_update_multi")) {
+            return new SingleRecordFiller(1, 32);
+        } else if (load.equals("index_join")) {
+            return new WisconsinFiller();
+        }
+        System.err.println("unknown load: " + load);
+        printUsage(System.err);
+        System.exit(1);
+        return null;
+    }
+
+    /**
+     * Create a new client for the load specified on the command line.
+     *
+     * @return a {@code Client} instance
+     */
+    private static Client newClient() {
+        if (load.equals("sr_select")) {
+            return new SingleRecordSelectClient(100000, 1);
+        } else if (load.equals("sr_update")) {
+            return new SingleRecordUpdateClient(100000, 1);
+        } else if (load.equals("sr_select_big")) {
+            return new SingleRecordSelectClient(100000000, 1);
+        } else if (load.equals("sr_update_big")) {
+            return new SingleRecordUpdateClient(100000000, 1);
+        } else if (load.equals("sr_select_multi")) {
+            return new SingleRecordSelectClient(1, 32);
+        } else if (load.equals("sr_update_multi")) {
+            return new SingleRecordUpdateClient(1, 32);
+        } else if (load.equals("index_join")) {
+            return new IndexJoinClient();
+        }
+        System.err.println("unknown load: " + load);
+        printUsage(System.err);
+        System.exit(1);
+        return null;
+    }
+
+    /**
+     * Create a load generator for the load specified on the command line.
+     *
+     * @return a {@code LoadGenerator} instance
+     */
+    private static LoadGenerator getLoadGenerator() {
+        if (generator.equals("b2b")) {
+            return new BackToBackLoadGenerator();
+        } else if (generator.equals("poisson")) {
+            double avgWaitTime = 1000d * threads / requestsPerSecond;
+            return new PoissonLoadGenerator(avgWaitTime);
+        }
+        System.err.println("unknown load generator: " + generator);
+        printUsage(System.err);
+        System.exit(1);
+        return null;
+    }
+
+    /**
+     * Shut down the database if it is a Derby embedded database.
+     */
+    private static void shutdownDatabase() throws SQLException {
+        if (driver.equals(DERBY_EMBEDDED_DRIVER)) {
+            try {
+                DriverManager.getConnection(url + ";shutdown=true");
+                System.err.println("WARNING: Shutdown of database didn't " +
+                                   "throw expected exception");
+            } catch (SQLException e) {
+                if (!"08006".equals(e.getSQLState())) {
+                    System.err.println("WARNING: Shutdown of database threw " +
+                                       "unexpected exception");
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+}

Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/Runner.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordFiller.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordFiller.java?rev=619404&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordFiller.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordFiller.java Thu Feb  7 05:25:24 2008
@@ -0,0 +1,121 @@
+/*
+
+Derby - Class org.apache.derbyTesting.perf.clients.SingleRecordFiller
+
+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.derbyTesting.perf.clients;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Random;
+
+/**
+ * Class which generates and populates tables that can be used by
+ * {@code SingleRecordSelectClient} and {@code SingleRecordUpdateClient}.
+ * This tables contain rows with an int column (id) and a varchar(100) column
+ * (text). The id column is declared as primary key.
+ */
+public class SingleRecordFiller implements DBFiller {
+
+    private final int numberOfTables;
+    private final int tableSize;
+
+    private static final int TEXT_SIZE = 100;
+
+    /**
+     * Generate a filler that creates the specified number of tables, each of
+     * which contains the specified number of records.
+     *
+     * @param records the number of records in each table
+     * @param tables the number of tables to create
+     */
+    public SingleRecordFiller(int records, int tables) {
+        tableSize = records;
+        numberOfTables = tables;
+    }
+
+    public void fill(Connection c) throws SQLException {
+        c.setAutoCommit(false);
+        Statement s = c.createStatement();
+        for (int table = 0; table < numberOfTables; table++) {
+            String tableName = getTableName(tableSize, table);
+            WisconsinFiller.dropTable(c, tableName);
+            s.executeUpdate(
+                    "CREATE TABLE " + tableName + "(ID INT PRIMARY KEY, " +
+                    "TEXT VARCHAR(" + TEXT_SIZE + "))");
+
+            PreparedStatement ps =
+                c.prepareStatement("INSERT INTO " + tableName +
+                                   "(ID, TEXT) VALUES (?, ?)");
+
+            for (int i = 0; i < tableSize; i++) {
+                ps.setInt(1, i);
+                ps.setString(2, randomString(i));
+                ps.executeUpdate();
+                if ((i % 1000) == 0) {
+                    c.commit();
+                }
+            }
+
+            ps.close();
+            c.commit();
+        }
+
+        s.close();
+    }
+
+    private static final String[] RANDOM_STRINGS = new String[16];
+    static {
+        final String alphabet = "abcdefghijklmnopqrstuvwxyz" +
+                                "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
+                                "01234567890_-+*/(){}[]&%$#!";
+        final Random r = new Random();
+        for (int i = 0; i < RANDOM_STRINGS.length; i++) {
+            StringBuffer buf = new StringBuffer(TEXT_SIZE);
+            for (int x = 0; x < TEXT_SIZE; x++) {
+                buf.append(alphabet.charAt(r.nextInt(alphabet.length())));
+            }
+            RANDOM_STRINGS[i] = buf.toString();
+        }
+    }
+
+    /**
+     * Pick a random string.
+     *
+     * @param seed a seed used to decide which random string to pick
+     * @return a (somewhat) random string
+     */
+    static String randomString(int seed) {
+        return RANDOM_STRINGS[(seed & 0x7fffffff) % RANDOM_STRINGS.length];
+    }
+
+    /**
+     * Get the name of a table generated by this class.
+     *
+     * @param records the number of records in the table
+     * @param table the number of the table, between 0 (inclusive) and the
+     * total number of tables (exclusive)
+     * @return the name of the table specified by the arguments
+     */
+    static String getTableName(int records, int table) {
+        return "SINGLE_RECORD_" + records + "_" + table;
+    }
+}

Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordFiller.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordSelectClient.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordSelectClient.java?rev=619404&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordSelectClient.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordSelectClient.java Thu Feb  7 05:25:24 2008
@@ -0,0 +1,76 @@
+/*
+
+Derby - Class org.apache.derbyTesting.perf.clients.SingleRecordSelectClient
+
+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.derbyTesting.perf.clients;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Random;
+
+/**
+ * Client which performs single-record lookups on tables generated by
+ * {@code SingleRecordFiller}. Each time the client's {@code doWork()} method
+ * is called, it will pick one of the tables randomly, and select one random
+ * record in that table.
+ */
+public class SingleRecordSelectClient implements Client {
+
+    private Connection conn;
+
+    private final PreparedStatement[] pss;
+    private final Random r;
+    private final int tableSize;
+
+    /**
+     * Construct a new single-record select client.
+     *
+     * @param records the number of records in each table in the test
+     * @param tables the number of tables in the test
+     */
+    public SingleRecordSelectClient(int records, int tables) {
+        tableSize = records;
+        r = new Random();
+        pss = new PreparedStatement[tables];
+    }
+
+    public void init(Connection c) throws SQLException {
+        for (int i = 0; i < pss.length; i++) {
+            String tableName = SingleRecordFiller.getTableName(tableSize, i);
+            String sql = "SELECT * FROM " + tableName + " WHERE ID = ?";
+            pss[i] = c.prepareStatement(sql);
+        }
+        c.setAutoCommit(false);
+        conn = c;
+    }
+
+    public void doWork() throws SQLException {
+        PreparedStatement ps = pss[r.nextInt(pss.length)];
+        ps.setInt(1, r.nextInt(tableSize));
+        ResultSet rs = ps.executeQuery();
+        rs.next();
+        rs.getInt(1);
+        rs.getString(2);
+        rs.close();
+        conn.commit();
+    }
+}

Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordSelectClient.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordUpdateClient.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordUpdateClient.java?rev=619404&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordUpdateClient.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordUpdateClient.java Thu Feb  7 05:25:24 2008
@@ -0,0 +1,73 @@
+/*
+
+Derby - Class org.apache.derbyTesting.perf.clients.SingleRecordUpdateClient
+
+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.derbyTesting.perf.clients;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.Random;
+
+/**
+ * Client which updates a single record at a time on tables generated by
+ * {@code SingleRecordFiller}. Each time the client's {@code doWork()} method
+ * is called, it will pick one of the tables randomly, and update the text
+ * column of one random record in that table.
+ */
+public class SingleRecordUpdateClient implements Client {
+
+    private Connection conn;
+
+    private final PreparedStatement[] pss;
+    private final Random r;
+    private final int tableSize;
+
+    /**
+     * Construct a new single-record update client.
+     *
+     * @param records the number of records in each table in the test
+     * @param tables the number of tables in the test
+     */
+    public SingleRecordUpdateClient(int records, int tables) {
+        tableSize = records;
+        r = new Random();
+        pss = new PreparedStatement[tables];
+    }
+
+    public void init(Connection c) throws SQLException {
+        for (int i = 0; i < pss.length; i++) {
+            String tableName = SingleRecordFiller.getTableName(tableSize, i);
+            String sql = "UPDATE " + tableName + " SET TEXT = ? WHERE ID = ?";
+            pss[i] = c.prepareStatement(sql);
+        }
+        c.setAutoCommit(false);
+        conn = c;
+    }
+
+    public void doWork() throws SQLException {
+        PreparedStatement ps = pss[r.nextInt(pss.length)];
+        ps.setString(1, SingleRecordFiller.randomString(r.nextInt()));
+        ps.setInt(2, r.nextInt(tableSize));
+        ps.executeUpdate();
+        conn.commit();
+    }
+
+}

Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/SingleRecordUpdateClient.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/WisconsinFiller.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/WisconsinFiller.java?rev=619404&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/WisconsinFiller.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/WisconsinFiller.java Thu Feb  7 05:25:24 2008
@@ -0,0 +1,75 @@
+/*
+
+Derby - Class org.apache.derbyTesting.perf.clients.WisconsinFiller
+
+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.derbyTesting.perf.clients;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Savepoint;
+import java.sql.Statement;
+import org.apache.derbyTesting.functionTests.tests.lang.wisconsin;
+
+/**
+ * Class which creates and populates the tables used by
+ * {@code IndexJoinClient}. These are the same tables as the ones used by the
+ * functional Wisconsin test found in the lang suite.
+ */
+public class WisconsinFiller implements DBFiller {
+
+    public void fill(Connection c) throws SQLException {
+        c.setAutoCommit(false);
+
+        dropTable(c, "TENKTUP1");
+        dropTable(c, "TENKTUP2");
+        dropTable(c, "ONEKTUP");
+        dropTable(c, "BPRIME");
+
+        wisconsin.createTables(c, false);
+
+        c.commit();
+    }
+
+    /**
+     * Helper method which drops a table if it exists. Nothing happens if
+     * the table doesn't exist.
+     *
+     * @param c the connection to use
+     * @param table the table to drop
+     * @throws SQLException if an unexpected database error occurs
+     */
+    static void dropTable(Connection c, String table) throws SQLException {
+        // Create a savepoint that we can roll back to if drop table fails.
+        // This is not needed by Derby, but some databases (e.g., PostgreSQL)
+        // don't allow more operations in a transaction if a statement fails,
+        // and we want to be able to run these tests against other databases
+        // than Derby.
+        Savepoint sp = c.setSavepoint();
+        Statement stmt = c.createStatement();
+        try {
+            stmt.executeUpdate("DROP TABLE " + table);
+        } catch (SQLException e) {
+            // OK to fail if table doesn't exist, roll back to savepoint
+            c.rollback(sp);
+        }
+        stmt.close();
+        c.releaseSavepoint(sp);
+    }
+}

Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/perf/clients/WisconsinFiller.java
------------------------------------------------------------------------------
    svn:eol-style = native