org.firebirdsql.pool.XPreparedStatementCache Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jaybird Show documentation
Show all versions of jaybird Show documentation
JDBC Driver for the Firebird RDBMS
/*
* Firebird Open Source J2ee connector - jdbc driver
*
* Distributable under LGPL license.
* You may obtain a copy of the License at http://www.gnu.org/copyleft/lgpl.html
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* LGPL License for more details.
*
* This file was created by members of the firebird development team.
* All individual contributions remain the Copyright (C) of those
* individuals. Contributors to this file are either listed here or
* can be obtained from a CVS history command.
*
* All rights reserved.
*/
package org.firebirdsql.pool;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.firebirdsql.logging.Logger;
import org.firebirdsql.logging.LoggerFactory;
/**
* This class represents a cache of prepared statements corresponding to
* one SQL statement. Instance of this class automatically prepares new
* {@link java.sql.PreparedStatement} instance if no free statements are
* available.
*
* @author Roman Rokytskyy
*/
class XPreparedStatementCache {
private static final boolean CACHE_PREPARED_STATEMENTS = true;
private static final boolean LOG_STATEMENT_IN_POOL = PoolDebugConfiguration.DEBUG_STMT_POOL;
private static Logger logChannel =
LoggerFactory.getLogger(XPreparedStatementCache.class, false);
private XStatementManager owner;
private BlockingStack freeReferences = new BlockingStack();
private HashMap workingReferences = new HashMap();
private String sql;
private int resultSetType;
private int resultSetConcurrency;
private int maxSize;
/**
* Create instance of this class for the specified SQL statement and
* result set type and concurrency.
*
* @param owner instance of {@link XStatementManager} that will prepare
* new statements.
*
* @param sql SQL statement to prepare.
*
* @param resultSetType type of result set.
*
* @param resultSetConcurrency result set concurrency.
*/
public XPreparedStatementCache(XStatementManager owner, String sql,
int resultSetType, int resultSetConcurrency, int maxSize)
{
this.owner = owner;
this.maxSize = maxSize;
if (sql == null)
throw new NullPointerException(
"Null objects cannot be guarded.");
this.sql = sql;
this.resultSetType = resultSetType;
this.resultSetConcurrency = resultSetConcurrency;
}
/**
* Reference prepared statement. This method checks prepared statement out
* of the pool. If no free statement is available, it prepares new one.
*
* @param connection instance of {@link Connection} to associate
* with prepared statement.
*
* @return free instance of {@link PreparedStatement}.
*
* @throws SQLException if prepared statement cannot be obtained from the
* pool.
*/
synchronized XCachablePreparedStatement take(Connection connection)
throws SQLException
{
if (sql == null)
throw new IllegalStateException(
"This reference guard was already destroyed.");
try {
XCachablePreparedStatement result;
if (!CACHE_PREPARED_STATEMENTS)
result = owner.prepareStatement(
sql, resultSetType, resultSetConcurrency, false);
else {
if (freeReferences.isEmpty()) {
if (LOG_STATEMENT_IN_POOL && logChannel != null)
logChannel.info(
"Found no free prepared statements, " +
"preparing new one.");
result = owner.prepareStatement(
sql, resultSetType, resultSetConcurrency,
workingReferences.size() < maxSize);
} else {
if (LOG_STATEMENT_IN_POOL && logChannel != null)
logChannel.info(
"Found free prepared statement in pool.");
result = (XCachablePreparedStatement)freeReferences.pop();
}
}
result.setConnection(connection);
workingReferences.put(result.getOriginal(), result);
return result;
} catch(InterruptedException iex) {
throw new SQLException("Cannot prepare SQL statement in pool");
}
}
/**
* Dereference object. If reference
is the same as guarded
* object, counter is simply decreased, otherwise exception is thrown.
*
* @param reference object to dereference.
*
* @throws IllegalArgumentException if reference
is not the
* same as guarded object.
*
* @throws SQLException if prepared statement cannot be returned into the
* pool.
*/
synchronized void put(Object reference) throws SQLException {
if (reference == null)
throw new NullPointerException();
try {
if (CACHE_PREPARED_STATEMENTS) {
XCachablePreparedStatement statement =
(XCachablePreparedStatement)reference;
if (statement.isCached()) {
statement.setConnection(null);
freeReferences.push(reference);
}
workingReferences.remove(statement.getOriginal());
// release statement if it is not cached
if (!statement.isCached())
statement.forceClose();
if (LOG_STATEMENT_IN_POOL && logChannel != null)
logChannel.info("Returned prepared statement to pool.");
} else
((XCachablePreparedStatement)reference).forceClose();
} catch(InterruptedException ex) {
logChannel.warn("Could not put statement back to pool.", ex);
}
}
/**
* Invalidate this pool. After invoking this method no other
* method can be invoked.
*/
synchronized void invalidate() throws SQLException {
sql = null;
// clear free references
SQLException error = null;
while(!freeReferences.isEmpty()) {
try {
XCachablePreparedStatement result =
(XCachablePreparedStatement)freeReferences.pop();
result.forceClose();
} catch(InterruptedException ex) {
// ignore
} catch(SQLException ex) {
if (error == null)
error = ex;
else
error.setNextException(ex);
}
}
// clear working references, even they're currently in use
// since we are invalidating the pool and there's no way back
Iterator iter = workingReferences.entrySet().iterator();
while(iter.hasNext()) {
Map.Entry entry = (Map.Entry)iter.next();
XCachablePreparedStatement item =
(XCachablePreparedStatement)entry.getValue();
try {
item.forceClose();
} catch(SQLException ex) {
if (error == null)
error = ex;
else
error.setNextException(ex);
}
}
workingReferences.clear();
if (error != null)
throw error;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy