/*
* 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.ignite.yardstick.cache.jdbc;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.apache.ignite.IgniteException;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.yardstick.IgniteBenchmarkArguments;
import org.yardstickframework.BenchmarkConfiguration;
import org.yardstickframework.BenchmarkDriverAdapter;
import static org.yardstickframework.BenchmarkUtils.jcommander;
/** Base class for benchmarks that measure raw performance of JDBC databases */
public abstract class JdbcAbstractBenchmark extends BenchmarkDriverAdapter {
/** Arguments. */
protected final IgniteBenchmarkArguments args = new IgniteBenchmarkArguments();
/** All {@link Connection}s associated with threads. */
private final List<Connection> threadConnections = new ArrayList<>();
/** Each connection is also a transaction, so we better pin them to threads. */
ThreadLocal<Connection> conn = new ThreadLocal<Connection>() {
@Override protected Connection initialValue() {
Connection conn;
try {
conn = connection();
if (args.createTempDatabase()) {
assert dbName != null;
conn.setCatalog(dbName);
}
}
catch (SQLException e) {
throw new IgniteException(e);
}
synchronized (threadConnections) {
threadConnections.add(conn);
}
return conn;
}
};
/** Dynamically generated DB name */
private String dbName;
/** {@inheritDoc} */
@Override public void setUp(BenchmarkConfiguration cfg) throws Exception {
super.setUp(cfg);
jcommander(cfg.commandLineArguments(), args, "<ignite-driver>");
Class.forName(args.jdbcDriver());
if (args.createTempDatabase())
createTestDatabase();
try (Connection conn = connection()) {
if (args.createTempDatabase())
conn.setCatalog(dbName);
populateTestDatabase(conn);
}
}
/** {@inheritDoc} */
@Override public void tearDown() throws Exception {
synchronized (threadConnections) {
for (Connection conn : threadConnections)
U.closeQuiet(conn);
threadConnections.clear();
}
if (args.createTempDatabase())
dropTestDatabase();
super.tearDown();
}
/** Create new, randomly named database to put dummy benchmark data in - no need in this for databases like H2 */
private void createTestDatabase() throws SQLException {
try (Connection conn = connection()) {
String uuid = UUID.randomUUID().toString().replace("-", "");
dbName = "benchmark" + getClass().getSimpleName() + uuid.substring(0, 16);
try (Statement stmt = conn.createStatement()) {
stmt.executeUpdate("create database " + dbName);
}
}
}
/** Drop previously created randomly named database - no need in this for databases like H2 */
private void dropTestDatabase() throws SQLException {
try (Connection conn = connection()) {
try (Statement stmt = conn.createStatement()) {
stmt.executeUpdate("drop database " + dbName);
}
}
}
/** Create benchmark DB schema from supplied SQL file path */
private void populateTestDatabase(Connection conn) throws IOException, SQLException {
assert conn != null;
List<String> queries = new ArrayList<>();
if (args.schemaDefinition() != null) {
try (FileReader fr = new FileReader(args.schemaDefinition())) {
try (BufferedReader br = new BufferedReader(fr)) {
String line;
while ((line = br.readLine()) != null) {
if (line.trim().isEmpty())
continue;
queries.add(line.trim());
}
}
}
}
for (String query : queries) {
try (PreparedStatement stmt = conn.prepareStatement(query)) {
stmt.executeUpdate();
}
}
}
/** Create new {@link Connection} from {@link #args}. Intended for use by {@link #setUp} and {@link #tearDown} */
private Connection connection() throws SQLException {
Connection conn = DriverManager.getConnection(args.jdbcUrl());
conn.setAutoCommit(true);
return conn;
}
/**
* Delete all data from the table specified
* @param tblName target table
* @throws SQLException if failed
*/
void clearTable(String tblName) throws SQLException {
try (Connection conn = connection()) {
try (PreparedStatement stmt = conn.prepareStatement("drop table " + tblName)) {
stmt.executeUpdate();
}
}
}
}