
com.caucho.v5.jdbc.JdbcConnectionPoolImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of baratine Show documentation
Show all versions of baratine Show documentation
A reactive Java web server.
package com.caucho.v5.jdbc;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Properties;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Inject;
import io.baratine.service.OnInit;
import io.baratine.service.Result;
import io.baratine.service.Service;
import io.baratine.service.Services;
import io.baratine.service.ServiceRef;
@Service
public class JdbcConnectionPoolImpl //implements JdbcService
{
private Logger _logger = Logger.getLogger(JdbcConnectionPoolImpl.class.toString());
@Inject
private Services _manager;
@Inject
private JdbcServiceImpl _jdbcService;
private TreeSet _idleList = new TreeSet<>();
private int _busyCount = 0;
private LinkedList> _waitingList = new LinkedList<>();
private int _minCapacity = 4;
private int _maxCapacity = 128;
private long _timeoutMs = 1000 * 60 * 5;
private JdbcService _self;
private JdbcServiceSync _selfSync;
private String _url;
private Properties _props;
private boolean _isClosing;
@OnInit
public void onInit()
{
_self = ServiceRef.current().as(JdbcService.class);
_selfSync = ServiceRef.current().as(JdbcServiceSync.class);
}
/*
@Override
public void execute(String sql, Result result)
{
if (_logger.isLoggable(Level.FINER)) {
_logger.log(Level.FINER, "execute: " + sql.substring(0, 16) + "...");
}
getConnection((conn, e) -> {
conn.execute(sql, new ConnResult(conn, result));
});
}
@Override
public void executeBatch(String[] sqls, Result result)
{
if (_logger.isLoggable(Level.FINER)) {
_logger.log(Level.FINER, "executeBatch: " + sqls.length);
}
getConnection((conn, e) -> {
conn.executeBatch(sqls, new ConnResult(conn, result));
});
}
@Override
public void query(String sql, Result result)
{
if (_logger.isLoggable(Level.FINER)) {
_logger.log(Level.FINER, "query: " + sql.substring(0, 16) + "...");
}
getConnection((conn, e) -> {
conn.query(sql, new ConnResult(conn, result));
});
}
@Override
public void queryParam(String sql, Object[] params, Result result)
{
if (_logger.isLoggable(Level.FINER)) {
_logger.log(Level.FINER, "queryParam: " + sql);
}
getConnection((conn, e) -> {
conn.queryParam(sql, params, new ConnResult(conn, result));
});
}
@Override
public void queryBatch(String sql, Object[][] paramsList, Result> result)
{
if (_logger.isLoggable(Level.FINER)) {
_logger.log(Level.FINER, "queryBatch: " + sql);
}
getConnection((conn, e) -> {
conn.queryBatch(sql, paramsList, new ConnResult>(conn, result));
});
}
@Override
public void queryBatch(String[] sqls, Object[][] paramsList, Result> result)
{
if (_logger.isLoggable(Level.FINER)) {
_logger.log(Level.FINER, "queryBatch: " + sqls.length);
}
getConnection((conn, e) -> {
conn.queryBatch(sqls, paramsList, new ConnResult>(conn, result));
});
}
@Override
public void close(Result result)
{
if (_logger.isLoggable(Level.FINE)) {
_logger.log(Level.FINE, "connection pool is closing: " + this);
}
_isClosing = true;
for (Entry e : _idleList) {
JdbcService conn = e.getConnection();
ServiceRef.toRef(conn).close();
}
for (Result r : _waitingList) {
r.fail(new SQLException("database pool is closing"));
}
}
*/
private void checkPool()
{
if (_isClosing) {
return;
}
if (_logger.isLoggable(Level.FINER)) {
_logger.log(Level.FINER, "connection pool state: idle=" + _idleList.size() + ",busy=" + _busyCount);
}
Iterator iter = _idleList.iterator();
while (iter.hasNext()) {
Entry entry = iter.next();
if (entry.isExpired(_timeoutMs)) {
iter.remove();
JdbcService conn = entry.getConnection();
if (_logger.isLoggable(Level.FINE)) {
_logger.log(Level.FINE, "closing expired connection service: " + conn);
}
ServiceRef.toRef(conn).close();
}
else {
break;
}
}
int totalSize = _idleList.size() + _busyCount;
int newCount;
if (totalSize < _minCapacity) {
newCount = _minCapacity - totalSize;
}
else if (_idleList.size() > 0) {
newCount = 0;
}
else if (_busyCount < _maxCapacity) {
newCount = 1;
}
else {
newCount = 0;
}
_busyCount += newCount;
if (newCount > 0) {
if (_logger.isLoggable(Level.FINE)) {
_logger.log(Level.FINE, "creating " + newCount + " new connections");
}
}
/*
for (int i = 0; i < newCount; i++) {
ServiceRef ref = _manager.newService(JdbcServiceImpl.class).start();
if (_logger.isLoggable(Level.FINE)) {
_logger.log(Level.FINE, "creating new connection service: " + ref);
}
JdbcService conn = ref.as(JdbcService.class);
conn.connect(_url, _props, (c, e) -> {
if (_logger.isLoggable(Level.FINER)) {
_logger.log(Level.FINER, "connection established: idle=" + _idleList.size() + ",busy=" + _busyCount);
}
if (e != null) {
e.printStackTrace();
}
else {
addIdle(c);
}
});
}
*/
}
private void addIdle(JdbcService conn)
{
if (_logger.isLoggable(Level.FINER)) {
_logger.log(Level.FINER, "adding idle connection service: idle=" + _idleList.size() + ",busy=" + _busyCount);
}
_busyCount--;
if (! _isClosing) {
_idleList.add(new Entry(conn));
notifyWaitingList();
}
}
private void failIdle(Throwable e, JdbcService conn)
{
if (_logger.isLoggable(Level.FINER)) {
_logger.log(Level.FINER, "fail idle connection service: idle=" + _idleList.size() + ",busy=" + _busyCount);
_logger.log(Level.FINER, e.getMessage(), e);
}
_busyCount--;
checkPool();
}
private void notifyWaitingList()
{
if (_isClosing) {
return;
}
Result result = _waitingList.pollFirst();
if (result != null) {
Entry entry = _idleList.pollFirst();
if (entry != null) {
_busyCount++;
result.ok(entry.getConnection());
}
else {
_waitingList.offerFirst(result);
}
}
}
private void getConnection(Result result)
{
_waitingList.add(result);
checkPool();
}
class ConnResult implements Result {
private JdbcService _conn;
private Result _result;
public ConnResult(JdbcService conn, Result result)
{
_conn = conn;
_result = result;
}
@Override
public void handle(T value, Throwable fail) throws Exception
{
if (_logger.isLoggable(Level.FINER)) {
_logger.log(Level.FINER, "query completed: idle=" + _idleList.size() + ",busy=" + _busyCount);
}
_result.handle(value, fail);
if (fail != null) {
failIdle(fail, _conn);
}
else {
addIdle(_conn);
}
}
}
static class Entry implements Comparable {
private JdbcService _conn;
private long _lastActivityTime;
public Entry(JdbcService conn)
{
_conn = conn;
_lastActivityTime = System.currentTimeMillis();
}
public JdbcService getConnection()
{
return _conn;
}
public boolean isExpired(long timeoutMs)
{
return System.currentTimeMillis() > _lastActivityTime + timeoutMs;
}
@Override
public int compareTo(Entry e)
{
return (int) (_lastActivityTime - e._lastActivityTime);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy