package sql; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Collections; import java.util.Queue; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import models.Configuration; import org.apache.log4j.Logger; public class SQL { private static final Logger LOGGER = Logger.getLogger(SQL.class); /** * Pool of available connections. */ private static final Queue pool = new ConcurrentLinkedQueue<>(); /** * Set of connections currently handed out. */ private static final Set busyConnections = Collections.newSetFromMap(new ConcurrentHashMap()); static { try { Class.forName("com.mysql.jdbc.Driver").newInstance(); } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { LOGGER.fatal("Cannot get mysql JDBC driver!", e); System.exit(1); } } public static MysqlConnection getConnection() { MysqlConnection con; for (;;) { con = pool.poll(); if (con == null) break; if (!con.isValid()) { con.release(); continue; } if (!busyConnections.add(con)) throw new RuntimeException("Tried to hand out a busy connection!"); return con; } // No pooled connection if (busyConnections.size() > 20) { LOGGER.warn("Too many open MySQL connections. Possible connection leak!"); return null; } try { // Create fresh connection Connection rawConnection = DriverManager.getConnection(Configuration.getDbUri(), Configuration.getDbUsername(), Configuration.getDbPassword()); // By convention in our program we don't want auto commit rawConnection.setAutoCommit(false); // Wrap into our proxy con = new MysqlConnection(rawConnection); // Keep track of busy mysql connection if (!busyConnections.add(con)) throw new RuntimeException("Tried to hand out a busy connection!"); return con; } catch (SQLException e) { LOGGER.info("Failed to connect to local mysql server", e); } return null; } static void returnConnection(MysqlConnection connection) { if (!busyConnections.remove(connection)) throw new RuntimeException("Tried to return a mysql connection to the pool that was not taken!"); pool.add(connection); } }// end class