Source Code Cross Referenced for JDBCConnectionPool.java in  » Testing » PolePosition-0.20 » com » versant » core » jdbc » conn » 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 » Testing » PolePosition 0.20 » com.versant.core.jdbc.conn 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright (c) 1998 - 2005 Versant Corporation
0003:         * All rights reserved. This program and the accompanying materials
0004:         * are made available under the terms of the Eclipse Public License v1.0
0005:         * which accompanies this distribution, and is available at
0006:         * http://www.eclipse.org/legal/epl-v10.html
0007:         *
0008:         * Contributors:
0009:         * Versant Corporation - initial API and implementation
0010:         */
0011:        package com.versant.core.jdbc.conn;
0012:
0013:        import com.versant.core.common.Debug;
0014:        import com.versant.core.jdo.PoolStatus;
0015:        import com.versant.core.metric.BaseMetric;
0016:        import com.versant.core.metric.Metric;
0017:        import com.versant.core.metric.PercentageMetric;
0018:        import com.versant.core.logging.LogEventStore;
0019:        import com.versant.core.jdbc.JdbcConfig;
0020:        import com.versant.core.jdbc.logging.JdbcConnectionEvent;
0021:        import com.versant.core.jdbc.logging.JdbcLogEvent;
0022:        import com.versant.core.jdbc.logging.JdbcPoolEvent;
0023:        import com.versant.core.jdbc.JdbcConnectionSource;
0024:        import com.versant.core.jdbc.sql.SqlDriver;
0025:        import com.versant.core.util.BeanUtils;
0026:
0027:        import java.sql.*;
0028:        import java.util.*;
0029:
0030:        import com.versant.core.common.BindingSupportImpl;
0031:        import com.versant.core.metric.HasMetrics;
0032:
0033:        /**
0034:         * JDBC connection pool with a PreparedStatement cache for each connection.
0035:         *
0036:         * @see PooledConnection
0037:         */
0038:        public final class JDBCConnectionPool implements  Runnable,
0039:                JdbcConnectionSource, HasMetrics {
0040:
0041:            private final Driver jdbcDriver;
0042:            private final SqlDriver sqlDriver;
0043:            private final Properties props;
0044:            private final String url;
0045:            private final LogEventStore pes;
0046:            private boolean clearBatch;
0047:            private final boolean waitForConOnStartup;
0048:            private boolean jdbcDisablePsCache;
0049:            private int psCacheMax;
0050:            private int maxActive;
0051:            private int maxIdle;
0052:            private int minIdle;
0053:            private int reserved;
0054:            private final boolean testOnAlloc;
0055:            private final boolean testOnReturn;
0056:            private final boolean testOnException;
0057:            private boolean testWhenIdle;
0058:            private String initSQL;
0059:            private boolean commitAfterInitSQL;
0060:            private String validateSQL;
0061:            private final int retryIntervalMs;
0062:            private final int retryCount;
0063:            private boolean closed;
0064:            private int conTimeout;
0065:            private int testInterval;
0066:            private boolean blockWhenFull;
0067:            private int maxConAge;
0068:            private int isolationLevel;
0069:
0070:            private PooledConnection idleHead; // next con to be given out
0071:            private PooledConnection idleTail; // last con returned
0072:            private PooledConnection idleHeadAC; // next autocommit con to be given out
0073:            private PooledConnection idleTailAC; // last autocommit con returned
0074:            private int idleCount;
0075:
0076:            private PooledConnection activeHead; // most recently allocated con
0077:            private PooledConnection activeTail; // least recently allocated con
0078:            private int activeCount;
0079:
0080:            private Thread cleanupThread;
0081:            private long timeLastTest = System.currentTimeMillis();
0082:
0083:            private Properties userProps;
0084:
0085:            private BaseMetric metricActive;
0086:            private BaseMetric metricIdle;
0087:            private BaseMetric metricMaxActive;
0088:            private BaseMetric metricCreated;
0089:            private BaseMetric metricClosed;
0090:            private BaseMetric metricAllocated;
0091:            private BaseMetric metricValidated;
0092:            private BaseMetric metricBad;
0093:            private BaseMetric metricTimedOut;
0094:            private BaseMetric metricExpired;
0095:            private BaseMetric metricWait;
0096:            private BaseMetric metricFull;
0097:
0098:            private int createdCount;
0099:            private int closedCount;
0100:            private int allocatedCount;
0101:            private int validatedCount;
0102:            private int badCount;
0103:            private int timedOutCount;
0104:            private int waitCount;
0105:            private int fullCount;
0106:            private int expiredCount;
0107:
0108:            private static final String CAT_POOL = "Con Pool";
0109:
0110:            /**
0111:             * Create the pool. Note that changes to jdbcConfig have no effect on the
0112:             * pool after construction i.e. fields in jdbcConfig are copied not
0113:             * referenced. The sqlDriver parameter is used to customize the pool
0114:             * to workaround bugs and so on in the JDBC driver or database. It can
0115:             * be null.
0116:             */
0117:            public JDBCConnectionPool(JdbcConfig jdbcConfig, LogEventStore pes,
0118:                    Driver jdbcDriver, SqlDriver sqlDriver) {
0119:                this .pes = pes;
0120:                this .jdbcDriver = jdbcDriver;
0121:                this .sqlDriver = sqlDriver;
0122:
0123:                url = jdbcConfig.url;
0124:                props = new Properties();
0125:                if (jdbcConfig.user != null) {
0126:                    props.put("user", jdbcConfig.user);
0127:                }
0128:                if (jdbcConfig.password != null) {
0129:                    props.put("password", jdbcConfig.password);
0130:                }
0131:                if (jdbcConfig.properties != null) {
0132:                    BeanUtils.parseProperties(jdbcConfig.properties, props);
0133:                }
0134:
0135:                //create a props for user
0136:                userProps = new Properties();
0137:                if (jdbcConfig.user != null) {
0138:                    userProps.put("user", jdbcConfig.user);
0139:                }
0140:                userProps.put("url", url);
0141:                userProps.put("driver", jdbcDriver.getClass().getName());
0142:                if (jdbcConfig.properties != null) {
0143:                    BeanUtils.parseProperties(jdbcConfig.properties, userProps);
0144:                }
0145:
0146:                jdbcDisablePsCache = jdbcConfig.jdbcDisablePsCache;
0147:                psCacheMax = jdbcConfig.psCacheMax;
0148:                waitForConOnStartup = jdbcConfig.waitForConOnStartup;
0149:                maxActive = jdbcConfig.maxActive;
0150:                maxIdle = jdbcConfig.maxIdle;
0151:                minIdle = jdbcConfig.minIdle;
0152:                reserved = jdbcConfig.reserved;
0153:                testOnAlloc = jdbcConfig.testOnAlloc;
0154:                testOnReturn = jdbcConfig.testOnRelease;
0155:                testOnException = jdbcConfig.testOnException;
0156:                testWhenIdle = jdbcConfig.testWhenIdle;
0157:                retryIntervalMs = jdbcConfig.retryIntervalMs > 0 ? jdbcConfig.retryIntervalMs
0158:                        : 100;
0159:                retryCount = jdbcConfig.retryCount;
0160:                conTimeout = jdbcConfig.conTimeout;
0161:                testInterval = jdbcConfig.testInterval;
0162:                blockWhenFull = jdbcConfig.blockWhenFull;
0163:                maxConAge = jdbcConfig.maxConAge;
0164:                isolationLevel = jdbcConfig.isolationLevel;
0165:
0166:                setValidateSQL(trimToNull(jdbcConfig.validateSQL));
0167:                setInitSQL(trimToNull(jdbcConfig.initSQL));
0168:
0169:                if (sqlDriver != null) {
0170:                    if (psCacheMax == 0) {
0171:                        psCacheMax = sqlDriver.getDefaultPsCacheMax();
0172:                    }
0173:                    clearBatch = sqlDriver.isClearBatchRequired();
0174:                    if (validateSQL == null) {
0175:                        setValidateSQL(sqlDriver.getConnectionValidateSQL());
0176:                    }
0177:                    if (initSQL == null) {
0178:                        setInitSQL(sqlDriver.getConnectionInitSQL());
0179:                    }
0180:                    if (!sqlDriver.isSetTransactionIsolationLevelSupported()) {
0181:                        isolationLevel = 0;
0182:                    }
0183:                }
0184:
0185:                // sanity check some settings
0186:                if (maxIdle > maxActive)
0187:                    maxIdle = maxActive;
0188:                if (minIdle > maxIdle)
0189:                    minIdle = maxIdle;
0190:            }
0191:
0192:            private String trimToNull(String s) {
0193:                if (s == null) {
0194:                    return null;
0195:                }
0196:                s = s.trim();
0197:                if (s.length() == 0) {
0198:                    return null;
0199:                }
0200:                return s;
0201:            }
0202:
0203:            public void init() {
0204:                if (cleanupThread != null)
0205:                    return;
0206:                cleanupThread = new Thread(this , "VOA Pool " + url);
0207:                cleanupThread.setDaemon(true);
0208:                cleanupThread.setPriority(Thread.MIN_PRIORITY);
0209:                cleanupThread.start();
0210:            }
0211:
0212:            /**
0213:             * Check that we can connect to the database and that the initSQL (if any)
0214:             * works.
0215:             */
0216:            public void check() throws Exception {
0217:                PooledConnection con = null;
0218:                try {
0219:                    if (waitForConOnStartup) {
0220:                        con = createPooledConnection(0, 10000);
0221:                    } else {
0222:                        con = createPooledConnection(-1, 10000);
0223:                    }
0224:                    if (!validateConnection(con)) {
0225:                        throw BindingSupportImpl.getInstance().runtime(
0226:                                "First connection failed validation SQL:\n"
0227:                                        + validateSQL);
0228:                    }
0229:                } finally {
0230:                    if (con != null)
0231:                        destroy(con);
0232:                }
0233:            }
0234:
0235:            /**
0236:             * Create a connection. If this fails then sleep for millis and try again.
0237:             * If retryCount is 0 then retry is done forever, if < 0 then there are
0238:             * no retries.
0239:             */
0240:            private Connection createRealConWithRetry(int retryCount, int millis) {
0241:                for (int n = 0;;) {
0242:                    try {
0243:                        return createRealCon();
0244:                    } catch (RuntimeException e) {
0245:                        if (BindingSupportImpl.getInstance()
0246:                                .isOwnDatastoreException(e)) {
0247:                            if (retryCount < 0
0248:                                    || (retryCount > 0 && ++n > retryCount))
0249:                                throw e;
0250:                            if (pes.isWarning()) {
0251:                                JdbcLogEvent ev = new JdbcLogEvent(0,
0252:                                        JdbcLogEvent.POOL_CON_FAILED, n + " "
0253:                                                + e.toString());
0254:                                ev.updateTotalMs();
0255:                                pes.log(ev);
0256:                            }
0257:                            try {
0258:                                Thread.sleep(millis);
0259:                            } catch (InterruptedException e1) {
0260:                                // ignore the interruption
0261:                            }
0262:                        } else {
0263:                            throw e;
0264:                        }
0265:                    }
0266:                }
0267:            }
0268:
0269:            public int getIsolationLevel() {
0270:                return isolationLevel;
0271:            }
0272:
0273:            /**
0274:             * If isolationLevel != 0 then the isolation level of newly created
0275:             * Connections is set to this.
0276:             *
0277:             * @see Connection#TRANSACTION_READ_COMMITTED etc
0278:             */
0279:            public void setIsolationLevel(int isolationLevel) {
0280:                this .isolationLevel = isolationLevel;
0281:            }
0282:
0283:            public void setClearBatch(boolean clearBatch) {
0284:                this .clearBatch = clearBatch;
0285:            }
0286:
0287:            public boolean isClearBatch() {
0288:                return clearBatch;
0289:            }
0290:
0291:            public boolean isJdbcDisablePsCache() {
0292:                return jdbcDisablePsCache;
0293:            }
0294:
0295:            public void setJdbcDisablePsCache(boolean jdbcDisablePsCache) {
0296:                this .jdbcDisablePsCache = jdbcDisablePsCache;
0297:            }
0298:
0299:            public int getPsCacheMax() {
0300:                return psCacheMax;
0301:            }
0302:
0303:            public void setPsCacheMax(int psCacheMax) {
0304:                this .psCacheMax = psCacheMax;
0305:            }
0306:
0307:            public String getInitSQL() {
0308:                return initSQL;
0309:            }
0310:
0311:            public void setInitSQL(String initSQL) {
0312:                String s = endsWithCommit(initSQL);
0313:                if (s != null) {
0314:                    commitAfterInitSQL = true;
0315:                    this .initSQL = s;
0316:                } else {
0317:                    commitAfterInitSQL = false;
0318:                    this .initSQL = initSQL;
0319:                }
0320:            }
0321:
0322:            /**
0323:             * If s ends with ;[{ws}]commit[;][{ws}] then return s minus this part. Otherwise
0324:             * return null.
0325:             */
0326:            private String endsWithCommit(String s) {
0327:                if (s == null)
0328:                    return null;
0329:                s = s.trim();
0330:                if (!s.endsWith("commit") && !s.endsWith("COMMIT"))
0331:                    return null;
0332:                for (int i = s.length() - 7; i >= 0; i--) {
0333:                    char c = s.charAt(i);
0334:                    if (!Character.isWhitespace(c)) {
0335:                        if (c == ';') {
0336:                            return s.substring(0, i);
0337:                        } else {
0338:                            break;
0339:                        }
0340:                    }
0341:                }
0342:                return null;
0343:            }
0344:
0345:            public String getValidateSQL() {
0346:                return validateSQL;
0347:            }
0348:
0349:            public void setValidateSQL(String validateSQL) {
0350:                this .validateSQL = validateSQL;
0351:            }
0352:
0353:            public int getConTimeout() {
0354:                return conTimeout;
0355:            }
0356:
0357:            public void setConTimeout(int conTimeout) {
0358:                this .conTimeout = conTimeout;
0359:            }
0360:
0361:            public int getTestInterval() {
0362:                return testInterval;
0363:            }
0364:
0365:            public void setTestInterval(int testInterval) {
0366:                this .testInterval = testInterval;
0367:            }
0368:
0369:            public boolean isTestWhenIdle() {
0370:                return testWhenIdle;
0371:            }
0372:
0373:            public void setTestWhenIdle(boolean on) {
0374:                testWhenIdle = on;
0375:            }
0376:
0377:            public boolean isBlockWhenFull() {
0378:                return blockWhenFull;
0379:            }
0380:
0381:            public void setBlockWhenFull(boolean blockWhenFull) {
0382:                this .blockWhenFull = blockWhenFull;
0383:            }
0384:
0385:            public int getMaxIdle() {
0386:                return maxIdle;
0387:            }
0388:
0389:            public void setMaxIdle(int maxIdle) {
0390:                this .maxIdle = maxIdle;
0391:                if (cleanupThread != null)
0392:                    cleanupThread.interrupt();
0393:            }
0394:
0395:            public int getMinIdle() {
0396:                return minIdle;
0397:            }
0398:
0399:            public void setMinIdle(int minIdle) {
0400:                this .minIdle = minIdle;
0401:                if (cleanupThread != null)
0402:                    cleanupThread.interrupt();
0403:            }
0404:
0405:            public int getMaxActive() {
0406:                return maxActive;
0407:            }
0408:
0409:            public void setMaxActive(int maxActive) {
0410:                this .maxActive = maxActive;
0411:                if (cleanupThread != null)
0412:                    cleanupThread.interrupt();
0413:            }
0414:
0415:            public int getReserved() {
0416:                return reserved;
0417:            }
0418:
0419:            public void setReserved(int reserved) {
0420:                this .reserved = reserved;
0421:            }
0422:
0423:            public int getIdleCount() {
0424:                return idleCount;
0425:            }
0426:
0427:            public int getActiveCount() {
0428:                return activeCount;
0429:            }
0430:
0431:            public int getMaxConAge() {
0432:                return maxConAge;
0433:            }
0434:
0435:            public void setMaxConAge(int maxConAge) {
0436:                this .maxConAge = maxConAge;
0437:            }
0438:
0439:            /**
0440:             * Fill s with status info for this pool.
0441:             */
0442:            public void fillStatus(PoolStatus s) {
0443:                s.fill(maxActive, activeCount, maxIdle, idleCount);
0444:            }
0445:
0446:            /**
0447:             * Get our JDBC URL.
0448:             */
0449:            public String getURL() {
0450:                return url;
0451:            }
0452:
0453:            /**
0454:             * Return the connection prop of the pool.
0455:             */
0456:            public Properties getConnectionProperties() {
0457:                return userProps;
0458:            }
0459:
0460:            /**
0461:             * Get the JDBC driver instance.
0462:             */
0463:            public Driver getJdbcDriver() {
0464:                return jdbcDriver;
0465:            }
0466:
0467:            /**
0468:             * Get the JDBC driver class or null if not known.
0469:             */
0470:            public String getDriverName() {
0471:                return jdbcDriver == null ? "(unknown)" : jdbcDriver.getClass()
0472:                        .getName();
0473:            }
0474:
0475:            /**
0476:             * Allocate a PooledConnection from the pool.
0477:             *
0478:             * @param highPriority If this is true then reserved high priority
0479:             * @param autoCommit Must the connection have autoCommit set?
0480:             */
0481:            public Connection getConnection(boolean highPriority,
0482:                    boolean autoCommit) throws SQLException {
0483:                // adjust local maxActive to maintain reserved connections if needed
0484:                int maxActive = this .maxActive - (highPriority ? 0 : reserved);
0485:                PooledConnection con = null;
0486:                for (;;) {
0487:                    synchronized (this ) {
0488:                        for (;;) {
0489:                            if (closed) {
0490:                                throw BindingSupportImpl.getInstance().fatal(
0491:                                        "Connection pool has been closed");
0492:                            }
0493:                            if (activeCount >= maxActive) {
0494:                                if (pes.isWarning()) {
0495:                                    JdbcPoolEvent event = new JdbcPoolEvent(0,
0496:                                            JdbcLogEvent.POOL_FULL,
0497:                                            highPriority);
0498:                                    update(event);
0499:                                    pes.log(event);
0500:                                    fullCount++;
0501:                                }
0502:                                if (blockWhenFull) {
0503:                                    try {
0504:                                        wait();
0505:                                    } catch (InterruptedException e) {
0506:                                        // ignore
0507:                                    }
0508:                                } else {
0509:                                    throw BindingSupportImpl.getInstance()
0510:                                            .poolFull(
0511:                                                    "JDBC connection pool is full: "
0512:                                                            + this );
0513:                                }
0514:                            } else {
0515:                                con = removeFromIdleHead(autoCommit);
0516:                                ++activeCount;
0517:                                break;
0518:                            }
0519:                        }
0520:                    }
0521:                    if (con == null) {
0522:                        try {
0523:                            waitCount++;
0524:                            con = createPooledConnection(retryCount,
0525:                                    retryIntervalMs);
0526:                        } finally {
0527:                            if (con == null) {
0528:                                synchronized (this ) {
0529:                                    --activeCount;
0530:                                }
0531:                            }
0532:                        }
0533:                        break;
0534:                    } else {
0535:                        if (testOnAlloc && !validateConnection(con)) {
0536:                            destroy(con);
0537:                            synchronized (this ) {
0538:                                --activeCount;
0539:                            }
0540:                        } else {
0541:                            break;
0542:                        }
0543:                    }
0544:                }
0545:                // make sure the autoCommit status on the con is correct
0546:                if (con.getCachedAutoCommit() != autoCommit) {
0547:                    if (autoCommit) { // do rollback if going from false -> true
0548:                        con.rollback();
0549:                    }
0550:                    con.setAutoCommit(autoCommit);
0551:                }
0552:                con.updateLastActivityTime();
0553:                addToActiveHead(con);
0554:                log(0, JdbcLogEvent.POOL_ALLOC, con, highPriority);
0555:                allocatedCount++;
0556:                return con;
0557:            }
0558:
0559:            /**
0560:             * Test 1 idle connection. If it fails, close it and repeat.
0561:             */
0562:            public void testIdleConnections() {
0563:                for (;;) {
0564:                    PooledConnection con;
0565:                    synchronized (this ) {
0566:                        // don't test if the pool is almost full - this will just
0567:                        // reduce throughput by making some thread wait for a con
0568:                        if (activeCount >= (maxActive - reserved - 1))
0569:                            break;
0570:                        con = removeFromIdleHead(false);
0571:                        if (con == null)
0572:                            break;
0573:                        ++activeCount;
0574:                    }
0575:                    if (validateConnection(con)) {
0576:                        synchronized (this ) {
0577:                            addToIdleTail(con);
0578:                            --activeCount;
0579:                        }
0580:                        break;
0581:                    } else {
0582:                        destroy(con);
0583:                        synchronized (this ) {
0584:                            --activeCount;
0585:                        }
0586:                    }
0587:                }
0588:            }
0589:
0590:            /**
0591:             * Check the integrity of the double linked with head and tail.
0592:             */
0593:            private void checkList(PooledConnection tail,
0594:                    PooledConnection head, int size) {
0595:                if (tail == null) {
0596:                    testTrue(head == null);
0597:                    return;
0598:                }
0599:                if (head == null) {
0600:                    testTrue(tail == null);
0601:                    return;
0602:                }
0603:                checkList(tail, size);
0604:                checkList(head, size);
0605:                testTrue(tail.prev == null);
0606:                testTrue(head.next == null);
0607:            }
0608:
0609:            /**
0610:             * Check the integrity of the double linked list containing pc.
0611:             */
0612:            private void checkList(PooledConnection pc, int size) {
0613:                if (pc == null)
0614:                    return;
0615:                int c = -1;
0616:                // check links to tail
0617:                for (PooledConnection i = pc; i != null; i = i.prev) {
0618:                    if (i.prev != null)
0619:                        testTrue(i.prev.next == i);
0620:                    ++c;
0621:                }
0622:                // check links to head
0623:                for (PooledConnection i = pc; i != null; i = i.next) {
0624:                    if (i.next != null)
0625:                        testTrue(i.next.prev == i);
0626:                    ++c;
0627:                }
0628:                if (size >= 0) {
0629:                    testEquals(size, c);
0630:                }
0631:            }
0632:
0633:            private static void testEquals(int a, int b) {
0634:                if (a != b) {
0635:                    throw BindingSupportImpl.getInstance().internal(
0636:                            "assertion failed: expected " + a + " got " + b);
0637:                }
0638:            }
0639:
0640:            private static void testTrue(boolean t) {
0641:                if (!t) {
0642:                    throw BindingSupportImpl.getInstance().internal(
0643:                            "assertion failed: expected true");
0644:                }
0645:            }
0646:
0647:            public void returnConnection(Connection con) throws SQLException {
0648:                con.close();
0649:            }
0650:
0651:            /**
0652:             * Return a PooledConnection to the pool. This is called by
0653:             * PooledConnection when it is closed. This is a NOP if the connection
0654:             * has been destroyed.
0655:             *
0656:             * @see PooledConnection#close
0657:             */
0658:            public void returnConnection(PooledConnection con) {
0659:                if (con.isDestroyed())
0660:                    return;
0661:                if ((testOnReturn || testOnException && con.isNeedsValidation())
0662:                        && !validateConnection(con)) {
0663:                    removeFromActiveList(con);
0664:                    destroy(con);
0665:                } else if (maxConAge > 0 && ++con.age >= maxConAge) {
0666:                    ++expiredCount;
0667:                    if (pes.isFine()) {
0668:                        JdbcLogEvent ev = new JdbcLogEvent(0,
0669:                                JdbcLogEvent.POOL_CON_EXPIRED, Integer
0670:                                        .toString(con.age));
0671:                        ev.updateTotalMs();
0672:                        pes.log(ev);
0673:                    }
0674:                    removeFromActiveList(con);
0675:                    destroy(con);
0676:                } else {
0677:                    synchronized (this ) {
0678:                        removeFromActiveList(con);
0679:                        addToIdleTail(con);
0680:                    }
0681:                }
0682:                log(0, JdbcLogEvent.POOL_RELEASE, con, false);
0683:            }
0684:
0685:            /**
0686:             * Close all idle connections. This method closes idleCount connections.
0687:             * If another thread is making new connections at the same time the
0688:             * idle list will not be empty on return.
0689:             */
0690:            public void closeIdleConnections() {
0691:                for (int i = idleCount; i > 0; i--) {
0692:                    PooledConnection con = removeFromIdleHead(false);
0693:                    if (con == null)
0694:                        break;
0695:                    destroy(con);
0696:                }
0697:                if (cleanupThread != null)
0698:                    cleanupThread.interrupt();
0699:            }
0700:
0701:            /**
0702:             * Destroy a connection silently ignoring SQLException's.
0703:             */
0704:            private void destroy(PooledConnection con) {
0705:                closedCount++;
0706:                con.destroy();
0707:            }
0708:
0709:            /**
0710:             * Close all connections and shutdown the pool.
0711:             */
0712:            public void destroy() {
0713:                closed = true;
0714:                if (cleanupThread != null)
0715:                    cleanupThread.interrupt();
0716:                for (;;) {
0717:                    PooledConnection con = removeFromIdleHead(false);
0718:                    if (con == null)
0719:                        break;
0720:                    destroy(con);
0721:                }
0722:                // this will cause any threads waiting for connections to get a
0723:                // closed exception
0724:                synchronized (this ) {
0725:                    notifyAll();
0726:                }
0727:            }
0728:
0729:            /**
0730:             * Close excess idle connections or create new idle connections if less
0731:             * than minIdle (but do not exceed maxActive in total).
0732:             */
0733:            public void checkIdleConnections() throws Exception {
0734:                // close excess idle connections
0735:                for (; idleCount > maxIdle;) {
0736:                    PooledConnection con = removeFromIdleHead(false);
0737:                    if (con == null)
0738:                        break;
0739:                    destroy(con);
0740:                }
0741:                // Start creating a new connection if there is space in the pool for 2
0742:                // more. Only add the connection to the pool once created if there is
0743:                // space for 1 more.
0744:                for (;;) {
0745:                    if (!needMoreIdleConnections(1))
0746:                        break;
0747:                    PooledConnection con = createPooledConnection(retryCount,
0748:                            retryIntervalMs);
0749:                    synchronized (this ) {
0750:                        if (needMoreIdleConnections(0)) {
0751:                            addToIdleTail(con);
0752:                            continue;
0753:                        }
0754:                    }
0755:                    destroy(con);
0756:                    break;
0757:                }
0758:            }
0759:
0760:            private synchronized boolean needMoreIdleConnections(int space) {
0761:                return idleCount < minIdle
0762:                        && idleCount + activeCount < (maxActive - space);
0763:            }
0764:
0765:            /**
0766:             * Close active connections that have been out of the pool for too long.
0767:             * This is a NOP if activeTimeout <= 0.
0768:             */
0769:            public void closeTimedOutConnections() {
0770:                if (conTimeout <= 0)
0771:                    return;
0772:                for (;;) {
0773:                    PooledConnection con;
0774:                    synchronized (this ) {
0775:                        if (activeTail == null)
0776:                            return;
0777:                        long t = activeTail.getLastActivityTime();
0778:                        if (t == 0)
0779:                            return;
0780:                        int s = (int) ((System.currentTimeMillis() - t) / 1000);
0781:                        if (s < conTimeout)
0782:                            return;
0783:                        con = activeTail;
0784:                        removeFromActiveList(con);
0785:                    }
0786:                    timedOutCount++;
0787:                    if (pes.isWarning()) {
0788:                        JdbcPoolEvent event = new JdbcPoolEvent(0,
0789:                                JdbcLogEvent.POOL_CON_TIMEOUT, false);
0790:                        event.setConnectionID(System.identityHashCode(con));
0791:                        update(event);
0792:                        pes.log(event);
0793:                    }
0794:                    destroy(con);
0795:                }
0796:            }
0797:
0798:            /**
0799:             * Return the con at the head of the idle list removing it from the list.
0800:             * If there is no idle con then null is returned. The con has its idle
0801:             * flag cleared.
0802:             *
0803:             * @param autoCommit An attempt is made to return a connction with
0804:             *      autoCommit in this state. If this is not possible a connection
0805:             *      with a different setting may be returned.
0806:             */
0807:            private synchronized PooledConnection removeFromIdleHead(
0808:                    boolean autoCommit) {
0809:                PooledConnection ans = removeFromIdleHeadImp(autoCommit);
0810:                return ans == null ? removeFromIdleHeadImp(!autoCommit) : ans;
0811:            }
0812:
0813:            private PooledConnection removeFromIdleHeadImp(boolean autoCommit) {
0814:                PooledConnection con;
0815:                if (autoCommit) {
0816:                    con = idleHeadAC;
0817:                    if (con == null)
0818:                        return null;
0819:                    idleHeadAC = con.prev;
0820:                    con.prev = null;
0821:                    if (idleHeadAC == null) {
0822:                        idleTailAC = null;
0823:                    } else {
0824:                        idleHeadAC.next = null;
0825:                    }
0826:                } else {
0827:                    con = idleHead;
0828:                    if (con == null)
0829:                        return null;
0830:                    idleHead = con.prev;
0831:                    con.prev = null;
0832:                    if (idleHead == null) {
0833:                        idleTail = null;
0834:                    } else {
0835:                        idleHead.next = null;
0836:                    }
0837:                }
0838:                --idleCount;
0839:                con.idle = false;
0840:                if (Debug.DEBUG) {
0841:                    checkList(idleTail, idleHead, -1);
0842:                    checkList(idleTailAC, idleHeadAC, -1);
0843:                }
0844:                return con;
0845:            }
0846:
0847:            /**
0848:             * Add con to the tail of the idle list. The con has its idle flag set.
0849:             * This will notify any blocked threads so they can get the newly idle
0850:             * connection.
0851:             */
0852:            private synchronized void addToIdleTail(PooledConnection con) {
0853:                if (Debug.DEBUG) {
0854:                    if (con.prev != null || con.next != null) {
0855:                        throw BindingSupportImpl.getInstance().internal(
0856:                                "con belongs to a list");
0857:                    }
0858:                }
0859:                con.idle = true;
0860:                if (con.getCachedAutoCommit()) {
0861:                    if (idleTailAC == null) {
0862:                        idleHeadAC = idleTailAC = con;
0863:                    } else {
0864:                        con.next = idleTailAC;
0865:                        idleTailAC.prev = con;
0866:                        idleTailAC = con;
0867:                    }
0868:                } else {
0869:                    if (idleTail == null) {
0870:                        idleHead = idleTail = con;
0871:                    } else {
0872:                        con.next = idleTail;
0873:                        idleTail.prev = con;
0874:                        idleTail = con;
0875:                    }
0876:                }
0877:                ++idleCount;
0878:                if (Debug.DEBUG) {
0879:                    checkList(idleTail, idleHead, -1);
0880:                    checkList(idleTailAC, idleHeadAC, -1);
0881:                }
0882:                notify();
0883:            }
0884:
0885:            /**
0886:             * Add con to the head of the active list. Note that this does not
0887:             * bump up activeCount.
0888:             */
0889:            private synchronized void addToActiveHead(PooledConnection con) {
0890:                if (Debug.DEBUG) {
0891:                    if (con.prev != null || con.next != null) {
0892:                        throw BindingSupportImpl.getInstance().internal(
0893:                                "con belongs to a list");
0894:                    }
0895:                }
0896:                if (activeHead == null) {
0897:                    activeHead = activeTail = con;
0898:                } else {
0899:                    con.prev = activeHead;
0900:                    activeHead.next = con;
0901:                    activeHead = con;
0902:                }
0903:                if (Debug.DEBUG)
0904:                    checkList(activeTail, activeHead, -1);
0905:            }
0906:
0907:            /**
0908:             * Remove con from the active list.
0909:             */
0910:            private synchronized void removeFromActiveList(PooledConnection con) {
0911:                if (con.prev != null) {
0912:                    con.prev.next = con.next;
0913:                } else {
0914:                    activeTail = con.next;
0915:                }
0916:                if (con.next != null) {
0917:                    con.next.prev = con.prev;
0918:                } else {
0919:                    activeHead = con.prev;
0920:                }
0921:                con.prev = con.next = null;
0922:                --activeCount;
0923:                if (Debug.DEBUG)
0924:                    checkList(activeTail, activeHead, -1);
0925:            }
0926:
0927:            private JdbcPoolEvent log(long txId, int type,
0928:                    PooledConnection con, boolean highPriority) {
0929:                if (pes.isFine()) {
0930:                    JdbcPoolEvent event = new JdbcPoolEvent(txId, type,
0931:                            highPriority);
0932:                    event.setAutoCommit(con.getCachedAutoCommit());
0933:                    event.setConnectionID(System.identityHashCode(con));
0934:                    update(event);
0935:                    pes.log(event);
0936:                    return event;
0937:                }
0938:                return null;
0939:            }
0940:
0941:            private void update(JdbcPoolEvent ev) {
0942:                ev.update(maxActive, activeCount, maxIdle, idleCount);
0943:            }
0944:
0945:            private Connection createRealCon() {
0946:                JdbcConnectionEvent ev = null;
0947:                if (pes.isFine()) {
0948:                    ev = new JdbcConnectionEvent(0, null, url,
0949:                            JdbcConnectionEvent.CON_OPEN);
0950:                    pes.log(ev);
0951:                }
0952:                Connection realCon = null;
0953:                try {
0954:                    realCon = jdbcDriver.connect(url, props);
0955:                    if (realCon == null) {
0956:                        throw BindingSupportImpl.getInstance().fatalDatastore(
0957:                                formatConnectionErr("Unable to connect to "
0958:                                        + url));
0959:                    }
0960:                } catch (SQLException x) {
0961:                    RuntimeException e = sqlDriver.mapException(x,
0962:                            formatConnectionErr("Unable to connect to " + url
0963:                                    + ":\n" + x), false);
0964:                    if (ev != null) {
0965:                        ev.setErrorMsg(e);
0966:                    }
0967:                    throw e;
0968:                } catch (RuntimeException x) {
0969:                    if (ev != null) {
0970:                        ev.setErrorMsg(x);
0971:                    }
0972:                    throw x;
0973:                } finally {
0974:                    if (ev != null) {
0975:                        ev.updateTotalMs();
0976:                    }
0977:                }
0978:                createdCount++;
0979:                return realCon;
0980:            }
0981:
0982:            private String formatConnectionErr(String msg) {
0983:                StringBuffer s = new StringBuffer();
0984:                s.append(msg);
0985:                s.append("\nJDBC Driver: " + jdbcDriver.getClass().getName());
0986:                ArrayList a = new ArrayList(props.keySet());
0987:                Collections.sort(a);
0988:                for (Iterator i = a.iterator(); i.hasNext();) {
0989:                    String p = (String) i.next();
0990:                    Object v = "password".equals(p) ? "(hidden)" : props.get(p);
0991:                    s.append('\n');
0992:                    s.append(p);
0993:                    s.append('=');
0994:                    s.append(v);
0995:                }
0996:                return s.toString();
0997:            }
0998:
0999:            /**
1000:             * Create an initialize a PooledConnection. This will run the initSQL
1001:             * and do setAutoCommit(false). It will not add it to the idle or active
1002:             * lists.
1003:             */
1004:            private PooledConnection createPooledConnection(int retryCount,
1005:                    int retryIntervalMs) throws SQLException {
1006:                Connection realCon = createRealConWithRetry(retryCount,
1007:                        retryIntervalMs);
1008:                PooledConnection pooledCon = new PooledConnection(
1009:                        JDBCConnectionPool.this , realCon, pes,
1010:                        !jdbcDisablePsCache, psCacheMax);
1011:                boolean ok = false;
1012:                try {
1013:                    initConnection(pooledCon);
1014:                    pooledCon.setAutoCommit(false);
1015:                    if (isolationLevel != 0) {
1016:                        pooledCon.setTransactionIsolation(isolationLevel);
1017:                    }
1018:                    ok = true;
1019:                } finally {
1020:                    if (!ok && realCon != null) {
1021:                        try {
1022:                            pooledCon.closeRealConnection();
1023:                        } catch (SQLException x) {
1024:                            // ignore
1025:                        }
1026:                    }
1027:                }
1028:                return pooledCon;
1029:            }
1030:
1031:            /**
1032:             * Initialize the connection with the initSQL (if any).
1033:             */
1034:            private void initConnection(Connection con) {
1035:                if (initSQL == null)
1036:                    return;
1037:                Statement stat = null;
1038:                try {
1039:                    stat = con.createStatement();
1040:                    stat.execute(initSQL);
1041:                } catch (SQLException e) {
1042:                    throw sqlDriver.mapException(e,
1043:                            "Error executing initSQL on new Connection: " + e
1044:                                    + "\n" + initSQL, true);
1045:                } finally {
1046:                    if (stat != null) {
1047:                        try {
1048:                            stat.close();
1049:                        } catch (SQLException e) {
1050:                            // ignore
1051:                        }
1052:                    }
1053:                }
1054:                if (commitAfterInitSQL) {
1055:                    try {
1056:                        con.commit();
1057:                    } catch (SQLException e) {
1058:                        throw sqlDriver.mapException(e,
1059:                                "Error doing commit after executing initSQL on new Connection: "
1060:                                        + e + "\n" + initSQL, true);
1061:                    }
1062:                }
1063:            }
1064:
1065:            /**
1066:             * Check that the connection is open and if so validate the connection with
1067:             * validateSQL (if any). Returns true if the connection is ok.
1068:             */
1069:            private boolean validateConnection(PooledConnection con) {
1070:                validatedCount++;
1071:                boolean ans = validateConnectionImp(con);
1072:                if (!ans)
1073:                    badCount++;
1074:                return ans;
1075:            }
1076:
1077:            private boolean validateConnectionImp(PooledConnection con) {
1078:                try {
1079:                    if (con.isClosed())
1080:                        return false;
1081:                    if (validateSQL != null) {
1082:                        PreparedStatement ps = null;
1083:                        ResultSet rs = null;
1084:                        try {
1085:                            ps = con.prepareStatement(validateSQL);
1086:                            rs = ps.executeQuery();
1087:                            if (!rs.next()) {
1088:                                if (pes.isWarning()) {
1089:                                    JdbcLogEvent ev = new JdbcLogEvent(0,
1090:                                            JdbcLogEvent.POOL_BAD_CON,
1091:                                            "No row returned");
1092:                                    ev.updateTotalMs();
1093:                                    pes.log(ev);
1094:                                }
1095:                                return false;
1096:                            }
1097:                        } finally {
1098:                            if (rs != null)
1099:                                rs.close();
1100:                            if (ps != null)
1101:                                ps.close();
1102:                        }
1103:                        if (!con.getCachedAutoCommit()) {
1104:                            con.rollback();
1105:                        }
1106:                    }
1107:                    return true;
1108:                } catch (SQLException e) {
1109:                    if (pes.isWarning()) {
1110:                        JdbcLogEvent ev = new JdbcLogEvent(0,
1111:                                JdbcLogEvent.POOL_BAD_CON, e.toString());
1112:                        ev.updateTotalMs();
1113:                        pes.log(ev);
1114:                    }
1115:                    return false;
1116:                }
1117:            }
1118:
1119:            /**
1120:             * Perform maintenance operations on the pool at periodic intervals.
1121:             */
1122:            public void run() {
1123:
1124:                for (;;) {
1125:
1126:                    try {
1127:                        Thread.sleep(5000);
1128:                    } catch (InterruptedException e) {
1129:                        // ignore
1130:                    }
1131:
1132:                    if (closed)
1133:                        break;
1134:
1135:                    if (duration(timeLastTest) >= testInterval) {
1136:                        timeLastTest = System.currentTimeMillis();
1137:                        if (testWhenIdle)
1138:                            testIdleConnections();
1139:                        if (conTimeout > 0)
1140:                            closeTimedOutConnections();
1141:                    }
1142:
1143:                    try {
1144:                        checkIdleConnections();
1145:                    } catch (Exception e) {
1146:                        // ignore
1147:                    }
1148:                }
1149:            }
1150:
1151:            private long duration(long start) {
1152:                return (System.currentTimeMillis() - start) / 1000;
1153:            }
1154:
1155:            /**
1156:             * Return our name and status.
1157:             */
1158:            public String toString() {
1159:                PoolStatus ps = new PoolStatus(url);
1160:                fillStatus(ps);
1161:                return ps.toString();
1162:            }
1163:
1164:            /**
1165:             * Add all BaseMetric's for this store to the List.
1166:             */
1167:            public void addMetrics(List list) {
1168:                list.add(metricActive = new BaseMetric("JDBCPoolActive",
1169:                        "Pool Active", CAT_POOL,
1170:                        "Number of active JDBC connections in pool", 0,
1171:                        Metric.CALC_AVERAGE));
1172:                list.add(metricMaxActive = new BaseMetric("JDBCPoolMaxActive",
1173:                        "Pool Max Active", CAT_POOL,
1174:                        "Max number of JDBC connections allowed in pool", 0,
1175:                        Metric.CALC_AVERAGE));
1176:                list.add(metricIdle = new BaseMetric("JDBCPoolIdle",
1177:                        "Pool Idle", CAT_POOL,
1178:                        "Number of idle JDBC connections in pool", 0,
1179:                        Metric.CALC_AVERAGE));
1180:                list
1181:                        .add(metricWait = new BaseMetric(
1182:                                "JDBCPoolWait",
1183:                                "Pool Wait",
1184:                                CAT_POOL,
1185:                                "Number of times that a caller had to wait for a connection",
1186:                                0, Metric.CALC_DELTA));
1187:                list
1188:                        .add(metricFull = new BaseMetric(
1189:                                "JDBCPoolFull",
1190:                                "Pool Full",
1191:                                CAT_POOL,
1192:                                "Number of times that the pool was full and a connection was needed",
1193:                                0, Metric.CALC_DELTA));
1194:                list
1195:                        .add(metricTimedOut = new BaseMetric(
1196:                                "JDBCConTimedOut",
1197:                                "Con Timed Out",
1198:                                CAT_POOL,
1199:                                "Number of active JDBC connections timed out and closed",
1200:                                0, Metric.CALC_DELTA));
1201:                list
1202:                        .add(metricExpired = new BaseMetric(
1203:                                "JDBCConExpired",
1204:                                "Con Expired",
1205:                                CAT_POOL,
1206:                                "Number of JDBC connections closed due to their age reaching the maximum lifespan",
1207:                                0, Metric.CALC_DELTA));
1208:                list
1209:                        .add(metricBad = new BaseMetric(
1210:                                "JDBCConBad",
1211:                                "Con Bad",
1212:                                CAT_POOL,
1213:                                "Number of JDBC connections that failed validation test",
1214:                                0, Metric.CALC_DELTA));
1215:                list.add(metricCreated = new BaseMetric("JDBCConCreated",
1216:                        "Con Created", CAT_POOL,
1217:                        "Number of JDBC connections created", 0,
1218:                        Metric.CALC_DELTA));
1219:                list.add(metricClosed = new BaseMetric("JDBCConClosed",
1220:                        "Con Closed", CAT_POOL,
1221:                        "Number of JDBC connections closed", 0,
1222:                        Metric.CALC_DELTA));
1223:                list.add(metricAllocated = new BaseMetric("JDBCConAllocated",
1224:                        "Con Allocated", CAT_POOL,
1225:                        "Number of JDBC connections given out by the pool", 3,
1226:                        Metric.CALC_DELTA_PER_SECOND));
1227:                list.add(metricValidated = new BaseMetric("JDBCConValidated",
1228:                        "Con Validated", CAT_POOL,
1229:                        "Number of JDBC connections tested by the pool", 0,
1230:                        Metric.CALC_DELTA));
1231:                list.add(new PercentageMetric("JdbcPoolPercentFull",
1232:                        "Pool % Full ", CAT_POOL,
1233:                        "Active connections as a percentage of the maximum",
1234:                        metricActive, metricMaxActive));
1235:            }
1236:
1237:            /**
1238:             * Get values for our metrics.
1239:             */
1240:            public void sampleMetrics(int[][] buf, int pos) {
1241:                buf[metricActive.getIndex()][pos] = activeCount;
1242:                buf[metricMaxActive.getIndex()][pos] = maxActive;
1243:                buf[metricIdle.getIndex()][pos] = idleCount;
1244:                buf[metricWait.getIndex()][pos] = waitCount;
1245:                buf[metricFull.getIndex()][pos] = fullCount;
1246:                buf[metricTimedOut.getIndex()][pos] = timedOutCount;
1247:                buf[metricExpired.getIndex()][pos] = expiredCount;
1248:                buf[metricBad.getIndex()][pos] = badCount;
1249:                buf[metricAllocated.getIndex()][pos] = allocatedCount;
1250:                buf[metricValidated.getIndex()][pos] = validatedCount;
1251:                buf[metricCreated.getIndex()][pos] = createdCount;
1252:                buf[metricClosed.getIndex()][pos] = closedCount;
1253:            }
1254:
1255:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.