1 22 23 24 package com.mchange.v2.c3p0.impl; 25 26 import com.mchange.v2.c3p0.stmt.*; 27 import com.mchange.v2.c3p0.ConnectionCustomizer; 28 import com.mchange.v2.c3p0.SQLWarnings; 29 import com.mchange.v2.c3p0.UnifiedConnectionTester; 30 import com.mchange.v2.c3p0.WrapperConnectionPoolDataSource; 31 32 import java.sql.Connection ; 33 import java.sql.SQLException ; 34 import java.sql.SQLWarning ; 35 import java.util.LinkedList ; 36 37 import javax.sql.ConnectionEvent ; 38 import javax.sql.ConnectionEventListener ; 39 import javax.sql.ConnectionPoolDataSource ; 40 import javax.sql.PooledConnection ; 41 42 import com.mchange.v1.db.sql.ConnectionUtils; 43 import com.mchange.v2.async.AsynchronousRunner; 44 import com.mchange.v2.async.ThreadPoolAsynchronousRunner; 45 import com.mchange.v2.log.MLevel; 46 import com.mchange.v2.log.MLog; 47 import com.mchange.v2.log.MLogger; 48 import com.mchange.v2.c3p0.ConnectionTester; 49 import com.mchange.v2.c3p0.QueryConnectionTester; 50 import com.mchange.v2.resourcepool.CannotAcquireResourceException; 51 import com.mchange.v2.resourcepool.ResourcePool; 52 import com.mchange.v2.resourcepool.ResourcePoolException; 53 import com.mchange.v2.resourcepool.ResourcePoolFactory; 54 import com.mchange.v2.resourcepool.TimeoutException; 55 import com.mchange.v2.sql.SqlUtils; 56 57 public final class C3P0PooledConnectionPool 58 { 59 private final static boolean ASYNCHRONOUS_CONNECTION_EVENT_LISTENER = false; 60 61 private final static Throwable [] EMPTY_THROWABLE_HOLDER = new Throwable [1]; 62 63 final static MLogger logger = MLog.getLogger( C3P0PooledConnectionPool.class ); 64 65 final ResourcePool rp; 66 final ConnectionEventListener cl = new ConnectionEventListenerImpl(); 67 68 final ConnectionTester connectionTester; 69 final GooGooStatementCache scache; 70 71 final int checkoutTimeout; 72 73 final AsynchronousRunner sharedTaskRunner; 74 75 final ThrowableHolderPool thp = new ThrowableHolderPool(); 76 77 C3P0PooledConnectionPool( final ConnectionPoolDataSource cpds, 78 final DbAuth auth, 79 int min, 80 int max, 81 int start, 82 int inc, 83 int acq_retry_attempts, 84 int acq_retry_delay, 85 boolean break_after_acq_failure, 86 int checkoutTimeout, int idleConnectionTestPeriod, int maxIdleTime, int maxIdleTimeExcessConnections, int maxConnectionAge, int propertyCycle, int unreturnedConnectionTimeout, boolean debugUnreturnedConnectionStackTraces, 94 final boolean testConnectionOnCheckout, 95 final boolean testConnectionOnCheckin, 96 int maxStatements, 97 int maxStatementsPerConnection, 98 final ConnectionTester connectionTester, 99 final ConnectionCustomizer connectionCustomizer, 100 final String testQuery, 101 final ResourcePoolFactory fact, 102 ThreadPoolAsynchronousRunner taskRunner, 103 final String parentDataSourceIdentityToken) throws SQLException 104 { 105 try 106 { 107 if (maxStatements > 0 && maxStatementsPerConnection > 0) 108 this.scache = new DoubleMaxStatementCache( taskRunner, maxStatements, maxStatementsPerConnection ); 109 else if (maxStatementsPerConnection > 0) 110 this.scache = new PerConnectionMaxOnlyStatementCache( taskRunner, maxStatementsPerConnection ); 111 else if (maxStatements > 0) 112 this.scache = new GlobalMaxOnlyStatementCache( taskRunner, maxStatements ); 113 else 114 this.scache = null; 115 116 this.connectionTester = connectionTester; 117 118 this.checkoutTimeout = checkoutTimeout; 119 120 this.sharedTaskRunner = taskRunner; 121 122 class PooledConnectionResourcePoolManager implements ResourcePool.Manager 123 { 124 128 final boolean connectionTesterIsDefault = (connectionTester instanceof DefaultConnectionTester); 129 final boolean c3p0PooledConnections = (cpds instanceof WrapperConnectionPoolDataSource); 130 131 public Object acquireResource() throws Exception 132 { 133 PooledConnection out; 134 135 if ( connectionCustomizer == null) 136 { 137 out = (auth.equals( C3P0ImplUtils.NULL_AUTH ) ? 138 cpds.getPooledConnection() : 139 cpds.getPooledConnection( auth.getUser(), 140 auth.getPassword() ) ); 141 } 142 else 143 { 144 try 145 { 146 WrapperConnectionPoolDataSourceBase wcpds = (WrapperConnectionPoolDataSourceBase) cpds; 147 148 out = (auth.equals( C3P0ImplUtils.NULL_AUTH ) ? 149 wcpds.getPooledConnection( connectionCustomizer, parentDataSourceIdentityToken ) : 150 wcpds.getPooledConnection( auth.getUser(), 151 auth.getPassword(), 152 connectionCustomizer, parentDataSourceIdentityToken ) ); 153 } 154 catch (ClassCastException e) 155 { 156 throw SqlUtils.toSQLException("Cannot use a ConnectionCustomizer with a non-c3p0 ConnectionPoolDataSource." + 157 " ConnectionPoolDataSource: " + cpds.getClass().getName(), e); 158 } 159 } 160 161 164 try 165 { 166 if (scache != null) 167 { 168 if (c3p0PooledConnections) 169 ((AbstractC3P0PooledConnection) out).initStatementCache(scache); 170 else 171 { 172 176 logger.warning("StatementPooling not " + 177 "implemented for external (non-c3p0) " + 178 "ConnectionPoolDataSources."); 179 } 180 } 181 182 Connection con = null; 184 try 185 { 186 con = out.getConnection(); 187 SQLWarnings.logAndClearWarnings( con ); 188 } 189 finally 190 { 191 ConnectionUtils.attemptClose( con ); 193 } 194 195 out.addConnectionEventListener( cl ); 196 return out; 197 } 198 catch (Exception e) 199 { 200 if (logger.isLoggable( MLevel.WARNING )) 201 logger.warning("A PooledConnection was acquired, but an Exception occurred while preparing it for use. " + 202 "Attempting to destroy."); 203 try { destroyResource( out ); } 204 catch (Exception e2) 205 { 206 if (logger.isLoggable( MLevel.WARNING )) 207 logger.log( MLevel.WARNING, 208 "An Exception occurred while trying to close partially acquired PooledConnection.", 209 e2 ); 210 } 211 212 throw e; 213 } 214 finally 215 { 216 if (logger.isLoggable( MLevel.FINEST )) 217 logger.finest(this + ".acquireResource() returning. " ); 218 } 222 } 223 224 230 public void refurbishResourceOnCheckout( Object resc ) throws Exception 231 { 232 if ( testConnectionOnCheckout ) 233 { 234 if ( logger.isLoggable( MLevel.FINER ) ) 235 finerLoggingTestPooledConnection( resc, "CHECKOUT" ); 236 else 237 testPooledConnection( resc ); 238 } 239 if ( connectionCustomizer != null ) 240 { 241 Connection physicalConnection = null; 242 try 243 { 244 physicalConnection = ((AbstractC3P0PooledConnection) resc).getPhysicalConnection(); 245 connectionCustomizer.onCheckOut( physicalConnection, parentDataSourceIdentityToken ); 246 } 247 catch (ClassCastException e) 248 { 249 throw SqlUtils.toSQLException("Cannot use a ConnectionCustomizer with a non-c3p0 PooledConnection." + 250 " PooledConnection: " + resc + 251 "; ConnectionPoolDataSource: " + cpds.getClass().getName(), e); 252 } 253 } 254 } 255 256 public void refurbishResourceOnCheckin( Object resc ) throws Exception 257 { 258 if ( connectionCustomizer != null ) 259 { 260 Connection physicalConnection = null; 261 try 262 { 263 physicalConnection = ((AbstractC3P0PooledConnection) resc).getPhysicalConnection(); 264 connectionCustomizer.onCheckIn( physicalConnection, parentDataSourceIdentityToken ); 265 SQLWarnings.logAndClearWarnings( physicalConnection ); 266 } 267 catch (ClassCastException e) 268 { 269 throw SqlUtils.toSQLException("Cannot use a ConnectionCustomizer with a non-c3p0 PooledConnection." + 270 " PooledConnection: " + resc + 271 "; ConnectionPoolDataSource: " + cpds.getClass().getName(), e); 272 } 273 } 274 else 275 { 276 PooledConnection pc = (PooledConnection ) resc; 277 Connection con = null; 278 279 try 280 { 281 pc.removeConnectionEventListener( cl ); 283 284 con = pc.getConnection(); 285 SQLWarnings.logAndClearWarnings(con); 286 } 287 finally 288 { 289 ConnectionUtils.attemptClose(con); 291 292 pc.addConnectionEventListener( cl ); 293 } 294 } 295 296 if ( testConnectionOnCheckin ) 297 { 298 if ( logger.isLoggable( MLevel.FINER ) ) 299 finerLoggingTestPooledConnection( resc, "CHECKIN" ); 300 else 301 testPooledConnection( resc ); 302 } 303 } 304 305 public void refurbishIdleResource( Object resc ) throws Exception 306 { 307 if ( logger.isLoggable( MLevel.FINER ) ) 308 finerLoggingTestPooledConnection( resc, "IDLE CHECK" ); 309 else 310 testPooledConnection( resc ); 311 } 312 313 private void finerLoggingTestPooledConnection(Object resc, String testImpetus) throws Exception 314 { 315 logger.finer("Testing PooledConnection [" + resc + "] on " + testImpetus + "."); 316 try 317 { 318 testPooledConnection( resc ); 319 logger.finer("Test of PooledConnection [" + resc + "] on "+testImpetus+" has SUCCEEDED."); 320 } 321 catch (Exception e) 322 { 323 logger.log(MLevel.FINER, "Test of PooledConnection [" + resc + "] on "+testImpetus+" has FAILED.", e); 324 e.fillInStackTrace(); 325 throw e; 326 } 327 } 328 329 private void testPooledConnection(Object resc) throws Exception 330 { 331 PooledConnection pc = (PooledConnection ) resc; 332 333 Throwable [] throwableHolder = EMPTY_THROWABLE_HOLDER; 334 int status; 335 Connection conn = null; 336 Throwable rootCause = null; 337 try 338 { 339 pc.removeConnectionEventListener( cl ); 341 342 conn = pc.getConnection(); 344 Connection testConn; 351 if (scache != null) { 353 if (testQuery == null && connectionTesterIsDefault && c3p0PooledConnections) 355 testConn = ((AbstractC3P0PooledConnection) pc).getPhysicalConnection(); 356 else testConn = conn; 358 } 359 else { 361 if (c3p0PooledConnections) 362 testConn = ((AbstractC3P0PooledConnection) pc).getPhysicalConnection(); 363 else 364 testConn = conn; 365 } 366 367 if ( testQuery == null ) 368 status = connectionTester.activeCheckConnection( testConn ); 369 else 370 { 371 if (connectionTester instanceof UnifiedConnectionTester) 372 { 373 throwableHolder = thp.getThrowableHolder(); 374 status = ((UnifiedConnectionTester) connectionTester).activeCheckConnection( testConn, testQuery, throwableHolder ); 375 } 376 else if (connectionTester instanceof QueryConnectionTester) 377 status = ((QueryConnectionTester) connectionTester).activeCheckConnection( testConn, testQuery ); 378 else 379 { 380 385 logger.warning("[c3p0] testQuery '" + testQuery + 386 "' ignored. Please set a ConnectionTester that implements " + 387 "com.mchange.v2.c3p0.QueryConnectionTester, or use the " + 388 "DefaultConnectionTester, to test with the testQuery."); 389 status = connectionTester.activeCheckConnection( testConn ); 390 } 391 } 392 } 393 catch (Exception e) 394 { 395 if (Debug.DEBUG) 396 logger.log(MLevel.FINE, "A Connection test failed with an Exception.", e); 397 status = ConnectionTester.CONNECTION_IS_INVALID; 399 rootCause = e; 402 } 403 finally 404 { 405 if (rootCause == null) 406 rootCause = throwableHolder[0]; 407 else if (throwableHolder[0] != null && logger.isLoggable(MLevel.FINE)) 408 logger.log(MLevel.FINE, "Internal Connection Test Exception", throwableHolder[0]); 409 410 if (throwableHolder != EMPTY_THROWABLE_HOLDER) 411 thp.returnThrowableHolder( throwableHolder ); 412 413 ConnectionUtils.attemptClose( conn ); pc.addConnectionEventListener( cl ); } 416 417 switch (status) 418 { 419 case ConnectionTester.CONNECTION_IS_OKAY: 420 break; case ConnectionTester.DATABASE_IS_INVALID: 422 rp.resetPool(); 423 case ConnectionTester.CONNECTION_IS_INVALID: 425 Exception throwMe; 426 if (rootCause == null) 427 throwMe = new SQLException ("Connection is invalid"); 428 else 429 throwMe = SqlUtils.toSQLException("Connection is invalid", rootCause); 430 throw throwMe; 431 default: 432 throw new Error ("Bad Connection Tester (" + 433 connectionTester + ") " + 434 "returned invalid status (" + status + ")."); 435 } 436 } 437 438 public void destroyResource(Object resc) throws Exception 439 { 440 try 441 { 442 if ( connectionCustomizer != null ) 443 { 444 Connection physicalConnection = null; 445 try 446 { 447 physicalConnection = ((AbstractC3P0PooledConnection) resc).getPhysicalConnection(); 448 connectionCustomizer.onDestroy( physicalConnection, parentDataSourceIdentityToken ); 449 } 450 catch (ClassCastException e) 451 { 452 throw SqlUtils.toSQLException("Cannot use a ConnectionCustomizer with a non-c3p0 PooledConnection." + 453 " PooledConnection: " + resc + 454 "; ConnectionPoolDataSource: " + cpds.getClass().getName(), e); 455 } 456 catch (Exception e) 457 { 458 if (logger.isLoggable( MLevel.WARNING )) 459 logger.log( MLevel.WARNING, 460 "An exception occurred while executing the onDestroy() method of " + connectionCustomizer + 461 ". c3p0 will attempt to destroy the target Connection regardless, but this issue " + 462 " should be investigated and fixed.", 463 e ); 464 } 465 } 466 467 if (Debug.DEBUG && Debug.TRACE == Debug.TRACE_MAX && logger.isLoggable( MLevel.FINER )) 468 logger.log( MLevel.FINER, "Preparing to destroy PooledConnection: " + resc); 469 470 ((PooledConnection ) resc).close(); 471 472 475 if (Debug.DEBUG && Debug.TRACE == Debug.TRACE_MAX && logger.isLoggable( MLevel.FINER )) 476 logger.log( MLevel.FINER, 477 "Successfully destroyed PooledConnection: " + resc ); 478 } 482 catch (Exception e) 483 { 484 486 if (Debug.DEBUG && Debug.TRACE == Debug.TRACE_MAX && logger.isLoggable( MLevel.FINER )) 487 logger.log( MLevel.FINER, "Failed to destroy PooledConnection: " + resc ); 488 492 throw e; 493 } 494 } 495 } 496 497 ResourcePool.Manager manager = new PooledConnectionResourcePoolManager(); 498 499 synchronized (fact) 500 { 501 fact.setMin( min ); 502 fact.setMax( max ); 503 fact.setStart( start ); 504 fact.setIncrement( inc ); 505 fact.setIdleResourceTestPeriod( idleConnectionTestPeriod * 1000); 506 fact.setResourceMaxIdleTime( maxIdleTime * 1000 ); 507 fact.setExcessResourceMaxIdleTime( maxIdleTimeExcessConnections * 1000 ); 508 fact.setResourceMaxAge( maxConnectionAge * 1000 ); 509 fact.setExpirationEnforcementDelay( propertyCycle * 1000 ); 510 fact.setDestroyOverdueResourceTime( unreturnedConnectionTimeout * 1000 ); 511 fact.setDebugStoreCheckoutStackTrace( debugUnreturnedConnectionStackTraces ); 512 fact.setAcquisitionRetryAttempts( acq_retry_attempts ); 513 fact.setAcquisitionRetryDelay( acq_retry_delay ); 514 fact.setBreakOnAcquisitionFailure( break_after_acq_failure ); 515 rp = fact.createPool( manager ); 516 } 517 } 518 catch (ResourcePoolException e) 519 { throw SqlUtils.toSQLException(e); } 520 } 521 522 public PooledConnection checkoutPooledConnection() throws SQLException 523 { 524 try { return (PooledConnection ) rp.checkoutResource( checkoutTimeout ); } 526 catch (TimeoutException e) 527 { throw SqlUtils.toSQLException("An attempt by a client to checkout a Connection has timed out.", e); } 528 catch (CannotAcquireResourceException e) 529 { throw SqlUtils.toSQLException("Connections could not be acquired from the underlying database!", "08001", e); } 530 catch (Exception e) 531 { throw SqlUtils.toSQLException(e); } 532 } 533 534 public void checkinPooledConnection(PooledConnection pcon) throws SQLException 535 { 536 try { rp.checkinResource( pcon ); } 538 catch (ResourcePoolException e) 539 { throw SqlUtils.toSQLException(e); } 540 } 541 542 public float getEffectivePropertyCycle() throws SQLException 543 { 544 try 545 { return rp.getEffectiveExpirationEnforcementDelay() / 1000f; } 546 catch (ResourcePoolException e) 547 { throw SqlUtils.toSQLException(e); } 548 } 549 550 public int getNumThreadsAwaitingCheckout() throws SQLException 551 { 552 try 553 { return rp.getNumCheckoutWaiters(); } 554 catch (ResourcePoolException e) 555 { throw SqlUtils.toSQLException(e); } 556 } 557 558 public int getStatementCacheNumStatements() 559 { return scache == null ? 0 : scache.getNumStatements(); } 560 561 public int getStatementCacheNumCheckedOut() 562 { return scache == null ? 0 : scache.getNumStatementsCheckedOut(); } 563 564 public int getStatementCacheNumConnectionsWithCachedStatements() 565 { return scache == null ? 0 : scache.getNumConnectionsWithCachedStatements(); } 566 567 public String dumpStatementCacheStatus() 568 { return scache == null ? "Statement caching disabled." : scache.dumpStatementCacheStatus(); } 569 570 public void close() throws SQLException 571 { close( true ); } 572 573 public void close( boolean close_outstanding_connections ) throws SQLException 574 { 575 Exception throwMe = null; 577 578 try { if (scache != null) scache.close(); } 579 catch (SQLException e) 580 { throwMe = e; } 581 582 try 583 { rp.close( close_outstanding_connections ); } 584 catch (ResourcePoolException e) 585 { 586 if ( throwMe != null && logger.isLoggable( MLevel.WARNING ) ) 587 logger.log( MLevel.WARNING, "An Exception occurred while closing the StatementCache.", throwMe); 588 throwMe = e; 589 } 590 591 if (throwMe != null) 592 throw SqlUtils.toSQLException( throwMe ); 593 } 594 595 class ConnectionEventListenerImpl implements ConnectionEventListener 596 { 597 598 public void connectionClosed(final ConnectionEvent evt) 617 { 618 620 if (ASYNCHRONOUS_CONNECTION_EVENT_LISTENER) 621 { 622 Runnable r = new Runnable () 623 { 624 public void run() 625 { doCheckinResource( evt ); } 626 }; 627 sharedTaskRunner.postRunnable( r ); 628 } 629 else 630 doCheckinResource( evt ); 631 } 632 633 private void doCheckinResource(ConnectionEvent evt) 634 { 635 try 636 { rp.checkinResource( evt.getSource() ); } 637 catch (Exception e) 638 { 639 logger.log( MLevel.WARNING, 641 "An Exception occurred while trying to check a PooledConection into a ResourcePool.", 642 e ); 643 } 644 } 645 646 public void connectionErrorOccurred(final ConnectionEvent evt) 664 { 665 if ( logger.isLoggable( MLevel.FINE ) ) 668 logger.fine("CONNECTION ERROR OCCURRED!"); 669 670 final PooledConnection pc = (PooledConnection ) evt.getSource(); 671 int status; 672 if (pc instanceof C3P0PooledConnection) 673 status = ((C3P0PooledConnection) pc).getConnectionStatus(); 674 else if (pc instanceof NewPooledConnection) 675 status = ((NewPooledConnection) pc).getConnectionStatus(); 676 else status = ConnectionTester.CONNECTION_IS_INVALID; 678 679 final int final_status = status; 680 681 if (ASYNCHRONOUS_CONNECTION_EVENT_LISTENER) 682 { 683 Runnable r = new Runnable () 684 { 685 public void run() 686 { doMarkPoolStatus( pc, final_status ); } 687 }; 688 sharedTaskRunner.postRunnable( r ); 689 } 690 else 691 doMarkPoolStatus( pc, final_status ); 692 } 693 694 private void doMarkPoolStatus(PooledConnection pc, int status) 695 { 696 try 697 { 698 switch (status) 699 { 700 case ConnectionTester.CONNECTION_IS_OKAY: 701 throw new RuntimeException ("connectionErrorOcccurred() should only be " + 702 "called for errors fatal to the Connection."); 703 case ConnectionTester.CONNECTION_IS_INVALID: 704 rp.markBroken( pc ); 705 break; 706 case ConnectionTester.DATABASE_IS_INVALID: 707 if (logger.isLoggable(MLevel.WARNING)) 708 logger.warning("A ConnectionTest has failed, reporting that all previously acquired Connections are likely invalid. " + 709 "The pool will be reset."); 710 rp.resetPool(); 711 break; 712 default: 713 throw new RuntimeException ("Bad Connection Tester (" + connectionTester + ") " + 714 "returned invalid status (" + status + ")."); 715 } 716 } 717 catch ( ResourcePoolException e ) 718 { 719 logger.log(MLevel.WARNING, "Uh oh... our resource pool is probably broken!", e); 722 } 723 } 724 } 725 726 public int getNumConnections() throws SQLException 727 { 728 try { return rp.getPoolSize(); } 729 catch ( Exception e ) 730 { 731 logger.log( MLevel.WARNING, null, e ); 733 throw SqlUtils.toSQLException( e ); 734 } 735 } 736 737 public int getNumIdleConnections() throws SQLException 738 { 739 try { return rp.getAvailableCount(); } 740 catch ( Exception e ) 741 { 742 logger.log( MLevel.WARNING, null, e ); 744 throw SqlUtils.toSQLException( e ); 745 } 746 } 747 748 public int getNumBusyConnections() throws SQLException 749 { 750 try 751 { 752 synchronized ( rp ) 753 { return (rp.getAwaitingCheckinCount() - rp.getExcludedCount()); } 754 } 755 catch ( Exception e ) 756 { 757 logger.log( MLevel.WARNING, null, e ); 759 throw SqlUtils.toSQLException( e ); 760 } 761 } 762 763 public int getNumUnclosedOrphanedConnections() throws SQLException 764 { 765 try { return rp.getExcludedCount(); } 766 catch ( Exception e ) 767 { 768 logger.log( MLevel.WARNING, null, e ); 770 throw SqlUtils.toSQLException( e ); 771 } 772 } 773 774 public long getStartTime() throws SQLException 775 { 776 try { return rp.getStartTime(); } 777 catch ( Exception e ) 778 { 779 logger.log( MLevel.WARNING, null, e ); 781 throw SqlUtils.toSQLException( e ); 782 } 783 } 784 785 public long getUpTime() throws SQLException 786 { 787 try { return rp.getUpTime(); } 788 catch ( Exception e ) 789 { 790 logger.log( MLevel.WARNING, null, e ); 792 throw SqlUtils.toSQLException( e ); 793 } 794 } 795 796 public long getNumFailedCheckins() throws SQLException 797 { 798 try { return rp.getNumFailedCheckins(); } 799 catch ( Exception e ) 800 { 801 logger.log( MLevel.WARNING, null, e ); 803 throw SqlUtils.toSQLException( e ); 804 } 805 } 806 807 public long getNumFailedCheckouts() throws SQLException 808 { 809 try { return rp.getNumFailedCheckouts(); } 810 catch ( Exception e ) 811 { 812 logger.log( MLevel.WARNING, null, e ); 814 throw SqlUtils.toSQLException( e ); 815 } 816 } 817 818 public long getNumFailedIdleTests() throws SQLException 819 { 820 try { return rp.getNumFailedIdleTests(); } 821 catch ( Exception e ) 822 { 823 logger.log( MLevel.WARNING, null, e ); 825 throw SqlUtils.toSQLException( e ); 826 } 827 } 828 829 public Throwable getLastCheckinFailure() throws SQLException 830 { 831 try { return rp.getLastCheckinFailure(); } 832 catch ( Exception e ) 833 { 834 logger.log( MLevel.WARNING, null, e ); 836 throw SqlUtils.toSQLException( e ); 837 } 838 } 839 840 public Throwable getLastCheckoutFailure() throws SQLException 841 { 842 try { return rp.getLastCheckoutFailure(); } 843 catch ( Exception e ) 844 { 845 logger.log( MLevel.WARNING, null, e ); 847 throw SqlUtils.toSQLException( e ); 848 } 849 } 850 851 public Throwable getLastIdleTestFailure() throws SQLException 852 { 853 try { return rp.getLastIdleCheckFailure(); } 854 catch ( Exception e ) 855 { 856 logger.log( MLevel.WARNING, null, e ); 858 throw SqlUtils.toSQLException( e ); 859 } 860 } 861 862 public Throwable getLastConnectionTestFailure() throws SQLException 863 { 864 try { return rp.getLastResourceTestFailure(); } 865 catch ( Exception e ) 866 { 867 logger.log( MLevel.WARNING, null, e ); 869 throw SqlUtils.toSQLException( e ); 870 } 871 } 872 873 public Throwable getLastAcquisitionFailure() throws SQLException 874 { 875 try { return rp.getLastAcquisitionFailure(); } 876 catch ( Exception e ) 877 { 878 logger.log( MLevel.WARNING, null, e ); 880 throw SqlUtils.toSQLException( e ); 881 } 882 } 883 884 891 public void reset() throws SQLException 892 { 893 try { rp.resetPool(); } 894 catch ( Exception e ) 895 { 896 logger.log( MLevel.WARNING, null, e ); 898 throw SqlUtils.toSQLException( e ); 899 } 900 } 901 902 final static class ThrowableHolderPool 903 { 904 LinkedList l = new LinkedList (); 905 906 synchronized Throwable [] getThrowableHolder() 907 { 908 if (l.size() == 0) 909 return new Throwable [1]; 910 else 911 return (Throwable []) l.remove(0); 912 } 913 914 synchronized void returnThrowableHolder(Throwable [] th) 915 { 916 th[0] = null; 917 l.add(th); 918 } 919 } 920 921 } 922 | Popular Tags |