ConnectionPartition implements Serializable { protected void trackConnectionFinalizer(ConnectionHandle connectionHandle) { if (!this.disableTracking){ Connection con = connectionHandle.getInternalConnection(); if (con != null && con instanceof Proxy && Proxy.getInvocationHandler(con) instanceof MemorizeTransactionProxy){ try { con = (Connection) Proxy.getInvocationHandler(con).invoke(con, ConnectionHandle.class.getMethod("getProxyTarget"), null); } catch (Throwable t) { logger.error("Error while attempting to track internal db connection", t); } } final Connection internalDBConnection = con; final BoneCP pool = connectionHandle.getPool(); connectionHandle.getPool().getFinalizableRefs().put(internalDBConnection, new FinalizableWeakReference<ConnectionHandle>(connectionHandle, connectionHandle.getPool().getFinalizableRefQueue()) { @SuppressWarnings("synthetic-access") public void finalizeReferent() { try { pool.getFinalizableRefs().remove(internalDBConnection); if (internalDBConnection != null && !internalDBConnection.isClosed()){ logger.warn("BoneCP detected an unclosed connection "+ConnectionPartition.this.poolName + "and will now attempt to close it for you. " + "You should be closing this connection in your application - enable connectionWatch for additional debugging assistance or set disableConnectionTracking to true to disable this feature entirely."); internalDBConnection.close(); updateCreatedConnections(-1); } } catch (Throwable t) { logger.error("Error while closing off internal db connection", t); } } }); } } ConnectionPartition(BoneCP pool); int getRemainingCapacity(); @Override String toString();  }
@Test public void testFinalizer() throws SQLException, InterruptedException{ ConnectionHandle mockConnectionHandle = createNiceMock(ConnectionHandle.class); expect(mockConnectionHandle.isInReplayMode()).andReturn(true).anyTimes(); Connection mockConnection = createNiceMock(Connection.class); Connection connection = MemorizeTransactionProxy.memorize(mockConnection, mockConnectionHandle); expect(mockConnectionHandle.getInternalConnection()).andReturn(connection).anyTimes(); mockConnection.close(); expectLastCall().once(); reset(this.mockPool, this.mockConfig); Map<Connection, Reference<ConnectionHandle>> refs = new HashMap<Connection, Reference<ConnectionHandle>>(); expect(this.mockPool.getFinalizableRefs()).andReturn(refs).anyTimes(); FinalizableReferenceQueue finalizableRefQueue = new FinalizableReferenceQueue(); expect(this.mockPool.getFinalizableRefQueue()).andReturn(finalizableRefQueue).anyTimes(); expect(mockConnectionHandle.getPool()).andReturn(this.mockPool).anyTimes(); expect(this.mockPool.getConfig()).andReturn(mockConfig).anyTimes(); expect(mockConfig.getPoolName()).andReturn("foo").once(); makeThreadSafe(this.mockPool, true); replay(mockConnection, mockConnectionHandle, this.mockPool, mockConfig); testClass.trackConnectionFinalizer(mockConnectionHandle); reset(mockConnectionHandle); mockConnectionHandle = null; for (int i=0; i < 500; i++){ System.gc();System.gc();System.gc(); Thread.sleep(20); try{ verify(mockConnection); break; } catch (Throwable t){ Thread.sleep(20); } } }
@Test public void testFinalizerCoverageException() throws SQLException, InterruptedException{ ConnectionHandle mockConnectionHandle = createNiceMock(ConnectionHandle.class); Connection mockConnection = createNiceMock(Connection.class); expect(mockConnectionHandle.getInternalConnection()).andReturn(mockConnection).anyTimes(); mockConnection.close(); expectLastCall().andThrow(new SQLException("fake reason")).once(); reset(this.mockPool); Map<Connection, Reference<ConnectionHandle>> refs = new HashMap<Connection, Reference<ConnectionHandle>>(); expect(this.mockPool.getFinalizableRefs()).andReturn(refs).anyTimes(); FinalizableReferenceQueue finalizableRefQueue = new FinalizableReferenceQueue(); expect(this.mockPool.getFinalizableRefQueue()).andReturn(finalizableRefQueue).anyTimes(); expect(mockConnectionHandle.getPool()).andReturn(this.mockPool).anyTimes(); replay(mockConnectionHandle, mockConnection, this.mockPool); testClass.trackConnectionFinalizer(mockConnectionHandle); testClass.statsLock = null; reset(mockLogger); mockLogger.error((String)anyObject()); expectLastCall().anyTimes(); replay(mockLogger); reset(mockConnectionHandle); mockConnectionHandle = null; for (int i=0; i < 100; i++){ System.gc();System.gc();System.gc(); Thread.sleep(20); try{ verify(mockLogger); break; } catch (Throwable t){ Thread.sleep(20); } } }
@Test public void testFinalizerException2() throws SQLException, InterruptedException, SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException{ ConnectionHandle mockConnectionHandle = createNiceMock(ConnectionHandle.class); expect(mockConnectionHandle.isInReplayMode()).andReturn(true).anyTimes(); Connection mockConnection = createNiceMock(Connection.class); Connection connection = new MemorizeTransactionProxyDummy(null,null).memorizeDummy(mockConnection, mockConnectionHandle); expect(mockConnectionHandle.getInternalConnection()).andReturn(connection).anyTimes(); makeThreadSafe(mockConnectionHandle, true); makeThreadSafe(mockConnection, true); mockLogger = TestUtils.mockLogger(testClass.getClass()); reset(mockLogger); makeThreadSafe(mockLogger, true); reset(this.mockPool); Map<Connection, Reference<ConnectionHandle>> refs = new HashMap<Connection, Reference<ConnectionHandle>>(); expect(this.mockPool.getFinalizableRefs()).andReturn(refs).anyTimes(); FinalizableReferenceQueue finalizableRefQueue = new FinalizableReferenceQueue(); expect(this.mockPool.getFinalizableRefQueue()).andReturn(finalizableRefQueue).anyTimes(); expect(mockConnectionHandle.getPool()).andReturn(this.mockPool).anyTimes(); replay(mockConnection, mockConnectionHandle, this.mockPool); testClass.trackConnectionFinalizer(mockConnectionHandle); reset(mockConnectionHandle); mockConnectionHandle = null; for (int i=0; i < 100; i++){ System.gc();System.gc();System.gc(); Thread.sleep(20); try{ verify(mockConnection); break; } catch (Throwable t){ t.printStackTrace(); Thread.sleep(20); } } }