pull/42/head
Brett Wooldridge
parent 6149affd88
commit 5765ed2116

@ -23,26 +23,75 @@ import java.util.Timer;
import com.zaxxer.hikari.util.ConcurrentBag.IBagManagable; import com.zaxxer.hikari.util.ConcurrentBag.IBagManagable;
/** /**
* The interface used by the Connection proxy and through which all interaction
* by other classes flow.
*
* @author Brett Wooldridge * @author Brett Wooldridge
*/ */
public interface IHikariConnectionProxy extends Connection, IBagManagable public interface IHikariConnectionProxy extends Connection, IBagManagable
{ {
void unclose(); /**
* Catpure the stack and start leak detection.
void realClose() throws SQLException; *
* @param leakThreshold the number of milliseconds before a leak is reported
void untrackStatement(Object statement); * @param houseKeepingTimer the timer to run the leak detection task with
*/
void captureStack(long leakThreshold, Timer houseKeepingTimer);
/**
* Check if the provided SQLException contains a SQLSTATE that indicates
* a disconnection from the server.
*
* @param sqle the SQLException to check
*/
void checkException(SQLException sqle); void checkException(SQLException sqle);
boolean isBrokenConnection(); /**
* Get the creation timestamp of the connection.
*
* @return the creation timestamp
*/
long getCreationTime(); long getCreationTime();
/**
* Get the last access timestamp of the connection.
*
* @return the last access timestamp
*/
long getLastAccess(); long getLastAccess();
/**
* Return the broken state of the connection. If checkException() detected
* a broken connection, this method will return true, otherwise false.
*
* @return the broken state of the connection
*/
boolean isBrokenConnection();
/**
* Actually close the underlying delegate Connection.
*
* @throws SQLException rethrown from the underlying delegate Connection
*/
void realClose() throws SQLException;
/**
* Reset the delegate Connection back to pristine state.
*
* @throws SQLException thrown if there is an error resetting any of the state
*/
void resetConnectionState() throws SQLException; void resetConnectionState() throws SQLException;
/* Leak Detection API */ /**
void captureStack(long leakThreshold, Timer houseKeepingTimer); * Make the Connection available for use again by marking it as not closed.
*/
void unclose();
/**
* Called by Statement and its subclasses when they are closed to remove them
* from the tracking list.
*
* @param statement the Statement to remove from tracking
*/
void untrackStatement(Object statement);
} }

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2013 Brett Wooldridge * Copyright (C) 2013, 2014 Brett Wooldridge
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -36,6 +36,10 @@ import org.slf4j.LoggerFactory;
import com.zaxxer.hikari.util.ClassLoaderUtils; import com.zaxxer.hikari.util.ClassLoaderUtils;
/** /**
* This class generates the proxy objects for {@link Connection}, {@link Statement},
* {@link PreparedStatement}, and {@link CallableStatement}. Additionally it injects
* method bodies into the {@link ProxyFactory} class methods that can instantiate
* instances of the generated proxies.
* *
* @author Brett Wooldridge * @author Brett Wooldridge
*/ */
@ -63,9 +67,13 @@ public final class JavassistProxyFactory
} }
} }
/**
* Simply invoking this method causes the initialization of this class. All work
* by this class is performed in static initialization.
*/
public static void initialize() public static void initialize()
{ {
// simply invoking this method causes the initialization of this class. // no-op
} }
private JavassistProxyFactory() private JavassistProxyFactory()

@ -23,7 +23,7 @@ import org.slf4j.LoggerFactory;
/** /**
* @author Brett Wooldridge * @author Brett Wooldridge
*/ */
public class LeakTask extends TimerTask class LeakTask extends TimerTask
{ {
private final long leakTime; private final long leakTime;
private StackTraceElement[] stackTrace; private StackTraceElement[] stackTrace;

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2013 Brett Wooldridge * Copyright (C) 2013, 2014 Brett Wooldridge
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -24,13 +24,30 @@ import java.sql.Statement;
import com.zaxxer.hikari.HikariPool; import com.zaxxer.hikari.HikariPool;
/** /**
* Injected proxy factory class. * A factory class that produces proxies around instances of the standard
* JDBC interfaces.
* *
* @author Brett Wooldridge * @author Brett Wooldridge
*/ */
public final class ProxyFactory public final class ProxyFactory
{ {
public static IHikariConnectionProxy getProxyConnection(HikariPool pool, Connection connection, int defaultIsolationLevel, boolean defaultAutoCommit, String defaultCatalog) private ProxyFactory()
{
// unconstrucable
}
/**
* Create a proxy for the specified {@link Connection} instance.
*
* @param pool the {@link HikariPool} that will own this proxy
* @param connection the {@link Connection} that will be wrapped by this proxy
* @param defaultIsolationLevel the default transaction isolation level of the underlying {@link Connection}
* @param defaultAutoCommit the default auto-commit state of the underlying {@link Connection}
* @param defaultIReadOnly the default readOnly state of the underlying {@link Connection}
* @param defaultCatalog the default catalog of the underlying {@link Connection}
* @return a proxy that wraps the specified {@link Connection}
*/
public static IHikariConnectionProxy getProxyConnection(HikariPool pool, Connection connection, int defaultIsolationLevel, boolean defaultAutoCommit, boolean defaultIReadOnly, String defaultCatalog)
{ {
// Body is injected by JavassistProxyFactory // Body is injected by JavassistProxyFactory
return null; return null;

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2013 Brett Wooldridge * Copyright (C) 2013, 2014 Brett Wooldridge
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -28,12 +28,12 @@ import java.util.concurrent.locks.AbstractQueuedLongSynchronizer;
* to LinkedBlockingQueue and LinkedTransferQueue for the purposes of a * to LinkedBlockingQueue and LinkedTransferQueue for the purposes of a
* connection pool. It uses ThreadLocal storage when possible to avoid * connection pool. It uses ThreadLocal storage when possible to avoid
* locks, but resorts to scanning a common collection if there are no * locks, but resorts to scanning a common collection if there are no
* available connections in the ThreadLocal list. Idle connections in * available items in the ThreadLocal list. Not-in-use items in the
* ThreadLocal lists can be "stolen" when the poll()ing thread has none * ThreadLocal lists can be "stolen" when the borrowing thread has none
* of its own. It is a "lock-less" implementation using a specialized * of its own. It is a "lock-less" implementation using a specialized
* AbstractQueuedLongSynchronizer to manage cross-thread signaling. * AbstractQueuedLongSynchronizer to manage cross-thread signaling.
* *
* Note that objects that are "borrowed" from the bag are not actually * Note that items that are "borrowed" from the bag are not actually
* removed from any collection, so garbage collection will not occur * removed from any collection, so garbage collection will not occur
* even if the reference is abandoned. Thus care must be taken to * even if the reference is abandoned. Thus care must be taken to
* "requite" borrowed objects otherwise a memory leak will result. Only * "requite" borrowed objects otherwise a memory leak will result. Only
@ -64,6 +64,12 @@ public class ConcurrentBag<T extends com.zaxxer.hikari.util.ConcurrentBag.IBagMa
boolean compareAndSetState(int expectedState, int newState); boolean compareAndSetState(int expectedState, int newState);
} }
/**
* This interface is implemented by a listener to the bag. The listener
* will be informed of when the bag has become empty. The usual course
* of action by the listener in this case is to attempt to add an item
* to the bag.
*/
public interface IBagStateListener public interface IBagStateListener
{ {
void bagIsEmpty(); void bagIsEmpty();
@ -180,7 +186,7 @@ public class ConcurrentBag<T extends com.zaxxer.hikari.util.ConcurrentBag.IBagMa
/** /**
* Remove a value from the bag. This method should only be called * Remove a value from the bag. This method should only be called
* with objects obtained by borrow() or reserve(). * with objects obtained by {@link #borrow(long, TimeUnit)} or {@link #reserve(IBagManagable)}.
* @param value the value to remove * @param value the value to remove
* @throws IllegalStateException if an attempt is made to remove an object * @throws IllegalStateException if an attempt is made to remove an object
* from the bag that was not borrowed or reserved first * from the bag that was not borrowed or reserved first
@ -200,7 +206,8 @@ public class ConcurrentBag<T extends com.zaxxer.hikari.util.ConcurrentBag.IBagMa
/** /**
* This method provides a "snaphot" in time of the IBagManagable * This method provides a "snaphot" in time of the IBagManagable
* items in the bag in the specified state. It does not "lock" * items in the bag in the specified state. It does not "lock"
* or reserve items in any way. * or reserve items in any way. Call {@link #reserve(IBagManagable)}
* on items in list before performing any action on them.
* *
* @param state one of STATE_NOT_IN_USE or STATE_IN_USE * @param state one of STATE_NOT_IN_USE or STATE_IN_USE
* @return a possibly empty list of objects having the state specified * @return a possibly empty list of objects having the state specified
@ -221,11 +228,29 @@ public class ConcurrentBag<T extends com.zaxxer.hikari.util.ConcurrentBag.IBagMa
return list; return list;
} }
/**
* The method is used to make an item in the bag "unavailable" for
* borrowing. It is primarily used when wanting to operate on items
* returned by the {@link #values(int)} method. Items that are
* reserved can be removed from the bag via {@link #remove(IBagManagable)}
* without the need to unreserve them. Items that are not removed
* from the bag can be make available for borrowing again by calling
* the {@link #unreserve(IBagManagable) method.
*
* @param value the item to reserve
* @return true if the item was able to be reserved, false otherwise
*/
public boolean reserve(T value) public boolean reserve(T value)
{ {
return value.compareAndSetState(STATE_NOT_IN_USE, STATE_RESERVED); return value.compareAndSetState(STATE_NOT_IN_USE, STATE_RESERVED);
} }
/**
* This method is used to make an item reserved via {@link #reserve(IBagManagable)}
* available again for borrowing.
*
* @param value the item to unreserve
*/
public void unreserve(T value) public void unreserve(T value)
{ {
final long checkInTime = System.nanoTime(); final long checkInTime = System.nanoTime();
@ -237,11 +262,23 @@ public class ConcurrentBag<T extends com.zaxxer.hikari.util.ConcurrentBag.IBagMa
synchronizer.releaseShared(checkInTime); synchronizer.releaseShared(checkInTime);
} }
/**
* Add a listener to the bag. There can only be one. If this method is
* called a second time, the original listener will be evicted.
*
* @param listener a listener to the bag
*/
public void addBagStateListener(IBagStateListener listener) public void addBagStateListener(IBagStateListener listener)
{ {
this.listener = listener; this.listener = listener;
} }
/**
* Get the number of threads pending (waiting) for an item from the
* bag to become available.
*
* @return the number of threads waiting for items from the bag
*/
public int getPendingQueue() public int getPendingQueue()
{ {
return synchronizer.getQueueLength(); return synchronizer.getQueueLength();

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2013 Brett Wooldridge * Copyright (C) 2013, 2014 Brett Wooldridge
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -31,7 +31,7 @@ public final class FastStatementList
private int size; private int size;
/** /**
* Construct a FastList with a default size of 16. * Construct a FastList with a default size of 32.
*/ */
public FastStatementList() public FastStatementList()
{ {

Loading…
Cancel
Save