Source Code Cross Referenced for SingleDB.java in  » Database-JDBC-Connection-Pool » sequoia-2.10.9 » org » continuent » sequoia » controller » loadbalancer » singledb » 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 » sequoia 2.10.9 » org.continuent.sequoia.controller.loadbalancer.singledb 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /**
0002:         * Sequoia: Database clustering technology.
0003:         * Copyright (C) 2002-2004 French National Institute For Research In Computer
0004:         * Science And Control (INRIA).
0005:         * Copyright (C) 2005 AmicoSoft, Inc. dba Emic Networks
0006:         * Contact: sequoia@continuent.org
0007:         * 
0008:         * Licensed under the Apache License, Version 2.0 (the "License");
0009:         * you may not use this file except in compliance with the License.
0010:         * You may obtain a copy of the License at
0011:         * 
0012:         * http://www.apache.org/licenses/LICENSE-2.0
0013:         * 
0014:         * Unless required by applicable law or agreed to in writing, software
0015:         * distributed under the License is distributed on an "AS IS" BASIS,
0016:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0017:         * See the License for the specific language governing permissions and
0018:         * limitations under the License. 
0019:         *
0020:         * Initial developer(s): Emmanuel Cecchet.
0021:         * Contributor(s): Vadim Kassin, Jaco Swart, Jean-Bernard van Zuylen.
0022:         */package org.continuent.sequoia.controller.loadbalancer.singledb;
0023:
0024:        import java.sql.Connection;
0025:        import java.sql.SQLException;
0026:        import java.sql.Savepoint;
0027:
0028:        import org.continuent.sequoia.common.exceptions.BadConnectionException;
0029:        import org.continuent.sequoia.common.exceptions.NoMoreBackendException;
0030:        import org.continuent.sequoia.common.exceptions.UnreachableBackendException;
0031:        import org.continuent.sequoia.common.i18n.Translate;
0032:        import org.continuent.sequoia.common.log.Trace;
0033:        import org.continuent.sequoia.common.xml.DatabasesXmlTags;
0034:        import org.continuent.sequoia.controller.backend.DatabaseBackend;
0035:        import org.continuent.sequoia.controller.backend.result.ControllerResultSet;
0036:        import org.continuent.sequoia.controller.backend.result.ExecuteResult;
0037:        import org.continuent.sequoia.controller.backend.result.ExecuteUpdateResult;
0038:        import org.continuent.sequoia.controller.backend.result.GeneratedKeysResult;
0039:        import org.continuent.sequoia.controller.cache.metadata.MetadataCache;
0040:        import org.continuent.sequoia.controller.connection.AbstractConnectionManager;
0041:        import org.continuent.sequoia.controller.connection.PooledConnection;
0042:        import org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer;
0043:        import org.continuent.sequoia.controller.loadbalancer.AllBackendsFailedException;
0044:        import org.continuent.sequoia.controller.loadbalancer.policies.WaitForCompletionPolicy;
0045:        import org.continuent.sequoia.controller.requestmanager.RAIDbLevels;
0046:        import org.continuent.sequoia.controller.requestmanager.TransactionMetaData;
0047:        import org.continuent.sequoia.controller.requests.AbstractRequest;
0048:        import org.continuent.sequoia.controller.requests.AbstractWriteRequest;
0049:        import org.continuent.sequoia.controller.requests.ParsingGranularities;
0050:        import org.continuent.sequoia.controller.requests.SelectRequest;
0051:        import org.continuent.sequoia.controller.requests.StoredProcedure;
0052:        import org.continuent.sequoia.controller.requests.UnknownReadRequest;
0053:        import org.continuent.sequoia.controller.virtualdatabase.VirtualDatabase;
0054:
0055:        /**
0056:         * Single Database request load balancer.
0057:         * <p>
0058:         * The requests coming from the request controller are directly forwarded to the
0059:         * single backend. This load balancer does not support multiple backends and
0060:         * does not update the recovery log (it is not meant to be used with a recovery
0061:         * log).
0062:         * 
0063:         * @author <a href="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
0064:         * @author <a href="mailto:vadim@kase.kz">Vadim Kassin </a>
0065:         * @author <a href="mailto:jaco.swart@iblocks.co.uk">Jaco Swart </a>
0066:         * @author <a href="mailto:jbvanzuylen@transwide.com">Jean-Bernard van Zuylen
0067:         *         </a>
0068:         * @version 1.0
0069:         */
0070:        public class SingleDB extends AbstractLoadBalancer {
0071:            //
0072:            // How the code is organized?
0073:            // 1. Member variables
0074:            // 2. Constructor(s)
0075:            // 3. Request handling
0076:            // 4. Transaction handling
0077:            // 5. Backend management
0078:            // 6. Debug/Monitoring
0079:            //
0080:
0081:            private DatabaseBackend backend;
0082:
0083:            private static Trace logger = Trace
0084:                    .getLogger("org.continuent.sequoia.controller.loadbalancer.SingleDB");
0085:
0086:            static Trace endUserLogger = Trace
0087:                    .getLogger("org.continuent.sequoia.enduser");
0088:
0089:            /*
0090:             * Constructors
0091:             */
0092:
0093:            /**
0094:             * Creates a new <code>SingleDB</code> instance.
0095:             * 
0096:             * @param vdb the <code>VirtualDatabase</code> this load balancer belongs to
0097:             * @throws Exception if there is not exactly one backend attached to the
0098:             *           <code>VirtualDatabase</code>
0099:             */
0100:            public SingleDB(VirtualDatabase vdb) throws Exception {
0101:                // We don't need to parse the requests, just send them to the backend
0102:                super (vdb, RAIDbLevels.SingleDB,
0103:                        ParsingGranularities.NO_PARSING);
0104:                this .waitForCompletionPolicy = new WaitForCompletionPolicy(
0105:                        WaitForCompletionPolicy.ALL, false,
0106:                        ParsingGranularities.NO_PARSING);
0107:            }
0108:
0109:            /*
0110:             * Request Handling
0111:             */
0112:
0113:            /**
0114:             * Performs a read request. It is up to the implementation to choose to which
0115:             * backend node(s) this request should be sent.
0116:             * 
0117:             * @param request an <code>SelectRequest</code>
0118:             * @param metadataCache MetadataCache (null if none)
0119:             * @return the corresponding <code>java.sql.ResultSet</code>
0120:             * @exception SQLException if an error occurs
0121:             */
0122:            public ControllerResultSet statementExecuteQuery(
0123:                    SelectRequest request, MetadataCache metadataCache)
0124:                    throws SQLException {
0125:                if (backend == null)
0126:                    throw new NoMoreBackendException(Translate.get(
0127:                            "loadbalancer.execute.no.backend.available",
0128:                            request.getId()));
0129:
0130:                try {
0131:                    AbstractConnectionManager cm = backend
0132:                            .getConnectionManager(request.getLogin());
0133:                    if (request.isAutoCommit()) {
0134:                        ControllerResultSet rs = null;
0135:                        boolean badConnection;
0136:                        do {
0137:                            badConnection = false;
0138:                            // Use a connection just for this request
0139:                            PooledConnection c = null;
0140:                            try {
0141:                                c = cm.retrieveConnectionInAutoCommit(request);
0142:                            } catch (UnreachableBackendException e1) {
0143:                                String backendName = backend.getName();
0144:                                String msg = Translate
0145:                                        .get(
0146:                                                "loadbalancer.backend.disabling.unreachable",
0147:                                                backendName);
0148:                                logger.error(msg);
0149:                                endUserLogger.error(msg);
0150:                                disableBackend(backend, true);
0151:                                backend = null;
0152:                                throw new SQLException(Translate.get(
0153:                                        "loadbalancer.backend.unreacheable",
0154:                                        backendName));
0155:                            }
0156:
0157:                            // Sanity check
0158:                            if (c == null)
0159:                                throw new SQLException(Translate.get(
0160:                                        "loadbalancer.backend.no.connection",
0161:                                        backend.getName()));
0162:
0163:                            // Execute Query
0164:                            try {
0165:                                rs = executeStatementExecuteQueryOnBackend(
0166:                                        request, backend, null, c
0167:                                                .getConnection(), metadataCache);
0168:                                cm.releaseConnectionInAutoCommit(request, c);
0169:                            } catch (SQLException e) {
0170:                                cm.releaseConnectionInAutoCommit(request, c);
0171:                                throw new SQLException(
0172:                                        Translate
0173:                                                .get(
0174:                                                        "loadbalancer.request.failed.on.backend",
0175:                                                        new String[] {
0176:                                                                request
0177:                                                                        .getSqlShortForm(vdb
0178:                                                                                .getSqlShortFormLength()),
0179:                                                                backend
0180:                                                                        .getName(),
0181:                                                                e.getMessage() }));
0182:                            } catch (BadConnectionException e) { // Get rid of the bad connection
0183:                                cm.deleteConnection(c);
0184:                                badConnection = true;
0185:                            } catch (Throwable e) {
0186:                                cm.releaseConnectionInAutoCommit(request, c);
0187:                                throw new SQLException(
0188:                                        Translate
0189:                                                .get(
0190:                                                        "loadbalancer.request.failed.on.backend",
0191:                                                        new String[] {
0192:                                                                request
0193:                                                                        .getSqlShortForm(vdb
0194:                                                                                .getSqlShortFormLength()),
0195:                                                                backend
0196:                                                                        .getName(),
0197:                                                                e.getMessage() }));
0198:                            }
0199:                        } while (badConnection);
0200:                        return rs;
0201:                    } else {
0202:                        long tid = request.getTransactionId();
0203:                        // Re-use the connection used by this transaction
0204:                        PooledConnection c = cm
0205:                                .retrieveConnectionForTransaction(tid);
0206:
0207:                        // Sanity check
0208:                        if (c == null)
0209:                            throw new SQLException(Translate.get(
0210:                                    "loadbalancer.unable.retrieve.connection",
0211:                                    new String[] { String.valueOf(tid),
0212:                                            backend.getName() }));
0213:
0214:                        // Execute Query
0215:                        ControllerResultSet rs = null;
0216:                        try {
0217:                            rs = executeStatementExecuteQueryOnBackend(request,
0218:                                    backend, null, c.getConnection(),
0219:                                    metadataCache);
0220:                        } catch (SQLException e) {
0221:                            throw new SQLException(
0222:                                    Translate
0223:                                            .get(
0224:                                                    "loadbalancer.request.failed.on.backend",
0225:                                                    new String[] {
0226:                                                            request
0227:                                                                    .getSqlShortForm(vdb
0228:                                                                            .getSqlShortFormLength()),
0229:                                                            backend.getName(),
0230:                                                            e.getMessage() }));
0231:                        } catch (BadConnectionException e) { // Get rid of the bad connection
0232:                            cm.deleteConnection(tid);
0233:                            throw new SQLException(Translate
0234:                                    .get("loadbalancer.connection.failed",
0235:                                            new String[] { String.valueOf(tid),
0236:                                                    backend.getName(),
0237:                                                    e.getMessage() }));
0238:                        } catch (Throwable e) {
0239:                            throw new SQLException(
0240:                                    Translate
0241:                                            .get(
0242:                                                    "loadbalancer.request.failed.on.backend",
0243:                                                    new String[] {
0244:                                                            request
0245:                                                                    .getSqlShortForm(vdb
0246:                                                                            .getSqlShortFormLength()),
0247:                                                            backend.getName(),
0248:                                                            e.getMessage() }));
0249:                        }
0250:                        return rs;
0251:                    }
0252:                } catch (RuntimeException e) {
0253:                    String msg = "Request '"
0254:                            + request.getSqlShortForm(vdb
0255:                                    .getSqlShortFormLength())
0256:                            + "' failed on backend " + backend.getURL() + " ("
0257:                            + e + ")";
0258:                    logger.fatal(msg, e);
0259:                    throw new SQLException(msg);
0260:                }
0261:            }
0262:
0263:            /**
0264:             * Performs a write request on the backend.
0265:             * 
0266:             * @param request an <code>AbstractWriteRequest</code>
0267:             * @return number of rows affected by the request
0268:             * @exception SQLException if an error occurs
0269:             */
0270:            public ExecuteUpdateResult statementExecuteUpdate(
0271:                    AbstractWriteRequest request) throws SQLException {
0272:                if (backend == null)
0273:                    throw new NoMoreBackendException(Translate.get(
0274:                            "loadbalancer.execute.no.backend.available",
0275:                            request.getId()));
0276:
0277:                try {
0278:                    AbstractConnectionManager cm = backend
0279:                            .getConnectionManager(request.getLogin());
0280:                    if (request.isAutoCommit()) {
0281:                        // We do not execute request outside the already open transactions if we
0282:                        // are disabling the backend.
0283:                        if (!backend.canAcceptTasks(request))
0284:                            throw new SQLException(Translate.get(
0285:                                    "loadbalancer.backend.is.disabling",
0286:                                    new String[] {
0287:                                            request.getSqlShortForm(vdb
0288:                                                    .getSqlShortFormLength()),
0289:                                            backend.getName() }));
0290:
0291:                        // Use a connection just for this request
0292:                        PooledConnection c = null;
0293:                        try {
0294:                            c = cm.retrieveConnectionInAutoCommit(request);
0295:                        } catch (UnreachableBackendException e1) {
0296:                            String backendName = backend.getName();
0297:                            String msg = Translate
0298:                                    .get(
0299:                                            "loadbalancer.backend.disabling.unreachable",
0300:                                            backendName);
0301:                            logger.error(msg);
0302:                            endUserLogger.error(msg);
0303:                            disableBackend(backend, true);
0304:                            backend = null;
0305:                            throw new SQLException(Translate.get(
0306:                                    "loadbalancer.backend.unreacheable",
0307:                                    backendName));
0308:                        }
0309:
0310:                        // Sanity check
0311:                        if (c == null)
0312:                            throw new SQLException(Translate.get(
0313:                                    "loadbalancer.backend.no.connection",
0314:                                    backend.getName()));
0315:
0316:                        // Execute Query
0317:                        ExecuteUpdateResult result;
0318:                        try {
0319:                            result = executeStatementExecuteUpdateOnBackend(
0320:                                    request, backend, null, c);
0321:                        } catch (Exception e) {
0322:                            throw new SQLException(
0323:                                    Translate
0324:                                            .get(
0325:                                                    "loadbalancer.request.failed.on.backend",
0326:                                                    new String[] {
0327:                                                            request
0328:                                                                    .getSqlShortForm(vdb
0329:                                                                            .getSqlShortFormLength()),
0330:                                                            backend.getName(),
0331:                                                            e.getMessage() }));
0332:                        } finally {
0333:                            cm.releaseConnectionInAutoCommit(request, c);
0334:                        }
0335:                        return result;
0336:                    } else { // Re-use the connection used by this transaction
0337:                        PooledConnection c = cm
0338:                                .retrieveConnectionForTransaction(request
0339:                                        .getTransactionId());
0340:
0341:                        // Sanity check
0342:                        if (c == null)
0343:                            throw new SQLException(Translate.get(
0344:                                    "loadbalancer.unable.retrieve.connection",
0345:                                    new String[] {
0346:                                            String.valueOf(request
0347:                                                    .getTransactionId()),
0348:                                            backend.getName() }));
0349:
0350:                        // Execute Query
0351:                        try {
0352:                            ExecuteUpdateResult result = executeStatementExecuteUpdateOnBackend(
0353:                                    request, backend, null, c);
0354:                            return result;
0355:                        } catch (Exception e) {
0356:                            throw new SQLException(
0357:                                    Translate
0358:                                            .get(
0359:                                                    "loadbalancer.request.failed.on.backend",
0360:                                                    new String[] {
0361:                                                            request
0362:                                                                    .getSqlShortForm(vdb
0363:                                                                            .getSqlShortFormLength()),
0364:                                                            backend.getName(),
0365:                                                            e.getMessage() }));
0366:                        }
0367:                    }
0368:                } catch (RuntimeException e) {
0369:                    String msg = Translate.get(
0370:                            "loadbalancer.request.failed.on.backend",
0371:                            new String[] {
0372:                                    request.getSqlShortForm(vdb
0373:                                            .getSqlShortFormLength()),
0374:                                    backend.getName(), e.getMessage() });
0375:                    endUserLogger.fatal(msg);
0376:                    logger.fatal(msg, e);
0377:                    throw new SQLException(msg);
0378:                }
0379:            }
0380:
0381:            /**
0382:             * @see AbstractLoadBalancer#statementExecuteUpdateWithKeys(AbstractWriteRequest,
0383:             *      MetadataCache)
0384:             */
0385:            public GeneratedKeysResult statementExecuteUpdateWithKeys(
0386:                    AbstractWriteRequest request, MetadataCache metadataCache)
0387:                    throws SQLException {
0388:                if (backend == null)
0389:                    throw new NoMoreBackendException(Translate.get(
0390:                            "loadbalancer.execute.no.backend.available",
0391:                            request.getId()));
0392:
0393:                if (!backend.getDriverCompliance().supportGetGeneratedKeys())
0394:                    throw new SQLException(
0395:                            Translate
0396:                                    .get(
0397:                                            "loadbalancer.backend.autogeneratedkeys.unsupported",
0398:                                            backend.getName()));
0399:
0400:                try {
0401:                    AbstractConnectionManager cm = backend
0402:                            .getConnectionManager(request.getLogin());
0403:                    if (request.isAutoCommit()) {
0404:                        // We do not execute request outside the already open transactions if we
0405:                        // are disabling the backend.
0406:                        if (!backend.canAcceptTasks(request))
0407:                            throw new SQLException(Translate.get(
0408:                                    "loadbalancer.backend.is.disabling",
0409:                                    new String[] {
0410:                                            request.getSqlShortForm(vdb
0411:                                                    .getSqlShortFormLength()),
0412:                                            backend.getName() }));
0413:
0414:                        // Use a connection just for this request
0415:                        PooledConnection c = null;
0416:                        try {
0417:                            c = cm.retrieveConnectionInAutoCommit(request);
0418:                        } catch (UnreachableBackendException e1) {
0419:                            String backendName = backend.getName();
0420:                            String msg = Translate
0421:                                    .get(
0422:                                            "loadbalancer.backend.disabling.unreachable",
0423:                                            backendName);
0424:                            logger.error(msg);
0425:                            endUserLogger.error(msg);
0426:                            disableBackend(backend, true);
0427:                            backend = null;
0428:                            throw new SQLException(Translate.get(
0429:                                    "loadbalancer.backend.unreacheable",
0430:                                    backendName));
0431:                        }
0432:
0433:                        // Sanity check
0434:                        if (c == null)
0435:                            throw new SQLException(Translate.get(
0436:                                    "loadbalancer.backend.no.connection",
0437:                                    backend.getName()));
0438:
0439:                        // Execute Query
0440:                        GeneratedKeysResult result;
0441:                        try {
0442:                            result = executeStatementExecuteUpdateWithKeysOnBackend(
0443:                                    request, backend, null, c, metadataCache);
0444:                        } catch (Exception e) {
0445:                            throw new SQLException(
0446:                                    Translate
0447:                                            .get(
0448:                                                    "loadbalancer.request.failed.on.backend",
0449:                                                    new String[] {
0450:                                                            request
0451:                                                                    .getSqlShortForm(vdb
0452:                                                                            .getSqlShortFormLength()),
0453:                                                            backend.getName(),
0454:                                                            e.getMessage() }));
0455:                        } finally {
0456:                            cm.releaseConnectionInAutoCommit(request, c);
0457:                        }
0458:                        return result;
0459:                    } else {
0460:                        // Re-use the connection used by this transaction
0461:                        PooledConnection c = cm
0462:                                .retrieveConnectionForTransaction(request
0463:                                        .getTransactionId());
0464:
0465:                        // Sanity check
0466:                        if (c == null)
0467:                            throw new SQLException(Translate.get(
0468:                                    "loadbalancer.unable.retrieve.connection",
0469:                                    new String[] {
0470:                                            String.valueOf(request
0471:                                                    .getTransactionId()),
0472:                                            backend.getName() }));
0473:
0474:                        // Execute Query
0475:                        try {
0476:                            GeneratedKeysResult result = executeStatementExecuteUpdateWithKeysOnBackend(
0477:                                    request, backend, null, c, metadataCache);
0478:                            return result;
0479:                        } catch (Exception e) {
0480:                            throw new SQLException(
0481:                                    Translate
0482:                                            .get(
0483:                                                    "loadbalancer.request.failed.on.backend",
0484:                                                    new String[] {
0485:                                                            request
0486:                                                                    .getSqlShortForm(vdb
0487:                                                                            .getSqlShortFormLength()),
0488:                                                            backend.getName(),
0489:                                                            e.getMessage() }));
0490:                        } finally {
0491:                            backend.removePendingRequest(request);
0492:                        }
0493:                    }
0494:                } catch (RuntimeException e) {
0495:                    String msg = Translate.get(
0496:                            "loadbalancer.request.failed.on.backend",
0497:                            new String[] {
0498:                                    request.getSqlShortForm(vdb
0499:                                            .getSqlShortFormLength()),
0500:                                    backend.getName(), e.getMessage() });
0501:                    logger.fatal(msg, e);
0502:                    endUserLogger.fatal(msg);
0503:                    throw new SQLException(msg);
0504:                }
0505:            }
0506:
0507:            /**
0508:             * @see org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer#statementExecute(org.continuent.sequoia.controller.requests.AbstractRequest,
0509:             *      org.continuent.sequoia.controller.cache.metadata.MetadataCache)
0510:             */
0511:            public ExecuteResult statementExecute(AbstractRequest request,
0512:                    MetadataCache metadataCache) throws SQLException {
0513:                if (backend == null)
0514:                    throw new SQLException(
0515:                            "No available backend to execute request "
0516:                                    + request.getId());
0517:
0518:                try {
0519:                    AbstractConnectionManager cm = backend
0520:                            .getConnectionManager(request.getLogin());
0521:                    if (request.isAutoCommit()) { // Use a connection just for this request
0522:                        PooledConnection c = null;
0523:                        try {
0524:                            c = cm.retrieveConnectionInAutoCommit(request);
0525:                        } catch (UnreachableBackendException e1) {
0526:                            String backendName = backend.getName();
0527:                            String msg = Translate
0528:                                    .get(
0529:                                            "loadbalancer.backend.disabling.unreachable",
0530:                                            backendName);
0531:                            logger.error(msg);
0532:                            endUserLogger.error(msg);
0533:                            disableBackend(backend, true);
0534:                            backend = null;
0535:                            throw new SQLException(Translate.get(
0536:                                    "loadbalancer.backend.unreacheable",
0537:                                    backendName));
0538:                        }
0539:
0540:                        // Sanity check
0541:                        if (c == null)
0542:                            throw new SQLException(Translate.get(
0543:                                    "loadbalancer.backend.no.connection",
0544:                                    backend.getName()));
0545:
0546:                        // Execute Query
0547:                        ExecuteResult rs = null;
0548:                        try {
0549:                            rs = AbstractLoadBalancer
0550:                                    .executeStatementExecuteOnBackend(request,
0551:                                            backend, null, c, metadataCache);
0552:                        } catch (Exception e) {
0553:                            throw new SQLException(
0554:                                    Translate
0555:                                            .get(
0556:                                                    "loadbalancer.request.failed.on.backend",
0557:                                                    new String[] {
0558:                                                            request
0559:                                                                    .getSqlShortForm(vdb
0560:                                                                            .getSqlShortFormLength()),
0561:                                                            backend.getName(),
0562:                                                            e.getMessage() }));
0563:                        } finally {
0564:                            cm.releaseConnectionInAutoCommit(request, c);
0565:                        }
0566:                        return rs;
0567:                    } else { // Re-use the connection used by this transaction
0568:                        PooledConnection c = cm
0569:                                .retrieveConnectionForTransaction(request
0570:                                        .getTransactionId());
0571:
0572:                        // Sanity check
0573:                        if (c == null)
0574:                            throw new SQLException(Translate.get(
0575:                                    "loadbalancer.unable.retrieve.connection",
0576:                                    new String[] {
0577:                                            String.valueOf(request
0578:                                                    .getTransactionId()),
0579:                                            backend.getName() }));
0580:
0581:                        // Execute Query
0582:                        try {
0583:                            return AbstractLoadBalancer
0584:                                    .executeStatementExecuteOnBackend(request,
0585:                                            backend, null, c, metadataCache);
0586:                        } catch (Exception e) {
0587:                            throw new SQLException(
0588:                                    Translate
0589:                                            .get(
0590:                                                    "loadbalancer.request.failed.on.backend",
0591:                                                    new String[] {
0592:                                                            request
0593:                                                                    .getSqlShortForm(vdb
0594:                                                                            .getSqlShortFormLength()),
0595:                                                            backend.getName(),
0596:                                                            e.getMessage() }));
0597:                        }
0598:                    }
0599:                } catch (RuntimeException e) {
0600:                    String msg = Translate.get(
0601:                            "loadbalancer.request.failed.on.backend",
0602:                            new String[] {
0603:                                    request.getSqlShortForm(vdb
0604:                                            .getSqlShortFormLength()),
0605:                                    backend.getName(), e.getMessage() });
0606:                    logger.fatal(msg, e);
0607:                    endUserLogger.fatal(msg);
0608:                    throw new SQLException(msg);
0609:                }
0610:            }
0611:
0612:            /**
0613:             * @see org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer#readOnlyCallableStatementExecuteQuery(StoredProcedure,
0614:             *      MetadataCache)
0615:             */
0616:            public ControllerResultSet readOnlyCallableStatementExecuteQuery(
0617:                    StoredProcedure proc, MetadataCache metadataCache)
0618:                    throws SQLException {
0619:                return callableStatementExecuteQuery(proc, metadataCache);
0620:            }
0621:
0622:            /**
0623:             * @see org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer#readOnlyCallableStatementExecute(org.continuent.sequoia.controller.requests.StoredProcedure,
0624:             *      org.continuent.sequoia.controller.cache.metadata.MetadataCache)
0625:             */
0626:            public ExecuteResult readOnlyCallableStatementExecute(
0627:                    StoredProcedure proc, MetadataCache metadataCache)
0628:                    throws SQLException {
0629:                return callableStatementExecute(proc, metadataCache);
0630:            }
0631:
0632:            /**
0633:             * @see org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer#callableStatementExecuteQuery(StoredProcedure,
0634:             *      MetadataCache)
0635:             */
0636:            public ControllerResultSet callableStatementExecuteQuery(
0637:                    StoredProcedure proc, MetadataCache metadataCache)
0638:                    throws SQLException {
0639:                if (backend == null)
0640:                    throw new SQLException(
0641:                            "No available backend to execute stored procedure "
0642:                                    + proc.getId());
0643:
0644:                try {
0645:                    AbstractConnectionManager cm = backend
0646:                            .getConnectionManager(proc.getLogin());
0647:                    if (proc.isAutoCommit()) { // Use a connection just for this request
0648:                        PooledConnection c = null;
0649:                        try {
0650:                            c = cm.retrieveConnectionInAutoCommit(proc);
0651:                        } catch (UnreachableBackendException e1) {
0652:                            String backendName = backend.getName();
0653:                            String msg = Translate
0654:                                    .get(
0655:                                            "loadbalancer.backend.disabling.unreachable",
0656:                                            backendName);
0657:                            logger.error(msg);
0658:                            endUserLogger.error(msg);
0659:                            disableBackend(backend, true);
0660:                            backend = null;
0661:                            throw new SQLException(Translate.get(
0662:                                    "loadbalancer.backend.unreacheable",
0663:                                    backendName));
0664:                        }
0665:
0666:                        // Sanity check
0667:                        if (c == null)
0668:                            throw new SQLException(Translate.get(
0669:                                    "loadbalancer.backend.no.connection",
0670:                                    backend.getName()));
0671:
0672:                        // Execute Query
0673:                        ControllerResultSet rs = null;
0674:                        try {
0675:                            rs = AbstractLoadBalancer
0676:                                    .executeCallableStatementExecuteQueryOnBackend(
0677:                                            proc, backend, null, c
0678:                                                    .getConnection(),
0679:                                            metadataCache);
0680:                        } catch (Exception e) {
0681:                            throw new SQLException(
0682:                                    Translate
0683:                                            .get(
0684:                                                    "loadbalancer.storedprocedure.failed.on.backend",
0685:                                                    new String[] {
0686:                                                            proc
0687:                                                                    .getSqlShortForm(vdb
0688:                                                                            .getSqlShortFormLength()),
0689:                                                            backend.getName(),
0690:                                                            e.getMessage() }));
0691:                        } finally {
0692:                            cm.releaseConnectionInAutoCommit(proc, c);
0693:                        }
0694:                        return rs;
0695:                    } else { // Re-use the connection used by this transaction
0696:                        PooledConnection c = cm
0697:                                .retrieveConnectionForTransaction(proc
0698:                                        .getTransactionId());
0699:
0700:                        // Sanity check
0701:                        if (c == null)
0702:                            throw new SQLException(Translate.get(
0703:                                    "loadbalancer.unable.retrieve.connection",
0704:                                    new String[] {
0705:                                            String.valueOf(proc
0706:                                                    .getTransactionId()),
0707:                                            backend.getName() }));
0708:
0709:                        // Execute Query
0710:                        try {
0711:                            ControllerResultSet result = AbstractLoadBalancer
0712:                                    .executeCallableStatementExecuteQueryOnBackend(
0713:                                            proc, backend, null, c
0714:                                                    .getConnection(),
0715:                                            metadataCache);
0716:                            return result;
0717:                        } catch (Exception e) {
0718:                            throw new SQLException(
0719:                                    Translate
0720:                                            .get(
0721:                                                    "loadbalancer.storedprocedure.failed.on.backend",
0722:                                                    new String[] {
0723:                                                            proc
0724:                                                                    .getSqlShortForm(vdb
0725:                                                                            .getSqlShortFormLength()),
0726:                                                            backend.getName(),
0727:                                                            e.getMessage() }));
0728:                        }
0729:                    }
0730:                } catch (RuntimeException e) {
0731:                    String msg = Translate.get(
0732:                            "loadbalancer.storedprocedure.failed.on.backend",
0733:                            new String[] {
0734:                                    proc.getSqlShortForm(vdb
0735:                                            .getSqlShortFormLength()),
0736:                                    backend.getName(), e.getMessage() });
0737:                    logger.fatal(msg, e);
0738:                    endUserLogger.fatal(msg);
0739:                    throw new SQLException(msg);
0740:                }
0741:            }
0742:
0743:            /**
0744:             * @see org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer#callableStatementExecuteUpdate(org.continuent.sequoia.controller.requests.StoredProcedure)
0745:             */
0746:            public ExecuteUpdateResult callableStatementExecuteUpdate(
0747:                    StoredProcedure proc) throws SQLException {
0748:                if (backend == null)
0749:                    throw new SQLException(
0750:                            "No available backend to execute stored procedure "
0751:                                    + proc.getId());
0752:
0753:                try {
0754:                    AbstractConnectionManager cm = backend
0755:                            .getConnectionManager(proc.getLogin());
0756:                    if (proc.isAutoCommit()) { // Use a connection just for this request
0757:                        PooledConnection c = null;
0758:                        try {
0759:                            c = cm.retrieveConnectionInAutoCommit(proc);
0760:                        } catch (UnreachableBackendException e1) {
0761:                            String backendName = backend.getName();
0762:                            String msg = Translate
0763:                                    .get(
0764:                                            "loadbalancer.backend.disabling.unreachable",
0765:                                            backendName);
0766:                            logger.error(msg);
0767:                            endUserLogger.error(msg);
0768:                            disableBackend(backend, true);
0769:                            backend = null;
0770:                            throw new SQLException(Translate.get(
0771:                                    "loadbalancer.backend.unreacheable",
0772:                                    backendName));
0773:                        }
0774:
0775:                        // Sanity check
0776:                        if (c == null)
0777:                            throw new SQLException(Translate.get(
0778:                                    "loadbalancer.backend.no.connection",
0779:                                    backend.getName()));
0780:
0781:                        // Execute Query
0782:                        ExecuteUpdateResult result;
0783:                        try {
0784:                            result = AbstractLoadBalancer
0785:                                    .executeCallableStatementExecuteUpdateOnBackend(
0786:                                            proc, backend, null, c);
0787:                        } catch (Exception e) {
0788:                            throw new SQLException(
0789:                                    Translate
0790:                                            .get(
0791:                                                    "loadbalancer.storedprocedure.failed.on.backend",
0792:                                                    new String[] {
0793:                                                            proc
0794:                                                                    .getSqlShortForm(vdb
0795:                                                                            .getSqlShortFormLength()),
0796:                                                            backend.getName(),
0797:                                                            e.getMessage() }));
0798:                        } finally {
0799:                            cm.releaseConnectionInAutoCommit(proc, c);
0800:                        }
0801:                        return result;
0802:                    } else { // Re-use the connection used by this transaction
0803:                        PooledConnection c = cm
0804:                                .retrieveConnectionForTransaction(proc
0805:                                        .getTransactionId());
0806:
0807:                        // Sanity check
0808:                        if (c == null)
0809:                            throw new SQLException(Translate.get(
0810:                                    "loadbalancer.unable.retrieve.connection",
0811:                                    new String[] {
0812:                                            String.valueOf(proc
0813:                                                    .getTransactionId()),
0814:                                            backend.getName() }));
0815:
0816:                        // Execute Query
0817:                        try {
0818:                            ExecuteUpdateResult result = AbstractLoadBalancer
0819:                                    .executeCallableStatementExecuteUpdateOnBackend(
0820:                                            proc, backend, null, c);
0821:                            return result;
0822:                        } catch (Exception e) {
0823:                            throw new SQLException(
0824:                                    Translate
0825:                                            .get(
0826:                                                    "loadbalancer.storedprocedure.failed.on.backend",
0827:                                                    new String[] {
0828:                                                            proc
0829:                                                                    .getSqlShortForm(vdb
0830:                                                                            .getSqlShortFormLength()),
0831:                                                            backend.getName(),
0832:                                                            e.getMessage() }));
0833:                        }
0834:                    }
0835:                } catch (RuntimeException e) {
0836:                    String msg = Translate.get(
0837:                            "loadbalancer.storedprocedure.failed.on.backend",
0838:                            new String[] {
0839:                                    proc.getSqlShortForm(vdb
0840:                                            .getSqlShortFormLength()),
0841:                                    backend.getName(), e.getMessage() });
0842:                    logger.fatal(msg, e);
0843:                    endUserLogger.fatal(msg);
0844:                    throw new SQLException(msg);
0845:                }
0846:            }
0847:
0848:            /**
0849:             * @see org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer#callableStatementExecute(StoredProcedure,
0850:             *      MetadataCache)
0851:             */
0852:            public ExecuteResult callableStatementExecute(StoredProcedure proc,
0853:                    MetadataCache metadataCache) throws SQLException {
0854:                if (backend == null)
0855:                    throw new SQLException(
0856:                            "No available backend to execute stored procedure "
0857:                                    + proc.getId());
0858:
0859:                try {
0860:                    AbstractConnectionManager cm = backend
0861:                            .getConnectionManager(proc.getLogin());
0862:                    if (proc.isAutoCommit()) { // Use a connection just for this request
0863:                        PooledConnection c = null;
0864:                        try {
0865:                            c = cm.retrieveConnectionInAutoCommit(proc);
0866:                        } catch (UnreachableBackendException e1) {
0867:                            String backendName = backend.getName();
0868:                            String msg = Translate
0869:                                    .get(
0870:                                            "loadbalancer.backend.disabling.unreachable",
0871:                                            backendName);
0872:                            logger.error(msg);
0873:                            endUserLogger.error(msg);
0874:                            disableBackend(backend, true);
0875:                            backend = null;
0876:                            throw new SQLException(Translate.get(
0877:                                    "loadbalancer.backend.unreacheable",
0878:                                    backendName));
0879:                        }
0880:
0881:                        // Sanity check
0882:                        if (c == null)
0883:                            throw new SQLException(Translate.get(
0884:                                    "loadbalancer.backend.no.connection",
0885:                                    backend.getName()));
0886:
0887:                        // Execute Query
0888:                        ExecuteResult rs = null;
0889:                        try {
0890:                            rs = AbstractLoadBalancer
0891:                                    .executeCallableStatementExecuteOnBackend(
0892:                                            proc, backend, null, c,
0893:                                            metadataCache);
0894:                        } catch (Exception e) {
0895:                            throw new SQLException(
0896:                                    Translate
0897:                                            .get(
0898:                                                    "loadbalancer.storedprocedure.failed.on.backend",
0899:                                                    new String[] {
0900:                                                            proc
0901:                                                                    .getSqlShortForm(vdb
0902:                                                                            .getSqlShortFormLength()),
0903:                                                            backend.getName(),
0904:                                                            e.getMessage() }));
0905:                        } finally {
0906:                            cm.releaseConnectionInAutoCommit(proc, c);
0907:                        }
0908:                        return rs;
0909:                    } else { // Re-use the connection used by this transaction
0910:                        PooledConnection c = cm
0911:                                .retrieveConnectionForTransaction(proc
0912:                                        .getTransactionId());
0913:
0914:                        // Sanity check
0915:                        if (c == null)
0916:                            throw new SQLException(Translate.get(
0917:                                    "loadbalancer.unable.retrieve.connection",
0918:                                    new String[] {
0919:                                            String.valueOf(proc
0920:                                                    .getTransactionId()),
0921:                                            backend.getName() }));
0922:
0923:                        // Execute Query
0924:                        try {
0925:                            ExecuteResult result = AbstractLoadBalancer
0926:                                    .executeCallableStatementExecuteOnBackend(
0927:                                            proc, backend, null, c,
0928:                                            metadataCache);
0929:                            return result;
0930:                        } catch (Exception e) {
0931:                            throw new SQLException(
0932:                                    Translate
0933:                                            .get(
0934:                                                    "loadbalancer.storedprocedure.failed.on.backend",
0935:                                                    new String[] {
0936:                                                            proc
0937:                                                                    .getSqlShortForm(vdb
0938:                                                                            .getSqlShortFormLength()),
0939:                                                            backend.getName(),
0940:                                                            e.getMessage() }));
0941:                        }
0942:                    }
0943:                } catch (RuntimeException e) {
0944:                    String msg = Translate.get(
0945:                            "loadbalancer.storedprocedure.failed.on.backend",
0946:                            new String[] {
0947:                                    proc.getSqlShortForm(vdb
0948:                                            .getSqlShortFormLength()),
0949:                                    backend.getName(), e.getMessage() });
0950:                    logger.fatal(msg, e);
0951:                    endUserLogger.fatal(msg);
0952:                    throw new SQLException(msg);
0953:                }
0954:            }
0955:
0956:            /**
0957:             * @see org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer#getPreparedStatementGetMetaData(AbstractRequest)
0958:             */
0959:            public ControllerResultSet getPreparedStatementGetMetaData(
0960:                    AbstractRequest request) throws SQLException {
0961:                if (backend == null)
0962:                    throw new NoMoreBackendException(Translate.get(
0963:                            "loadbalancer.execute.no.backend.available",
0964:                            request.getSqlOrTemplate()));
0965:
0966:                try {
0967:                    AbstractConnectionManager cm = backend
0968:                            .getConnectionManager(request.getLogin());
0969:                    ControllerResultSet rs = null;
0970:                    boolean badConnection;
0971:                    do {
0972:                        badConnection = false;
0973:                        // Use a connection just for this request
0974:                        PooledConnection c = null;
0975:                        try {
0976:                            c = cm.retrieveConnectionInAutoCommit(request);
0977:                        } catch (UnreachableBackendException e1) {
0978:                            String backendName = backend.getName();
0979:                            String msg = Translate
0980:                                    .get(
0981:                                            "loadbalancer.backend.disabling.unreachable",
0982:                                            backendName);
0983:                            logger.error(msg);
0984:                            endUserLogger.error(msg);
0985:                            disableBackend(backend, true);
0986:                            backend = null;
0987:                            throw new SQLException(Translate.get(
0988:                                    "loadbalancer.backend.unreacheable",
0989:                                    backendName));
0990:                        }
0991:
0992:                        // Sanity check
0993:                        if (c == null)
0994:                            throw new SQLException(Translate.get(
0995:                                    "loadbalancer.backend.no.connection",
0996:                                    backend.getName()));
0997:
0998:                        // Execute Query
0999:                        try {
1000:                            rs = preparedStatementGetMetaDataOnBackend(request
1001:                                    .getSqlOrTemplate(), backend, c
1002:                                    .getConnection());
1003:                            cm.releaseConnectionInAutoCommit(request, c);
1004:                        } catch (SQLException e) {
1005:                            cm.releaseConnectionInAutoCommit(request, c);
1006:                            throw new SQLException(
1007:                                    Translate
1008:                                            .get(
1009:                                                    "loadbalancer.request.failed.on.backend",
1010:                                                    new String[] {
1011:                                                            request
1012:                                                                    .getSqlOrTemplate(),
1013:                                                            backend.getName(),
1014:                                                            e.getMessage() }));
1015:                        } catch (BadConnectionException e) { // Get rid of the bad connection
1016:                            cm.deleteConnection(c);
1017:                            badConnection = true;
1018:                        } catch (Throwable e) {
1019:                            cm.releaseConnectionInAutoCommit(request, c);
1020:                            throw new SQLException(
1021:                                    Translate
1022:                                            .get(
1023:                                                    "loadbalancer.request.failed.on.backend",
1024:                                                    new String[] {
1025:                                                            request
1026:                                                                    .getSqlOrTemplate(),
1027:                                                            backend.getName(),
1028:                                                            e.getMessage() }));
1029:                        }
1030:                    } while (badConnection);
1031:                    return rs;
1032:                } catch (RuntimeException e) {
1033:                    String msg = Translate.get(
1034:                            "loadbalancer.getmetadata.failed", new String[] {
1035:                                    request.getSqlOrTemplate(),
1036:                                    backend.getURL(), e.getMessage() });
1037:                    logger.fatal(msg, e);
1038:                    endUserLogger.fatal(msg);
1039:                    throw new SQLException(msg);
1040:                }
1041:            }
1042:
1043:            /*
1044:             * Transaction management
1045:             */
1046:
1047:            /**
1048:             * @see org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer#abort(org.continuent.sequoia.controller.requestmanager.TransactionMetaData)
1049:             */
1050:            public void abort(TransactionMetaData tm) throws SQLException {
1051:                rollback(tm);
1052:            }
1053:
1054:            /**
1055:             * Begins a new transaction.
1056:             * 
1057:             * @param tm the transaction marker metadata
1058:             * @exception SQLException if an error occurs
1059:             */
1060:            public void begin(TransactionMetaData tm) throws SQLException {
1061:                if (backend == null)
1062:                    throw new SQLException(
1063:                            "No available backend to begin transaction "
1064:                                    + tm.getTransactionId());
1065:
1066:                // We do not accept new transactions if we are disabling the backend
1067:                if (!backend.canAcceptTasks(null))
1068:                    throw new SQLException(Translate.get(
1069:                            "loadbalancer.backend.is.disabling", new String[] {
1070:                                    "begin transaction "
1071:                                            + tm.getTransactionId(),
1072:                                    backend.getName() }));
1073:
1074:                try {
1075:                    PooledConnection c = backend.getConnectionManager(
1076:                            tm.getLogin()).getConnectionForTransaction(
1077:                            tm.getTransactionId());
1078:
1079:                    if (c == null)
1080:                        throw new SQLException(Translate.get(
1081:                                "loadbalancer.backend.no.connection", backend
1082:                                        .getName()));
1083:
1084:                    c.getConnection().setAutoCommit(false);
1085:                } catch (Exception e) {
1086:                    throw new SQLException("Begin of transaction "
1087:                            + tm.getTransactionId() + " failed on backend "
1088:                            + backend.getURL() + " (" + e + ")");
1089:                }
1090:            }
1091:
1092:            /**
1093:             * Commits a transaction.
1094:             * 
1095:             * @param tm the transaction marker metadata
1096:             * @exception SQLException if an error occurs
1097:             */
1098:            public void commit(TransactionMetaData tm) throws SQLException {
1099:                if (backend == null)
1100:                    throw new SQLException(
1101:                            "No available backend to commit transaction "
1102:                                    + tm.getTransactionId());
1103:
1104:                try {
1105:                    AbstractConnectionManager cm = backend
1106:                            .getConnectionManager(tm.getLogin());
1107:                    PooledConnection pc = cm
1108:                            .retrieveConnectionForTransaction(tm
1109:                                    .getTransactionId());
1110:
1111:                    if (pc == null)
1112:                        throw new SQLException(
1113:                                "No connection found for transaction "
1114:                                        + tm.getTransactionId());
1115:
1116:                    try {
1117:                        Connection c = pc.getConnection();
1118:                        c.commit();
1119:                        c.setAutoCommit(true);
1120:                    } catch (SQLException e) {
1121:                        throw new SQLException(Translate.get(
1122:                                "loadbalancer.commit.failed", new String[] {
1123:                                        String.valueOf(tm.getTransactionId()),
1124:                                        backend.getName(), e.getMessage() }));
1125:                    } finally {
1126:                        cm.releaseConnectionForTransaction(tm
1127:                                .getTransactionId());
1128:                    }
1129:                } catch (RuntimeException e) {
1130:                    String msg = Translate.get("loadbalancer.commit.failed",
1131:                            new String[] {
1132:                                    String.valueOf(tm.getTransactionId()),
1133:                                    backend.getName(), e.getMessage() });
1134:                    logger.fatal(msg, e);
1135:                    endUserLogger.fatal(msg);
1136:                    throw new SQLException(msg);
1137:                }
1138:            }
1139:
1140:            /**
1141:             * Rollbacks a transaction.
1142:             * 
1143:             * @param tm the transaction marker metadata
1144:             * @exception SQLException if an error occurs
1145:             */
1146:            public void rollback(TransactionMetaData tm) throws SQLException {
1147:                if (backend == null)
1148:                    throw new SQLException(
1149:                            "No available backend to rollback transaction "
1150:                                    + tm.getTransactionId());
1151:
1152:                try {
1153:                    AbstractConnectionManager cm = backend
1154:                            .getConnectionManager(tm.getLogin());
1155:                    PooledConnection pc = cm
1156:                            .retrieveConnectionForTransaction(tm
1157:                                    .getTransactionId());
1158:
1159:                    if (pc == null)
1160:                        throw new SQLException(
1161:                                "No connection found for transaction "
1162:                                        + tm.getTransactionId());
1163:
1164:                    try {
1165:                        Connection c = pc.getConnection();
1166:                        c.rollback();
1167:                        c.setAutoCommit(true);
1168:                    } catch (SQLException e) {
1169:                        throw new SQLException(Translate.get(
1170:                                "loadbalancer.rollback.failed", new String[] {
1171:                                        String.valueOf(tm.getTransactionId()),
1172:                                        backend.getName(), e.getMessage() }));
1173:                    } finally {
1174:                        cm.releaseConnectionForTransaction(tm
1175:                                .getTransactionId());
1176:                    }
1177:                } catch (RuntimeException e) {
1178:                    String msg = Translate.get("loadbalancer.rollback.failed",
1179:                            new String[] {
1180:                                    String.valueOf(tm.getTransactionId()),
1181:                                    backend.getName(), e.getMessage() });
1182:                    logger.fatal(msg, e);
1183:                    endUserLogger.fatal(msg);
1184:                    throw new SQLException(msg);
1185:                }
1186:            }
1187:
1188:            /**
1189:             * Rollback a transaction to a savepoint
1190:             * 
1191:             * @param tm The transaction marker metadata
1192:             * @param savepointName The name of the savepoint
1193:             * @throws SQLException if an error occurs
1194:             */
1195:            public void rollbackToSavepoint(TransactionMetaData tm,
1196:                    String savepointName) throws SQLException {
1197:                if (backend == null)
1198:                    throw new SQLException(
1199:                            "No available backend to rollback transaction "
1200:                                    + tm.getTransactionId());
1201:
1202:                try {
1203:                    AbstractConnectionManager cm = backend
1204:                            .getConnectionManager(tm.getLogin());
1205:                    PooledConnection c = cm.retrieveConnectionForTransaction(tm
1206:                            .getTransactionId());
1207:
1208:                    if (c == null)
1209:                        throw new SQLException(
1210:                                "No connection found for transaction "
1211:                                        + tm.getTransactionId());
1212:
1213:                    Savepoint savepoint = backend.getSavepoint(new Long(tm
1214:                            .getTransactionId()), savepointName);
1215:
1216:                    if (savepoint == null)
1217:                        throw new SQLException("No savepoint with name "
1218:                                + savepointName
1219:                                + " has been found for transaction "
1220:                                + tm.getTransactionId());
1221:
1222:                    try {
1223:                        c.getConnection().rollback(savepoint);
1224:                    } catch (SQLException e) {
1225:                        throw new SQLException(Translate.get(
1226:                                "loadbalancer.rollbacksavepoint.failed",
1227:                                new String[] { savepointName,
1228:                                        String.valueOf(tm.getTransactionId()),
1229:                                        backend.getName(), e.getMessage() }));
1230:                    }
1231:                } catch (RuntimeException e) {
1232:                    String msg = Translate.get(
1233:                            "loadbalancer.rollbacksavepoint.failed",
1234:                            new String[] { savepointName,
1235:                                    String.valueOf(tm.getTransactionId()),
1236:                                    backend.getName(), e.getMessage() });
1237:                    logger.fatal(msg, e);
1238:                    endUserLogger.fatal(msg);
1239:                    throw new SQLException(msg);
1240:                }
1241:            }
1242:
1243:            /**
1244:             * Release a savepoint from a transaction
1245:             * 
1246:             * @param tm The transaction marker metadata
1247:             * @param savepointName The name of the savepoint ro release
1248:             * @throws SQLException if an error occurs
1249:             */
1250:            public void releaseSavepoint(TransactionMetaData tm,
1251:                    String savepointName) throws SQLException {
1252:                if (backend == null)
1253:                    throw new SQLException(
1254:                            "No available backend to release savepoint from "
1255:                                    + " transaction " + tm.getTransactionId());
1256:
1257:                try {
1258:                    AbstractConnectionManager cm = backend
1259:                            .getConnectionManager(tm.getLogin());
1260:                    PooledConnection c = cm.retrieveConnectionForTransaction(tm
1261:                            .getTransactionId());
1262:
1263:                    if (c == null)
1264:                        throw new SQLException(
1265:                                "No connection found for transaction "
1266:                                        + tm.getTransactionId());
1267:
1268:                    Savepoint savepoint = backend.getSavepoint(new Long(tm
1269:                            .getTransactionId()), savepointName);
1270:
1271:                    if (savepoint == null)
1272:                        throw new SQLException("No savepoint with name "
1273:                                + savepointName + " has been "
1274:                                + "found for transaction "
1275:                                + tm.getTransactionId());
1276:
1277:                    try {
1278:                        c.getConnection().releaseSavepoint(savepoint);
1279:                    } catch (SQLException e) {
1280:                        throw new SQLException(Translate.get(
1281:                                "loadbalancer.releasesavepoint.failed",
1282:                                new String[] { savepointName,
1283:                                        String.valueOf(tm.getTransactionId()),
1284:                                        backend.getName(), e.getMessage() }));
1285:                    } finally {
1286:                        backend.removeSavepoint(
1287:                                new Long(tm.getTransactionId()), savepoint);
1288:                    }
1289:                } catch (RuntimeException e) {
1290:                    String msg = Translate.get(
1291:                            "loadbalancer.releasesavepoint.failed",
1292:                            new String[] { savepointName,
1293:                                    String.valueOf(tm.getTransactionId()),
1294:                                    backend.getName(), e.getMessage() });
1295:                    logger.fatal(msg, e);
1296:                    endUserLogger.fatal(msg);
1297:                    throw new SQLException(msg);
1298:                }
1299:            }
1300:
1301:            /**
1302:             * Set a savepoint to a transaction.
1303:             * 
1304:             * @param tm The transaction marker metadata
1305:             * @param savepointName The name of the new savepoint
1306:             * @throws AllBackendsFailedException if no backend succeeded in setting the
1307:             *           savepoint.
1308:             * @throws SQLException if an error occurs
1309:             */
1310:            public void setSavepoint(TransactionMetaData tm,
1311:                    String savepointName) throws AllBackendsFailedException,
1312:                    SQLException {
1313:                if (backend == null)
1314:                    throw new SQLException(
1315:                            "No available backend to set savepoint to "
1316:                                    + " transaction " + tm.getTransactionId());
1317:
1318:                try {
1319:                    AbstractConnectionManager cm = backend
1320:                            .getConnectionManager(tm.getLogin());
1321:                    PooledConnection c = cm.retrieveConnectionForTransaction(tm
1322:                            .getTransactionId());
1323:
1324:                    if (c == null)
1325:                        throw new SQLException(
1326:                                "No connection found for transaction "
1327:                                        + tm.getTransactionId());
1328:
1329:                    Savepoint savepoint = null;
1330:                    try {
1331:                        savepoint = c.getConnection().setSavepoint(
1332:                                savepointName);
1333:                    } catch (SQLException e) {
1334:                        throw new SQLException(Translate.get(
1335:                                "loadbalancer.setsavepoint.failed",
1336:                                new String[] { savepointName,
1337:                                        String.valueOf(tm.getTransactionId()),
1338:                                        backend.getName(), e.getMessage() }));
1339:                    } finally {
1340:                        if (savepoint != null)
1341:                            backend.addSavepoint(
1342:                                    new Long(tm.getTransactionId()), savepoint);
1343:                    }
1344:                } catch (RuntimeException e) {
1345:                    String msg = Translate.get(
1346:                            "loadbalancer.setsavepoint.failed", new String[] {
1347:                                    savepointName,
1348:                                    String.valueOf(tm.getTransactionId()),
1349:                                    backend.getName(), e.getMessage() });
1350:                    logger.fatal(msg, e);
1351:                    endUserLogger.fatal(msg);
1352:                    throw new SQLException(msg);
1353:                }
1354:            }
1355:
1356:            /**
1357:             * @see org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer#closePersistentConnection(java.lang.String,
1358:             *      long)
1359:             */
1360:            public void closePersistentConnection(String login,
1361:                    long persistentConnectionId) throws SQLException {
1362:                AbstractConnectionManager cm = backend
1363:                        .getConnectionManager(login);
1364:                if (cm != null) {
1365:                    // Release the connection if it exists
1366:                    cm
1367:                            .releasePersistentConnectionInAutoCommit(persistentConnectionId);
1368:                    backend.removePersistentConnection(persistentConnectionId);
1369:                }
1370:            }
1371:
1372:            /**
1373:             * @see org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer#openPersistentConnection(String,
1374:             *      long)
1375:             */
1376:            public void openPersistentConnection(String login,
1377:                    long persistentConnectionId) throws SQLException {
1378:                AbstractConnectionManager cm = backend
1379:                        .getConnectionManager(login);
1380:                if (cm == null) {
1381:                    throw new SQLException(
1382:                            "No connection manager found for user " + login);
1383:                }
1384:
1385:                // Get a new connection
1386:                AbstractRequest request = new UnknownReadRequest("", false, 0,
1387:                        "");
1388:                request.setLogin(login);
1389:                request.setPersistentConnection(true);
1390:                request.setPersistentConnectionId(persistentConnectionId);
1391:                try {
1392:                    PooledConnection c = cm
1393:                            .retrieveConnectionInAutoCommit(request);
1394:                    backend.addPersistentConnection(request
1395:                            .getPersistentConnectionId(), c);
1396:                } catch (UnreachableBackendException e) {
1397:                    throw new SQLException(
1398:                            "Backend is not reachable to open persistent conenction "
1399:                                    + persistentConnectionId);
1400:                }
1401:            }
1402:
1403:            /*
1404:             * Backends management
1405:             */
1406:
1407:            /**
1408:             * Enables a backend that was previously disabled. Asks the corresponding
1409:             * connection manager to initialize the connections if needed.
1410:             * 
1411:             * @param db the database backend to enable
1412:             * @param writeEnabled True if the backend must be enabled for writes
1413:             * @throws SQLException if an error occurs
1414:             */
1415:            public void enableBackend(DatabaseBackend db, boolean writeEnabled)
1416:                    throws SQLException {
1417:                if (backend != null) {
1418:                    if (backend.isReadEnabled())
1419:                        throw new SQLException(
1420:                                "SingleDB load balancer accepts only one backend and "
1421:                                        + backend.getName()
1422:                                        + " is already enabled. Skipping "
1423:                                        + db.getName() + " initialization.");
1424:                }
1425:                backend = db;
1426:                logger.info(Translate.get("loadbalancer.backend.enabling", db
1427:                        .getName()));
1428:                if (!backend.isInitialized())
1429:                    backend.initializeConnections();
1430:                backend.enableRead();
1431:                if (writeEnabled)
1432:                    backend.enableWrite();
1433:            }
1434:
1435:            /**
1436:             * Disables a backend that was previously enabled. Asks the corresponding
1437:             * connection manager to finalize the connections if needed.
1438:             * 
1439:             * @param db the database backend to disable
1440:             * @param forceDisable true if disabling must be forced on the backend
1441:             * @throws SQLException if an error occurs
1442:             */
1443:            public void disableBackend(DatabaseBackend db, boolean forceDisable)
1444:                    throws SQLException {
1445:                if (backend.equals(db)) {
1446:                    logger.info(Translate.get("loadbalancer.backend.disabling",
1447:                            db.getName()));
1448:                    backend.disable();
1449:                    if (backend.isInitialized())
1450:                        backend.finalizeConnections();
1451:                    backend = null;
1452:                } else {
1453:                    String msg = "Trying to disable a non-existing backend "
1454:                            + db.getName();
1455:                    logger.warn(msg);
1456:                    throw new SQLException(msg);
1457:                }
1458:            }
1459:
1460:            /**
1461:             * @see org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer#setWeight(String,
1462:             *      int)
1463:             */
1464:            public void setWeight(String name, int w) throws SQLException {
1465:                throw new SQLException(
1466:                        "Weight is not supported with this load balancer");
1467:            }
1468:
1469:            /**
1470:             * @see org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer#getNumberOfEnabledBackends()
1471:             */
1472:            public int getNumberOfEnabledBackends() {
1473:                if (backend == null)
1474:                    return 0;
1475:                else
1476:                    return 1;
1477:            }
1478:
1479:            /*
1480:             * Debug/Monitoring
1481:             */
1482:
1483:            /**
1484:             * Gets information about the request load balancer
1485:             * 
1486:             * @return <code>String</code> containing information
1487:             */
1488:            public String getInformation() {
1489:                if (backend == null)
1490:                    return "SingleDB Request load balancer: !!!Warning!!! No enabled backend node found\n";
1491:                else
1492:                    return "SingleDB Request load balancer using "
1493:                            + backend.getURL() + "\n";
1494:            }
1495:
1496:            /**
1497:             * @see org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer#getXmlImpl()
1498:             */
1499:            public String getXmlImpl() {
1500:                return "<" + DatabasesXmlTags.ELT_SingleDB + "/>";
1501:            }
1502:
1503:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.