Class ResetAbandonedTimer

All Implemented Interfaces:
InvocationHandler, ResetAbandonedTimerMBean

public class ResetAbandonedTimer extends AbstractQueryReport implements ResetAbandonedTimerMBean
Resets the abandoned timer on any activity on the connection, on query execution and on every read of a ResultSet obtained from the pooled connection. Each stamp is taken when the individual call completes, so a single call that blocks longer than the configured abandoned timeout can still be abandoned. Stamps are tied to the borrow that started the call, so a late call from an earlier borrow cannot keep a newer borrower's connection alive. The interceptor is useful when the abandoned timeout is fairly low and long-running batch work must stay alive.

With JMX enabled, it publishes an MBean below its connection's MBean. It is released when the connection goes out of service (the chain teardown reset(null, null)), when the pool closes, or when the pool MBean is deregistered - not on an ordinary return and re-borrow.

  • Constructor Details

    • ResetAbandonedTimer

      public ResetAbandonedTimer()
      Default constructor.
  • Method Details

    • reset

      public void reset(ConnectionPool parent, PooledConnection con)
      Description copied from class: AbstractCreateStatementInterceptor
      no-op for this interceptor. no state is stored.
      Overrides:
      reset in class AbstractCreateStatementInterceptor
      Parameters:
      parent - - the connection pool owning the connection
      con - - the pooled connection
    • unregisterMBean

      public void unregisterMBean()
      Description copied from class: JdbcInterceptor
      Releases any MBean this interceptor published for the connection it serves, without tearing down the connection state. The pool calls this when it releases its own MBean while the pool stays live; the connection and its chain remain usable, and a later borrow can publish the interceptor again. The default does nothing; an interceptor that publishes an MBean overrides it.
      Overrides:
      unregisterMBean in class JdbcInterceptor
    • resetTimer

      public boolean resetTimer()
      Resets the abandoned timer of the pooled connection this interceptor is bound to, and only while that connection is checked out. This is the implementation of the MBean operation; the activity hooks below stamp through stampFor(long), which adds a borrow gate on top of this one. The flag alone is what keeps the management operation off a connection that is idle in the pool, where a stamp had nothing to avert - the abandoned check looks only at connections that are held - and did undo the age ConnectionPool.checkIdle() measures it by. That flag is also what keeps the stamp from the close's own finally: by the time that finally runs, the borrow it would answer for is over. What the flag cannot tell apart is the late finally of a call that was in flight when its borrow ended and whose connection has since been borrowed again - the flag is up again by then, for a borrow the late call is not part of - which is why the hooks are gated on the borrow, not on this flag alone.
      Specified by:
      resetTimer in interface ResetAbandonedTimerMBean
      Returns:
      true if the timestamp of a checked-out connection was reset, false if this interceptor is bound to no connection or to one that is not checked out
    • invoke

      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
      Description copied from class: JdbcInterceptor
      Gets invoked each time an operation on Connection is invoked.

      The base implementation passes the call to the next interceptor in the chain. When there is no next interceptor, the call fails fast with a NullPointerException: a chain built by the pool always ends in the ProxyConnection terminal, so reaching this case means a chain was hand-built without a terminal link. Interceptors that do not answer a call themselves continue it with super.invoke(proxy, method, args).

      Specified by:
      invoke in interface InvocationHandler
      Overrides:
      invoke in class AbstractCreateStatementInterceptor
      Throws:
      Throwable
    • createStatement

      public Object createStatement(Object proxy, Method method, Object[] args, Object statement, long time)
      Wraps the query reporting statement proxy so that the result sets handed to the application reset the abandoned timer while they are read. Statements that this interceptor does not proxy are passed through unchanged.
      Overrides:
      createStatement in class AbstractQueryReport
      Parameters:
      proxy - the actual proxy object
      method - the method that was called. It will be one of the methods defined in AbstractCreateStatementInterceptor.STATEMENT_TYPES
      args - the arguments to the method
      statement - the statement that the underlying connection created
      time - elapsed time in milliseconds, measured with the monotonic clock
      Returns:
      a Statement object
    • prepareCall

      protected void prepareCall(String query, long time)
      Description copied from class: AbstractQueryReport
      Invoked when prepareCall has been called and completed.
      Specified by:
      prepareCall in class AbstractQueryReport
      Parameters:
      query - - the string used to prepare the statement with
      time - - the time it took to invoke prepare
    • prepareStatement

      protected void prepareStatement(String sql, long time)
      Description copied from class: AbstractQueryReport
      Invoked when prepareStatement has been called and completed.
      Specified by:
      prepareStatement in class AbstractQueryReport
      Parameters:
      sql - - the string used to prepare the statement with
      time - - the time it took to invoke prepare
    • closeInvoked

      public void closeInvoked()
      Takes the borrow down. The base class fires this hook on the connection-level close, on the way down to the pool and once per borrow, so it is where this instance stops belonging to a checked-out connection - and it comes down here, on the way to the pool, rather than at the unbind below, because that unbind does not happen on a return at all: the chain stays bound to its pooled connection for the whole idle period, so a flag left up until then would leave every hook of this interceptor, and the MBean operation, acting on a connection the application let go of.

      What this hook still does not do is stamp. It runs at the end of a borrow rather than during it, which is precisely where a stamp has nothing left to avert. An abandonment or suspect decision is a decision about a borrow that is still held, and the sweep that makes it has looked at this connection before the close started. What a stamp here does change is the state the return is reported from, and that read happens below this hook, in the pool: PooledConnection.setTimestamp(long) clears the suspect flag and moves the timestamp the elapsed time of that report is computed from, so resetting here hands ConnectionPool.returnConnection a connection that reads as never suspected, and neither half of that report - neither the log line nor the notification - ever speaks for the connections it exists for. The stamp a returned connection does need, the timestamp it goes idle under, is the return path's own to write and it writes it, below this hook. The close is therefore the one call on a borrowed connection this interceptor leaves unstamped, and the flag lowered here is what keeps it that way: invoke(Object, Method, Object[]) stamps once the call it wraps has run, so without the flag its finally would take that stamp after the connection is back in the pool and its state has been settled - which is the same interference one layer down. The override stays because the hook is abstract in the base class.

      Specified by:
      closeInvoked in class AbstractCreateStatementInterceptor