//
// Copyright 2012 leafclick s.r.o. <info@leafclick.com>
//
// Licensed 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 fan.cpool;
import fan.sys.*;
import fan.sql.*;
import java.sql.*;
import java.util.Enumeration;
import com.jolbox.bonecp.BoneCP;
import com.jolbox.bonecp.BoneCPConfig;
public class CPool extends Service$ implements Service {
public final Log log()
{
if (log == null) log = Log.get("cpool");
return log;
}
// constructor factory called by Foo.make
public static CPool make(CPoolConfig config) {
CPool self = new CPool();
make$(self, config);
return self;
}
// constructor implementation called by subclasses
public static void make$(CPool self, CPoolConfig config) {
self.config = config;
org.slf4j.impl.StaticLoggerBinder binder = org.slf4j.impl.StaticLoggerBinder.getSingleton();
}
// boiler plate for reflection
public Type typeof() {
if (type == null) type = Type.find("cpool::CPool");
return type;
}
private static Type type;
@Override
public boolean isInstalled() {
return Service$.isInstalled(this);
}
@Override
public boolean isRunning() {
return Service$.isRunning(this);
}
@Override
public Service install() {
return Service$.install(this);
}
@Override
public Service uninstall() {
return Service$.uninstall(this);
}
@Override
public Service start() {
return Service$.start(this);
}
@Override
public Service stop() {
return Service$.stop(this);
}
public void onStart() {
listRegisteredDrivers();
Connection connection = null;
try {
// setup the connection pool
BoneCPConfig boneCPConfig = new BoneCPConfig();
boneCPConfig.setJdbcUrl(config.url);
boneCPConfig.setUsername(config.username);
boneCPConfig.setPassword(config.password);
boneCPConfig.setMinConnectionsPerPartition((int) config.minConnectionsPerPartition);
boneCPConfig.setMaxConnectionsPerPartition((int) config.maxConnectionsPerPartition);
boneCPConfig.setPartitionCount((int) config.partitionCount);
boneCPConfig.setAcquireIncrement((int) config.acquireIncrement);
boneCPConfig.setReleaseHelperThreads((int) config.releaseHelperThreads);
boneCPConfig.setLogStatementsEnabled(config.logStatementsEnabled);
synchronized (poolLock) {
if (connectionPool == null)
connectionPool = new BoneCP(boneCPConfig); // setup the connection pool
else {
throw Err.make("Connection pool already started! Please shutdown the service first.");
}
}
// test connectivity
connection = connectionPool.getConnection(); // fetch a connection
if (connection != null) {
log().info("Connection pool has been started.");
} else {
connectionPool.shutdown(); // shutdown connection pool.
throw Err.make("Can't start sql connection pool!");
}
} catch (SQLException e) {
log().err("Connection pool setup error", e);
} finally {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
log().err("Connection cleanup error", e);
}
}
}
}
public void onStop() {
synchronized (poolLock) {
if (connectionPool != null)
connectionPool.shutdown(); // shutdown connection pool.
connectionPool = null;
}
}
private void listRegisteredDrivers() {
try {
Enumeration enumeration = DriverManager.getDrivers();
while (enumeration.hasMoreElements()) {
Driver d = (Driver) enumeration.nextElement();
log().debug("Registered JDBC driver: " + d.getClass().getName());
}
} catch (Exception e) {
throw Err.make("Error listing registered JDBC drivers", e);
}
}
public SqlConn getConnection()
{
try {
java.sql.Connection jconn = null;
synchronized (poolLock) {
if (connectionPool != null) {
jconn = connectionPool.getConnection();
} else {
throw new SQLException("Connection pool is not initialized!");
}
}
return SqlConnImplPeer.wrapConnection(jconn);
} catch (SQLException e) {
throw SqlErr.make(e.getMessage(), Err.make(e));
}
}
static { loadDrivers(); }
private static void loadDrivers()
{
try
{
String val = Pod.find("sql").config("java.drivers");
if (val == null) { return; }
String[] classNames = val.split(",");
for (int i=0; i<classNames.length; ++i)
{
String className = classNames[i].trim();
try
{
Class.forName(className);
}
catch (Exception e)
{
System.out.println("WARNING: Cannot preload JDBC driver: " + className);
}
}
}
catch (Throwable e)
{
System.out.println(e);
}
}
private static Object poolLock = new Object();
private BoneCP connectionPool = null;
private Log log;
public CPoolConfig config;
}