Source Code Cross Referenced for ConnectionPool.java in  » Database-JDBC-Connection-Pool » proxool » org » logicalcobwebs » proxool » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database JDBC Connection Pool » proxool » org.logicalcobwebs.proxool 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * This software is released under a licence similar to the Apache Software Licence.
0003:         * See org.logicalcobwebs.proxool.package.html for details.
0004:         * The latest version is available at http://proxool.sourceforge.net
0005:         */
0006:        package org.logicalcobwebs.proxool;
0007:
0008:        import java.sql.Connection;
0009:        import java.sql.SQLException;
0010:        import java.util.Collection;
0011:        import java.util.Date;
0012:        import java.util.HashSet;
0013:        import java.util.Iterator;
0014:        import java.util.List;
0015:        import java.util.Set;
0016:        import java.util.TreeSet;
0017:
0018:        import org.logicalcobwebs.concurrent.ReaderPreferenceReadWriteLock;
0019:        import org.logicalcobwebs.concurrent.WriterPreferenceReadWriteLock;
0020:        import org.apache.commons.logging.Log;
0021:        import org.apache.commons.logging.LogFactory;
0022:        import org.logicalcobwebs.proxool.admin.Admin;
0023:        import org.logicalcobwebs.proxool.util.FastArrayList;
0024:
0025:        /**
0026:         * This is where most things happen. (In fact, probably too many things happen in this one
0027:         * class).
0028:         * @version $Revision: 1.84 $, $Date: 2006/03/23 11:44:57 $
0029:         * @author billhorsman
0030:         * @author $Author: billhorsman $ (current maintainer)
0031:         */
0032:        class ConnectionPool implements  ConnectionPoolStatisticsIF {
0033:
0034:            /**
0035:             * Use this for messages that aren't useful for the pool specific log
0036:             */
0037:            private static final Log LOG = LogFactory
0038:                    .getLog(ConnectionPool.class);
0039:
0040:            /**
0041:             * Here we deviate from the standard of using the classname for the log
0042:             * name. Here we want to use the alias for the pool so that we can log
0043:             * each pool to different places. So we have to instantiate the log later.
0044:             */
0045:            private Log log;
0046:
0047:            private ReaderPreferenceReadWriteLock connectionStatusReadWriteLock = new ReaderPreferenceReadWriteLock();
0048:
0049:            /**
0050:             * If you want to shutdown the pool you should get a write lock on this. And if you use the pool then
0051:             * get a read lock. This stops us trying to shutdown the pool whilst it is in use. Only, we don't want
0052:             * to delay shutdown just because some greedy user has got a connection active. Shutdown should be
0053:             * relatively immediate. So we don't ask for a read lock for the whole time that a connection is active.
0054:             */
0055:            private WriterPreferenceReadWriteLock primaryReadWriteLock = new WriterPreferenceReadWriteLock();
0056:
0057:            private static final String[] STATUS_DESCRIPTIONS = { "NULL",
0058:                    "AVAILABLE", "ACTIVE", "OFFLINE" };
0059:
0060:            private static final String MSG_MAX_CONNECTION_COUNT = "Couldn't get connection because we are at maximum connection count and there are none available";
0061:
0062:            /** This is the pool itself */
0063:            private List proxyConnections;
0064:
0065:            /** This is the "round robin" that makes sure we use all the connections */
0066:            private int nextAvailableConnection = 0;
0067:
0068:            private long connectionsServedCount = 0;
0069:
0070:            private long connectionsRefusedCount = 0;
0071:
0072:            /** This keeps a count of how many connections there are in each state */
0073:            private int[] connectionCountByState = new int[4];
0074:
0075:            private ConnectionPoolDefinition definition;
0076:
0077:            private CompositeConnectionListener compositeConnectionListener = new CompositeConnectionListener();
0078:
0079:            private CompositeStateListener compositeStateListener = new CompositeStateListener();
0080:
0081:            private long timeOfLastRefusal = 0;
0082:
0083:            private int upState;
0084:
0085:            private static boolean loggedLegend;
0086:
0087:            private Admin admin;
0088:
0089:            private boolean locked = false;
0090:
0091:            private Date dateStarted = new Date();
0092:
0093:            private boolean connectionPoolUp = false;
0094:
0095:            /**
0096:             * This gets set during {@link #shutdown}. We use it to notify shutdown
0097:             * that all connections are now non-active.
0098:             */
0099:            private Thread shutdownThread;
0100:
0101:            private Prototyper prototyper;
0102:
0103:            /**
0104:             * Initialised in {@link ConnectionPool#ConnectionPool constructor}.
0105:             */
0106:            private ConnectionResetter connectionResetter;
0107:
0108:            private ConnectionValidatorIF connectionValidator;
0109:
0110:            protected ConnectionPool(ConnectionPoolDefinition definition)
0111:                    throws ProxoolException {
0112:
0113:                // Use the FastArrayList for performance and thread safe
0114:                // behaviour. We set its behaviour to "fast"  (meaning reads are
0115:                // unsynchronized, whilst writes are not).
0116:                FastArrayList fal = new FastArrayList();
0117:                fal.setFast(true);
0118:                proxyConnections = fal;
0119:
0120:                log = LogFactory.getLog("org.logicalcobwebs.proxool."
0121:                        + definition.getAlias());
0122:                connectionResetter = new ConnectionResetter(log, definition
0123:                        .getDriver());
0124:                setDefinition(definition);
0125:
0126:                connectionValidator = new DefaultConnectionValidator();
0127:
0128:                if (definition.getStatistics() != null) {
0129:                    try {
0130:                        admin = new Admin(definition);
0131:                    } catch (ProxoolException e) {
0132:                        log.error("Failed to initialise statistics", e);
0133:                    }
0134:                }
0135:
0136:                ShutdownHook.init();
0137:            }
0138:
0139:            /** Starts up house keeping and prototyper threads. */
0140:            protected void start() throws ProxoolException {
0141:                connectionPoolUp = true;
0142:                prototyper = new Prototyper(this );
0143:                HouseKeeperController.register(this );
0144:            }
0145:
0146:            /**
0147:             * Get a connection from the pool.  If none are available or there was an Exception
0148:             * then an exception is thrown and something written to the log
0149:             */
0150:            protected Connection getConnection() throws SQLException {
0151:
0152:                String requester = Thread.currentThread().getName();
0153:
0154:                /*
0155:                 *If we're busy, we need to return as quickly as possible. Because this is unsynchronized
0156:                 * we run the risk of refusing a connection when we might actually be able to. But that will
0157:                 * only happen when we're right at or near maximum connections anyway.
0158:                 */
0159:
0160:                try {
0161:                    prototyper.quickRefuse();
0162:                } catch (SQLException e) {
0163:                    connectionsRefusedCount++;
0164:                    if (admin != null) {
0165:                        admin.connectionRefused();
0166:                    }
0167:                    log.info(displayStatistics() + " - "
0168:                            + MSG_MAX_CONNECTION_COUNT);
0169:                    timeOfLastRefusal = System.currentTimeMillis();
0170:                    setUpState(StateListenerIF.STATE_OVERLOADED);
0171:                    throw e;
0172:                }
0173:
0174:                prototyper.checkSimultaneousBuildThrottle();
0175:
0176:                ProxyConnection proxyConnection = null;
0177:
0178:                try {
0179:
0180:                    // We need to look at all the connections, but we don't want to keep looping round forever
0181:                    for (int connectionsTried = 0; connectionsTried < proxyConnections
0182:                            .size(); connectionsTried++) {
0183:                        // By doing this in a try/catch we avoid needing to synch on the size().  We need to do be
0184:                        // able to cope with connections being removed whilst we are going round this loop
0185:                        try {
0186:                            proxyConnection = (ProxyConnection) proxyConnections
0187:                                    .get(nextAvailableConnection);
0188:                        } catch (ArrayIndexOutOfBoundsException e) {
0189:                            // This is thrown by a Vector (which we no longer use), but is
0190:                            // kept here for a while.
0191:                            nextAvailableConnection = 0;
0192:                            proxyConnection = (ProxyConnection) proxyConnections
0193:                                    .get(nextAvailableConnection);
0194:                        } catch (IndexOutOfBoundsException e) {
0195:                            // This is thrown by a true List
0196:                            nextAvailableConnection = 0;
0197:                            proxyConnection = (ProxyConnection) proxyConnections
0198:                                    .get(nextAvailableConnection);
0199:                        }
0200:                        // setActive() returns false if the ProxyConnection wasn't available.  You
0201:                        // can't set it active twice (at least, not without making it available again
0202:                        // in between)
0203:                        if (proxyConnection != null
0204:                                && proxyConnection.setStatus(
0205:                                        ProxyConnectionIF.STATUS_AVAILABLE,
0206:                                        ProxyConnectionIF.STATUS_ACTIVE)) {
0207:
0208:                            // Okay. So we have it. But is it working ok?
0209:                            if (getDefinition().isTestBeforeUse()) {
0210:                                if (!testConnection(proxyConnection)) {
0211:                                    // Oops. No it's not. Let's choose another.
0212:                                    proxyConnection = null;
0213:                                }
0214:                            }
0215:                            if (proxyConnection != null) {
0216:                                nextAvailableConnection++;
0217:                                break;
0218:                            }
0219:                        } else {
0220:                            proxyConnection = null;
0221:                        }
0222:                        nextAvailableConnection++;
0223:                    }
0224:                    // Did we get one?
0225:                    if (proxyConnection == null) {
0226:                        try {
0227:                            // No!  Let's see if we can create one
0228:                            proxyConnection = prototyper.buildConnection(
0229:                                    ProxyConnection.STATUS_ACTIVE, "on demand");
0230:
0231:                            // Okay. So we have it. But is it working ok?
0232:                            if (getDefinition().isTestBeforeUse()) {
0233:                                if (!testConnection(proxyConnection)) {
0234:                                    // Oops. No it's not. There's not much more we can do for now
0235:                                    throw new SQLException(
0236:                                            "Created a new connection but it failed its test");
0237:                                }
0238:                            }
0239:                        } catch (SQLException e) {
0240:                            throw e;
0241:                        } catch (ProxoolException e) {
0242:                            log.debug("Couldn't get connection", e);
0243:                            throw new SQLException(e.toString());
0244:                        } catch (Throwable e) {
0245:                            log.error("Couldn't get connection", e);
0246:                            throw new SQLException(e.toString());
0247:                        }
0248:                    }
0249:
0250:                } catch (SQLException e) {
0251:                    throw e;
0252:                } catch (Throwable t) {
0253:                    log.error("Problem getting connection", t);
0254:                    throw new SQLException(t.toString());
0255:                } finally {
0256:                    if (proxyConnection != null) {
0257:                        connectionsServedCount++;
0258:                        proxyConnection.setRequester(requester);
0259:                    } else {
0260:                        connectionsRefusedCount++;
0261:                        if (admin != null) {
0262:                            admin.connectionRefused();
0263:                        }
0264:                        timeOfLastRefusal = System.currentTimeMillis();
0265:                        setUpState(StateListenerIF.STATE_OVERLOADED);
0266:                    }
0267:                }
0268:
0269:                if (proxyConnection == null) {
0270:                    throw new SQLException(
0271:                            "Unknown reason for not getting connection. Sorry.");
0272:                }
0273:
0274:                if (log.isDebugEnabled() && getDefinition().isVerbose()) {
0275:                    log.debug(displayStatistics() + " - Connection #"
0276:                            + proxyConnection.getId() + " served");
0277:                }
0278:
0279:                // This gives the proxy connection a chance to reset itself before it is served.
0280:                proxyConnection.open();
0281:
0282:                return ProxyFactory.getWrappedConnection(proxyConnection);
0283:            }
0284:
0285:            /**
0286:             * Test the connection (if required)
0287:             * If the connection fails the test, it is removed from the pool.
0288:             * If no ConnectionValidatorIF is defined, then the test always succeed.
0289:             * 
0290:             * @param proxyConnection the connection to test
0291:             * @return TRUE if the connection pass the test, FALSE if it fails
0292:             */
0293:            private boolean testConnection(ProxyConnectionIF proxyConnection) {
0294:                // is validation enabled ?
0295:                if (connectionValidator == null) {
0296:                    return true;
0297:                }
0298:
0299:                // validate the connection
0300:                boolean success = connectionValidator.validate(getDefinition(),
0301:                        proxyConnection.getConnection());
0302:
0303:                if (success) {
0304:                    if (LOG.isDebugEnabled()) {
0305:                        LOG.debug(displayStatistics() + " - Connection #"
0306:                                + proxyConnection.getId() + " tested: OK");
0307:                    }
0308:                } else {
0309:                    proxyConnection.setStatus(ProxyConnectionIF.STATUS_NULL);
0310:                    removeProxyConnection(proxyConnection,
0311:                            "it didn't pass the validation",
0312:                            ConnectionPool.REQUEST_EXPIRY, true);
0313:                }
0314:
0315:                // return 
0316:                return success;
0317:            }
0318:
0319:            /**
0320:             * Add a ProxyConnection to the pool
0321:             * @param proxyConnection new connection
0322:             * @return true if the connection was added or false if it wasn't (for instance, if the definition it
0323:             * was built with is out of date).
0324:             */
0325:            protected boolean addProxyConnection(
0326:                    ProxyConnectionIF proxyConnection) {
0327:                boolean added = false;
0328:                try {
0329:                    acquireConnectionStatusWriteLock();
0330:                    if (proxyConnection.getDefinition() == getDefinition()) {
0331:                        proxyConnections.add(proxyConnection);
0332:                        connectionCountByState[proxyConnection.getStatus()]++;
0333:                        added = true;
0334:                    }
0335:                } finally {
0336:                    releaseConnectionStatusWriteLock();
0337:                }
0338:                return added;
0339:            }
0340:
0341:            protected static String getStatusDescription(int status) {
0342:                try {
0343:                    return STATUS_DESCRIPTIONS[status];
0344:                } catch (ArrayIndexOutOfBoundsException e) {
0345:                    return "Unknown status: " + status;
0346:                }
0347:            }
0348:
0349:            /**
0350:             * When you have finished with a Connection you should put it back here.  That will make it available to others.
0351:             * Unless it's due for expiry, in which case it will... expire
0352:             */
0353:            protected void putConnection(ProxyConnectionIF proxyConnection) {
0354:
0355:                if (admin != null) {
0356:                    long now = System.currentTimeMillis();
0357:                    long start = proxyConnection.getTimeLastStartActive();
0358:                    if (now - start < 0) {
0359:                        log.warn("Future start time detected. #"
0360:                                + proxyConnection.getId() + " start = "
0361:                                + new Date(start) + " (" + (now - start)
0362:                                + " milliseconds)");
0363:                    } else if (now - start > 1000000) {
0364:                        log.warn("Suspiciously long active time. #"
0365:                                + proxyConnection.getId() + " start = "
0366:                                + new Date(start));
0367:                    }
0368:                    admin.connectionReturned(now - start);
0369:                }
0370:
0371:                // It's possible that this connection is due for expiry
0372:                if (proxyConnection.isMarkedForExpiry()) {
0373:                    if (proxyConnection.setStatus(
0374:                            ProxyConnectionIF.STATUS_ACTIVE,
0375:                            ProxyConnectionIF.STATUS_NULL)) {
0376:                        expireProxyConnection(proxyConnection, proxyConnection
0377:                                .getReasonForMark(), REQUEST_EXPIRY);
0378:                    }
0379:                } else {
0380:
0381:                    // Optionally, test it to see if it is ok
0382:                    if (getDefinition().isTestAfterUse()) {
0383:                        // It will get removed by this call if it is no good
0384:                        testConnection(proxyConnection);
0385:                    }
0386:
0387:                    // Let's make it available for someone else
0388:                    if (!proxyConnection.setStatus(
0389:                            ProxyConnectionIF.STATUS_ACTIVE,
0390:                            ProxyConnectionIF.STATUS_AVAILABLE)) {
0391:                        if (proxyConnection.getStatus() == ProxyConnectionIF.STATUS_AVAILABLE) {
0392:                            // This is *probably* because the connection has been closed twice.
0393:                            // Although we can't tell for sure. We'll have to refactor this to use
0394:                            // throw away wrappers to avoid this problem.
0395:                            log
0396:                                    .warn("Unable to close connection "
0397:                                            + proxyConnection.getId()
0398:                                            + " - I suspect that it has been closed already. Closing it more"
0399:                                            + " than once is unwise and should be avoided.");
0400:                        } else {
0401:                            log
0402:                                    .warn("Unable to set status of connection "
0403:                                            + proxyConnection.getId()
0404:                                            + " from "
0405:                                            + getStatusDescription(ProxyConnectionIF.STATUS_ACTIVE)
0406:                                            + " to "
0407:                                            + getStatusDescription(ProxyConnectionIF.STATUS_AVAILABLE)
0408:                                            + " because it's state was "
0409:                                            + getStatusDescription(proxyConnection
0410:                                                    .getStatus()));
0411:                        }
0412:                    }
0413:                }
0414:
0415:                if (log.isDebugEnabled() && getDefinition().isVerbose()) {
0416:                    log.debug(displayStatistics() + " - Connection #"
0417:                            + proxyConnection.getId() + " returned (now "
0418:                            + getStatusDescription(proxyConnection.getStatus())
0419:                            + ")");
0420:                }
0421:
0422:            }
0423:
0424:            /** This means that there's something wrong the connection and it's probably best if no one uses it again. */
0425:            protected void throwConnection(ProxyConnectionIF proxyConnection,
0426:                    String reason) {
0427:                expireConnectionAsSoonAsPossible(proxyConnection, reason, true);
0428:            }
0429:
0430:            /** Get a ProxyConnection by index */
0431:            private ProxyConnectionIF getProxyConnection(int i) {
0432:                return (ProxyConnectionIF) proxyConnections.get(i);
0433:            }
0434:
0435:            /**
0436:             * Return an array of all the connections
0437:             * @return array of connections
0438:             */
0439:            protected ProxyConnectionIF[] getProxyConnections() {
0440:                return (ProxyConnectionIF[]) proxyConnections
0441:                        .toArray(new ProxyConnectionIF[proxyConnections.size()]);
0442:            }
0443:
0444:            /**
0445:             * Remove a ProxyConnection by calling its {@link ConnectionListenerIF#onDeath onDeath} event,
0446:             * closing it (for real) and then removing it from the list.
0447:             * @param proxyConnection the connection to remove
0448:             * @param reason for log audit
0449:             * @param forceExpiry true means close now, whether it is active or not; false means if it is active then
0450:             * merely mark it for expiry so that it is removed as soon as it finished being active
0451:             * @param triggerSweep if true then this removal will trigger a prototype sweep
0452:             */
0453:            protected void removeProxyConnection(
0454:                    ProxyConnectionIF proxyConnection, String reason,
0455:                    boolean forceExpiry, boolean triggerSweep) {
0456:                // Just check that it is null
0457:                if (forceExpiry || proxyConnection.isNull()) {
0458:
0459:                    proxyConnection.setStatus(ProxyConnectionIF.STATUS_NULL);
0460:
0461:                    /* Run some code everytime we destroy a connection */
0462:
0463:                    try {
0464:                        onDeath(proxyConnection.getConnection());
0465:                    } catch (SQLException e) {
0466:                        log.error("Problem during onDeath (ignored)", e);
0467:                    }
0468:
0469:                    // The reallyClose() method also decrements the connectionCount.
0470:                    try {
0471:                        proxyConnection.reallyClose();
0472:                    } catch (SQLException e) {
0473:                        log.error(e);
0474:                    }
0475:
0476:                    try {
0477:                        // If we're shutting down then getting a write lock will cause a deadlock
0478:                        if (isConnectionPoolUp()) {
0479:                            acquireConnectionStatusWriteLock();
0480:                        }
0481:                        proxyConnections.remove(proxyConnection);
0482:                    } finally {
0483:                        if (isConnectionPoolUp()) {
0484:                            releaseConnectionStatusWriteLock();
0485:                        }
0486:                    }
0487:
0488:                    if (log.isDebugEnabled()) {
0489:                        log.debug(displayStatistics()
0490:                                + " - #"
0491:                                + FormatHelper
0492:                                        .formatMediumNumber(proxyConnection
0493:                                                .getId()) + " removed because "
0494:                                + reason + ".");
0495:                    }
0496:
0497:                    if (triggerSweep) {
0498:                        PrototyperController.triggerSweep(getDefinition()
0499:                                .getAlias());
0500:                    }
0501:
0502:                } else {
0503:                    log.error(displayStatistics()
0504:                            + " - #"
0505:                            + FormatHelper.formatMediumNumber(proxyConnection
0506:                                    .getId())
0507:                            + " was not removed because isNull() was false.");
0508:                }
0509:            }
0510:
0511:            protected void expireProxyConnection(
0512:                    ProxyConnectionIF proxyConnection, String reason,
0513:                    boolean forceExpiry) {
0514:                removeProxyConnection(proxyConnection, reason, forceExpiry,
0515:                        true);
0516:            }
0517:
0518:            /**
0519:             * Call this to shutdown gracefully.
0520:             *  @param delay how long to wait for connections to become free before forcing them to close anyway
0521:             */
0522:            protected void shutdown(int delay, String finalizerName)
0523:                    throws Throwable {
0524:
0525:                final String alias = getDefinition().getAlias();
0526:                try {
0527:                    /* This will stop us giving out any more connections and may
0528:                    cause some of the threads to die. */
0529:
0530:                    acquirePrimaryWriteLock();
0531:
0532:                    if (connectionPoolUp) {
0533:
0534:                        connectionPoolUp = false;
0535:                        long startFinalize = System.currentTimeMillis();
0536:                        shutdownThread = Thread.currentThread();
0537:
0538:                        if (delay > 0) {
0539:                            log
0540:                                    .info("Shutting down '"
0541:                                            + alias
0542:                                            + "' pool started at "
0543:                                            + dateStarted
0544:                                            + " - waiting for "
0545:                                            + delay
0546:                                            + " milliseconds for everything to stop.  [ "
0547:                                            + finalizerName + "]");
0548:                        } else {
0549:                            log.info("Shutting down '" + alias
0550:                                    + "' pool immediately [" + finalizerName
0551:                                    + "]");
0552:                        }
0553:
0554:                        /* Interrupt the threads (in case they're sleeping) */
0555:
0556:                        boolean connectionClosedManually = false;
0557:                        try {
0558:
0559:                            try {
0560:                                HouseKeeperController.cancel(alias);
0561:                            } catch (ProxoolException e) {
0562:                                log
0563:                                        .error(
0564:                                                "Shutdown couldn't cancel house keeper",
0565:                                                e);
0566:                            }
0567:
0568:                            // Cancel the admin thread (for statistics)
0569:                            if (admin != null) {
0570:                                admin.cancelAll();
0571:                            }
0572:
0573:                            /* Patience, patience. */
0574:
0575:                            if (connectionCountByState[ProxyConnectionIF.STATUS_ACTIVE] != 0) {
0576:                                long endWait = startFinalize + delay;
0577:                                LOG
0578:                                        .info("Waiting until "
0579:                                                + new Date(endWait)
0580:                                                + " for all connections to become inactive (active count is "
0581:                                                + connectionCountByState[ProxyConnectionIF.STATUS_ACTIVE]
0582:                                                + ").");
0583:                                while (true) {
0584:                                    long timeout = endWait
0585:                                            - System.currentTimeMillis();
0586:                                    if (timeout > 0) {
0587:                                        synchronized (Thread.currentThread()) {
0588:                                            try {
0589:                                                Thread.currentThread().wait(
0590:                                                        timeout);
0591:                                            } catch (InterruptedException e) {
0592:                                                log
0593:                                                        .debug("Interrupted whilst sleeping.");
0594:                                            }
0595:                                        }
0596:                                    }
0597:                                    int activeCount = connectionCountByState[ProxyConnectionIF.STATUS_ACTIVE];
0598:                                    if (activeCount == 0) {
0599:                                        break;
0600:                                    }
0601:                                    if (System.currentTimeMillis() < endWait) {
0602:                                        LOG
0603:                                                .info("Still waiting for active count to reach zero (currently "
0604:                                                        + activeCount + ").");
0605:                                    } else {
0606:                                        // There are still connections active. Oh well, we're not _that_ patient
0607:                                        LOG
0608:                                                .warn("Shutdown waited for "
0609:                                                        + (System
0610:                                                                .currentTimeMillis() - startFinalize)
0611:                                                        + " milliseconds for all "
0612:                                                        + "the connections to become inactive but the active count is still "
0613:                                                        + activeCount
0614:                                                        + ". Shutting down anyway.");
0615:                                        break;
0616:                                    }
0617:                                    Thread.sleep(100);
0618:                                }
0619:                            }
0620:
0621:                            prototyper.cancel();
0622:
0623:                            // Silently close all connections
0624:                            for (int i = proxyConnections.size() - 1; i >= 0; i--) {
0625:                                long id = getProxyConnection(i).getId();
0626:                                try {
0627:                                    connectionClosedManually = true;
0628:                                    removeProxyConnection(
0629:                                            getProxyConnection(i),
0630:                                            "of shutdown", true, false);
0631:                                    if (log.isDebugEnabled()) {
0632:                                        log.debug("Connection #" + id
0633:                                                + " closed");
0634:                                    }
0635:                                } catch (Throwable t) {
0636:                                    if (log.isDebugEnabled()) {
0637:                                        log.debug(
0638:                                                "Problem closing connection #"
0639:                                                        + id, t);
0640:                                    }
0641:
0642:                                }
0643:                            }
0644:
0645:                        } catch (Throwable t) {
0646:                            log.error("Unknown problem finalizing pool", t);
0647:                        } finally {
0648:
0649:                            ConnectionPoolManager.getInstance()
0650:                                    .removeConnectionPool(alias);
0651:
0652:                            if (log.isDebugEnabled()) {
0653:                                log
0654:                                        .info("'"
0655:                                                + alias
0656:                                                + "' pool has been closed down by "
0657:                                                + finalizerName
0658:                                                + " in "
0659:                                                + (System.currentTimeMillis() - startFinalize)
0660:                                                + " milliseconds.");
0661:                                if (!connectionClosedManually) {
0662:                                    log
0663:                                            .debug("No connections required manual removal.");
0664:                                }
0665:                            }
0666:                            super .finalize();
0667:                        }
0668:                    } else {
0669:                        if (log.isDebugEnabled()) {
0670:                            log
0671:                                    .debug("Ignoring duplicate attempt to shutdown '"
0672:                                            + alias
0673:                                            + "' pool by "
0674:                                            + finalizerName);
0675:                        }
0676:                    }
0677:                } catch (Throwable t) {
0678:                    log.error(finalizerName + " couldn't shutdown pool", t);
0679:                } finally {
0680:                    releasePrimaryWriteLock();
0681:                }
0682:            }
0683:
0684:            /**
0685:             * You should {@link #acquireConnectionStatusReadLock acquire}
0686:             * a read lock if you want this to be accurate (but that might have
0687:             * an impact on the performance of your pool).
0688:             * @see ConnectionPoolStatisticsIF#getAvailableConnectionCount
0689:             */
0690:            public int getAvailableConnectionCount() {
0691:                return connectionCountByState[ConnectionInfoIF.STATUS_AVAILABLE];
0692:            }
0693:
0694:            /**
0695:             * You should {@link #acquireConnectionStatusReadLock acquire}
0696:             * a read lock if you want this to be accurate (but that might have
0697:             * an impact on the performance of your pool).
0698:             * @see ConnectionPoolStatisticsIF#getActiveConnectionCount
0699:             */
0700:            public int getActiveConnectionCount() {
0701:                return connectionCountByState[ConnectionInfoIF.STATUS_ACTIVE];
0702:            }
0703:
0704:            /**
0705:             * You should {@link #acquireConnectionStatusReadLock acquire}
0706:             * a read lock if you want this to be accurate (but that might have
0707:             * an impact on the performance of your pool).
0708:             * @see ConnectionPoolStatisticsIF#getOfflineConnectionCount
0709:             */
0710:            public int getOfflineConnectionCount() {
0711:                return connectionCountByState[ConnectionInfoIF.STATUS_OFFLINE];
0712:            }
0713:
0714:            protected String displayStatistics() {
0715:
0716:                if (!loggedLegend) {
0717:                    log
0718:                            .info("Proxool statistics legend: \"s - r  (a/t/o)\" > s=served, r=refused (only shown if non-zero), a=active, t=total, o=offline (being tested)");
0719:                    loggedLegend = true;
0720:                }
0721:
0722:                StringBuffer statistics = new StringBuffer();
0723:                statistics.append(FormatHelper
0724:                        .formatBigNumber(getConnectionsServedCount()));
0725:
0726:                if (getConnectionsRefusedCount() > 0) {
0727:                    statistics.append(" -");
0728:                    statistics.append(FormatHelper
0729:                            .formatBigNumber(getConnectionsRefusedCount()));
0730:                }
0731:
0732:                statistics.append(" (");
0733:                statistics.append(FormatHelper
0734:                        .formatSmallNumber(getActiveConnectionCount()));
0735:                statistics.append("/");
0736:                statistics.append(FormatHelper
0737:                        .formatSmallNumber(getAvailableConnectionCount()
0738:                                + getActiveConnectionCount()));
0739:                statistics.append("/");
0740:                statistics.append(FormatHelper
0741:                        .formatSmallNumber(getOfflineConnectionCount()));
0742:                statistics.append(")");
0743:
0744:                // Don't need this triple check any more.
0745:                /*
0746:                if (getDefinition().getDebugLevel() == ConnectionPoolDefinitionIF.DEBUG_LEVEL_LOUD) {
0747:                    statistics.append(", cc=");
0748:                    statistics.append(connectionCount);
0749:                    statistics.append(", ccc=");
0750:                    statistics.append(connectedConnectionCount);
0751:                }
0752:                 */
0753:
0754:                return statistics.toString();
0755:            }
0756:
0757:            protected void expireAllConnections(String reason, boolean merciful) {
0758:
0759:                // Do this in two stages because expiring a connection will trigger
0760:                // the prototyper to make more. And that might mean we end up
0761:                // killing a newly made connection;
0762:                Set pcs = new HashSet();
0763:                for (int i = proxyConnections.size() - 1; i >= 0; i--) {
0764:                    pcs.add(proxyConnections.get(i));
0765:                }
0766:
0767:                Iterator i = pcs.iterator();
0768:                while (i.hasNext()) {
0769:                    ProxyConnectionIF pc = (ProxyConnectionIF) i.next();
0770:                    expireConnectionAsSoonAsPossible(pc, reason, merciful);
0771:                }
0772:            }
0773:
0774:            protected void expireConnectionAsSoonAsPossible(
0775:                    ProxyConnectionIF proxyConnection, String reason,
0776:                    boolean merciful) {
0777:                if (proxyConnection.setStatus(
0778:                        ProxyConnectionIF.STATUS_AVAILABLE,
0779:                        ProxyConnectionIF.STATUS_OFFLINE)) {
0780:                    if (proxyConnection.setStatus(
0781:                            ProxyConnectionIF.STATUS_OFFLINE,
0782:                            ProxyConnectionIF.STATUS_NULL)) {
0783:                        // It is.  Expire it now .
0784:                        expireProxyConnection(proxyConnection, reason,
0785:                                REQUEST_EXPIRY);
0786:                    }
0787:                } else {
0788:                    // Oh no, it's in use.
0789:
0790:                    if (merciful) {
0791:                        //Never mind, we'll mark it for expiry
0792:                        // next time it is available.  This will happen in the
0793:                        // putConnection() method.
0794:                        proxyConnection.markForExpiry(reason);
0795:                        if (log.isDebugEnabled()) {
0796:                            log.debug(displayStatistics()
0797:                                    + " - #"
0798:                                    + FormatHelper
0799:                                            .formatMediumNumber(proxyConnection
0800:                                                    .getId())
0801:                                    + " marked for expiry.");
0802:                        }
0803:                    } else {
0804:                        // So? Kill, kill, kill
0805:
0806:                        // We have to make sure it's null first.
0807:                        expireProxyConnection(proxyConnection, reason,
0808:                                FORCE_EXPIRY);
0809:                    }
0810:
0811:                } // END if (proxyConnection.setOffline())
0812:            }
0813:
0814:            protected void registerRemovedConnection(int status) {
0815:                prototyper.connectionRemoved();
0816:                connectionCountByState[status]--;
0817:            }
0818:
0819:            /**
0820:             * You should {@link #acquireConnectionStatusWriteLock acquire} a write lock
0821:             * before calling this method
0822:             * @param oldStatus so we know which count to decrement
0823:             * @param newStatus so we know which count to increment
0824:             */
0825:            protected void changeStatus(int oldStatus, int newStatus) {
0826:                // LOG.debug("About to change status");
0827:                connectionCountByState[oldStatus]--;
0828:                connectionCountByState[newStatus]++;
0829:                // LOG.debug("Changing status from " + oldStatus + " to " + newStatus);
0830:                // Check to see if shutdown is waiting for all connections to become
0831:                // non-active
0832:                if (shutdownThread != null
0833:                        && connectionCountByState[ProxyConnectionIF.STATUS_ACTIVE] == 0) {
0834:                    synchronized (shutdownThread) {
0835:                        shutdownThread.notify();
0836:                    }
0837:                }
0838:
0839:            }
0840:
0841:            public long getConnectionsServedCount() {
0842:                return connectionsServedCount;
0843:            }
0844:
0845:            public long getConnectionsRefusedCount() {
0846:                return connectionsRefusedCount;
0847:            }
0848:
0849:            protected ConnectionPoolDefinition getDefinition() {
0850:                return definition;
0851:            }
0852:
0853:            /**
0854:             * Changes both the way that any new connections will be made, and the behaviour of the pool. Consider
0855:             * calling expireAllConnections() if you're in a hurry.
0856:             */
0857:            protected synchronized void setDefinition(
0858:                    ConnectionPoolDefinition definition)
0859:                    throws ProxoolException {
0860:                this .definition = definition;
0861:
0862:                try {
0863:                    Class.forName(definition.getDriver());
0864:                } catch (ClassNotFoundException e) {
0865:                    log.error("Couldn't load class " + definition.getDriver(),
0866:                            e);
0867:                    throw new ProxoolException("Couldn't load class "
0868:                            + definition.getDriver());
0869:                } catch (NullPointerException e) {
0870:                    log.error("Definition did not contain driver", e);
0871:                    throw new ProxoolException(
0872:                            "Definition did not contain driver");
0873:                }
0874:
0875:            }
0876:
0877:            /**
0878:             * @deprecated use {@link #addStateListener(StateListenerIF)} instead.
0879:             */
0880:            public void setStateListener(StateListenerIF stateListener) {
0881:                addStateListener(stateListener);
0882:            }
0883:
0884:            public void addStateListener(StateListenerIF stateListener) {
0885:                this .compositeStateListener.addListener(stateListener);
0886:            }
0887:
0888:            public boolean removeStateListener(StateListenerIF stateListener) {
0889:                return this .compositeStateListener
0890:                        .removeListener(stateListener);
0891:            }
0892:
0893:            /**
0894:             * @deprecated use {@link #addConnectionListener(ConnectionListenerIF)} instead.
0895:             */
0896:            public void setConnectionListener(
0897:                    ConnectionListenerIF connectionListener) {
0898:                addConnectionListener(connectionListener);
0899:            }
0900:
0901:            public void addConnectionListener(
0902:                    ConnectionListenerIF connectionListener) {
0903:                this .compositeConnectionListener
0904:                        .addListener(connectionListener);
0905:            }
0906:
0907:            public boolean removeConnectionListener(
0908:                    ConnectionListenerIF connectionListener) {
0909:                return this .compositeConnectionListener
0910:                        .removeListener(connectionListener);
0911:            }
0912:
0913:            /** Call the onBirth() method on each StateListenerIF . */
0914:            protected void onBirth(Connection connection) throws SQLException {
0915:                this .compositeConnectionListener.onBirth(connection);
0916:            }
0917:
0918:            /** Call the onDeath() method on each StateListenerIF . */
0919:            protected void onDeath(Connection connection) throws SQLException {
0920:                this .compositeConnectionListener.onDeath(connection);
0921:            }
0922:
0923:            /** Call the onExecute() method on each StateListenerIF . */
0924:            protected void onExecute(String command, long elapsedTime,
0925:                    Exception exception) throws SQLException {
0926:                if (exception == null) {
0927:                    this .compositeConnectionListener.onExecute(command,
0928:                            elapsedTime);
0929:                } else {
0930:                    this .compositeConnectionListener.onFail(command, exception);
0931:                }
0932:            }
0933:
0934:            /**
0935:             * Is there a {@link ConnectionListenerIF listener} for connections
0936:             * @return true if there is a listener registered.
0937:             */
0938:            protected boolean isConnectionListenedTo() {
0939:                return !compositeConnectionListener.isEmpty();
0940:            }
0941:
0942:            public String toString() {
0943:                return getDefinition().toString();
0944:            }
0945:
0946:            public int getUpState() {
0947:                return upState;
0948:            }
0949:
0950:            public void setUpState(int upState) {
0951:                if (this .upState != upState) {
0952:                    compositeStateListener.upStateChanged(upState);
0953:                    this .upState = upState;
0954:                }
0955:            }
0956:
0957:            protected Collection getConnectionInfos() {
0958:                Collection cis = null;
0959:                cis = new TreeSet();
0960:                Iterator i = proxyConnections.iterator();
0961:                while (i.hasNext()) {
0962:                    ConnectionInfoIF connectionInfo = (ConnectionInfoIF) i
0963:                            .next();
0964:                    ConnectionInfo ci = new ConnectionInfo();
0965:                    ci.setAge(connectionInfo.getAge());
0966:                    ci.setBirthDate(connectionInfo.getBirthDate());
0967:                    ci.setId(connectionInfo.getId());
0968:                    ci.setMark(connectionInfo.getMark());
0969:                    ci.setRequester(connectionInfo.getRequester());
0970:                    ci.setStatus(connectionInfo.getStatus());
0971:                    ci.setTimeLastStartActive(connectionInfo
0972:                            .getTimeLastStartActive());
0973:                    ci.setTimeLastStopActive(connectionInfo
0974:                            .getTimeLastStopActive());
0975:                    ci.setDelegateUrl(connectionInfo.getDelegateUrl());
0976:                    ci.setProxyHashcode(connectionInfo.getProxyHashcode());
0977:                    ci
0978:                            .setDelegateHashcode(connectionInfo
0979:                                    .getDelegateHashcode());
0980:                    String[] sqlCalls = connectionInfo.getSqlCalls();
0981:                    for (int j = 0; j < sqlCalls.length; j++) {
0982:                        ci.addSqlCall(sqlCalls[j]);
0983:                    }
0984:                    cis.add(ci);
0985:                }
0986:                return cis;
0987:            }
0988:
0989:            /**
0990:             * Manually expire a connection.
0991:             * @param id the id of the connection to kill
0992:             * @param forceExpiry use true to expire even if it is in use
0993:             * @return true if the connection was found and expired, else false
0994:             */
0995:            public boolean expireConnection(long id, boolean forceExpiry) {
0996:                boolean success = false;
0997:                ProxyConnection proxyConnection = null;
0998:
0999:                // We need to look at all the connections, but we don't want to keep looping round forever
1000:                for (int connectionsTried = 0; connectionsTried < proxyConnections
1001:                        .size(); connectionsTried++) {
1002:                    // By doing this in a try/catch we avoid needing to synch on the size().  We need to do be
1003:                    // able to cope with connections being removed whilst we are going round this loop
1004:                    try {
1005:                        proxyConnection = (ProxyConnection) proxyConnections
1006:                                .get(nextAvailableConnection);
1007:                    } catch (IndexOutOfBoundsException e) {
1008:                        nextAvailableConnection = 0;
1009:                        proxyConnection = (ProxyConnection) proxyConnections
1010:                                .get(nextAvailableConnection);
1011:                    }
1012:
1013:                    if (proxyConnection.getId() == id) {
1014:                        // This is the one
1015:                        proxyConnection.setStatus(
1016:                                ProxyConnectionIF.STATUS_AVAILABLE,
1017:                                ProxyConnectionIF.STATUS_OFFLINE);
1018:                        proxyConnection.setStatus(
1019:                                ProxyConnectionIF.STATUS_OFFLINE,
1020:                                ProxyConnectionIF.STATUS_NULL);
1021:                        removeProxyConnection(proxyConnection,
1022:                                "it was manually killed", forceExpiry, true);
1023:                        success = true;
1024:                        break;
1025:                    }
1026:
1027:                    nextAvailableConnection++;
1028:                }
1029:
1030:                if (!success) {
1031:                    if (log.isDebugEnabled()) {
1032:                        log.debug(displayStatistics()
1033:                                + " - couldn't find "
1034:                                + FormatHelper
1035:                                        .formatMediumNumber(proxyConnection
1036:                                                .getId())
1037:                                + " and I've just been asked to expire it");
1038:                    }
1039:                }
1040:
1041:                return success;
1042:            }
1043:
1044:            public Log getLog() {
1045:                return log;
1046:            }
1047:
1048:            /**
1049:             * {@link ConnectionResetter#initialise Initialises} the ConnectionResetter.
1050:             * @param connection sample Connection to use for default values
1051:             */
1052:            protected void initialiseConnectionResetter(Connection connection) {
1053:                connectionResetter.initialise(connection);
1054:            }
1055:
1056:            /**
1057:             * {@link ConnectionResetter#reset Resets} a Connection to its
1058:             * original state.
1059:             * @param connection the one to reset
1060:             */
1061:            protected boolean resetConnection(Connection connection, String id) {
1062:                return connectionResetter.reset(connection, id);
1063:            }
1064:
1065:            /**
1066:             * @see ConnectionPoolStatisticsIF#getDateStarted
1067:             */
1068:            public Date getDateStarted() {
1069:                return dateStarted;
1070:            }
1071:
1072:            /**
1073:             * Get the admin for this pool
1074:             * @return admin
1075:             */
1076:            protected Admin getAdmin() {
1077:                return admin;
1078:            }
1079:
1080:            protected boolean isLocked() {
1081:                return locked;
1082:            }
1083:
1084:            protected void lock() {
1085:                locked = true;
1086:            }
1087:
1088:            protected void unlock() {
1089:                locked = false;
1090:            }
1091:
1092:            /**
1093:             * Call this if you want to do something important to the pool. Like shut it down.
1094:             * @throws InterruptedException if we couldn't
1095:             */
1096:            protected void acquirePrimaryReadLock() throws InterruptedException {
1097:                //        if (log.isDebugEnabled()) {
1098:                //            try {
1099:                //                throw new RuntimeException("TRACE ONLY");
1100:                //            } catch (RuntimeException e) {
1101:                //                log.debug("About to acquire primary read lock", e);
1102:                //            }
1103:                //            // log.debug("About to acquire primary read lock");
1104:                //        }
1105:                primaryReadWriteLock.readLock().acquire();
1106:                //        if (log.isDebugEnabled()) {
1107:                //            try {
1108:                //                throw new RuntimeException("TRACE ONLY");
1109:                //            } catch (RuntimeException e) {
1110:                //                log.debug("Acquired primary read lock", e);
1111:                //            }
1112:                //            //log.debug("Acquired primary read lock");
1113:                //        }
1114:            }
1115:
1116:            /**
1117:             * @see #acquirePrimaryReadLock
1118:             */
1119:            protected void releasePrimaryReadLock() {
1120:                //        try {
1121:                //            throw new RuntimeException("TRACE ONLY");
1122:                //        } catch (RuntimeException e) {
1123:                //            log.debug("Released primary read lock", e);
1124:                //        }
1125:                //log.debug("Released primary read lock");
1126:                primaryReadWriteLock.readLock().release();
1127:            }
1128:
1129:            /**
1130:             * Call this everytime you build a connection. It ensures that we're not
1131:             * trying to shutdown the pool whilst we are building a connection. So you
1132:             * should check that the pool is still {@link #isConnectionPoolUp up}.
1133:             * @throws InterruptedException if there was a problem.
1134:             */
1135:            protected void acquirePrimaryWriteLock()
1136:                    throws InterruptedException {
1137:                //        boolean success = false;
1138:                //        try {
1139:                //            if (log.isDebugEnabled()) {
1140:                //                try {
1141:                //                    throw new RuntimeException("TRACE ONLY");
1142:                //                } catch (RuntimeException e) {
1143:                //                    log.debug("About to acquire primary write lock", e);
1144:                //                }
1145:                //                //log.debug("About to acquire primary write lock");
1146:                //            }
1147:                primaryReadWriteLock.writeLock().acquire();
1148:                //            success = true;
1149:                //            if (log.isDebugEnabled()) {
1150:                //                try {
1151:                //                    throw new RuntimeException("TRACE ONLY");
1152:                //                } catch (RuntimeException e) {
1153:                //                    log.debug("Acquired primary write lock", e);
1154:                //                }
1155:                //                //log.debug("Acquired primary write lock");
1156:                //            }
1157:                //        } finally {
1158:                //            if (log.isDebugEnabled() && !success) {
1159:                //                try {
1160:                //                    throw new RuntimeException("TRACE ONLY");
1161:                //                } catch (RuntimeException e) {
1162:                //                    log.debug("Failed to acquire primary write lock", e);
1163:                //                }
1164:                //                //log.debug("Failed to acquire primary write lock");
1165:                //            }
1166:                //        }
1167:            }
1168:
1169:            /**
1170:             * @see #acquirePrimaryReadLock
1171:             */
1172:            protected void releasePrimaryWriteLock() {
1173:                primaryReadWriteLock.writeLock().release();
1174:                //        try {
1175:                //            throw new RuntimeException("TRACE ONLY");
1176:                //        } catch (RuntimeException e) {
1177:                //            log.debug("Released primary write lock", e);
1178:                //        }
1179:                //log.debug("Released primary write lock");
1180:            }
1181:
1182:            /**
1183:             * Is the pool up?
1184:             * @return false is the connection pool has been {@link #shutdown shutdown}
1185:             * (or is in the process of being shutdown).
1186:             */
1187:            protected boolean isConnectionPoolUp() {
1188:                return connectionPoolUp;
1189:            }
1190:
1191:            protected static final boolean FORCE_EXPIRY = true;
1192:
1193:            protected static final boolean REQUEST_EXPIRY = false;
1194:
1195:            /**
1196:             * The time (in milliseconds) that we last refused a connection
1197:             * @return timeOfLastRefusal
1198:             */
1199:            protected long getTimeOfLastRefusal() {
1200:                return timeOfLastRefusal;
1201:            }
1202:
1203:            protected void acquireConnectionStatusWriteLock() {
1204:                try {
1205:                    //            try {
1206:                    //                throw new RuntimeException("TRACE ONLY");
1207:                    //            } catch (RuntimeException e) {
1208:                    //                LOG.debug("About to acquire connectionStatus write lock", e);
1209:                    //            }
1210:                    connectionStatusReadWriteLock.writeLock().acquire();
1211:                    //            try {
1212:                    //                throw new RuntimeException("TRACE ONLY");
1213:                    //            } catch (RuntimeException e) {
1214:                    //                LOG.debug("Acquired connectionStatus write lock", e);
1215:                    //            }
1216:                } catch (InterruptedException e) {
1217:                    log
1218:                            .error(
1219:                                    "Couldn't acquire connectionStatus write lock",
1220:                                    e);
1221:                }
1222:            }
1223:
1224:            protected void releaseConnectionStatusWriteLock() {
1225:                connectionStatusReadWriteLock.writeLock().release();
1226:                //        try {
1227:                //            throw new RuntimeException("TRACE ONLY");
1228:                //        } catch (RuntimeException e) {
1229:                //            LOG.debug("Released connectionStatus write lock", e);
1230:                //        }
1231:            }
1232:
1233:            protected void acquireConnectionStatusReadLock() {
1234:                try {
1235:                    connectionStatusReadWriteLock.readLock().acquire();
1236:                } catch (InterruptedException e) {
1237:                    log.error("Couldn't acquire connectionStatus read lock", e);
1238:                }
1239:            }
1240:
1241:            protected boolean attemptConnectionStatusReadLock(long msecs) {
1242:                try {
1243:                    return connectionStatusReadWriteLock.readLock().attempt(
1244:                            msecs);
1245:                } catch (InterruptedException e) {
1246:                    log.error("Couldn't acquire connectionStatus read lock", e);
1247:                    return false;
1248:                }
1249:            }
1250:
1251:            protected void releaseConnectionStatusReadLock() {
1252:                connectionStatusReadWriteLock.readLock().release();
1253:                //        LOG.debug("Released connectionStatus read lock");
1254:            }
1255:
1256:            protected Prototyper getPrototyper() {
1257:                return prototyper;
1258:            }
1259:
1260:            public long getConnectionCount() {
1261:                return getPrototyper().getConnectionCount();
1262:            }
1263:        }
1264:
1265:        /*
1266:         Revision history:
1267:         $Log: ConnectionPool.java,v $
1268:         Revision 1.84  2006/03/23 11:44:57  billhorsman
1269:         More information when quickly refusing
1270:
1271:         Revision 1.83  2006/01/18 14:40:01  billhorsman
1272:         Unbundled Jakarta's Commons Logging.
1273:
1274:         Revision 1.82  2005/10/07 08:19:05  billhorsman
1275:         New sqlCalls gives list of SQL calls rather than just he most recent (for when a connection makes more than one call before being returned to the pool)
1276:
1277:         Revision 1.81  2005/10/02 12:32:02  billhorsman
1278:         Make connectionCount available to statistics
1279:
1280:         Revision 1.80  2005/09/26 09:54:14  billhorsman
1281:         Avoid suspected deadlock when getting a detailed snapshot. Only attempt to get the concurrent lock for 10 seconds before giving up.
1282:
1283:         Revision 1.79  2005/05/04 16:26:31  billhorsman
1284:         Only add a new connection if the definition matches
1285:
1286:         Revision 1.78  2004/03/25 22:02:15  brenuart
1287:         First step towards pluggable ConnectionBuilderIF & ConnectionValidatorIF.
1288:         Include some minor refactoring that lead to deprecation of some PrototyperController methods.
1289:
1290:         Revision 1.76  2004/02/23 17:47:32  billhorsman
1291:         Improved message that gets logged if the state change of a connection fails.
1292:
1293:         Revision 1.75  2004/02/23 17:38:58  billhorsman
1294:         Improved message that gets logged if you close a connection more than once.
1295:
1296:         Revision 1.74  2004/02/12 13:02:17  billhorsman
1297:         Catch correct exception when iterating through list.
1298:
1299:         Revision 1.73  2003/12/09 18:54:55  billhorsman
1300:         Make closure of statement during connection test more robust - credit to John Hume
1301:
1302:         Revision 1.72  2003/11/04 13:52:01  billhorsman
1303:         Fixed warning message
1304:
1305:         Revision 1.71  2003/10/30 00:11:15  billhorsman
1306:         Debug info and error logged if unsuccessful attempt to put connection back in pool. Plus connectioninfo comparator changed
1307:
1308:         Revision 1.70  2003/09/30 18:39:08  billhorsman
1309:         New test-before-use, test-after-use and fatal-sql-exception-wrapper-class properties.
1310:
1311:         Revision 1.69  2003/09/30 07:50:04  billhorsman
1312:         Smarter throwing of caught SQLExceptions without wrapping them up inside another (and losing the stack trace)
1313:
1314:         Revision 1.68  2003/09/20 17:04:06  billhorsman
1315:         Fix for incorrect OFFLINE count when house keeper removed a connection if the test SQL failed. This
1316:         meant that the offline count went negative. The only consequence of that is that the logs look funny.
1317:
1318:         Revision 1.67  2003/08/30 14:54:04  billhorsman
1319:         Checkstyle
1320:
1321:         Revision 1.66  2003/04/10 08:23:54  billhorsman
1322:         removed very frequent debug
1323:
1324:         Revision 1.65  2003/03/11 23:58:04  billhorsman
1325:         fixed deadlock on connection expiry
1326:
1327:         Revision 1.64  2003/03/11 14:51:49  billhorsman
1328:         more concurrency fixes relating to snapshots
1329:
1330:         Revision 1.63  2003/03/11 01:16:29  billhorsman
1331:         removed misleasing debug
1332:
1333:         Revision 1.62  2003/03/11 00:32:13  billhorsman
1334:         fixed negative timeout
1335:
1336:         Revision 1.61  2003/03/10 23:39:51  billhorsman
1337:         shutdown is now notified when active count reaches
1338:         zero
1339:
1340:         Revision 1.60  2003/03/10 16:26:35  billhorsman
1341:         removed debug traces
1342:
1343:         Revision 1.59  2003/03/10 15:26:44  billhorsman
1344:         refactoringn of concurrency stuff (and some import
1345:         optimisation)
1346:
1347:         Revision 1.58  2003/03/05 18:42:32  billhorsman
1348:         big refactor of prototyping and house keeping to
1349:         drastically reduce the number of threads when using
1350:         many pools
1351:
1352:         Revision 1.57  2003/03/03 16:06:44  billhorsman
1353:         name house keeper and prototyper threads now includes alias
1354:
1355:         Revision 1.56  2003/03/03 11:11:57  billhorsman
1356:         fixed licence
1357:
1358:         Revision 1.55  2003/02/28 18:08:55  billhorsman
1359:         OVERLOAD state is now triggered immediately rather
1360:         than waiting for house keeper
1361:
1362:         Revision 1.54  2003/02/28 10:10:25  billhorsman
1363:         on death now gets called for connections killed during shutdown
1364:
1365:         Revision 1.53  2003/02/26 16:05:52  billhorsman
1366:         widespread changes caused by refactoring the way we
1367:         update and redefine pool definitions.
1368:
1369:         Revision 1.52  2003/02/26 12:57:30  billhorsman
1370:         added TO DO
1371:
1372:         Revision 1.51  2003/02/19 23:46:10  billhorsman
1373:         renamed monitor package to admin
1374:
1375:         Revision 1.50  2003/02/19 23:07:46  billhorsman
1376:         state changes are now only calculated every time the house
1377:         keeper runs, but it's more accurate
1378:
1379:         Revision 1.49  2003/02/19 22:38:33  billhorsman
1380:         fatal sql exception causes house keeper to run
1381:         immediately
1382:
1383:         Revision 1.48  2003/02/18 16:49:59  chr32
1384:         Added possibility to remove connection and state listeners.
1385:
1386:         Revision 1.47  2003/02/12 12:27:16  billhorsman
1387:         log proxy hashcode too
1388:
1389:         Revision 1.46  2003/02/07 17:26:04  billhorsman
1390:         deprecated removeAllConnectionPools in favour of
1391:         shutdown (and dropped unreliable finalize() method)
1392:
1393:         Revision 1.45  2003/02/07 14:19:01  billhorsman
1394:         fixed deprecated use of debugLevel property
1395:
1396:         Revision 1.44  2003/02/07 14:16:46  billhorsman
1397:         support for StatisticsListenerIF
1398:
1399:         Revision 1.43  2003/02/07 10:27:47  billhorsman
1400:         change in shutdown procedure to allow re-registration
1401:
1402:         Revision 1.42  2003/02/07 01:48:15  chr32
1403:         Started using new composite listeners.
1404:
1405:         Revision 1.41  2003/02/06 17:41:04  billhorsman
1406:         now uses imported logging
1407:
1408:         Revision 1.40  2003/02/04 17:18:30  billhorsman
1409:         move ShutdownHook init code
1410:
1411:         Revision 1.39  2003/02/04 15:59:50  billhorsman
1412:         finalize now shuts down StatsRoller timer
1413:
1414:         Revision 1.38  2003/02/02 23:35:48  billhorsman
1415:         removed ReloadMonitor to remove use of System properties
1416:
1417:         Revision 1.37  2003/01/31 16:53:16  billhorsman
1418:         checkstyle
1419:
1420:         Revision 1.36  2003/01/31 11:49:28  billhorsman
1421:         use Admin instead of Stats
1422:
1423:         Revision 1.35  2003/01/31 00:20:05  billhorsman
1424:         statistics is now a string to allow multiple,
1425:         comma-delimited values (plus better logging of errors
1426:         during destruction)
1427:
1428:         Revision 1.34  2003/01/30 17:22:21  billhorsman
1429:         add statistics support
1430:
1431:         Revision 1.33  2003/01/27 18:26:35  billhorsman
1432:         refactoring of ProxyConnection and ProxyStatement to
1433:         make it easier to write JDK 1.2 patch
1434:
1435:         Revision 1.32  2003/01/15 14:51:40  billhorsman
1436:         checkstyle
1437:
1438:         Revision 1.31  2003/01/15 12:01:37  billhorsman
1439:         added getDateStarted()
1440:
1441:         Revision 1.30  2003/01/15 00:07:43  billhorsman
1442:         now uses FastArrayList instead of Vector for thread safe
1443:         improvements
1444:
1445:         Revision 1.29  2002/12/18 12:16:22  billhorsman
1446:         double checking of connection state counts
1447:
1448:         Revision 1.28  2002/12/17 17:15:39  billhorsman
1449:         Better synchronization of status stuff
1450:
1451:         Revision 1.27  2002/12/17 16:52:51  billhorsman
1452:         synchronize part of removeProxyConnection to avoid
1453:         possible bug where connection by status count drifts.
1454:
1455:         Revision 1.26  2002/12/12 12:28:34  billhorsman
1456:         just in case: changed == 0 to < 1
1457:
1458:         Revision 1.25  2002/12/12 10:48:47  billhorsman
1459:         checkstyle
1460:
1461:         Revision 1.24  2002/12/03 12:24:00  billhorsman
1462:         fixed fatal sql exception
1463:
1464:         Revision 1.23  2002/11/12 20:24:12  billhorsman
1465:         checkstyle
1466:
1467:         Revision 1.22  2002/11/12 20:18:23  billhorsman
1468:         Made connection resetter a bit more friendly. Now, if it encounters any problems during
1469:         reset then that connection is thrown away. This is going to cause you problems if you
1470:         always close connections in an unstable state (e.g. with transactions open. But then
1471:         again, it's better to know about that as soon as possible, right?
1472:
1473:         Revision 1.21  2002/11/09 15:48:55  billhorsman
1474:         new isConnectionListenedTo() to stop unnecessary processing
1475:         if nobody is listening
1476:
1477:         Revision 1.20  2002/11/08 18:03:50  billhorsman
1478:         when connections are closed because they have been
1479:         active for too long then a log message is written
1480:         of level WARN, and it includes the name of the
1481:         thread responsible (reminder, name your threads).
1482:
1483:         Revision 1.19  2002/11/07 19:31:25  billhorsman
1484:         added sanity check against suspected situation where you
1485:         can make more connections than the maximumConnectionCount
1486:
1487:         Revision 1.18  2002/11/07 19:17:55  billhorsman
1488:         removed obsolete method
1489:
1490:         Revision 1.17  2002/11/06 20:27:30  billhorsman
1491:         supports the ConnectionResetter
1492:
1493:         Revision 1.16  2002/11/05 21:24:18  billhorsman
1494:         cosmetic: changed format of statistics dumped to log to make it less confusing for locales that use a space separator for thousands
1495:
1496:         Revision 1.15  2002/11/02 13:57:33  billhorsman
1497:         checkstyle
1498:
1499:         Revision 1.14  2002/10/30 21:19:17  billhorsman
1500:         make use of ProxyFactory
1501:
1502:         Revision 1.13  2002/10/29 23:00:33  billhorsman
1503:         fixed sign error in prototyper (that meant that protoyping never happened)
1504:
1505:         Revision 1.12  2002/10/29 22:58:22  billhorsman
1506:         added connection hashcode to debug
1507:
1508:         Revision 1.11  2002/10/28 19:44:03  billhorsman
1509:         small change to cleanup log
1510:
1511:         Revision 1.10  2002/10/27 13:02:45  billhorsman
1512:         change to prototyper logic to make it clearer (but no functional change)
1513:
1514:         Revision 1.9  2002/10/27 12:07:45  billhorsman
1515:         fix bug where prototyper kept making connections up to maximum. Log now gives reason why connection was prototyped. Fix bug where definition with no properties was not allowed (it is now).
1516:
1517:         Revision 1.8  2002/10/25 10:12:52  billhorsman
1518:         Improvements and fixes to the way connection pools close down. Including new ReloadMonitor to detect when a class is reloaded. Much better logging too.
1519:
1520:         Revision 1.7  2002/10/24 17:25:20  billhorsman
1521:         cleaned up logging and made it more informative
1522:
1523:         Revision 1.6  2002/10/23 21:04:36  billhorsman
1524:         checkstyle fixes (reduced max line width and lenient naming convention
1525:
1526:         Revision 1.5  2002/10/16 11:46:23  billhorsman
1527:         removed obsolete cleanupClob method and made onBirth call failsafe
1528:
1529:         Revision 1.4  2002/09/19 10:33:57  billhorsman
1530:         added ProxyConnection#toString
1531:
1532:         Revision 1.3  2002/09/18 13:48:56  billhorsman
1533:         checkstyle and doc
1534:
1535:         Revision 1.2  2002/09/13 12:13:50  billhorsman
1536:         added debug and fixed ClassCastException during housekeeping
1537:
1538:         Revision 1.1.1.1  2002/09/13 08:12:55  billhorsman
1539:         new
1540:
1541:         Revision 1.13  2002/08/24 19:57:15  billhorsman
1542:         checkstyle changes
1543:
1544:         Revision 1.12  2002/08/24 19:44:13  billhorsman
1545:         fixes for logging
1546:
1547:         Revision 1.11  2002/07/10 16:14:47  billhorsman
1548:         widespread layout changes and move constants into ProxoolConstants
1549:
1550:         Revision 1.10  2002/07/04 09:05:36  billhorsmaNn
1551:         Fixes
1552:
1553:         Revision 1.9  2002/07/02 11:19:08  billhorsman
1554:         layout code and imports
1555:
1556:         Revision 1.8  2002/07/02 11:14:26  billhorsman
1557:         added test (andbug fixes) for FileLogger
1558:
1559:         Revision 1.7  2002/07/02 08:39:55  billhorsman
1560:         getConnectionInfos now returns a Collection instead of an array. displayStatistics is
1561:         now available to ProxoolFacade. Prototyper no longer tries to make connections
1562:         when maximum is reached (stopping unnecessary log messages). bug fix.
1563:
1564:         Revision 1.6  2002/06/28 11:19:47  billhorsman
1565:         improved doc
1566:
1567:         */
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.