import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
import org.tizen.dynamicanalyzer.util.CommonUtil;
import org.tizen.dynamicanalyzer.util.DALogger;
public class SqlConnectionManager {
private static final DALogger DA_LOG = DALogger.getInstance();
- private static Connection connection = null;
-
+ // apply multi connection of DB
+ private static final int CONNECTION_COUNT_UPDATE = 8;
+ private static final int CONNECTION_COUNT_QUERY = 8;
+ private static BlockingQueue<Connection> updateConnections = null;
+ private static BlockingQueue<Connection> queryConnections = null;
+ private static int realUpdateConnCount = 0;
+ private static int realQueryConnCount = 0;
+
+ // DATABASE state
+ private enum State {
+ NOT_CONNECTED,
+ CONNECTED,
+ TO_BE_CLOSED
+ }
+
+ private static State state = State.NOT_CONNECTED;
+
public static boolean establishConnection(String dbFilePath) {
boolean result = true;
try {
synchronized (SqlConnectionManager.class) {
- if (connection == null) {
+ if (updateConnections == null && queryConnections == null) {
+ updateConnections = new LinkedBlockingQueue<Connection>();
+ queryConnections = new LinkedBlockingQueue<Connection>();
+ realUpdateConnCount = 0;
+ realQueryConnCount = 0;
+
Class.forName("org.hsqldb.jdbcDriver");
String dbUrl = "jdbc:hsqldb:"
+ dbFilePath
- + ";shutdown=false;hsqldb.default_table_type=cached;hsqldb.large_data=true;hdqldb.log_data=false"; //$NON-NLS-1$
- connection = DriverManager.getConnection(dbUrl, "SA", "");
- SQLWarning warning = connection.getWarnings();
- while (warning != null) {
- DA_LOG.debug("[DB] Message: " + warning.getMessage());
- DA_LOG.debug("[DB] SQL state: " + warning.getSQLState());
- DA_LOG.debug("[DB] Vendor code: "
- + warning.getErrorCode());
- warning = warning.getNextWarning();
+ + ";shutdown=false;hsqldb.default_table_type=cached"
+ + ";hsqldb.tx=mvcc;hsqldb.large_data=true;hdqldb.log_data=false"; //$NON-NLS-1$
+
+ Connection conn;
+ // establish update connection pool
+ for (int i = 0; i < CONNECTION_COUNT_UPDATE; i++) {
+ conn = DriverManager.getConnection(dbUrl, "SA", "");
+ updateConnections.offer(conn);
+ realUpdateConnCount++;
+
+ SQLWarning warning = conn.getWarnings();
+ while (warning != null) {
+ DA_LOG.debug("[DB][" + i + "] Message: "
+ + warning.getMessage());
+ DA_LOG.debug("[DB][" + i + "] SQL state: "
+ + warning.getSQLState());
+ DA_LOG.debug("[DB][" + i + "] Vendor code: "
+ + warning.getErrorCode());
+ warning = warning.getNextWarning();
+ }
}
+
+ // establish query connection pool
+ for (int i = 0; i < CONNECTION_COUNT_QUERY; i++) {
+ conn = DriverManager.getConnection(dbUrl, "SA", "");
+ queryConnections.offer(conn);
+ realQueryConnCount++;
+
+ SQLWarning warning = conn.getWarnings();
+ while (warning != null) {
+ DA_LOG.debug("[DB][" + i + "] Message: "
+ + warning.getMessage());
+ DA_LOG.debug("[DB][" + i + "] SQL state: "
+ + warning.getSQLState());
+ DA_LOG.debug("[DB][" + i + "] Vendor code: "
+ + warning.getErrorCode());
+ warning = warning.getNextWarning();
+ }
+ }
+
+ state = State.CONNECTED;
}
}
} catch (ClassNotFoundException e) {
} catch (SQLException e) {
e.printStackTrace();
} finally {
- if (connection == null)
+ if (updateConnections == null || queryConnections == null)
result = false;
else
result = true;
public static void closeConnection() {
synchronized (SqlConnectionManager.class) {
- if (connection != null) {
- try {
- Statement st = connection.createStatement();
- st.execute("SHUTDOWN");
- CommonUtil.tryClose(st);
- connection.close();
- } catch (SQLException se) {
- if (!se.getSQLState().equals("XJ015")) {
- DA_LOG.debug("DB did not shutdown normally");
+ // set close state
+ // this value prevent other thread from getting connection
+ state = State.TO_BE_CLOSED;
+
+ // close update connection
+ if (updateConnections != null) {
+ synchronized (updateConnections) {
+ while (updateConnections.size() != realUpdateConnCount) {
+ // wait until other execution is finished
+ try {
+ updateConnections.wait();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ // close all connection
+ Connection conn;
+ while ((conn = updateConnections.poll()) != null) {
+ try {
+ conn.close();
+ } catch (SQLException e) {
+ e.printStackTrace();
}
}
- connection = null;
}
+
+ // close query connection
+ if (queryConnections != null) {
+ synchronized (queryConnections) {
+ while (queryConnections.size() != realQueryConnCount) {
+ // wait until other execution is finished
+ try {
+ queryConnections.wait();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ // close all connection
+ Connection conn;
+ while ((conn = queryConnections.poll()) != null) {
+ // if it is last connection of database
+ if(queryConnections.size() == 0) {
+ Statement st = null;
+ try {
+ st = conn.createStatement();
+ st.execute("SHUTDOWN");
+ } catch (SQLException se) {
+ if (!se.getSQLState().equals("XJ015")) {
+ DA_LOG.debug("DB did not shutdown normally");
+ }
+ } finally {
+ CommonUtil.tryClose(st);
+ }
+ }
+
+ try {
+ conn.close();
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ updateConnections = null;
+ queryConnections = null;
+
+ state = State.NOT_CONNECTED;
}
}
- public static boolean isConnected() {
- return (connection != null);
- }
+ private static Connection getUpdateConnection() {
+ Connection retConn = null;
+ if (state == State.CONNECTED) {
+ try {
+ retConn = updateConnections.take();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
- private static void semaphoreAcquire() {
+ return retConn;
+ }
+ private static void putUpdateConnection(Connection conn) {
+ if (conn != null) {
+ try {
+ updateConnections.put(conn);
+ synchronized (updateConnections) {
+ updateConnections.notifyAll();
+ }
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
}
- private static void semaphoreRelease() {
+ private static Connection getQueryConnection() {
+ Connection retConn = null;
+ if (state == State.CONNECTED) {
+ try {
+ retConn = queryConnections.take();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ return retConn;
+ }
+ private static void putQueryConnection(Connection conn) {
+ if (conn != null) {
+ try {
+ queryConnections.put(conn);
+ synchronized (queryConnections) {
+ queryConnections.notifyAll();
+ }
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
}
public static void executeUpdate(String statement) {
+ Connection conn = null;
Statement sm = null;
try {
- if (connection != null) {
- semaphoreAcquire();
- sm = connection.createStatement();
+ conn = getUpdateConnection();
+ if (conn != null) {
+ sm = conn.createStatement();
sm.executeUpdate(statement);
+ putUpdateConnection(conn);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
CommonUtil.tryClose(sm);
- semaphoreRelease();
}
}
public static void executePreparedWithType(String query,
List<List<Object>> data, List<String> columnType) {
+ Connection conn = null;
PreparedStatement prep = null;
if (data.size() == 0)
return;
try {
- if (connection != null) {
+ conn = getUpdateConnection();
+ if (conn != null) {
int batchCount = 0;
- prep = connection.prepareStatement(query);
+ prep = conn.prepareStatement(query);
// count ? in query
int questionCount = 0;
return;
}
- connection.setAutoCommit(false);
+ conn.setAutoCommit(false);
for (int k = 0; k < datasize; k++) {
List<Object> row = data.get(k);
if (batchCount > 0)
prep.executeBatch();
- connection.commit();
- connection.setAutoCommit(true);
+ conn.commit();
+ conn.setAutoCommit(true);
+
+ putUpdateConnection(conn);
}
} catch (SQLException e) {
e.printStackTrace();
// (no need to check the type of each column)
public static void executePreparedWithInterface(String query,
List<List<Object>> data, IPreparedStatement ip) {
+ Connection conn = null;
PreparedStatement prep = null;
if (data.size() == 0)
return;
try {
- if (connection != null) {
+ conn = getUpdateConnection();
+ if (conn != null) {
int batchCount = 0;
- prep = connection.prepareStatement(query);
+ prep = conn.prepareStatement(query);
// count ? in query
int questionCount = 0;
// set data into prepared statement
int datasize = data.size();
- connection.setAutoCommit(false);
+ conn.setAutoCommit(false);
for (int k = 0; k < datasize; k++) {
List<Object> row = data.get(k);
if (batchCount > 0)
prep.executeBatch();
- connection.commit();
- connection.setAutoCommit(true);
+ conn.commit();
+ conn.setAutoCommit(true);
+
+ putUpdateConnection(conn);
}
} catch (SQLException e) {
e.printStackTrace();
}
public static List<List<Object>> executeQuery(String query) {
+ Connection conn = null;
Statement sm = null;
ResultSet rs = null;
List<List<Object>> result = null;
+
try {
- if (connection != null) {
- semaphoreAcquire();
- sm = connection.createStatement();
+ conn = getQueryConnection();
+ if (conn != null) {
+ sm = conn.createStatement();
rs = sm.executeQuery(query);
if (rs != null) {
result = new ArrayList<List<Object>>();
result.add(rowData);
}
}
+
+ putQueryConnection(conn);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
CommonUtil.tryClose(sm);
- semaphoreRelease();
}
return result;