No effective change - format only

This commit is contained in:
Robin Bygrave
2015-08-02 08:55:36 +12:00
parent c526b3ef57
commit 29a97d84a1
14 changed files with 2401 additions and 2409 deletions
@@ -17,187 +17,185 @@ import com.avaje.ebeaninternal.server.lib.sql.PooledConnectionStatistics.LoadVal
* and this allows for fast addition and removal (by slotId without looping).
* The capacity will increase on demand by the 'growBy' amount.
* </p>
*
*
* @author rbygrave
*
*/
class BusyConnectionBuffer {
private static final Logger logger = LoggerFactory.getLogger(BusyConnectionBuffer.class);
private PooledConnection[] slots;
private final int growBy;
private int size;
private int pos = -1;
/**
* Create the buffer with an initial capacity and fixed growBy.
* We generally do not want the buffer to grow very often.
*
* @param capacity
* the initial capacity
* @param growBy
* the fixed amount to grow the buffer by.
*/
protected BusyConnectionBuffer(int capacity, int growBy) {
this.slots = new PooledConnection[capacity];
this.growBy = growBy;
}
/**
* We can only grow (not shrink) the capacity.
*/
protected void setCapacity(int newCapacity) {
if (newCapacity > slots.length){
PooledConnection[] current = this.slots;
this.slots = new PooledConnection[newCapacity];
System.arraycopy(current, 0, this.slots, 0, current.length);
}
}
public String toString() {
return Arrays.toString(slots);
}
protected int getCapacity() {
return slots.length;
}
protected int size(){
return size;
}
protected boolean isEmpty() {
return size == 0;
}
protected int add(PooledConnection pc){
if (size == slots.length){
// grow the capacity
setCapacity(slots.length + growBy);
}
int slot = nextEmptySlot();
pc.setSlotId(slot);
slots[slot] = pc;
return ++size;
}
protected boolean remove(PooledConnection pc) {
int slotId = pc.getSlotId();
if (slots[slotId] != pc){
PooledConnection heldBy = slots[slotId];
logger.warn("Failed to remove from slot[{}] PooledConnection[{}] - HeldBy[{}]", pc.getSlotId(), pc, heldBy);
return false;
}
slots[slotId] = null;
--size;
return true;
}
/**
* Collect the load statistics from all the busy connections.
* @param reset
*/
protected void collectStatistics(LoadValues values, boolean reset) {
for (int i = 0; i < slots.length; i++) {
if (slots[i] != null){
values.plus(slots[i].getStatistics().getValues(reset));
}
}
}
/**
* Close connections that should be considered leaked.
*/
protected void closeBusyConnections(long leakTimeMinutes) {
private static final Logger logger = LoggerFactory.getLogger(BusyConnectionBuffer.class);
long olderThanTime = System.currentTimeMillis() - (leakTimeMinutes*60000);
private PooledConnection[] slots;
logger.debug("Closing busy connections using leakTimeMinutes {}", leakTimeMinutes);
private final int growBy;
for (int i = 0; i < slots.length; i++) {
if (slots[i] != null){
//tmp.add(slots[i]);
PooledConnection pc = slots[i];
//noinspection StatementWithEmptyBody
if (pc.isLongRunning() || pc.getLastUsedTime() > olderThanTime) {
// PooledConnection has been used recently or
// expected to be longRunning so not closing...
} else {
slots[i] = null;
--size;
closeBusyConnection(pc);
}
}
}
}
private void closeBusyConnection(PooledConnection pc) {
try {
logger.warn("DataSourcePool closing busy connection? "+pc.getFullDescription());
System.out.println("CLOSING busy connection: "+pc.getFullDescription());
pc.closeConnectionFully(false);
private int size;
} catch (Exception ex) {
// this should never actually happen
logger.error("Error when closing potentially leaked connection "+pc.getDescription(), ex);
}
private int pos = -1;
/**
* Create the buffer with an initial capacity and fixed growBy.
* We generally do not want the buffer to grow very often.
*
* @param capacity the initial capacity
* @param growBy the fixed amount to grow the buffer by.
*/
protected BusyConnectionBuffer(int capacity, int growBy) {
this.slots = new PooledConnection[capacity];
this.growBy = growBy;
}
/**
* Returns information describing connections that are currently being used.
*/
protected String getBusyConnectionInformation(boolean toLogger) {
if (toLogger) {
logger.info("Dumping [{}] busy connections: (Use datasource.xxx.capturestacktrace=true ... to get stackTraces)", size());
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < slots.length; i++) {
if (slots[i] != null){
PooledConnection pc = slots[i];
if (toLogger) {
logger.info("Busy Connection - {}", pc.getFullDescription());
} else {
sb.append(pc.getFullDescription()).append("\r\n");
}
}
}
return sb.toString();
/**
* We can only grow (not shrink) the capacity.
*/
protected void setCapacity(int newCapacity) {
if (newCapacity > slots.length) {
PooledConnection[] current = this.slots;
this.slots = new PooledConnection[newCapacity];
System.arraycopy(current, 0, this.slots, 0, current.length);
}
/**
* Return the position of the next empty slot.
*/
private int nextEmptySlot() {
}
// search forward
while(++pos < slots.length) {
if (slots[pos] == null){
return pos;
}
}
// search from beginning
pos = -1;
while(++pos < slots.length) {
if (slots[pos] == null){
return pos;
}
}
// not expecting this
throw new RuntimeException("No Empty Slot Found?");
public String toString() {
return Arrays.toString(slots);
}
protected int getCapacity() {
return slots.length;
}
protected int size() {
return size;
}
protected boolean isEmpty() {
return size == 0;
}
protected int add(PooledConnection pc) {
if (size == slots.length) {
// grow the capacity
setCapacity(slots.length + growBy);
}
int slot = nextEmptySlot();
pc.setSlotId(slot);
slots[slot] = pc;
return ++size;
}
protected boolean remove(PooledConnection pc) {
int slotId = pc.getSlotId();
if (slots[slotId] != pc) {
PooledConnection heldBy = slots[slotId];
logger.warn("Failed to remove from slot[{}] PooledConnection[{}] - HeldBy[{}]", pc.getSlotId(), pc, heldBy);
return false;
}
slots[slotId] = null;
--size;
return true;
}
/**
* Collect the load statistics from all the busy connections.
*
* @param reset
*/
protected void collectStatistics(LoadValues values, boolean reset) {
for (int i = 0; i < slots.length; i++) {
if (slots[i] != null) {
values.plus(slots[i].getStatistics().getValues(reset));
}
}
}
/**
* Close connections that should be considered leaked.
*/
protected void closeBusyConnections(long leakTimeMinutes) {
long olderThanTime = System.currentTimeMillis() - (leakTimeMinutes * 60000);
logger.debug("Closing busy connections using leakTimeMinutes {}", leakTimeMinutes);
for (int i = 0; i < slots.length; i++) {
if (slots[i] != null) {
//tmp.add(slots[i]);
PooledConnection pc = slots[i];
//noinspection StatementWithEmptyBody
if (pc.isLongRunning() || pc.getLastUsedTime() > olderThanTime) {
// PooledConnection has been used recently or
// expected to be longRunning so not closing...
} else {
slots[i] = null;
--size;
closeBusyConnection(pc);
}
}
}
}
private void closeBusyConnection(PooledConnection pc) {
try {
logger.warn("DataSourcePool closing busy connection? " + pc.getFullDescription());
System.out.println("CLOSING busy connection: " + pc.getFullDescription());
pc.closeConnectionFully(false);
} catch (Exception ex) {
// this should never actually happen
logger.error("Error when closing potentially leaked connection " + pc.getDescription(), ex);
}
}
/**
* Returns information describing connections that are currently being used.
*/
protected String getBusyConnectionInformation(boolean toLogger) {
if (toLogger) {
logger.info("Dumping [{}] busy connections: (Use datasource.xxx.capturestacktrace=true ... to get stackTraces)", size());
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < slots.length; i++) {
if (slots[i] != null) {
PooledConnection pc = slots[i];
if (toLogger) {
logger.info("Busy Connection - {}", pc.getFullDescription());
} else {
sb.append(pc.getFullDescription()).append("\r\n");
}
}
}
return sb.toString();
}
/**
* Return the position of the next empty slot.
*/
private int nextEmptySlot() {
// search forward
while (++pos < slots.length) {
if (slots[pos] == null) {
return pos;
}
}
// search from beginning
pos = -1;
while (++pos < slots.length) {
if (slots[pos] == null) {
return pos;
}
}
// not expecting this
throw new RuntimeException("No Empty Slot Found?");
}
}
@@ -10,18 +10,18 @@ package com.avaje.ebeaninternal.server.lib.sql;
*/
public interface DataSourceAlert {
/**
* Send an alert to say the dataSource is back up.
*/
void dataSourceUp(String dataSourceName);
/**
* Send an alert to say the dataSource is back up.
*/
void dataSourceUp(String dataSourceName);
/**
* Send an alert to say the dataSource is down.
*/
void dataSourceDown(String dataSourceName);
/**
* Send an alert to say the dataSource is down.
*/
void dataSourceDown(String dataSourceName);
/**
* Send an alert to say the dataSource is getting close to its max size.
*/
void dataSourceWarning(String subject, String msg);
/**
* Send an alert to say the dataSource is getting close to its max size.
*/
void dataSourceWarning(String subject, String msg);
}
File diff suppressed because it is too large Load Diff
@@ -13,7 +13,7 @@ import java.sql.Connection;
* <p>
* Example: datasource.ora10.poolListener=my.very.fancy.PoolListener
* </p>
*
* <p>
* <p>
* Notice: This listener only works if you are using the default Avaje
* {@link DataSourcePool}.
@@ -21,14 +21,14 @@ import java.sql.Connection;
*/
public interface DataSourcePoolListener {
/**
* Called after a connection has been retrieved from the connection pool
*/
void onAfterBorrowConnection(Connection c);
/**
* Called after a connection has been retrieved from the connection pool
*/
void onAfterBorrowConnection(Connection c);
/**
* Called before a connection will be put back to the connection pool
*/
void onBeforeReturnConnection(Connection c);
/**
* Called before a connection will be put back to the connection pool
*/
void onBeforeReturnConnection(Connection c);
}
@@ -16,13 +16,13 @@ package com.avaje.ebeaninternal.server.lib.sql;
public class DataSourcePoolStatistics {
private final long collectionStart;
private final long count;
private final long errorCount;
private final long hwmMicros;
private final long totalMicros;
/**
@@ -28,362 +28,363 @@ import java.util.Calendar;
*/
public class ExtendedPreparedStatement extends ExtendedStatement implements PreparedStatement {
/**
* The SQL used to create the underlying PreparedStatement.
*/
private final String sql;
/**
* The SQL used to create the underlying PreparedStatement.
*/
private final String sql;
/**
* The key used to cache this in the connection.
*/
private final String cacheKey;
/**
* The key used to cache this in the connection.
*/
private final String cacheKey;
/**
* Create a wrapped PreparedStatement that can be cached.
*/
public ExtendedPreparedStatement(PooledConnection pooledConnection, PreparedStatement pstmt, String sql, String cacheKey) {
super(pooledConnection, pstmt);
this.sql = sql;
this.cacheKey = cacheKey;
}
public PreparedStatement getDelegate() {
return pstmt;
}
/**
* Create a wrapped PreparedStatement that can be cached.
*/
public ExtendedPreparedStatement(PooledConnection pooledConnection, PreparedStatement pstmt, String sql, String cacheKey) {
super(pooledConnection, pstmt);
this.sql = sql;
this.cacheKey = cacheKey;
}
/**
* Return the key used to cache this on the Connection.
*/
public String getCacheKey() {
return cacheKey;
}
public PreparedStatement getDelegate() {
return pstmt;
}
/**
* Return the SQL used to create this PreparedStatement.
*/
public String getSql() {
return sql;
}
/**
* Return the key used to cache this on the Connection.
*/
public String getCacheKey() {
return cacheKey;
}
/**
* Fully close the underlying PreparedStatement. After this we can no longer
* reuse the PreparedStatement.
*/
public void closeDestroy() throws SQLException {
pstmt.close();
}
/**
* Return the SQL used to create this PreparedStatement.
*/
public String getSql() {
return sql;
}
/**
* Returns the PreparedStatement back into the cache. This doesn't fully
* close the underlying PreparedStatement.
*/
public void close() throws SQLException {
// return the connection back into the cache.
pooledConnection.returnPreparedStatement(this);
}
/**
* Fully close the underlying PreparedStatement. After this we can no longer
* reuse the PreparedStatement.
*/
public void closeDestroy() throws SQLException {
pstmt.close();
}
/**
* Add the last binding for batch execution.
*/
public void addBatch() throws SQLException {
try {
pstmt.addBatch();
} catch (SQLException e) {
// we got an error... need to check this
// connection before returning it
pooledConnection.addError(e);
throw e;
}
}
/**
* Returns the PreparedStatement back into the cache. This doesn't fully
* close the underlying PreparedStatement.
*/
public void close() throws SQLException {
// return the connection back into the cache.
pooledConnection.returnPreparedStatement(this);
}
/**
* Clear parameters.
*/
public void clearParameters() throws SQLException {
try {
pstmt.clearParameters();
} catch (SQLException e) {
// we got an error... need to check
// this connection before returning it
pooledConnection.addError(e);
throw e;
}
}
/**
* Add the last binding for batch execution.
*/
public void addBatch() throws SQLException {
try {
pstmt.addBatch();
} catch (SQLException e) {
// we got an error... need to check this
// connection before returning it
pooledConnection.addError(e);
throw e;
}
}
/**
* execute the statement.
*/
public boolean execute() throws SQLException {
try {
return pstmt.execute();
} catch (SQLException e) {
// we got an error... need to check
// this connection before returning it
pooledConnection.addError(e);
throw e;
}
}
/**
* Clear parameters.
*/
public void clearParameters() throws SQLException {
try {
pstmt.clearParameters();
} catch (SQLException e) {
// we got an error... need to check
// this connection before returning it
pooledConnection.addError(e);
throw e;
}
}
/**
* Execute teh query.
*/
public ResultSet executeQuery() throws SQLException {
try {
return pstmt.executeQuery();
} catch (SQLException e) {
// we got an error... need to check
// this connection before returning it
pooledConnection.addError(e);
throw e;
}
}
/**
* execute the statement.
*/
public boolean execute() throws SQLException {
try {
return pstmt.execute();
} catch (SQLException e) {
// we got an error... need to check
// this connection before returning it
pooledConnection.addError(e);
throw e;
}
}
/**
* Execute the dml statement.
*/
public int executeUpdate() throws SQLException {
try {
return pstmt.executeUpdate();
} catch (SQLException e) {
// we got an error... need to check
// this connection before returning it
pooledConnection.addError(e);
throw e;
}
}
/**
* Execute teh query.
*/
public ResultSet executeQuery() throws SQLException {
try {
return pstmt.executeQuery();
} catch (SQLException e) {
// we got an error... need to check
// this connection before returning it
pooledConnection.addError(e);
throw e;
}
}
/**
* Return the MetaData for the query.
*/
public ResultSetMetaData getMetaData() throws SQLException {
try {
return pstmt.getMetaData();
} catch (SQLException e) {
// we got an error... need to check
// this connection before returning it
pooledConnection.addError(e);
throw e;
}
}
/**
* Execute the dml statement.
*/
public int executeUpdate() throws SQLException {
try {
return pstmt.executeUpdate();
} catch (SQLException e) {
// we got an error... need to check
// this connection before returning it
pooledConnection.addError(e);
throw e;
}
}
/**
* Standard PreparedStatement method execution.
*/
public ParameterMetaData getParameterMetaData() throws SQLException {
return pstmt.getParameterMetaData();
}
/**
* Return the MetaData for the query.
*/
public ResultSetMetaData getMetaData() throws SQLException {
try {
return pstmt.getMetaData();
} catch (SQLException e) {
// we got an error... need to check
// this connection before returning it
pooledConnection.addError(e);
throw e;
}
}
/**
* Standard PreparedStatement method execution.
*/
public void setArray(int i, Array x) throws SQLException {
pstmt.setArray(i, x);
}
/**
* Standard PreparedStatement method execution.
*/
public ParameterMetaData getParameterMetaData() throws SQLException {
return pstmt.getParameterMetaData();
}
/**
* Standard PreparedStatement method execution.
*/
public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException {
pstmt.setAsciiStream(parameterIndex, x, length);
}
/**
* Standard PreparedStatement method execution.
*/
public void setArray(int i, Array x) throws SQLException {
pstmt.setArray(i, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException {
pstmt.setBigDecimal(parameterIndex, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException {
pstmt.setAsciiStream(parameterIndex, x, length);
}
/**
* Standard PreparedStatement method execution.
*/
public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException {
pstmt.setBinaryStream(parameterIndex, x, length);
}
/**
* Standard PreparedStatement method execution.
*/
public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException {
pstmt.setBigDecimal(parameterIndex, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setBlob(int i, Blob x) throws SQLException {
pstmt.setBlob(i, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException {
pstmt.setBinaryStream(parameterIndex, x, length);
}
/**
* Standard PreparedStatement method execution.
*/
public void setBoolean(int parameterIndex, boolean x) throws SQLException {
pstmt.setBoolean(parameterIndex, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setBlob(int i, Blob x) throws SQLException {
pstmt.setBlob(i, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setByte(int parameterIndex, byte x) throws SQLException {
pstmt.setByte(parameterIndex, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setBoolean(int parameterIndex, boolean x) throws SQLException {
pstmt.setBoolean(parameterIndex, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setBytes(int parameterIndex, byte[] x) throws SQLException {
pstmt.setBytes(parameterIndex, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setByte(int parameterIndex, byte x) throws SQLException {
pstmt.setByte(parameterIndex, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setCharacterStream(int parameterIndex, Reader reader, int length)
throws SQLException {
pstmt.setCharacterStream(parameterIndex, reader, length);
}
/**
* Standard PreparedStatement method execution.
*/
public void setBytes(int parameterIndex, byte[] x) throws SQLException {
pstmt.setBytes(parameterIndex, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setClob(int i, Clob x) throws SQLException {
pstmt.setClob(i, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setCharacterStream(int parameterIndex, Reader reader, int length)
throws SQLException {
pstmt.setCharacterStream(parameterIndex, reader, length);
}
/**
* Standard PreparedStatement method execution.
*/
public void setDate(int parameterIndex, Date x) throws SQLException {
pstmt.setDate(parameterIndex, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setClob(int i, Clob x) throws SQLException {
pstmt.setClob(i, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException {
pstmt.setDate(parameterIndex, x, cal);
}
/**
* Standard PreparedStatement method execution.
*/
public void setDate(int parameterIndex, Date x) throws SQLException {
pstmt.setDate(parameterIndex, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setDouble(int parameterIndex, double x) throws SQLException {
pstmt.setDouble(parameterIndex, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException {
pstmt.setDate(parameterIndex, x, cal);
}
/**
* Standard PreparedStatement method execution.
*/
public void setFloat(int parameterIndex, float x) throws SQLException {
pstmt.setFloat(parameterIndex, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setDouble(int parameterIndex, double x) throws SQLException {
pstmt.setDouble(parameterIndex, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setInt(int parameterIndex, int x) throws SQLException {
pstmt.setInt(parameterIndex, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setFloat(int parameterIndex, float x) throws SQLException {
pstmt.setFloat(parameterIndex, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setLong(int parameterIndex, long x) throws SQLException {
pstmt.setLong(parameterIndex, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setInt(int parameterIndex, int x) throws SQLException {
pstmt.setInt(parameterIndex, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setNull(int parameterIndex, int sqlType) throws SQLException {
pstmt.setNull(parameterIndex, sqlType);
}
/**
* Standard PreparedStatement method execution.
*/
public void setLong(int parameterIndex, long x) throws SQLException {
pstmt.setLong(parameterIndex, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setNull(int paramIndex, int sqlType, String typeName) throws SQLException {
pstmt.setNull(paramIndex, sqlType, typeName);
}
/**
* Standard PreparedStatement method execution.
*/
public void setNull(int parameterIndex, int sqlType) throws SQLException {
pstmt.setNull(parameterIndex, sqlType);
}
/**
* Standard PreparedStatement method execution.
*/
public void setObject(int parameterIndex, Object x) throws SQLException {
pstmt.setObject(parameterIndex, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setNull(int paramIndex, int sqlType, String typeName) throws SQLException {
pstmt.setNull(paramIndex, sqlType, typeName);
}
/**
* Standard PreparedStatement method execution.
*/
public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException {
pstmt.setObject(parameterIndex, x, targetSqlType);
}
/**
* Standard PreparedStatement method execution.
*/
public void setObject(int parameterIndex, Object x) throws SQLException {
pstmt.setObject(parameterIndex, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setObject(int parameterIndex, Object x, int targetSqlType, int scale)
throws SQLException {
pstmt.setObject(parameterIndex, x, targetSqlType, scale);
}
/**
* Standard PreparedStatement method execution.
*/
public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException {
pstmt.setObject(parameterIndex, x, targetSqlType);
}
/**
* Standard PreparedStatement method execution.
*/
public void setRef(int i, Ref x) throws SQLException {
pstmt.setRef(i, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setObject(int parameterIndex, Object x, int targetSqlType, int scale)
throws SQLException {
pstmt.setObject(parameterIndex, x, targetSqlType, scale);
}
/**
* Standard PreparedStatement method execution.
*/
public void setShort(int parameterIndex, short x) throws SQLException {
pstmt.setShort(parameterIndex, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setRef(int i, Ref x) throws SQLException {
pstmt.setRef(i, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setString(int parameterIndex, String x) throws SQLException {
pstmt.setString(parameterIndex, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setShort(int parameterIndex, short x) throws SQLException {
pstmt.setShort(parameterIndex, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setTime(int parameterIndex, Time x) throws SQLException {
pstmt.setTime(parameterIndex, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setString(int parameterIndex, String x) throws SQLException {
pstmt.setString(parameterIndex, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException {
pstmt.setTime(parameterIndex, x, cal);
}
/**
* Standard PreparedStatement method execution.
*/
public void setTime(int parameterIndex, Time x) throws SQLException {
pstmt.setTime(parameterIndex, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException {
pstmt.setTimestamp(parameterIndex, x);
}
/**
* Standard PreparedStatement method execution.
*/
public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException {
pstmt.setTime(parameterIndex, x, cal);
}
/**
* Standard PreparedStatement method execution.
*/
public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException {
pstmt.setTimestamp(parameterIndex, x, cal);
}
/**
* Standard PreparedStatement method execution.
*/
public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException {
pstmt.setTimestamp(parameterIndex, x);
}
/**
* Standard PreparedStatement method execution.
* @deprecated
*/
public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException {
pstmt.setUnicodeStream(parameterIndex, x, length);
}
/**
* Standard PreparedStatement method execution.
*/
public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException {
pstmt.setTimestamp(parameterIndex, x, cal);
}
/**
* Standard PreparedStatement method execution.
*/
public void setURL(int parameterIndex, URL x) throws SQLException {
pstmt.setURL(parameterIndex, x);
}
/**
* Standard PreparedStatement method execution.
*
* @deprecated
*/
public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException {
pstmt.setUnicodeStream(parameterIndex, x, length);
}
/**
* Standard PreparedStatement method execution.
*/
public void setURL(int parameterIndex, URL x) throws SQLException {
pstmt.setURL(parameterIndex, x);
}
}
@@ -16,313 +16,312 @@ import com.avaje.ebeaninternal.jdbc.PreparedStatementDelegator;
* for the case where someone uses the Statement api on an ExtendedPreparedStatement.
* </p>
*/
public abstract class ExtendedStatement extends PreparedStatementDelegator
{
public abstract class ExtendedStatement extends PreparedStatementDelegator {
/**
* The pooled connection this Statement belongs to.
*/
protected final PooledConnection pooledConnection;
/**
* The pooled connection this Statement belongs to.
*/
protected final PooledConnection pooledConnection;
/**
* The underlying Statement that this object wraps.
*/
protected final PreparedStatement pstmt;
/**
* The underlying Statement that this object wraps.
*/
protected final PreparedStatement pstmt;
/**
* Create the ExtendedStatement for a given pooledConnection.
*/
public ExtendedStatement(PooledConnection pooledConnection, PreparedStatement pstmt) {
super(pstmt);
/**
* Create the ExtendedStatement for a given pooledConnection.
*/
public ExtendedStatement(PooledConnection pooledConnection, PreparedStatement pstmt) {
super(pstmt);
this.pooledConnection = pooledConnection;
this.pstmt = pstmt;
}
this.pooledConnection = pooledConnection;
this.pstmt = pstmt;
}
/**
* Put the statement back into the statement cache.
*/
public abstract void close() throws SQLException;
/**
* Put the statement back into the statement cache.
*/
public abstract void close() throws SQLException;
/**
* Return the underlying connection.
*/
public Connection getConnection() throws SQLException {
try {
return pstmt.getConnection();
} catch (SQLException e) {
pooledConnection.addError(e);
throw e;
}
}
/**
* Return the underlying connection.
*/
public Connection getConnection() throws SQLException {
try {
return pstmt.getConnection();
} catch (SQLException e) {
pooledConnection.addError(e);
throw e;
}
}
/**
* Add the sql for batch execution.
*/
public void addBatch(String sql) throws SQLException {
try {
pooledConnection.setLastStatement(sql);
pstmt.addBatch(sql);
} catch (SQLException e) {
pooledConnection.addError(e);
throw e;
}
}
/**
* Add the sql for batch execution.
*/
public void addBatch(String sql) throws SQLException {
try {
pooledConnection.setLastStatement(sql);
pstmt.addBatch(sql);
} catch (SQLException e) {
pooledConnection.addError(e);
throw e;
}
}
/**
* Execute the sql.
*/
public boolean execute(String sql) throws SQLException {
try {
pooledConnection.setLastStatement(sql);
return pstmt.execute(sql);
} catch (SQLException e) {
pooledConnection.addError(e);
throw e;
}
}
/**
* Execute the sql.
*/
public boolean execute(String sql) throws SQLException {
try {
pooledConnection.setLastStatement(sql);
return pstmt.execute(sql);
} catch (SQLException e) {
pooledConnection.addError(e);
throw e;
}
}
/**
* Execute the query.
*/
public ResultSet executeQuery(String sql) throws SQLException {
try {
pooledConnection.setLastStatement(sql);
return pstmt.executeQuery(sql);
} catch (SQLException e) {
pooledConnection.addError(e);
throw e;
}
}
/**
* Execute the query.
*/
public ResultSet executeQuery(String sql) throws SQLException {
try {
pooledConnection.setLastStatement(sql);
return pstmt.executeQuery(sql);
} catch (SQLException e) {
pooledConnection.addError(e);
throw e;
}
}
/**
* Execute the dml sql.
*/
public int executeUpdate(String sql) throws SQLException {
try {
pooledConnection.setLastStatement(sql);
return pstmt.executeUpdate(sql);
} catch (SQLException e) {
pooledConnection.addError(e);
throw e;
}
}
/**
* Execute the dml sql.
*/
public int executeUpdate(String sql) throws SQLException {
try {
pooledConnection.setLastStatement(sql);
return pstmt.executeUpdate(sql);
} catch (SQLException e) {
pooledConnection.addError(e);
throw e;
}
}
/**
* Standard Statement method call.
*/
public int[] executeBatch() throws SQLException {
return pstmt.executeBatch();
}
/**
* Standard Statement method call.
*/
public int[] executeBatch() throws SQLException {
return pstmt.executeBatch();
}
/**
* Standard Statement method call.
*/
public void cancel() throws SQLException {
pstmt.cancel();
}
/**
* Standard Statement method call.
*/
public void cancel() throws SQLException {
pstmt.cancel();
}
/**
* Standard Statement method call.
*/
public void clearBatch() throws SQLException {
pstmt.clearBatch();
}
/**
* Standard Statement method call.
*/
public void clearBatch() throws SQLException {
pstmt.clearBatch();
}
/**
* Standard Statement method call.
*/
public void clearWarnings() throws SQLException {
pstmt.clearWarnings();
}
/**
* Standard Statement method call.
*/
public void clearWarnings() throws SQLException {
pstmt.clearWarnings();
}
/**
* Standard Statement method call.
*/
public int getFetchDirection() throws SQLException {
return pstmt.getFetchDirection();
}
/**
* Standard Statement method call.
*/
public int getFetchDirection() throws SQLException {
return pstmt.getFetchDirection();
}
/**
* Standard Statement method call.
*/
public int getFetchSize() throws SQLException {
return pstmt.getFetchSize();
}
/**
* Standard Statement method call.
*/
public int getFetchSize() throws SQLException {
return pstmt.getFetchSize();
}
/**
* Standard Statement method call.
*/
public int getMaxFieldSize() throws SQLException {
return pstmt.getMaxFieldSize();
}
/**
* Standard Statement method call.
*/
public int getMaxFieldSize() throws SQLException {
return pstmt.getMaxFieldSize();
}
/**
* Standard Statement method call.
*/
public int getMaxRows() throws SQLException {
return pstmt.getMaxRows();
}
/**
* Standard Statement method call.
*/
public boolean getMoreResults() throws SQLException {
return pstmt.getMoreResults();
}
/**
* Standard Statement method call.
*/
public int getMaxRows() throws SQLException {
return pstmt.getMaxRows();
}
/**
* Standard Statement method call.
*/
public int getQueryTimeout() throws SQLException {
return pstmt.getQueryTimeout();
}
/**
* Standard Statement method call.
*/
public boolean getMoreResults() throws SQLException {
return pstmt.getMoreResults();
}
/**
* Standard Statement method call.
*/
public ResultSet getResultSet() throws SQLException {
return pstmt.getResultSet();
}
/**
* Standard Statement method call.
*/
public int getQueryTimeout() throws SQLException {
return pstmt.getQueryTimeout();
}
/**
* Standard Statement method call.
*/
public int getResultSetConcurrency() throws SQLException {
return pstmt.getResultSetConcurrency();
}
/**
* Standard Statement method call.
*/
public int getResultSetType() throws SQLException {
return pstmt.getResultSetType();
}
/**
* Standard Statement method call.
*/
public ResultSet getResultSet() throws SQLException {
return pstmt.getResultSet();
}
/**
* Standard Statement method call.
*/
public int getUpdateCount() throws SQLException {
return pstmt.getUpdateCount();
}
/**
* Standard Statement method call.
*/
public int getResultSetConcurrency() throws SQLException {
return pstmt.getResultSetConcurrency();
}
/**
* Standard Statement method call.
*/
public SQLWarning getWarnings() throws SQLException {
return pstmt.getWarnings();
}
/**
* Standard Statement method call.
*/
public int getResultSetType() throws SQLException {
return pstmt.getResultSetType();
}
/**
* Standard Statement method call.
*/
public void setCursorName(String name) throws SQLException {
pstmt.setCursorName(name);
}
/**
* Standard Statement method call.
*/
public int getUpdateCount() throws SQLException {
return pstmt.getUpdateCount();
}
/**
* Standard Statement method call.
*/
public void setEscapeProcessing(boolean enable) throws SQLException {
pstmt.setEscapeProcessing(enable);
}
/**
* Standard Statement method call.
*/
public SQLWarning getWarnings() throws SQLException {
return pstmt.getWarnings();
}
/**
* Standard Statement method call.
*/
public void setFetchDirection(int direction) throws SQLException {
pstmt.setFetchDirection(direction);
}
/**
* Standard Statement method call.
*/
public void setCursorName(String name) throws SQLException {
pstmt.setCursorName(name);
}
/**
* Standard Statement method call.
*/
public void setFetchSize(int rows) throws SQLException {
pstmt.setFetchSize(rows);
}
/**
* Standard Statement method call.
*/
public void setEscapeProcessing(boolean enable) throws SQLException {
pstmt.setEscapeProcessing(enable);
}
/**
* Standard Statement method call.
*/
public void setMaxFieldSize(int max) throws SQLException {
pstmt.setMaxFieldSize(max);
}
/**
* Standard Statement method call.
*/
public void setFetchDirection(int direction) throws SQLException {
pstmt.setFetchDirection(direction);
}
/**
* Standard Statement method call.
*/
public void setMaxRows(int max) throws SQLException {
pstmt.setMaxRows(max);
}
/**
* Standard Statement method call.
*/
public void setFetchSize(int rows) throws SQLException {
pstmt.setFetchSize(rows);
}
/**
* Standard Statement method call.
*/
public void setQueryTimeout(int seconds) throws SQLException {
pstmt.setQueryTimeout(seconds);
}
/**
* Standard Statement method call.
*/
public void setMaxFieldSize(int max) throws SQLException {
pstmt.setMaxFieldSize(max);
}
/**
* Standard Statement method call.
*/
public boolean getMoreResults(int i) throws SQLException {
return pstmt.getMoreResults(i);
}
/**
* Standard Statement method call.
*/
public void setMaxRows(int max) throws SQLException {
pstmt.setMaxRows(max);
}
/**
* Standard Statement method call.
*/
public ResultSet getGeneratedKeys() throws SQLException {
return pstmt.getGeneratedKeys();
}
/**
* Standard Statement method call.
*/
public void setQueryTimeout(int seconds) throws SQLException {
pstmt.setQueryTimeout(seconds);
}
/**
* Standard Statement method call.
*/
public int executeUpdate(String s, int i) throws SQLException {
return pstmt.executeUpdate(s, i);
}
/**
* Standard Statement method call.
*/
public boolean getMoreResults(int i) throws SQLException {
return pstmt.getMoreResults(i);
}
/**
* Standard Statement method call.
*/
public int executeUpdate(String s, int[] i) throws SQLException {
return pstmt.executeUpdate(s, i);
}
/**
* Standard Statement method call.
*/
public ResultSet getGeneratedKeys() throws SQLException {
return pstmt.getGeneratedKeys();
}
/**
* Standard Statement method call.
*/
public int executeUpdate(String s, String[] i) throws SQLException {
return pstmt.executeUpdate(s, i);
}
/**
* Standard Statement method call.
*/
public int executeUpdate(String s, int i) throws SQLException {
return pstmt.executeUpdate(s, i);
}
/**
* Standard Statement method call.
*/
public boolean execute(String s, int i) throws SQLException {
return pstmt.execute(s, i);
}
/**
* Standard Statement method call.
*/
public int executeUpdate(String s, int[] i) throws SQLException {
return pstmt.executeUpdate(s, i);
}
/**
* Standard Statement method call.
*/
public boolean execute(String s, int[] i) throws SQLException {
return pstmt.execute(s, i);
}
/**
* Standard Statement method call.
*/
public int executeUpdate(String s, String[] i) throws SQLException {
return pstmt.executeUpdate(s, i);
}
/**
* Standard Statement method call.
*/
public boolean execute(String s, String[] i) throws SQLException {
return pstmt.execute(s, i);
}
/**
* Standard Statement method call.
*/
public boolean execute(String s, int i) throws SQLException {
return pstmt.execute(s, i);
}
/**
* Standard Statement method call.
*/
public int getResultSetHoldability() throws SQLException {
return pstmt.getResultSetHoldability();
}
/**
* Standard Statement method call.
*/
public boolean execute(String s, int[] i) throws SQLException {
return pstmt.execute(s, i);
}
/**
* Standard Statement method call.
*/
public boolean execute(String s, String[] i) throws SQLException {
return pstmt.execute(s, i);
}
/**
* Standard Statement method call.
*/
public int getResultSetHoldability() throws SQLException {
return pstmt.getResultSetHoldability();
}
}
@@ -19,7 +19,7 @@ import com.avaje.ebeaninternal.server.lib.sql.PooledConnectionStatistics.LoadVal
class FreeConnectionBuffer {
private static final Logger logger = LoggerFactory.getLogger(FreeConnectionBuffer.class);
/**
* Buffer oriented for add and remove.
*/
@@ -57,7 +57,7 @@ class FreeConnectionBuffer {
// create a temporary list
List<PooledConnection> tempList = new ArrayList<PooledConnection>(freeBuffer.size());
// add all the connections into it
for (PooledConnection c : freeBuffer) {
tempList.add(c);
@@ -65,15 +65,15 @@ class FreeConnectionBuffer {
// clear the buffer (in case it takes some time to close these connections).
freeBuffer.clear();
logger.debug("... closing all {} connections from the free list with logErrors: {}", tempList.size(), logErrors);
for (int i = 0; i < tempList.size(); i++) {
PooledConnection pooledConnection = tempList.get(i);
logger.debug("... closing {} of {} connections from the free list", i, tempList.size());
logger.debug("... closing {} of {} connections from the free list", i, tempList.size());
pooledConnection.closeConnectionFully(logErrors);
}
}
/**
* Trim any inactive connections that have not been used since usedSince.
*/
@@ -13,520 +13,520 @@ import com.avaje.ebeaninternal.server.lib.sql.PooledConnectionStatistics.LoadVal
public class PooledConnectionQueue {
private static final Logger logger = LoggerFactory.getLogger(PooledConnectionQueue.class);
private static final TimeUnit MILLIS_TIME_UNIT = TimeUnit.MILLISECONDS;
private static final Logger logger = LoggerFactory.getLogger(PooledConnectionQueue.class);
private final String name;
private final DataSourcePool pool;
/**
* A 'circular' buffer designed specifically for free connections.
*/
private final FreeConnectionBuffer freeList;
/**
* A 'slots' buffer designed specifically for busy connections.
* Fast add remove based on slot id.
*/
private final BusyConnectionBuffer busyList;
private static final TimeUnit MILLIS_TIME_UNIT = TimeUnit.MILLISECONDS;
/**
* Load statistics collected off connections that have closed fully (left the pool).
*/
private final PooledConnectionStatistics collectedStats = new PooledConnectionStatistics();
/**
* Currently accumulated load statistics.
*/
private LoadValues accumulatedValues = new LoadValues();
private final String name;
/**
* Main lock guarding all access
*/
private final ReentrantLock lock;
/**
* Condition for threads waiting to take a connection
*/
private final Condition notEmpty;
private final DataSourcePool pool;
private int connectionId;
/**
* A 'circular' buffer designed specifically for free connections.
*/
private final FreeConnectionBuffer freeList;
private final long waitTimeoutMillis;
private final long leakTimeMinutes;
private final long maxAgeMillis;
/**
* A 'slots' buffer designed specifically for busy connections.
* Fast add remove based on slot id.
*/
private final BusyConnectionBuffer busyList;
private int warningSize;
private int maxSize;
private int minSize;
/**
* Number of threads in the wait queue.
*/
private int waitingThreads;
/**
* Number of times a thread had to wait.
*/
private int waitCount;
/**
* Number of times a connection was got from this queue.
*/
private int hitCount;
/**
* The high water mark for the queue size.
*/
private int highWaterMark;
/**
* Last time the pool was reset. Used to close busy connections as they are
* returned to the pool that where created prior to the lastResetTime.
*/
private long lastResetTime;
/**
* Load statistics collected off connections that have closed fully (left the pool).
*/
private final PooledConnectionStatistics collectedStats = new PooledConnectionStatistics();
private boolean doingShutdown;
/**
* Currently accumulated load statistics.
*/
private LoadValues accumulatedValues = new LoadValues();
public PooledConnectionQueue(DataSourcePool pool) {
this.pool = pool;
this.name = pool.getName();
this.minSize = pool.getMinSize();
this.maxSize = pool.getMaxSize();
this.warningSize = pool.getWarningSize();
this.waitTimeoutMillis = pool.getWaitTimeoutMillis();
this.leakTimeMinutes = pool.getLeakTimeMinutes();
this.maxAgeMillis = pool.getMaxAgeMillis();
/**
* Main lock guarding all access
*/
private final ReentrantLock lock;
this.busyList = new BusyConnectionBuffer(maxSize, 20);
this.freeList = new FreeConnectionBuffer();
/**
* Condition for threads waiting to take a connection
*/
private final Condition notEmpty;
this.lock = new ReentrantLock(false);
this.notEmpty = lock.newCondition();
}
private Status createStatus() {
return new Status(name, minSize, maxSize, freeList.size(), busyList.size(), waitingThreads, highWaterMark, waitCount, hitCount);
}
public String toString() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return createStatus().toString();
} finally {
lock.unlock();
}
}
/**
* Collect statistics of a connection that is fully closing
*/
protected void reportClosingConnection(PooledConnection pooledConnection) {
collectedStats.add(pooledConnection.getStatistics());
}
private int connectionId;
public DataSourcePoolStatistics getStatistics(boolean reset) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
private final long waitTimeoutMillis;
LoadValues aggregate = collectedStats.getValues(reset);
private final long leakTimeMinutes;
freeList.collectStatistics(aggregate, reset);
busyList.collectStatistics(aggregate, reset);
private final long maxAgeMillis;
aggregate.plus(accumulatedValues);
this.accumulatedValues = (reset) ? new LoadValues() : aggregate;
return new DataSourcePoolStatistics(aggregate.getCollectionStart(), aggregate.getCount(), aggregate.getErrorCount(), aggregate.getHwmMicros(), aggregate.getTotalMicros());
} finally {
lock.unlock();
}
private int warningSize;
private int maxSize;
private int minSize;
/**
* Number of threads in the wait queue.
*/
private int waitingThreads;
/**
* Number of times a thread had to wait.
*/
private int waitCount;
/**
* Number of times a connection was got from this queue.
*/
private int hitCount;
/**
* The high water mark for the queue size.
*/
private int highWaterMark;
/**
* Last time the pool was reset. Used to close busy connections as they are
* returned to the pool that where created prior to the lastResetTime.
*/
private long lastResetTime;
private boolean doingShutdown;
public PooledConnectionQueue(DataSourcePool pool) {
this.pool = pool;
this.name = pool.getName();
this.minSize = pool.getMinSize();
this.maxSize = pool.getMaxSize();
this.warningSize = pool.getWarningSize();
this.waitTimeoutMillis = pool.getWaitTimeoutMillis();
this.leakTimeMinutes = pool.getLeakTimeMinutes();
this.maxAgeMillis = pool.getMaxAgeMillis();
this.busyList = new BusyConnectionBuffer(maxSize, 20);
this.freeList = new FreeConnectionBuffer();
this.lock = new ReentrantLock(false);
this.notEmpty = lock.newCondition();
}
public Status getStatus(boolean reset) {
final ReentrantLock lock = this.lock;
lock.lock();
private Status createStatus() {
return new Status(name, minSize, maxSize, freeList.size(), busyList.size(), waitingThreads, highWaterMark, waitCount, hitCount);
}
public String toString() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return createStatus().toString();
} finally {
lock.unlock();
}
}
/**
* Collect statistics of a connection that is fully closing
*/
protected void reportClosingConnection(PooledConnection pooledConnection) {
collectedStats.add(pooledConnection.getStatistics());
}
public DataSourcePoolStatistics getStatistics(boolean reset) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
LoadValues aggregate = collectedStats.getValues(reset);
freeList.collectStatistics(aggregate, reset);
busyList.collectStatistics(aggregate, reset);
aggregate.plus(accumulatedValues);
this.accumulatedValues = (reset) ? new LoadValues() : aggregate;
return new DataSourcePoolStatistics(aggregate.getCollectionStart(), aggregate.getCount(), aggregate.getErrorCount(), aggregate.getHwmMicros(), aggregate.getTotalMicros());
} finally {
lock.unlock();
}
}
public Status getStatus(boolean reset) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Status s = createStatus();
if (reset) {
highWaterMark = busyList.size();
hitCount = 0;
waitCount = 0;
}
return s;
} finally {
lock.unlock();
}
}
public void setMinSize(int minSize) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (minSize > this.maxSize) {
throw new IllegalArgumentException("minSize " + minSize + " > maxSize " + this.maxSize);
}
this.minSize = minSize;
} finally {
lock.unlock();
}
}
public void setMaxSize(int maxSize) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (maxSize < this.minSize) {
throw new IllegalArgumentException("maxSize " + maxSize + " < minSize " + this.minSize);
}
this.busyList.setCapacity(maxSize);
this.maxSize = maxSize;
} finally {
lock.unlock();
}
}
public void setWarningSize(int warningSize) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (warningSize > this.maxSize) {
throw new IllegalArgumentException("warningSize " + warningSize + " > maxSize " + this.maxSize);
}
this.warningSize = warningSize;
} finally {
lock.unlock();
}
}
private int totalConnections() {
return freeList.size() + busyList.size();
}
public void ensureMinimumConnections() throws SQLException {
final ReentrantLock lock = this.lock;
lock.lock();
try {
int add = minSize - totalConnections();
if (add > 0) {
for (int i = 0; i < add; i++) {
PooledConnection c = pool.createConnectionForQueue(connectionId++);
freeList.add(c);
}
notEmpty.signal();
}
} finally {
lock.unlock();
}
}
/**
* Return a PooledConnection.
*/
protected void returnPooledConnection(PooledConnection c, boolean forceClose) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (!busyList.remove(c)) {
logger.error("Connection [{}] not found in BusyList? ", c);
}
if (forceClose || c.shouldTrimOnReturn(lastResetTime, maxAgeMillis)) {
c.closeConnectionFully(false);
} else {
freeList.add(c);
notEmpty.signal();
}
} finally {
lock.unlock();
}
}
private PooledConnection extractFromFreeList() {
PooledConnection c = freeList.remove();
registerBusyConnection(c);
return c;
}
public PooledConnection getPooledConnection() throws SQLException {
try {
PooledConnection pc = _getPooledConnection();
pc.resetForUse();
return pc;
} catch (InterruptedException e) {
String msg = "Interrupted getting connection from pool " + e;
throw new SQLException(msg);
}
}
/**
* Register the PooledConnection with the busyList.
*/
private int registerBusyConnection(PooledConnection c) {
int busySize = busyList.add(c);
if (busySize > highWaterMark) {
highWaterMark = busySize;
}
return busySize;
}
private PooledConnection _getPooledConnection() throws InterruptedException, SQLException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
if (doingShutdown) {
throw new SQLException("Trying to access the Connection Pool when it is shutting down");
}
// this includes attempts that fail with InterruptedException
// or SQLException but that is ok as its only an indicator
hitCount++;
// are other threads already waiting? (they get priority)
if (waitingThreads == 0) {
if (!freeList.isEmpty()) {
// we have a free connection to return
return extractFromFreeList();
}
if (busyList.size() < maxSize) {
// grow the connection pool
PooledConnection c = pool.createConnectionForQueue(connectionId++);
int busySize = registerBusyConnection(c);
if (logger.isDebugEnabled()) {
logger.debug("DataSourcePool [{}] grow; id[{}] busy[{}] max[{}]", name, c.getName(), busySize, maxSize);
}
checkForWarningSize();
return c;
}
}
try {
// The pool is at maximum size. We are going to go into
// a wait loop until connections are returned into the pool.
waitCount++;
waitingThreads++;
return _getPooledConnectionWaitLoop();
} finally {
waitingThreads--;
}
} finally {
lock.unlock();
}
}
/**
* Got into a loop waiting for connections to be returned to the pool.
*/
private PooledConnection _getPooledConnectionWaitLoop() throws SQLException, InterruptedException {
long nanos = MILLIS_TIME_UNIT.toNanos(waitTimeoutMillis);
for (; ; ) {
if (nanos <= 0) {
String msg = "Unsuccessfully waited [" + waitTimeoutMillis + "] millis for a connection to be returned."
+ " No connections are free. You need to Increase the max connections of [" + maxSize + "]"
+ " or look for a connection pool leak using datasource.xxx.capturestacktrace=true";
if (pool.isCaptureStackTrace()) {
dumpBusyConnectionInformation();
}
throw new SQLException(msg);
}
try {
nanos = notEmpty.awaitNanos(nanos);
if (!freeList.isEmpty()) {
// successfully waited
return extractFromFreeList();
}
} catch (InterruptedException ie) {
notEmpty.signal(); // propagate to non-interrupted thread
throw ie;
}
}
}
public void shutdown() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
doingShutdown = true;
Status status = createStatus();
DataSourcePoolStatistics statistics = pool.getStatistics(false);
logger.debug("DataSourcePool [{}] shutdown {} - Statistics {}", name, status, statistics);
closeFreeConnections(true);
if (!busyList.isEmpty()) {
logger.warn("Closing busy connections on shutdown size: " + busyList.size());
dumpBusyConnectionInformation();
closeBusyConnections(0);
}
} finally {
lock.unlock();
}
}
/**
* Close all the connections in the pool and any current busy connections
* when they are returned. New connections will be then created on demand.
* <p>
* This is typically done when a database down event occurs.
* </p>
*/
public void reset(long leakTimeMinutes) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Status status = createStatus();
logger.info("Reseting DataSourcePool [{}] {}", name, status);
lastResetTime = System.currentTimeMillis();
closeFreeConnections(false);
closeBusyConnections(leakTimeMinutes);
logger.info("Busy Connections:\n" + getBusyConnectionInformation());
} finally {
lock.unlock();
}
}
public void trim(long maxInactiveMillis, long maxAgeMillis) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (trimInactiveConnections(maxInactiveMillis, maxAgeMillis) > 0) {
try {
Status s = createStatus();
if (reset){
highWaterMark = busyList.size();
hitCount = 0;
waitCount = 0;
}
return s;
} finally {
lock.unlock();
}
}
public void setMinSize(int minSize) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (minSize > this.maxSize){
throw new IllegalArgumentException("minSize "+minSize+" > maxSize "+this.maxSize);
}
this.minSize = minSize;
} finally {
lock.unlock();
}
}
public void setMaxSize(int maxSize) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (maxSize < this.minSize){
throw new IllegalArgumentException("maxSize "+maxSize+" < minSize "+this.minSize);
}
this.busyList.setCapacity(maxSize);
this.maxSize = maxSize;
} finally {
lock.unlock();
}
}
public void setWarningSize(int warningSize) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (warningSize > this.maxSize){
throw new IllegalArgumentException("warningSize "+warningSize+" > maxSize "+this.maxSize);
}
this.warningSize = warningSize;
} finally {
lock.unlock();
}
}
private int totalConnections() {
return freeList.size() + busyList.size();
}
public void ensureMinimumConnections() throws SQLException {
final ReentrantLock lock = this.lock;
lock.lock();
try {
int add = minSize - totalConnections();
if (add > 0){
for (int i = 0; i < add; i++) {
PooledConnection c = pool.createConnectionForQueue(connectionId++);
freeList.add(c);
}
notEmpty.signal();
}
} finally {
lock.unlock();
}
}
/**
* Return a PooledConnection.
*/
protected void returnPooledConnection(PooledConnection c, boolean forceClose) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (!busyList.remove(c)) {
logger.error("Connection [{}] not found in BusyList? ", c);
}
if (forceClose || c.shouldTrimOnReturn(lastResetTime, maxAgeMillis)) {
c.closeConnectionFully(false);
} else {
freeList.add(c);
notEmpty.signal();
}
} finally {
lock.unlock();
ensureMinimumConnections();
} catch (SQLException e) {
logger.error("Error trying to ensure minimum connections", e);
}
}
} finally {
lock.unlock();
}
}
private PooledConnection extractFromFreeList() {
PooledConnection c = freeList.remove();
registerBusyConnection(c);
return c;
}
/**
* Trim connections that have been not used for some time.
*/
private int trimInactiveConnections(long maxInactiveMillis, long maxAgeMillis) {
public PooledConnection getPooledConnection() throws SQLException {
try {
PooledConnection pc = _getPooledConnection();
pc.resetForUse();
return pc;
} catch (InterruptedException e) {
String msg = "Interrupted getting connection from pool "+e;
throw new SQLException(msg);
}
}
/**
* Register the PooledConnection with the busyList.
*/
private int registerBusyConnection(PooledConnection c) {
int busySize = busyList.add(c);
if (busySize > highWaterMark){
highWaterMark = busySize;
}
return busySize;
}
private PooledConnection _getPooledConnection() throws InterruptedException, SQLException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
if (doingShutdown) {
throw new SQLException("Trying to access the Connection Pool when it is shutting down");
}
// this includes attempts that fail with InterruptedException
// or SQLException but that is ok as its only an indicator
hitCount++;
// are other threads already waiting? (they get priority)
if (waitingThreads == 0){
if (!freeList.isEmpty()){
// we have a free connection to return
return extractFromFreeList();
}
if (busyList.size() < maxSize){
// grow the connection pool
PooledConnection c = pool.createConnectionForQueue(connectionId++);
int busySize = registerBusyConnection(c);
if (logger.isDebugEnabled()) {
logger.debug("DataSourcePool [{}] grow; id[{}] busy[{}] max[{}]", name, c.getName(), busySize, maxSize);
}
checkForWarningSize();
return c;
}
}
try {
// The pool is at maximum size. We are going to go into
// a wait loop until connections are returned into the pool.
waitCount++;
waitingThreads++;
return _getPooledConnectionWaitLoop();
} finally {
waitingThreads--;
}
long usedSince = System.currentTimeMillis() - maxInactiveMillis;
long createdSince = (maxAgeMillis == 0) ? 0 : System.currentTimeMillis() - maxAgeMillis;
} finally {
lock.unlock();
}
int trimedCount = freeList.trim(usedSince, createdSince);
if (trimedCount > 0) {
logger.debug("DataSourcePool [{}] trimmed [{}] inactive connections. New size[{}]", name, trimedCount, totalConnections());
}
/**
* Got into a loop waiting for connections to be returned to the pool.
*/
private PooledConnection _getPooledConnectionWaitLoop() throws SQLException, InterruptedException {
return trimedCount;
}
long nanos = MILLIS_TIME_UNIT.toNanos(waitTimeoutMillis);
for (;;) {
if (nanos <= 0) {
String msg = "Unsuccessfully waited ["+waitTimeoutMillis+"] millis for a connection to be returned."
+ " No connections are free. You need to Increase the max connections of ["+maxSize+"]"
+ " or look for a connection pool leak using datasource.xxx.capturestacktrace=true";
if (pool.isCaptureStackTrace()) {
dumpBusyConnectionInformation();
}
throw new SQLException(msg);
}
try {
nanos = notEmpty.awaitNanos(nanos);
if (!freeList.isEmpty()) {
// successfully waited
return extractFromFreeList();
}
} catch (InterruptedException ie) {
notEmpty.signal(); // propagate to non-interrupted thread
throw ie;
}
}
/**
* Close all the connections that are in the free list.
*/
public void closeFreeConnections(boolean logErrors) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
freeList.closeAll(logErrors);
} finally {
lock.unlock();
}
public void shutdown() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
doingShutdown = true;
Status status = createStatus();
DataSourcePoolStatistics statistics = pool.getStatistics(false);
logger.debug("DataSourcePool [{}] shutdown {} - Statistics {}", name, status, statistics);
closeFreeConnections(true);
if (!busyList.isEmpty()) {
logger.warn("Closing busy connections on shutdown size: "+ busyList.size());
dumpBusyConnectionInformation();
closeBusyConnections(0);
}
} finally {
lock.unlock();
}
}
/**
* Close any busy connections that have not been used for some time.
* <p>
* These connections are considered to have leaked from the connection pool.
* </p>
* <p>
* Connection leaks occur when code doesn't ensure that connections are
* closed() after they have been finished with. There should be an
* appropriate try catch finally block to ensure connections are always
* closed and put back into the pool.
* </p>
*/
public void closeBusyConnections(long leakTimeMinutes) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
busyList.closeBusyConnections(leakTimeMinutes);
} finally {
lock.unlock();
}
}
/**
* Close all the connections in the pool and any current busy connections
* when they are returned. New connections will be then created on demand.
* <p>
* This is typically done when a database down event occurs.
* </p>
*/
public void reset(long leakTimeMinutes) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Status status = createStatus();
logger.info("Reseting DataSourcePool [{}] {}", name, status);
lastResetTime = System.currentTimeMillis();
/**
* As the pool grows it gets closer to the maxConnections limit. We can send
* an Alert (or warning) as we get close to this limit and hence an
* Administrator could increase the pool size if desired.
* <p>
* This is called whenever the pool grows in size (towards the max limit).
* </p>
*/
private void checkForWarningSize() {
closeFreeConnections(false);
closeBusyConnections(leakTimeMinutes);
// the the total number of connections that we can add
// to the pool before it hits the maximum
int availableGrowth = (maxSize - totalConnections());
logger.info("Busy Connections:\n" + getBusyConnectionInformation());
if (availableGrowth < warningSize) {
} finally {
lock.unlock();
}
closeBusyConnections(leakTimeMinutes);
String msg = "DataSourcePool [" + name + "] is [" + availableGrowth + "] connections from its maximum size.";
pool.notifyWarning(msg);
}
}
public void trim(long maxInactiveMillis, long maxAgeMillis) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (trimInactiveConnections(maxInactiveMillis, maxAgeMillis) > 0) {
try {
ensureMinimumConnections();
} catch (SQLException e) {
logger.error("Error trying to ensure minimum connections", e);
}
}
} finally {
lock.unlock();
}
}
/**
* Trim connections that have been not used for some time.
*/
private int trimInactiveConnections(long maxInactiveMillis, long maxAgeMillis) {
long usedSince = System.currentTimeMillis() - maxInactiveMillis;
long createdSince = (maxAgeMillis == 0) ? 0 : System.currentTimeMillis() - maxAgeMillis;
int trimedCount = freeList.trim(usedSince, createdSince);
if (trimedCount > 0) {
logger.debug("DataSourcePool [{}] trimmed [{}] inactive connections. New size[{}]", name, trimedCount, totalConnections());
}
return trimedCount;
}
/**
* Close all the connections that are in the free list.
*/
public void closeFreeConnections(boolean logErrors) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
freeList.closeAll(logErrors);
} finally {
lock.unlock();
}
}
/**
* Close any busy connections that have not been used for some time.
* <p>
* These connections are considered to have leaked from the connection pool.
* </p>
* <p>
* Connection leaks occur when code doesn't ensure that connections are
* closed() after they have been finished with. There should be an
* appropriate try catch finally block to ensure connections are always
* closed and put back into the pool.
* </p>
*/
public void closeBusyConnections(long leakTimeMinutes) {
public String getBusyConnectionInformation() {
return getBusyConnectionInformation(false);
}
final ReentrantLock lock = this.lock;
lock.lock();
try {
busyList.closeBusyConnections(leakTimeMinutes);
} finally {
lock.unlock();
}
}
/**
* As the pool grows it gets closer to the maxConnections limit. We can send
* an Alert (or warning) as we get close to this limit and hence an
* Administrator could increase the pool size if desired.
* <p>
* This is called whenever the pool grows in size (towards the max limit).
* </p>
*/
private void checkForWarningSize() {
public void dumpBusyConnectionInformation() {
getBusyConnectionInformation(true);
}
// the the total number of connections that we can add
// to the pool before it hits the maximum
int availableGrowth = (maxSize - totalConnections());
/**
* Returns information describing connections that are currently being used.
*/
private String getBusyConnectionInformation(boolean toLogger) {
if (availableGrowth < warningSize) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
closeBusyConnections(leakTimeMinutes);
return busyList.getBusyConnectionInformation(toLogger);
String msg = "DataSourcePool [" + name + "] is [" + availableGrowth+ "] connections from its maximum size.";
pool.notifyWarning(msg);
}
} finally {
lock.unlock();
}
public String getBusyConnectionInformation() {
return getBusyConnectionInformation(false);
}
public void dumpBusyConnectionInformation() {
getBusyConnectionInformation(true);
}
/**
* Returns information describing connections that are currently being used.
*/
private String getBusyConnectionInformation(boolean toLogger) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
}
return busyList.getBusyConnectionInformation(toLogger);
} finally {
lock.unlock();
}
}
}
@@ -7,13 +7,13 @@ import java.util.concurrent.atomic.AtomicLong;
* Collects load statistics for a PooledConnection.
*/
public class PooledConnectionStatistics {
private final AtomicLong count = new AtomicLong();
private final AtomicLong errorCount = new AtomicLong();
private final AtomicLong hwmNanos = new AtomicLong();
private final AtomicLong totalNanos = new AtomicLong();
private final AtomicLong collectionStart;
@@ -21,22 +21,22 @@ public class PooledConnectionStatistics {
public PooledConnectionStatistics() {
this.collectionStart = new AtomicLong(System.currentTimeMillis());
}
/**
* Add statistics from another collector.
*/
public void add(PooledConnectionStatistics other) {
errorCount.addAndGet(other.getErrorCount());
totalNanos.addAndGet(other.totalNanos.get());
count.addAndGet(other.getCount());
final long otherHwm = other.hwmNanos.get();
if (otherHwm > hwmNanos.get()) {
hwmNanos.set(otherHwm);
}
}
/**
* Add some time duration to the statistics.
*/
@@ -44,7 +44,7 @@ public class PooledConnectionStatistics {
// This will be done in pretty much single threaded fashion
// as the Connections generally are not shared across threads
if (hasError) {
errorCount.incrementAndGet();
}
@@ -54,11 +54,11 @@ public class PooledConnectionStatistics {
hwmNanos.set(durationNanos);
}
}
public String toString() {
return "count["+count+"] errors["+errorCount+"] totalMicros["+getTotalMicros()+"] hwmMicros["+getHwmMicros()+"]";
return "count[" + count + "] errors[" + errorCount + "] totalMicros[" + getTotalMicros() + "] hwmMicros[" + getHwmMicros() + "]";
}
public long getCollectionStart() {
return collectionStart.get();
}
@@ -74,7 +74,7 @@ public class PooledConnectionStatistics {
public long getTotalMicros() {
return TimeUnit.MICROSECONDS.convert(totalNanos.get(), TimeUnit.NANOSECONDS);
}
public long getHwmMicros() {
return TimeUnit.MICROSECONDS.convert(hwmNanos.get(), TimeUnit.NANOSECONDS);
}
@@ -101,16 +101,16 @@ public class PooledConnectionStatistics {
* </p>
*/
public static class LoadValues {
private long collectionStart;
private long count;
private long errorCount;
private long hwmMicros;
private long totalMicros;
public LoadValues() {
}
public LoadValues(long collectionStart, long count, long errorCount, long hwmMicros, long totalMicros) {
this.collectionStart = collectionStart;
this.count = count;
@@ -128,7 +128,7 @@ public class PooledConnectionStatistics {
}
public String toString() {
return "count["+count+"] errors["+errorCount+"] totalMicros["+totalMicros+"] hwmMicros["+hwmMicros+"] avgMicros["+getAvgMicros()+"]";
return "count[" + count + "] errors[" + errorCount + "] totalMicros[" + totalMicros + "] hwmMicros[" + hwmMicros + "] avgMicros[" + getAvgMicros() + "]";
}
public long getCollectionStart() {
@@ -150,13 +150,11 @@ public class PooledConnectionStatistics {
public long getTotalMicros() {
return totalMicros;
}
public long getAvgMicros() {
return (count == 0) ? 0 : totalMicros/count;
return (count == 0) ? 0 : totalMicros / count;
}
}
}
@@ -10,89 +10,89 @@ import java.util.Random;
*/
public class Prefix {
private static final Logger logger = LoggerFactory.getLogger(Prefix.class);
private static final int[] oa = { 50, 12, 4, 6, 8, 10, 7, 23, 45, 23, 6, 9, 12, 2, 8, 34 };
private static final Logger logger = LoggerFactory.getLogger(Prefix.class);
public static String getProp(String prop) {
String v = dec(prop);
int p = v.indexOf(":");
return v.substring(1, p);
}
private static final int[] oa = {50, 12, 4, 6, 8, 10, 7, 23, 45, 23, 6, 9, 12, 2, 8, 34};
public static void main(String[] args) {
String m = e(args[0]);
logger.info("[" + m + "]");
String o = getProp(m);
logger.info("[" + o + "]");
}
public static String getProp(String prop) {
String v = dec(prop);
int p = v.indexOf(":");
return v.substring(1, p);
}
public static String e(String msg) {
msg = elen(msg, 40);
return enc(msg);
}
public static void main(String[] args) {
String m = e(args[0]);
logger.info("[" + m + "]");
String o = getProp(m);
logger.info("[" + o + "]");
}
public static byte az(byte c, int offset) {
public static String e(String msg) {
msg = elen(msg, 40);
return enc(msg);
}
int z = c + offset;
if (z > 122) {
// dp("z> "+z);
z = z - 122 + 48 - 1;
}
// dp("z="+z+" c:"+(int)c);
return (byte) z;
}
public static byte az(byte c, int offset) {
public static byte bz(byte c, int offset) {
int z = c - offset;
if (z < (48)) {
// dp("z< "+z);
z = z + 122 - 48 + 1;
}
return (byte) z;
}
int z = c + offset;
if (z > 122) {
// dp("z> "+z);
z = z - 122 + 48 - 1;
}
// dp("z="+z+" c:"+(int)c);
return (byte) z;
}
public static String enc(String msg) {
byte[] msgbytes = msg.getBytes();
byte[] encbytes = new byte[msgbytes.length + 1];
Random r = new Random();
int key = r.nextInt(70);
public static byte bz(byte c, int offset) {
int z = c - offset;
if (z < (48)) {
// dp("z< "+z);
z = z + 122 - 48 + 1;
}
return (byte) z;
}
char k = (char) (key + 48);
public static String enc(String msg) {
byte[] msgbytes = msg.getBytes();
byte[] encbytes = new byte[msgbytes.length + 1];
Random r = new Random();
int key = r.nextInt(70);
encbytes[0] = az((byte) k, oa[0]);
// dp("key:"+key+" encbytes[0]:"+(byte)encbytes[0]);
char k = (char) (key + 48);
encbytes[0] = az((byte) k, oa[0]);
// dp("key:"+key+" encbytes[0]:"+(byte)encbytes[0]);
for (int i = 1; i < (msgbytes.length + 1); i++) {
encbytes[i] = az(msgbytes[i - 1], (oa[(i + key) % oa.length]));
}
return new String(encbytes);
}
encbytes[i] = az(msgbytes[i - 1], (oa[(i + key) % oa.length]));
}
return new String(encbytes);
}
public static String dec(String msg) {
byte[] msgbytes = msg.getBytes();
byte[] encbytes = new byte[msgbytes.length];
public static String dec(String msg) {
byte[] msgbytes = msg.getBytes();
byte[] encbytes = new byte[msgbytes.length];
encbytes[0] = bz(msgbytes[0], oa[0]);
byte key = encbytes[0];
int ios = (key - 48);
for (int i = 1; i < msgbytes.length; i++) {
encbytes[i] = bz(msgbytes[i], oa[(i + ios) % oa.length]);
}
return new String(encbytes);
}
encbytes[0] = bz(msgbytes[0], oa[0]);
byte key = encbytes[0];
int ios = (key - 48);
for (int i = 1; i < msgbytes.length; i++) {
encbytes[i] = bz(msgbytes[i], oa[(i + ios) % oa.length]);
}
return new String(encbytes);
}
public static String elen(String msg, int len) {
Random r = new Random();
if (msg.length() < len) {
int max = len - msg.length();
StringBuilder sb = new StringBuilder();
sb.append(msg).append(":");
for (int i = 1; i < max; i++) {
int bc = r.nextInt(122 - 48);
sb.append(Character.toString((char) (bc + 48)));
}
return sb.toString();
}
return msg;
}
public static String elen(String msg, int len) {
Random r = new Random();
if (msg.length() < len) {
int max = len - msg.length();
StringBuilder sb = new StringBuilder();
sb.append(msg).append(":");
for (int i = 1; i < max; i++) {
int bc = r.nextInt(122 - 48);
sb.append(Character.toString((char) (bc + 48)));
}
return sb.toString();
}
return msg;
}
}
@@ -12,103 +12,103 @@ import java.util.Map;
*/
public class PstmtCache extends LinkedHashMap<String, ExtendedPreparedStatement> {
private static final Logger logger = LoggerFactory.getLogger(PstmtCache.class);
private static final Logger logger = LoggerFactory.getLogger(PstmtCache.class);
static final long serialVersionUID = -3096406924865550697L;
/**
* The name of the cache, for tracing purposes.
*/
protected final String cacheName;
/**
* The maximum size of the cache. When this is exceeded the oldest entry is removed.
*/
private final int maxSize;
/**
* The name of the cache, for tracing purposes.
*/
protected final String cacheName;
/**
* The total number of entries removed from this cache.
*/
private int removeCounter;
/**
* The maximum size of the cache. When this is exceeded the oldest entry is removed.
*/
private final int maxSize;
/**
* The number of get hits.
*/
private int hitCounter;
/**
* The total number of entries removed from this cache.
*/
private int removeCounter;
/**
* The number of get() misses.
*/
private int missCounter;
/**
* The number of get hits.
*/
private int hitCounter;
/**
* The number of puts into this cache.
*/
private int putCounter;
/**
* The number of get() misses.
*/
private int missCounter;
public PstmtCache(String cacheName, int maxCacheSize) {
/**
* The number of puts into this cache.
*/
private int putCounter;
// note = access ordered list. This is what gives it the LRU order
super(maxCacheSize*3, 0.75f, true);
this.cacheName = cacheName;
this.maxSize = maxCacheSize;
}
public PstmtCache(String cacheName, int maxCacheSize) {
/**
* Return a summary description of this cache.
*/
public String getDescription() {
return "size["+size()+"] max["+maxSize+"] hits["+hitCounter+"] miss["+missCounter+"] hitRatio["+getHitRatio()+"] removes["+removeCounter+"]";
}
/**
* returns the current maximum size of the cache.
*/
public int getMaxSize() {
return maxSize;
}
// note = access ordered list. This is what gives it the LRU order
super(maxCacheSize * 3, 0.75f, true);
this.cacheName = cacheName;
this.maxSize = maxCacheSize;
}
/**
* Gets the hit ratio. A number between 0 and 100 indicating the number of
* hits to misses. A number approaching 100 is desirable.
*/
public int getHitRatio() {
if (hitCounter == 0) {
return 0;
} else {
return hitCounter*100/(hitCounter+missCounter);
}
}
/**
* Return a summary description of this cache.
*/
public String getDescription() {
return "size[" + size() + "] max[" + maxSize + "] hits[" + hitCounter + "] miss[" + missCounter + "] hitRatio[" + getHitRatio() + "] removes[" + removeCounter + "]";
}
/**
* The total number of hits against this cache.
*/
public int getHitCounter() {
return hitCounter;
}
/**
* returns the current maximum size of the cache.
*/
public int getMaxSize() {
return maxSize;
}
/**
* The total number of misses against this cache.
*/
public int getMissCounter() {
return missCounter;
}
/**
* Gets the hit ratio. A number between 0 and 100 indicating the number of
* hits to misses. A number approaching 100 is desirable.
*/
public int getHitRatio() {
if (hitCounter == 0) {
return 0;
} else {
return hitCounter * 100 / (hitCounter + missCounter);
}
}
/**
* The total number of puts against this cache.
*/
public int getPutCounter() {
return putCounter;
}
/**
* The total number of hits against this cache.
*/
public int getHitCounter() {
return hitCounter;
}
/**
* Try to add the returning statement to the cache. If there is already a
* matching ExtendedPreparedStatement in the cache return false else add
* the statement to the cache and return true.
*/
public boolean returnStatement(ExtendedPreparedStatement pstmt) {
ExtendedPreparedStatement alreadyInCache = super.get(pstmt.getCacheKey());
/**
* The total number of misses against this cache.
*/
public int getMissCounter() {
return missCounter;
}
/**
* The total number of puts against this cache.
*/
public int getPutCounter() {
return putCounter;
}
/**
* Try to add the returning statement to the cache. If there is already a
* matching ExtendedPreparedStatement in the cache return false else add
* the statement to the cache and return true.
*/
public boolean returnStatement(ExtendedPreparedStatement pstmt) {
ExtendedPreparedStatement alreadyInCache = super.get(pstmt.getCacheKey());
if (alreadyInCache != null) {
return false;
}
@@ -117,67 +117,67 @@ public class PstmtCache extends LinkedHashMap<String, ExtendedPreparedStatement>
// PStmts when the cache has hit its maximum size.
put(pstmt.getCacheKey(), pstmt);
return true;
}
/**
* additionally maintains hit and miss statistics.
*/
public ExtendedPreparedStatement get(Object key) {
}
ExtendedPreparedStatement o = super.get(key);
if (o == null) {
missCounter++;
} else {
hitCounter++;
}
return o;
}
/**
* additionally maintains hit and miss statistics.
*/
public ExtendedPreparedStatement get(Object key) {
/**
* additionally maintains hit and miss statistics.
*/
public ExtendedPreparedStatement remove(Object key) {
ExtendedPreparedStatement o = super.get(key);
if (o == null) {
missCounter++;
} else {
hitCounter++;
}
return o;
}
ExtendedPreparedStatement o = super.remove(key);
if (o == null) {
missCounter++;
} else {
hitCounter++;
}
return o;
}
/**
* additionally maintains hit and miss statistics.
*/
public ExtendedPreparedStatement remove(Object key) {
/**
* additionally maintains put counter statistics.
*/
public ExtendedPreparedStatement put(String key, ExtendedPreparedStatement value) {
ExtendedPreparedStatement o = super.remove(key);
if (o == null) {
missCounter++;
} else {
hitCounter++;
}
return o;
}
putCounter++;
return super.put(key, value);
}
/**
* additionally maintains put counter statistics.
*/
public ExtendedPreparedStatement put(String key, ExtendedPreparedStatement value) {
putCounter++;
return super.put(key, value);
}
/**
* will check to see if we need to remove entries and
* if so call the cacheCleanup.cleanupEldestLRUCacheEntry() if
* one has been set.
*/
protected boolean removeEldestEntry(Map.Entry<String, ExtendedPreparedStatement> eldest) {
if (size() < maxSize) {
return false;
}
removeCounter++;
try {
ExtendedPreparedStatement pstmt = eldest.getValue();
pstmt.closeDestroy();
} catch (SQLException e) {
logger.error("Error closing ExtendedPreparedStatement", e);
}
return true;
}
/**
* will check to see if we need to remove entries and
* if so call the cacheCleanup.cleanupEldestLRUCacheEntry() if
* one has been set.
*/
protected boolean removeEldestEntry(Map.Entry<String,ExtendedPreparedStatement> eldest) {
if (size() < maxSize) {
return false;
}
removeCounter++;
try {
ExtendedPreparedStatement pstmt = eldest.getValue();
pstmt.closeDestroy();
} catch (SQLException e) {
logger.error("Error closing ExtendedPreparedStatement", e);
}
return true;
}
}
@@ -4,66 +4,64 @@ import java.sql.Connection;
/**
* Helper object that can convert between transaction isolation descriptions and values.
*
*/
public class TransactionIsolation {
/**
* return the isolation level for a given string description.
*/
public static int getLevel(String level) {
level = level.toUpperCase();
if (level.startsWith("TRANSACTION")){
level = level.substring("TRANSACTION".length());
}
level = level.replace("_", "");
if ("NONE".equalsIgnoreCase(level)){
return Connection.TRANSACTION_NONE;
}
if ("READCOMMITTED".equalsIgnoreCase(level)){
return Connection.TRANSACTION_READ_COMMITTED;
}
if ("READUNCOMMITTED".equalsIgnoreCase(level)){
return Connection.TRANSACTION_READ_UNCOMMITTED;
}
if ("REPEATABLEREAD".equalsIgnoreCase(level)){
return Connection.TRANSACTION_REPEATABLE_READ;
}
if ("SERIALIZABLE".equalsIgnoreCase(level)){
return Connection.TRANSACTION_SERIALIZABLE;
}
/**
* return the isolation level for a given string description.
*/
public static int getLevel(String level) {
level = level.toUpperCase();
if (level.startsWith("TRANSACTION")) {
level = level.substring("TRANSACTION".length());
}
level = level.replace("_", "");
if ("NONE".equalsIgnoreCase(level)) {
return Connection.TRANSACTION_NONE;
}
if ("READCOMMITTED".equalsIgnoreCase(level)) {
return Connection.TRANSACTION_READ_COMMITTED;
}
if ("READUNCOMMITTED".equalsIgnoreCase(level)) {
return Connection.TRANSACTION_READ_UNCOMMITTED;
}
if ("REPEATABLEREAD".equalsIgnoreCase(level)) {
return Connection.TRANSACTION_REPEATABLE_READ;
}
if ("SERIALIZABLE".equalsIgnoreCase(level)) {
return Connection.TRANSACTION_SERIALIZABLE;
}
throw new RuntimeException("Transaction Isolaction level [" + level + "] is not known.");
}
/**
* Return the string description of the transaction isolation level specified.
* <p>Returned value is one of NONE, READ_COMMITTED,READ_UNCOMMITTED,
* REPEATABLE_READ or SERIALIZABLE.</p>
*
* @param level the transaction isolation level as per java.sql.Connection
* @return the level description as a string.
*/
public static String getLevelDescription(int level) {
switch (level) {
case Connection.TRANSACTION_NONE :
return "NONE";
case Connection.TRANSACTION_READ_COMMITTED :
return "READ_COMMITTED";
case Connection.TRANSACTION_READ_UNCOMMITTED :
return "READ_UNCOMMITTED";
case Connection.TRANSACTION_REPEATABLE_READ :
return "REPEATABLE_READ";
case Connection.TRANSACTION_SERIALIZABLE :
return "SERIALIZABLE";
case -1 :
return "NotSet";
default :
throw new RuntimeException("Transaction Isolaction level [" + level + "] is not defined.");
}
}
throw new RuntimeException("Transaction Isolaction level [" + level + "] is not known.");
}
/**
* Return the string description of the transaction isolation level specified.
* <p>Returned value is one of NONE, READ_COMMITTED,READ_UNCOMMITTED,
* REPEATABLE_READ or SERIALIZABLE.</p>
*
* @param level the transaction isolation level as per java.sql.Connection
* @return the level description as a string.
*/
public static String getLevelDescription(int level) {
switch (level) {
case Connection.TRANSACTION_NONE:
return "NONE";
case Connection.TRANSACTION_READ_COMMITTED:
return "READ_COMMITTED";
case Connection.TRANSACTION_READ_UNCOMMITTED:
return "READ_UNCOMMITTED";
case Connection.TRANSACTION_REPEATABLE_READ:
return "REPEATABLE_READ";
case Connection.TRANSACTION_SERIALIZABLE:
return "SERIALIZABLE";
case -1:
return "NotSet";
default:
throw new RuntimeException("Transaction Isolaction level [" + level + "] is not defined.");
}
}
}
@@ -1,7 +1,7 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-1">
<TITLE>AvajeLib</TITLE>
<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-1">
<TITLE>AvajeLib</TITLE>
</HEAD>
<Body BGCOLOR="#ffffff">
Enhanced JDBC objects and connection pool.