KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > continuent > sequoia > controller > loadbalancer > singledb > SingleDB


1 /**
2  * Sequoia: Database clustering technology.
3  * Copyright (C) 2002-2004 French National Institute For Research In Computer
4  * Science And Control (INRIA).
5  * Copyright (C) 2005 AmicoSoft, Inc. dba Emic Networks
6  * Contact: sequoia@continuent.org
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  * Initial developer(s): Emmanuel Cecchet.
21  * Contributor(s): Vadim Kassin, Jaco Swart, Jean-Bernard van Zuylen.
22  */

23
24 package org.continuent.sequoia.controller.loadbalancer.singledb;
25
26 import java.sql.Connection JavaDoc;
27 import java.sql.SQLException JavaDoc;
28 import java.sql.Savepoint JavaDoc;
29
30 import org.continuent.sequoia.common.exceptions.BadConnectionException;
31 import org.continuent.sequoia.common.exceptions.NoMoreBackendException;
32 import org.continuent.sequoia.common.exceptions.UnreachableBackendException;
33 import org.continuent.sequoia.common.i18n.Translate;
34 import org.continuent.sequoia.common.log.Trace;
35 import org.continuent.sequoia.common.xml.DatabasesXmlTags;
36 import org.continuent.sequoia.controller.backend.DatabaseBackend;
37 import org.continuent.sequoia.controller.backend.result.ControllerResultSet;
38 import org.continuent.sequoia.controller.backend.result.ExecuteResult;
39 import org.continuent.sequoia.controller.backend.result.ExecuteUpdateResult;
40 import org.continuent.sequoia.controller.backend.result.GeneratedKeysResult;
41 import org.continuent.sequoia.controller.cache.metadata.MetadataCache;
42 import org.continuent.sequoia.controller.connection.AbstractConnectionManager;
43 import org.continuent.sequoia.controller.connection.PooledConnection;
44 import org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer;
45 import org.continuent.sequoia.controller.loadbalancer.AllBackendsFailedException;
46 import org.continuent.sequoia.controller.loadbalancer.policies.WaitForCompletionPolicy;
47 import org.continuent.sequoia.controller.requestmanager.RAIDbLevels;
48 import org.continuent.sequoia.controller.requestmanager.TransactionMetaData;
49 import org.continuent.sequoia.controller.requests.AbstractRequest;
50 import org.continuent.sequoia.controller.requests.AbstractWriteRequest;
51 import org.continuent.sequoia.controller.requests.ParsingGranularities;
52 import org.continuent.sequoia.controller.requests.SelectRequest;
53 import org.continuent.sequoia.controller.requests.StoredProcedure;
54 import org.continuent.sequoia.controller.requests.UnknownReadRequest;
55 import org.continuent.sequoia.controller.virtualdatabase.VirtualDatabase;
56
57 /**
58  * Single Database request load balancer.
59  * <p>
60  * The requests coming from the request controller are directly forwarded to the
61  * single backend. This load balancer does not support multiple backends and
62  * does not update the recovery log (it is not meant to be used with a recovery
63  * log).
64  *
65  * @author <a HREF="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
66  * @author <a HREF="mailto:vadim@kase.kz">Vadim Kassin </a>
67  * @author <a HREF="mailto:jaco.swart@iblocks.co.uk">Jaco Swart </a>
68  * @author <a HREF="mailto:jbvanzuylen@transwide.com">Jean-Bernard van Zuylen
69  * </a>
70  * @version 1.0
71  */

72 public class SingleDB extends AbstractLoadBalancer
73 {
74   //
75
// How the code is organized?
76
// 1. Member variables
77
// 2. Constructor(s)
78
// 3. Request handling
79
// 4. Transaction handling
80
// 5. Backend management
81
// 6. Debug/Monitoring
82
//
83

84   private DatabaseBackend backend;
85
86   private static Trace logger = Trace
87                                             .getLogger("org.continuent.sequoia.controller.loadbalancer.SingleDB");
88
89   static Trace endUserLogger = Trace
90                                             .getLogger("org.continuent.sequoia.enduser");
91
92   /*
93    * Constructors
94    */

95
96   /**
97    * Creates a new <code>SingleDB</code> instance.
98    *
99    * @param vdb the <code>VirtualDatabase</code> this load balancer belongs to
100    * @throws Exception if there is not exactly one backend attached to the
101    * <code>VirtualDatabase</code>
102    */

103   public SingleDB(VirtualDatabase vdb) throws Exception JavaDoc
104   {
105     // We don't need to parse the requests, just send them to the backend
106
super(vdb, RAIDbLevels.SingleDB, ParsingGranularities.NO_PARSING);
107     this.waitForCompletionPolicy = new WaitForCompletionPolicy(
108         WaitForCompletionPolicy.ALL, false, ParsingGranularities.NO_PARSING);
109   }
110
111   /*
112    * Request Handling
113    */

114
115   /**
116    * Performs a read request. It is up to the implementation to choose to which
117    * backend node(s) this request should be sent.
118    *
119    * @param request an <code>SelectRequest</code>
120    * @param metadataCache MetadataCache (null if none)
121    * @return the corresponding <code>java.sql.ResultSet</code>
122    * @exception SQLException if an error occurs
123    */

124   public ControllerResultSet statementExecuteQuery(SelectRequest request,
125       MetadataCache metadataCache) throws SQLException JavaDoc
126   {
127     if (backend == null)
128       throw new NoMoreBackendException(Translate.get(
129           "loadbalancer.execute.no.backend.available", request.getId()));
130
131     try
132     {
133       AbstractConnectionManager cm = backend.getConnectionManager(request
134           .getLogin());
135       if (request.isAutoCommit())
136       {
137         ControllerResultSet rs = null;
138         boolean badConnection;
139         do
140         {
141           badConnection = false;
142           // Use a connection just for this request
143
PooledConnection c = null;
144           try
145           {
146             c = cm.retrieveConnectionInAutoCommit(request);
147           }
148           catch (UnreachableBackendException e1)
149           {
150             String JavaDoc backendName = backend.getName();
151             String JavaDoc msg = Translate.get(
152                 "loadbalancer.backend.disabling.unreachable", backendName);
153             logger.error(msg);
154             endUserLogger.error(msg);
155             disableBackend(backend, true);
156             backend = null;
157             throw new SQLException JavaDoc(Translate.get(
158                 "loadbalancer.backend.unreacheable", backendName));
159           }
160
161           // Sanity check
162
if (c == null)
163             throw new SQLException JavaDoc(Translate.get(
164                 "loadbalancer.backend.no.connection", backend.getName()));
165
166           // Execute Query
167
try
168           {
169             rs = executeStatementExecuteQueryOnBackend(request, backend, null,
170                 c.getConnection(), metadataCache);
171             cm.releaseConnectionInAutoCommit(request, c);
172           }
173           catch (SQLException JavaDoc e)
174           {
175             cm.releaseConnectionInAutoCommit(request, c);
176             throw new SQLException JavaDoc(Translate.get(
177                 "loadbalancer.request.failed.on.backend", new String JavaDoc[]{
178                     request.getSqlShortForm(vdb.getSqlShortFormLength()),
179                     backend.getName(), e.getMessage()}));
180           }
181           catch (BadConnectionException e)
182           { // Get rid of the bad connection
183
cm.deleteConnection(c);
184             badConnection = true;
185           }
186           catch (Throwable JavaDoc e)
187           {
188             cm.releaseConnectionInAutoCommit(request, c);
189             throw new SQLException JavaDoc(Translate.get(
190                 "loadbalancer.request.failed.on.backend", new String JavaDoc[]{
191                     request.getSqlShortForm(vdb.getSqlShortFormLength()),
192                     backend.getName(), e.getMessage()}));
193           }
194         }
195         while (badConnection);
196         return rs;
197       }
198       else
199       {
200         long tid = request.getTransactionId();
201         // Re-use the connection used by this transaction
202
PooledConnection c = cm.retrieveConnectionForTransaction(tid);
203
204         // Sanity check
205
if (c == null)
206           throw new SQLException JavaDoc(Translate.get(
207               "loadbalancer.unable.retrieve.connection", new String JavaDoc[]{
208                   String.valueOf(tid), backend.getName()}));
209
210         // Execute Query
211
ControllerResultSet rs = null;
212         try
213         {
214           rs = executeStatementExecuteQueryOnBackend(request, backend, null, c
215               .getConnection(), metadataCache);
216         }
217         catch (SQLException JavaDoc e)
218         {
219           throw new SQLException JavaDoc(Translate.get(
220               "loadbalancer.request.failed.on.backend", new String JavaDoc[]{
221                   request.getSqlShortForm(vdb.getSqlShortFormLength()),
222                   backend.getName(), e.getMessage()}));
223         }
224         catch (BadConnectionException e)
225         { // Get rid of the bad connection
226
cm.deleteConnection(tid);
227           throw new SQLException JavaDoc(Translate.get(
228               "loadbalancer.connection.failed", new String JavaDoc[]{
229                   String.valueOf(tid), backend.getName(), e.getMessage()}));
230         }
231         catch (Throwable JavaDoc e)
232         {
233           throw new SQLException JavaDoc(Translate.get(
234               "loadbalancer.request.failed.on.backend", new String JavaDoc[]{
235                   request.getSqlShortForm(vdb.getSqlShortFormLength()),
236                   backend.getName(), e.getMessage()}));
237         }
238         return rs;
239       }
240     }
241     catch (RuntimeException JavaDoc e)
242     {
243       String JavaDoc msg = "Request '"
244           + request.getSqlShortForm(vdb.getSqlShortFormLength())
245           + "' failed on backend " + backend.getURL() + " (" + e + ")";
246       logger.fatal(msg, e);
247       throw new SQLException JavaDoc(msg);
248     }
249   }
250
251   /**
252    * Performs a write request on the backend.
253    *
254    * @param request an <code>AbstractWriteRequest</code>
255    * @return number of rows affected by the request
256    * @exception SQLException if an error occurs
257    */

258   public ExecuteUpdateResult statementExecuteUpdate(AbstractWriteRequest request)
259       throws SQLException JavaDoc
260   {
261     if (backend == null)
262       throw new NoMoreBackendException(Translate.get(
263           "loadbalancer.execute.no.backend.available", request.getId()));
264
265     try
266     {
267       AbstractConnectionManager cm = backend.getConnectionManager(request
268           .getLogin());
269       if (request.isAutoCommit())
270       {
271         // We do not execute request outside the already open transactions if we
272
// are disabling the backend.
273
if (!backend.canAcceptTasks(request))
274           throw new SQLException JavaDoc(Translate.get(
275               "loadbalancer.backend.is.disabling", new String JavaDoc[]{
276                   request.getSqlShortForm(vdb.getSqlShortFormLength()),
277                   backend.getName()}));
278
279         // Use a connection just for this request
280
PooledConnection c = null;
281         try
282         {
283           c = cm.retrieveConnectionInAutoCommit(request);
284         }
285         catch (UnreachableBackendException e1)
286         {
287           String JavaDoc backendName = backend.getName();
288           String JavaDoc msg = Translate.get(
289               "loadbalancer.backend.disabling.unreachable", backendName);
290           logger.error(msg);
291           endUserLogger.error(msg);
292           disableBackend(backend, true);
293           backend = null;
294           throw new SQLException JavaDoc(Translate.get(
295               "loadbalancer.backend.unreacheable", backendName));
296         }
297
298         // Sanity check
299
if (c == null)
300           throw new SQLException JavaDoc(Translate.get(
301               "loadbalancer.backend.no.connection", backend.getName()));
302
303         // Execute Query
304
ExecuteUpdateResult result;
305         try
306         {
307           result = executeStatementExecuteUpdateOnBackend(request, backend,
308               null, c.getConnection());
309         }
310         catch (Exception JavaDoc e)
311         {
312           throw new SQLException JavaDoc(Translate.get(
313               "loadbalancer.request.failed.on.backend", new String JavaDoc[]{
314                   request.getSqlShortForm(vdb.getSqlShortFormLength()),
315                   backend.getName(), e.getMessage()}));
316         }
317         finally
318         {
319           cm.releaseConnectionInAutoCommit(request, c);
320         }
321         return result;
322       }
323       else
324       { // Re-use the connection used by this transaction
325
PooledConnection c = cm.retrieveConnectionForTransaction(request
326             .getTransactionId());
327
328         // Sanity check
329
if (c == null)
330           throw new SQLException JavaDoc(Translate.get(
331               "loadbalancer.unable.retrieve.connection",
332               new String JavaDoc[]{String.valueOf(request.getTransactionId()),
333                   backend.getName()}));
334
335         // Execute Query
336
try
337         {
338           ExecuteUpdateResult result = executeStatementExecuteUpdateOnBackend(
339               request, backend, null, c.getConnection());
340           return result;
341         }
342         catch (Exception JavaDoc e)
343         {
344           throw new SQLException JavaDoc(Translate.get(
345               "loadbalancer.request.failed.on.backend", new String JavaDoc[]{
346                   request.getSqlShortForm(vdb.getSqlShortFormLength()),
347                   backend.getName(), e.getMessage()}));
348         }
349       }
350     }
351     catch (RuntimeException JavaDoc e)
352     {
353       String JavaDoc msg = Translate.get("loadbalancer.request.failed.on.backend",
354           new String JavaDoc[]{request.getSqlShortForm(vdb.getSqlShortFormLength()),
355               backend.getName(), e.getMessage()});
356       endUserLogger.fatal(msg);
357       logger.fatal(msg, e);
358       throw new SQLException JavaDoc(msg);
359     }
360   }
361
362   /**
363    * @see AbstractLoadBalancer#statementExecuteUpdateWithKeys(AbstractWriteRequest,
364    * MetadataCache)
365    */

366   public GeneratedKeysResult statementExecuteUpdateWithKeys(
367       AbstractWriteRequest request, MetadataCache metadataCache)
368       throws SQLException JavaDoc
369   {
370     if (backend == null)
371       throw new NoMoreBackendException(Translate.get(
372           "loadbalancer.execute.no.backend.available", request.getId()));
373
374     if (!backend.getDriverCompliance().supportGetGeneratedKeys())
375       throw new SQLException JavaDoc(Translate.get(
376           "loadbalancer.backend.autogeneratedkeys.unsupported", backend
377               .getName()));
378
379     try
380     {
381       AbstractConnectionManager cm = backend.getConnectionManager(request
382           .getLogin());
383       if (request.isAutoCommit())
384       {
385         // We do not execute request outside the already open transactions if we
386
// are disabling the backend.
387
if (!backend.canAcceptTasks(request))
388           throw new SQLException JavaDoc(Translate.get(
389               "loadbalancer.backend.is.disabling", new String JavaDoc[]{
390                   request.getSqlShortForm(vdb.getSqlShortFormLength()),
391                   backend.getName()}));
392
393         // Use a connection just for this request
394
PooledConnection c = null;
395         try
396         {
397           c = cm.retrieveConnectionInAutoCommit(request);
398         }
399         catch (UnreachableBackendException e1)
400         {
401           String JavaDoc backendName = backend.getName();
402           String JavaDoc msg = Translate.get(
403               "loadbalancer.backend.disabling.unreachable", backendName);
404           logger.error(msg);
405           endUserLogger.error(msg);
406           disableBackend(backend, true);
407           backend = null;
408           throw new SQLException JavaDoc(Translate.get(
409               "loadbalancer.backend.unreacheable", backendName));
410         }
411
412         // Sanity check
413
if (c == null)
414           throw new SQLException JavaDoc(Translate.get(
415               "loadbalancer.backend.no.connection", backend.getName()));
416
417         // Execute Query
418
GeneratedKeysResult result;
419         try
420         {
421           result = executeStatementExecuteUpdateWithKeysOnBackend(request,
422               backend, null, c.getConnection(), metadataCache);
423         }
424         catch (Exception JavaDoc e)
425         {
426           throw new SQLException JavaDoc(Translate.get(
427               "loadbalancer.request.failed.on.backend", new String JavaDoc[]{
428                   request.getSqlShortForm(vdb.getSqlShortFormLength()),
429                   backend.getName(), e.getMessage()}));
430         }
431         finally
432         {
433           cm.releaseConnectionInAutoCommit(request, c);
434         }
435         return result;
436       }
437       else
438       {
439         // Re-use the connection used by this transaction
440
PooledConnection c = cm.retrieveConnectionForTransaction(request
441             .getTransactionId());
442
443         // Sanity check
444
if (c == null)
445           throw new SQLException JavaDoc(Translate.get(
446               "loadbalancer.unable.retrieve.connection",
447               new String JavaDoc[]{String.valueOf(request.getTransactionId()),
448                   backend.getName()}));
449
450         // Execute Query
451
try
452         {
453           GeneratedKeysResult result = executeStatementExecuteUpdateWithKeysOnBackend(
454               request, backend, null, c.getConnection(), metadataCache);
455           return result;
456         }
457         catch (Exception JavaDoc e)
458         {
459           throw new SQLException JavaDoc(Translate.get(
460               "loadbalancer.request.failed.on.backend", new String JavaDoc[]{
461                   request.getSqlShortForm(vdb.getSqlShortFormLength()),
462                   backend.getName(), e.getMessage()}));
463         }
464         finally
465         {
466           backend.removePendingRequest(request);
467         }
468       }
469     }
470     catch (RuntimeException JavaDoc e)
471     {
472       String JavaDoc msg = Translate.get("loadbalancer.request.failed.on.backend",
473           new String JavaDoc[]{request.getSqlShortForm(vdb.getSqlShortFormLength()),
474               backend.getName(), e.getMessage()});
475       logger.fatal(msg, e);
476       endUserLogger.fatal(msg);
477       throw new SQLException JavaDoc(msg);
478     }
479   }
480
481   /**
482    * @see org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer#statementExecute(org.continuent.sequoia.controller.requests.AbstractRequest,
483    * org.continuent.sequoia.controller.cache.metadata.MetadataCache)
484    */

485   public ExecuteResult statementExecute(AbstractRequest request,
486       MetadataCache metadataCache) throws SQLException JavaDoc
487   {
488     if (backend == null)
489       throw new SQLException JavaDoc("No available backend to execute request "
490           + request.getId());
491
492     try
493     {
494       AbstractConnectionManager cm = backend.getConnectionManager(request
495           .getLogin());
496       if (request.isAutoCommit())
497       { // Use a connection just for this request
498
PooledConnection c = null;
499         try
500         {
501           c = cm.retrieveConnectionInAutoCommit(request);
502         }
503         catch (UnreachableBackendException e1)
504         {
505           String JavaDoc backendName = backend.getName();
506           String JavaDoc msg = Translate.get(
507               "loadbalancer.backend.disabling.unreachable", backendName);
508           logger.error(msg);
509           endUserLogger.error(msg);
510           disableBackend(backend, true);
511           backend = null;
512           throw new SQLException JavaDoc(Translate.get(
513               "loadbalancer.backend.unreacheable", backendName));
514         }
515
516         // Sanity check
517
if (c == null)
518           throw new SQLException JavaDoc(Translate.get(
519               "loadbalancer.backend.no.connection", backend.getName()));
520
521         // Execute Query
522
ExecuteResult rs = null;
523         try
524         {
525           rs = AbstractLoadBalancer.executeStatementExecuteOnBackend(request,
526               backend, null, c.getConnection(), metadataCache);
527         }
528         catch (Exception JavaDoc e)
529         {
530           throw new SQLException JavaDoc(Translate.get(
531               "loadbalancer.request.failed.on.backend", new String JavaDoc[]{
532                   request.getSqlShortForm(vdb.getSqlShortFormLength()),
533                   backend.getName(), e.getMessage()}));
534         }
535         finally
536         {
537           cm.releaseConnectionInAutoCommit(request, c);
538         }
539         return rs;
540       }
541       else
542       { // Re-use the connection used by this transaction
543
PooledConnection c = cm.retrieveConnectionForTransaction(request
544             .getTransactionId());
545
546         // Sanity check
547
if (c == null)
548           throw new SQLException JavaDoc(Translate.get(
549               "loadbalancer.unable.retrieve.connection",
550               new String JavaDoc[]{String.valueOf(request.getTransactionId()),
551                   backend.getName()}));
552
553         // Execute Query
554
try
555         {
556           return AbstractLoadBalancer.executeStatementExecuteOnBackend(request,
557               backend, null, c.getConnection(), metadataCache);
558         }
559         catch (Exception JavaDoc e)
560         {
561           throw new SQLException JavaDoc(Translate.get(
562               "loadbalancer.request.failed.on.backend", new String JavaDoc[]{
563                   request.getSqlShortForm(vdb.getSqlShortFormLength()),
564                   backend.getName(), e.getMessage()}));
565         }
566       }
567     }
568     catch (RuntimeException JavaDoc e)
569     {
570       String JavaDoc msg = Translate.get("loadbalancer.request.failed.on.backend",
571           new String JavaDoc[]{request.getSqlShortForm(vdb.getSqlShortFormLength()),
572               backend.getName(), e.getMessage()});
573       logger.fatal(msg, e);
574       endUserLogger.fatal(msg);
575       throw new SQLException JavaDoc(msg);
576     }
577   }
578
579   /**
580    * @see org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer#readOnlyCallableStatementExecuteQuery(StoredProcedure,
581    * MetadataCache)
582    */

583   public ControllerResultSet readOnlyCallableStatementExecuteQuery(
584       StoredProcedure proc, MetadataCache metadataCache) throws SQLException JavaDoc
585   {
586     return callableStatementExecuteQuery(proc, metadataCache);
587   }
588
589   /**
590    * @see org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer#readOnlyCallableStatementExecute(org.continuent.sequoia.controller.requests.StoredProcedure,
591    * org.continuent.sequoia.controller.cache.metadata.MetadataCache)
592    */

593   public ExecuteResult readOnlyCallableStatementExecute(StoredProcedure proc,
594       MetadataCache metadataCache) throws SQLException JavaDoc
595   {
596     return callableStatementExecute(proc, metadataCache);
597   }
598
599   /**
600    * @see org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer#callableStatementExecuteQuery(StoredProcedure,
601    * MetadataCache)
602    */

603   public ControllerResultSet callableStatementExecuteQuery(
604       StoredProcedure proc, MetadataCache metadataCache) throws SQLException JavaDoc
605   {
606     if (backend == null)
607       throw new SQLException JavaDoc(
608           "No available backend to execute stored procedure " + proc.getId());
609
610     try
611     {
612       AbstractConnectionManager cm = backend.getConnectionManager(proc
613           .getLogin());
614       if (proc.isAutoCommit())
615       { // Use a connection just for this request
616
PooledConnection c = null;
617         try
618         {
619           c = cm.retrieveConnectionInAutoCommit(proc);
620         }
621         catch (UnreachableBackendException e1)
622         {
623           String JavaDoc backendName = backend.getName();
624           String JavaDoc msg = Translate.get(
625               "loadbalancer.backend.disabling.unreachable", backendName);
626           logger.error(msg);
627           endUserLogger.error(msg);
628           disableBackend(backend, true);
629           backend = null;
630           throw new SQLException JavaDoc(Translate.get(
631               "loadbalancer.backend.unreacheable", backendName));
632         }
633
634         // Sanity check
635
if (c == null)
636           throw new SQLException JavaDoc(Translate.get(
637               "loadbalancer.backend.no.connection", backend.getName()));
638
639         // Execute Query
640
ControllerResultSet rs = null;
641         try
642         {
643           rs = AbstractLoadBalancer
644               .executeCallableStatementExecuteQueryOnBackend(proc, backend,
645                   null, c.getConnection(), metadataCache);
646         }
647         catch (Exception JavaDoc e)
648         {
649           throw new SQLException JavaDoc(Translate.get(
650               "loadbalancer.storedprocedure.failed.on.backend", new String JavaDoc[]{
651                   proc.getSqlShortForm(vdb.getSqlShortFormLength()),
652                   backend.getName(), e.getMessage()}));
653         }
654         finally
655         {
656           cm.releaseConnectionInAutoCommit(proc, c);
657         }
658         return rs;
659       }
660       else
661       { // Re-use the connection used by this transaction
662
PooledConnection c = cm.retrieveConnectionForTransaction(proc
663             .getTransactionId());
664
665         // Sanity check
666
if (c == null)
667           throw new SQLException JavaDoc(Translate.get(
668               "loadbalancer.unable.retrieve.connection", new String JavaDoc[]{
669                   String.valueOf(proc.getTransactionId()), backend.getName()}));
670
671         // Execute Query
672
try
673         {
674           ControllerResultSet result = AbstractLoadBalancer
675               .executeCallableStatementExecuteQueryOnBackend(proc, backend,
676                   null, c.getConnection(), metadataCache);
677           return result;
678         }
679         catch (Exception JavaDoc e)
680         {
681           throw new SQLException JavaDoc(Translate.get(
682               "loadbalancer.storedprocedure.failed.on.backend", new String JavaDoc[]{
683                   proc.getSqlShortForm(vdb.getSqlShortFormLength()),
684                   backend.getName(), e.getMessage()}));
685         }
686       }
687     }
688     catch (RuntimeException JavaDoc e)
689     {
690       String JavaDoc msg = Translate.get(
691           "loadbalancer.storedprocedure.failed.on.backend", new String JavaDoc[]{
692               proc.getSqlShortForm(vdb.getSqlShortFormLength()),
693               backend.getName(), e.getMessage()});
694       logger.fatal(msg, e);
695       endUserLogger.fatal(msg);
696       throw new SQLException JavaDoc(msg);
697     }
698   }
699
700   /**
701    * @see org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer#callableStatementExecuteUpdate(org.continuent.sequoia.controller.requests.StoredProcedure)
702    */

703   public ExecuteUpdateResult callableStatementExecuteUpdate(StoredProcedure proc)
704       throws SQLException JavaDoc
705   {
706     if (backend == null)
707       throw new SQLException JavaDoc(
708           "No available backend to execute stored procedure " + proc.getId());
709
710     try
711     {
712       AbstractConnectionManager cm = backend.getConnectionManager(proc
713           .getLogin());
714       if (proc.isAutoCommit())
715       { // Use a connection just for this request
716
PooledConnection c = null;
717         try
718         {
719           c = cm.retrieveConnectionInAutoCommit(proc);
720         }
721         catch (UnreachableBackendException e1)
722         {
723           String JavaDoc backendName = backend.getName();
724           String JavaDoc msg = Translate.get(
725               "loadbalancer.backend.disabling.unreachable", backendName);
726           logger.error(msg);
727           endUserLogger.error(msg);
728           disableBackend(backend, true);
729           backend = null;
730           throw new SQLException JavaDoc(Translate.get(
731               "loadbalancer.backend.unreacheable", backendName));
732         }
733
734         // Sanity check
735
if (c == null)
736           throw new SQLException JavaDoc(Translate.get(
737               "loadbalancer.backend.no.connection", backend.getName()));
738
739         // Execute Query
740
ExecuteUpdateResult result;
741         try
742         {
743           result = AbstractLoadBalancer
744               .executeCallableStatementExecuteUpdateOnBackend(proc, backend,
745                   null, c.getConnection());
746         }
747         catch (Exception JavaDoc e)
748         {
749           throw new SQLException JavaDoc(Translate.get(
750               "loadbalancer.storedprocedure.failed.on.backend", new String JavaDoc[]{
751                   proc.getSqlShortForm(vdb.getSqlShortFormLength()),
752                   backend.getName(), e.getMessage()}));
753         }
754         finally
755         {
756           cm.releaseConnectionInAutoCommit(proc, c);
757         }
758         return result;
759       }
760       else
761       { // Re-use the connection used by this transaction
762
PooledConnection c = cm.retrieveConnectionForTransaction(proc
763             .getTransactionId());
764
765         // Sanity check
766
if (c == null)
767           throw new SQLException JavaDoc(Translate.get(
768               "loadbalancer.unable.retrieve.connection", new String JavaDoc[]{
769                   String.valueOf(proc.getTransactionId()), backend.getName()}));
770
771         // Execute Query
772
try
773         {
774           ExecuteUpdateResult result = AbstractLoadBalancer
775               .executeCallableStatementExecuteUpdateOnBackend(proc, backend,
776                   null, c.getConnection());
777           return result;
778         }
779         catch (Exception JavaDoc e)
780         {
781           throw new SQLException JavaDoc(Translate.get(
782               "loadbalancer.storedprocedure.failed.on.backend", new String JavaDoc[]{
783                   proc.getSqlShortForm(vdb.getSqlShortFormLength()),
784                   backend.getName(), e.getMessage()}));
785         }
786       }
787     }
788     catch (RuntimeException JavaDoc e)
789     {
790       String JavaDoc msg = Translate.get(
791           "loadbalancer.storedprocedure.failed.on.backend", new String JavaDoc[]{
792               proc.getSqlShortForm(vdb.getSqlShortFormLength()),
793               backend.getName(), e.getMessage()});
794       logger.fatal(msg, e);
795       endUserLogger.fatal(msg);
796       throw new SQLException JavaDoc(msg);
797     }
798   }
799
800   /**
801    * @see org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer#callableStatementExecute(StoredProcedure,
802    * MetadataCache)
803    */

804   public ExecuteResult callableStatementExecute(StoredProcedure proc,
805       MetadataCache metadataCache) throws SQLException JavaDoc
806   {
807     if (backend == null)
808       throw new SQLException JavaDoc(
809           "No available backend to execute stored procedure " + proc.getId());
810
811     try
812     {
813       AbstractConnectionManager cm = backend.getConnectionManager(proc
814           .getLogin());
815       if (proc.isAutoCommit())
816       { // Use a connection just for this request
817
PooledConnection c = null;
818         try
819         {
820           c = cm.retrieveConnectionInAutoCommit(proc);
821         }
822         catch (UnreachableBackendException e1)
823         {
824           String JavaDoc backendName = backend.getName();
825           String JavaDoc msg = Translate.get(
826               "loadbalancer.backend.disabling.unreachable", backendName);
827           logger.error(msg);
828           endUserLogger.error(msg);
829           disableBackend(backend, true);
830           backend = null;
831           throw new SQLException JavaDoc(Translate.get(
832               "loadbalancer.backend.unreacheable", backendName));
833         }
834
835         // Sanity check
836
if (c == null)
837           throw new SQLException JavaDoc(Translate.get(
838               "loadbalancer.backend.no.connection", backend.getName()));
839
840         // Execute Query
841
ExecuteResult rs = null;
842         try
843         {
844           rs = AbstractLoadBalancer.executeCallableStatementExecuteOnBackend(
845               proc, backend, null, c.getConnection(), metadataCache);
846         }
847         catch (Exception JavaDoc e)
848         {
849           throw new SQLException JavaDoc(Translate.get(
850               "loadbalancer.storedprocedure.failed.on.backend", new String JavaDoc[]{
851                   proc.getSqlShortForm(vdb.getSqlShortFormLength()),
852                   backend.getName(), e.getMessage()}));
853         }
854         finally
855         {
856           cm.releaseConnectionInAutoCommit(proc, c);
857         }
858         return rs;
859       }
860       else
861       { // Re-use the connection used by this transaction
862
PooledConnection c = cm.retrieveConnectionForTransaction(proc
863             .getTransactionId());
864
865         // Sanity check
866
if (c == null)
867           throw new SQLException JavaDoc(Translate.get(
868               "loadbalancer.unable.retrieve.connection", new String JavaDoc[]{
869                   String.valueOf(proc.getTransactionId()), backend.getName()}));
870
871         // Execute Query
872
try
873         {
874           ExecuteResult result = AbstractLoadBalancer
875               .executeCallableStatementExecuteOnBackend(proc, backend, null, c
876                   .getConnection(), metadataCache);
877           return result;
878         }
879         catch (Exception JavaDoc e)
880         {
881           throw new SQLException JavaDoc(Translate.get(
882               "loadbalancer.storedprocedure.failed.on.backend", new String JavaDoc[]{
883                   proc.getSqlShortForm(vdb.getSqlShortFormLength()),
884                   backend.getName(), e.getMessage()}));
885         }
886       }
887     }
888     catch (RuntimeException JavaDoc e)
889     {
890       String JavaDoc msg = Translate.get(
891           "loadbalancer.storedprocedure.failed.on.backend", new String JavaDoc[]{
892               proc.getSqlShortForm(vdb.getSqlShortFormLength()),
893               backend.getName(), e.getMessage()});
894       logger.fatal(msg, e);
895       endUserLogger.fatal(msg);
896       throw new SQLException JavaDoc(msg);
897     }
898   }
899
900   /**
901    * @see org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer#getPreparedStatementGetMetaData(AbstractRequest)
902    */

903   public ControllerResultSet getPreparedStatementGetMetaData(
904       AbstractRequest request) throws SQLException JavaDoc
905   {
906     if (backend == null)
907       throw new NoMoreBackendException(Translate.get(
908           "loadbalancer.execute.no.backend.available", request
909               .getSqlOrTemplate()));
910
911     try
912     {
913       AbstractConnectionManager cm = backend.getConnectionManager(request
914           .getLogin());
915       ControllerResultSet rs = null;
916       boolean badConnection;
917       do
918       {
919         badConnection = false;
920         // Use a connection just for this request
921
PooledConnection c = null;
922         try
923         {
924           c = cm.retrieveConnectionInAutoCommit(request);
925         }
926         catch (UnreachableBackendException e1)
927         {
928           String JavaDoc backendName = backend.getName();
929           String JavaDoc msg = Translate.get(
930               "loadbalancer.backend.disabling.unreachable", backendName);
931           logger.error(msg);
932           endUserLogger.error(msg);
933           disableBackend(backend, true);
934           backend = null;
935           throw new SQLException JavaDoc(Translate.get(
936               "loadbalancer.backend.unreacheable", backendName));
937         }
938
939         // Sanity check
940
if (c == null)
941           throw new SQLException JavaDoc(Translate.get(
942               "loadbalancer.backend.no.connection", backend.getName()));
943
944         // Execute Query
945
try
946         {
947           rs = preparedStatementGetMetaDataOnBackend(
948               request.getSqlOrTemplate(), backend, c.getConnection());
949           cm.releaseConnectionInAutoCommit(request, c);
950         }
951         catch (SQLException JavaDoc e)
952         {
953           cm.releaseConnectionInAutoCommit(request, c);
954           throw new SQLException JavaDoc(Translate.get(
955               "loadbalancer.request.failed.on.backend",
956               new String JavaDoc[]{request.getSqlOrTemplate(), backend.getName(),
957                   e.getMessage()}));
958         }
959         catch (BadConnectionException e)
960         { // Get rid of the bad connection
961
cm.deleteConnection(c);
962           badConnection = true;
963         }
964         catch (Throwable JavaDoc e)
965         {
966           cm.releaseConnectionInAutoCommit(request, c);
967           throw new SQLException JavaDoc(Translate.get(
968               "loadbalancer.request.failed.on.backend",
969               new String JavaDoc[]{request.getSqlOrTemplate(), backend.getName(),
970                   e.getMessage()}));
971         }
972       }
973       while (badConnection);
974       return rs;
975     }
976     catch (RuntimeException JavaDoc e)
977     {
978       String JavaDoc msg = Translate.get("loadbalancer.getmetadata.failed",
979           new String JavaDoc[]{request.getSqlOrTemplate(), backend.getURL(),
980               e.getMessage()});
981       logger.fatal(msg, e);
982       endUserLogger.fatal(msg);
983       throw new SQLException JavaDoc(msg);
984     }
985   }
986
987   /*
988    * Transaction management
989    */

990
991   /**
992    * @see org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer#abort(org.continuent.sequoia.controller.requestmanager.TransactionMetaData)
993    */

994   public void abort(TransactionMetaData tm) throws SQLException JavaDoc
995   {
996     rollback(tm);
997   }
998
999   /**
1000   * Begins a new transaction.
1001   *
1002   * @param tm the transaction marker metadata
1003   * @exception SQLException if an error occurs
1004   */

1005  public void begin(TransactionMetaData tm) throws SQLException JavaDoc
1006  {
1007    if (backend == null)
1008      throw new SQLException JavaDoc("No available backend to begin transaction "
1009          + tm.getTransactionId());
1010
1011    // We do not accept new transactions if we are disabling the backend
1012
if (!backend.canAcceptTasks(null))
1013      throw new SQLException JavaDoc(Translate.get("loadbalancer.backend.is.disabling",
1014          new String JavaDoc[]{"begin transaction " + tm.getTransactionId(),
1015              backend.getName()}));
1016
1017    try
1018    {
1019      PooledConnection c = backend.getConnectionManager(tm.getLogin())
1020          .getConnectionForTransaction(tm.getTransactionId());
1021
1022      if (c == null)
1023        throw new SQLException JavaDoc(Translate.get(
1024            "loadbalancer.backend.no.connection", backend.getName()));
1025
1026      c.getConnection().setAutoCommit(false);
1027    }
1028    catch (Exception JavaDoc e)
1029    {
1030      throw new SQLException JavaDoc("Begin of transaction " + tm.getTransactionId()
1031          + " failed on backend " + backend.getURL() + " (" + e + ")");
1032    }
1033  }
1034
1035  /**
1036   * Commits a transaction.
1037   *
1038   * @param tm the transaction marker metadata
1039   * @exception SQLException if an error occurs
1040   */

1041  public void commit(TransactionMetaData tm) throws SQLException JavaDoc
1042  {
1043    if (backend == null)
1044      throw new SQLException JavaDoc("No available backend to commit transaction "
1045          + tm.getTransactionId());
1046
1047    try
1048    {
1049      AbstractConnectionManager cm = backend
1050          .getConnectionManager(tm.getLogin());
1051      PooledConnection pc = cm.retrieveConnectionForTransaction(tm
1052          .getTransactionId());
1053
1054      if (pc == null)
1055        throw new SQLException JavaDoc("No connection found for transaction "
1056            + tm.getTransactionId());
1057
1058      try
1059      {
1060        Connection JavaDoc c = pc.getConnection();
1061        c.commit();
1062        c.setAutoCommit(true);
1063      }
1064      catch (SQLException JavaDoc e)
1065      {
1066        throw new SQLException JavaDoc(Translate.get("loadbalancer.commit.failed",
1067            new String JavaDoc[]{String.valueOf(tm.getTransactionId()),
1068                backend.getName(), e.getMessage()}));
1069      }
1070      finally
1071      {
1072        cm.releaseConnectionForTransaction(tm.getTransactionId());
1073      }
1074    }
1075    catch (RuntimeException JavaDoc e)
1076    {
1077      String JavaDoc msg = Translate.get("loadbalancer.commit.failed", new String JavaDoc[]{
1078          String.valueOf(tm.getTransactionId()), backend.getName(),
1079          e.getMessage()});
1080      logger.fatal(msg, e);
1081      endUserLogger.fatal(msg);
1082      throw new SQLException JavaDoc(msg);
1083    }
1084  }
1085
1086  /**
1087   * Rollbacks a transaction.
1088   *
1089   * @param tm the transaction marker metadata
1090   * @exception SQLException if an error occurs
1091   */

1092  public void rollback(TransactionMetaData tm) throws SQLException JavaDoc
1093  {
1094    if (backend == null)
1095      throw new SQLException JavaDoc("No available backend to rollback transaction "
1096          + tm.getTransactionId());
1097
1098    try
1099    {
1100      AbstractConnectionManager cm = backend
1101          .getConnectionManager(tm.getLogin());
1102      PooledConnection pc = cm.retrieveConnectionForTransaction(tm
1103          .getTransactionId());
1104
1105      if (pc == null)
1106        throw new SQLException JavaDoc("No connection found for transaction "
1107            + tm.getTransactionId());
1108
1109      try
1110      {
1111        Connection JavaDoc c = pc.getConnection();
1112        c.rollback();
1113        c.setAutoCommit(true);
1114      }
1115      catch (SQLException JavaDoc e)
1116      {
1117        throw new SQLException JavaDoc(Translate.get("loadbalancer.rollback.failed",
1118            new String JavaDoc[]{String.valueOf(tm.getTransactionId()),
1119                backend.getName(), e.getMessage()}));
1120      }
1121      finally
1122      {
1123        cm.releaseConnectionForTransaction(tm.getTransactionId());
1124      }
1125    }
1126    catch (RuntimeException JavaDoc e)
1127    {
1128      String JavaDoc msg = Translate.get("loadbalancer.rollback.failed", new String JavaDoc[]{
1129          String.valueOf(tm.getTransactionId()), backend.getName(),
1130          e.getMessage()});
1131      logger.fatal(msg, e);
1132      endUserLogger.fatal(msg);
1133      throw new SQLException JavaDoc(msg);
1134    }
1135  }
1136
1137  /**
1138   * Rollback a transaction to a savepoint
1139   *
1140   * @param tm The transaction marker metadata
1141   * @param savepointName The name of the savepoint
1142   * @throws SQLException if an error occurs
1143   */

1144  public void rollbackToSavepoint(TransactionMetaData tm, String JavaDoc savepointName)
1145      throws SQLException JavaDoc
1146  {
1147    if (backend == null)
1148      throw new SQLException JavaDoc("No available backend to rollback transaction "
1149          + tm.getTransactionId());
1150
1151    try
1152    {
1153      AbstractConnectionManager cm = backend
1154          .getConnectionManager(tm.getLogin());
1155      PooledConnection c = cm.retrieveConnectionForTransaction(tm
1156          .getTransactionId());
1157
1158      if (c == null)
1159        throw new SQLException JavaDoc("No connection found for transaction "
1160            + tm.getTransactionId());
1161
1162      Savepoint JavaDoc savepoint = backend.getSavepoint(
1163          new Long JavaDoc(tm.getTransactionId()), savepointName);
1164
1165      if (savepoint == null)
1166        throw new SQLException JavaDoc("No savepoint with name " + savepointName
1167            + " has been found for transaction " + tm.getTransactionId());
1168
1169      try
1170      {
1171        c.getConnection().rollback(savepoint);
1172      }
1173      catch (SQLException JavaDoc e)
1174      {
1175        throw new SQLException JavaDoc(Translate.get(
1176            "loadbalancer.rollbacksavepoint.failed", new String JavaDoc[]{
1177                savepointName, String.valueOf(tm.getTransactionId()),
1178                backend.getName(), e.getMessage()}));
1179      }
1180    }
1181    catch (RuntimeException JavaDoc e)
1182    {
1183      String JavaDoc msg = Translate.get("loadbalancer.rollbacksavepoint.failed",
1184          new String JavaDoc[]{savepointName, String.valueOf(tm.getTransactionId()),
1185              backend.getName(), e.getMessage()});
1186      logger.fatal(msg, e);
1187      endUserLogger.fatal(msg);
1188      throw new SQLException JavaDoc(msg);
1189    }
1190  }
1191
1192  /**
1193   * Release a savepoint from a transaction
1194   *
1195   * @param tm The transaction marker metadata
1196   * @param savepointName The name of the savepoint ro release
1197   * @throws SQLException if an error occurs
1198   */

1199  public void releaseSavepoint(TransactionMetaData tm, String JavaDoc savepointName)
1200      throws SQLException JavaDoc
1201  {
1202    if (backend == null)
1203      throw new SQLException JavaDoc("No available backend to release savepoint from "
1204          + " transaction " + tm.getTransactionId());
1205
1206    try
1207    {
1208      AbstractConnectionManager cm = backend
1209          .getConnectionManager(tm.getLogin());
1210      PooledConnection c = cm.retrieveConnectionForTransaction(tm
1211          .getTransactionId());
1212
1213      if (c == null)
1214        throw new SQLException JavaDoc("No connection found for transaction "
1215            + tm.getTransactionId());
1216
1217      Savepoint JavaDoc savepoint = backend.getSavepoint(
1218          new Long JavaDoc(tm.getTransactionId()), savepointName);
1219
1220      if (savepoint == null)
1221        throw new SQLException JavaDoc("No savepoint with name " + savepointName
1222            + " has been " + "found for transaction " + tm.getTransactionId());
1223
1224      try
1225      {
1226        c.getConnection().releaseSavepoint(savepoint);
1227      }
1228      catch (SQLException JavaDoc e)
1229      {
1230        throw new SQLException JavaDoc(Translate.get(
1231            "loadbalancer.releasesavepoint.failed", new String JavaDoc[]{savepointName,
1232                String.valueOf(tm.getTransactionId()), backend.getName(),
1233                e.getMessage()}));
1234      }
1235      finally
1236      {
1237        backend.removeSavepoint(new Long JavaDoc(tm.getTransactionId()), savepoint);
1238      }
1239    }
1240    catch (RuntimeException JavaDoc e)
1241    {
1242      String JavaDoc msg = Translate.get("loadbalancer.releasesavepoint.failed",
1243          new String JavaDoc[]{savepointName, String.valueOf(tm.getTransactionId()),
1244              backend.getName(), e.getMessage()});
1245      logger.fatal(msg, e);
1246      endUserLogger.fatal(msg);
1247      throw new SQLException JavaDoc(msg);
1248    }
1249  }
1250
1251  /**
1252   * Set a savepoint to a transaction.
1253   *
1254   * @param tm The transaction marker metadata
1255   * @param savepointName The name of the new savepoint
1256   * @throws AllBackendsFailedException if no backend succeeded in setting the
1257   * savepoint.
1258   * @throws SQLException if an error occurs
1259   */

1260  public void setSavepoint(TransactionMetaData tm, String JavaDoc savepointName)
1261      throws AllBackendsFailedException, SQLException JavaDoc
1262  {
1263    if (backend == null)
1264      throw new SQLException JavaDoc("No available backend to set savepoint to "
1265          + " transaction " + tm.getTransactionId());
1266
1267    try
1268    {
1269      AbstractConnectionManager cm = backend
1270          .getConnectionManager(tm.getLogin());
1271      PooledConnection c = cm.retrieveConnectionForTransaction(tm
1272          .getTransactionId());
1273
1274      if (c == null)
1275        throw new SQLException JavaDoc("No connection found for transaction "
1276            + tm.getTransactionId());
1277
1278      Savepoint JavaDoc savepoint = null;
1279      try
1280      {
1281        savepoint = c.getConnection().setSavepoint(savepointName);
1282      }
1283      catch (SQLException JavaDoc e)
1284      {
1285        throw new SQLException JavaDoc(Translate.get(
1286            "loadbalancer.setsavepoint.failed", new String JavaDoc[]{savepointName,
1287                String.valueOf(tm.getTransactionId()), backend.getName(),
1288                e.getMessage()}));
1289      }
1290      finally
1291      {
1292        if (savepoint != null)
1293          backend.addSavepoint(new Long JavaDoc(tm.getTransactionId()), savepoint);
1294      }
1295    }
1296    catch (RuntimeException JavaDoc e)
1297    {
1298      String JavaDoc msg = Translate.get("loadbalancer.setsavepoint.failed",
1299          new String JavaDoc[]{savepointName, String.valueOf(tm.getTransactionId()),
1300              backend.getName(), e.getMessage()});
1301      logger.fatal(msg, e);
1302      endUserLogger.fatal(msg);
1303      throw new SQLException JavaDoc(msg);
1304    }
1305  }
1306
1307  /**
1308   * @see org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer#closePersistentConnection(java.lang.String,
1309   * long)
1310   */

1311  public void closePersistentConnection(String JavaDoc login,
1312      long persistentConnectionId) throws SQLException JavaDoc
1313  {
1314    AbstractConnectionManager cm = backend.getConnectionManager(login);
1315    if (cm != null)
1316    {
1317      // Release the connection if it exists
1318
cm.releasePersistentConnectionInAutoCommit(persistentConnectionId);
1319      backend.removePersistentConnection(persistentConnectionId);
1320    }
1321  }
1322
1323  /**
1324   * @see org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer#openPersistentConnection(String,
1325   * long)
1326   */

1327  public void openPersistentConnection(String JavaDoc login, long persistentConnectionId)
1328      throws SQLException JavaDoc
1329  {
1330    AbstractConnectionManager cm = backend.getConnectionManager(login);
1331    if (cm == null)
1332    {
1333      throw new SQLException JavaDoc("No connection manager found for user " + login);
1334    }
1335
1336    // Get a new connection
1337
AbstractRequest request = new UnknownReadRequest("", false, 0, "");
1338    request.setLogin(login);
1339    request.setPersistentConnection(true);
1340    request.setPersistentConnectionId(persistentConnectionId);
1341    try
1342    {
1343      PooledConnection c = cm.retrieveConnectionInAutoCommit(request);
1344      backend.addPersistentConnection(request.getPersistentConnectionId(), c);
1345    }
1346    catch (UnreachableBackendException e)
1347    {
1348      throw new SQLException JavaDoc(
1349          "Backend is not reachable to open persistent conenction "
1350              + persistentConnectionId);
1351    }
1352  }
1353
1354  /*
1355   * Backends management
1356   */

1357
1358  /**
1359   * Enables a backend that was previously disabled. Asks the corresponding
1360   * connection manager to initialize the connections if needed.
1361   *
1362   * @param db the database backend to enable
1363   * @param writeEnabled True if the backend must be enabled for writes
1364   * @throws SQLException if an error occurs
1365   */

1366  public void enableBackend(DatabaseBackend db, boolean writeEnabled)
1367      throws SQLException JavaDoc
1368  {
1369    if (backend != null)
1370    {
1371      if (backend.isReadEnabled())
1372        throw new SQLException JavaDoc(
1373            "SingleDB load balancer accepts only one backend and "
1374                + backend.getName() + " is already enabled. Skipping "
1375                + db.getName() + " initialization.");
1376    }
1377    backend = db;
1378    logger.info(Translate.get("loadbalancer.backend.enabling", db.getName()));
1379    if (!backend.isInitialized())
1380      backend.initializeConnections();
1381    backend.enableRead();
1382    if (writeEnabled)
1383      backend.enableWrite();
1384  }
1385
1386  /**
1387   * Disables a backend that was previously enabled. Asks the corresponding
1388   * connection manager to finalize the connections if needed.
1389   *
1390   * @param db the database backend to disable
1391   * @param forceDisable true if disabling must be forced on the backend
1392   * @throws SQLException if an error occurs
1393   */

1394  public void disableBackend(DatabaseBackend db, boolean forceDisable)
1395      throws SQLException JavaDoc
1396  {
1397    if (backend.equals(db))
1398    {
1399      logger
1400          .info(Translate.get("loadbalancer.backend.disabling", db.getName()));
1401      backend.disable();
1402      if (backend.isInitialized())
1403        backend.finalizeConnections();
1404      backend = null;
1405    }
1406    else
1407    {
1408      String JavaDoc msg = "Trying to disable a non-existing backend " + db.getName();
1409      logger.warn(msg);
1410      throw new SQLException JavaDoc(msg);
1411    }
1412  }
1413
1414  /**
1415   * @see org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer#setWeight(String,
1416   * int)
1417   */

1418  public void setWeight(String JavaDoc name, int w) throws SQLException JavaDoc
1419  {
1420    throw new SQLException JavaDoc("Weight is not supported with this load balancer");
1421  }
1422
1423  /**
1424   * @see org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer#getNumberOfEnabledBackends()
1425   */

1426  public int getNumberOfEnabledBackends()
1427  {
1428    if (backend == null)
1429      return 0;
1430    else
1431      return 1;
1432  }
1433
1434  /*
1435   * Debug/Monitoring
1436   */

1437
1438  /**
1439   * Gets information about the request load balancer
1440   *
1441   * @return <code>String</code> containing information
1442   */

1443  public String JavaDoc getInformation()
1444  {
1445    if (backend == null)
1446      return "SingleDB Request load balancer: !!!Warning!!! No enabled backend node found\n";
1447    else
1448      return "SingleDB Request load balancer using " + backend.getURL() + "\n";
1449  }
1450
1451  /**
1452   * @see org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer#getXmlImpl()
1453   */

1454  public String JavaDoc getXmlImpl()
1455  {
1456    return "<" + DatabasesXmlTags.ELT_SingleDB + "/>";
1457  }
1458
1459}
Popular Tags