KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > continuent > sequoia > controller > requestmanager > distributed > RAIDb1DistributedRequestManager


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  * Copyright (C) 2005-2006 Continuent, Inc.
7  * Contact: sequoia@continuent.org
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  * Initial developer(s): Emmanuel Cecchet.
22  * Contributor(s): Jean-Bernard van Zuylen, Damian Arregui.
23  */

24
25 package org.continuent.sequoia.controller.requestmanager.distributed;
26
27 import java.io.Serializable JavaDoc;
28 import java.sql.SQLException JavaDoc;
29 import java.util.ArrayList JavaDoc;
30 import java.util.Iterator JavaDoc;
31 import java.util.List JavaDoc;
32
33 import javax.management.NotCompliantMBeanException JavaDoc;
34
35 import org.continuent.hedera.adapters.MulticastRequestAdapter;
36 import org.continuent.hedera.adapters.MulticastResponse;
37 import org.continuent.hedera.common.Member;
38 import org.continuent.sequoia.common.exceptions.NoMoreBackendException;
39 import org.continuent.sequoia.common.exceptions.NoResultAvailableException;
40 import org.continuent.sequoia.common.i18n.Translate;
41 import org.continuent.sequoia.controller.backend.result.ControllerResultSet;
42 import org.continuent.sequoia.controller.backend.result.ExecuteResult;
43 import org.continuent.sequoia.controller.backend.result.ExecuteUpdateResult;
44 import org.continuent.sequoia.controller.backend.result.GeneratedKeysResult;
45 import org.continuent.sequoia.controller.cache.result.AbstractResultCache;
46 import org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer;
47 import org.continuent.sequoia.controller.loadbalancer.AllBackendsFailedException;
48 import org.continuent.sequoia.controller.recoverylog.RecoveryLog;
49 import org.continuent.sequoia.controller.requests.AbstractRequest;
50 import org.continuent.sequoia.controller.requests.AbstractWriteRequest;
51 import org.continuent.sequoia.controller.requests.SelectRequest;
52 import org.continuent.sequoia.controller.requests.StoredProcedure;
53 import org.continuent.sequoia.controller.requests.StoredProcedureCallResult;
54 import org.continuent.sequoia.controller.requests.UnknownWriteRequest;
55 import org.continuent.sequoia.controller.scheduler.AbstractScheduler;
56 import org.continuent.sequoia.controller.virtualdatabase.DistributedVirtualDatabase;
57 import org.continuent.sequoia.controller.virtualdatabase.protocol.DistributedAbort;
58 import org.continuent.sequoia.controller.virtualdatabase.protocol.DistributedCallableStatementExecute;
59 import org.continuent.sequoia.controller.virtualdatabase.protocol.DistributedCallableStatementExecuteQuery;
60 import org.continuent.sequoia.controller.virtualdatabase.protocol.DistributedCallableStatementExecuteUpdate;
61 import org.continuent.sequoia.controller.virtualdatabase.protocol.DistributedCommit;
62 import org.continuent.sequoia.controller.virtualdatabase.protocol.DistributedReleaseSavepoint;
63 import org.continuent.sequoia.controller.virtualdatabase.protocol.DistributedRequest;
64 import org.continuent.sequoia.controller.virtualdatabase.protocol.DistributedRollback;
65 import org.continuent.sequoia.controller.virtualdatabase.protocol.DistributedRollbackToSavepoint;
66 import org.continuent.sequoia.controller.virtualdatabase.protocol.DistributedSetSavepoint;
67 import org.continuent.sequoia.controller.virtualdatabase.protocol.DistributedStatementExecute;
68 import org.continuent.sequoia.controller.virtualdatabase.protocol.DistributedStatementExecuteQuery;
69 import org.continuent.sequoia.controller.virtualdatabase.protocol.DistributedStatementExecuteUpdate;
70 import org.continuent.sequoia.controller.virtualdatabase.protocol.DistributedStatementExecuteUpdateWithKeys;
71 import org.continuent.sequoia.controller.virtualdatabase.protocol.ExecRemoteStatementExecuteQuery;
72 import org.continuent.sequoia.controller.virtualdatabase.protocol.MessageTimeouts;
73
74 /**
75  * This class defines a RAIDb1DistributedRequestManager
76  *
77  * @author <a HREF="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
78  * @author <a HREF="mailto:jbvanzuylen@transwide.com">Jean-Bernard van Zuylen
79  * </a>
80  * @author <a HREF="mailto:Damian.Arregui@emicnetworks.com">Damian Arregui</a>
81  * @version 1.0
82  */

83 public class RAIDb1DistributedRequestManager extends DistributedRequestManager
84 {
85   /**
86    * Creates a new <code>RAIDb1DistributedRequestManager</code> instance
87    *
88    * @param vdb the virtual database this request manager belongs to
89    * @param scheduler the Request Scheduler to use
90    * @param cache a Query Cache implementation
91    * @param loadBalancer the Request Load Balancer to use
92    * @param recoveryLog the Log Recovery to use
93    * @param beginTimeout timeout in seconds for begin
94    * @param commitTimeout timeout in seconds for commit
95    * @param rollbackTimeout timeout in seconds for rollback
96    * @throws SQLException if an error occurs
97    * @throws NotCompliantMBeanException if the MBean is not JMX compliant
98    */

99   public RAIDb1DistributedRequestManager(DistributedVirtualDatabase vdb,
100       AbstractScheduler scheduler, AbstractResultCache cache,
101       AbstractLoadBalancer loadBalancer, RecoveryLog recoveryLog,
102       long beginTimeout, long commitTimeout, long rollbackTimeout)
103       throws SQLException JavaDoc, NotCompliantMBeanException JavaDoc
104   {
105     super(vdb, scheduler, cache, loadBalancer, recoveryLog, beginTimeout,
106         commitTimeout, rollbackTimeout);
107   }
108
109   /**
110    * @see org.continuent.sequoia.controller.requestmanager.distributed.DistributedRequestManager#distributedStatementExecuteQuery(org.continuent.sequoia.controller.requests.SelectRequest)
111    */

112   public ControllerResultSet distributedStatementExecuteQuery(
113       SelectRequest request) throws SQLException JavaDoc
114   {
115     return executeRequestReturningResultSet(request,
116         new DistributedStatementExecuteQuery(request), dvdb
117             .getMessageTimeouts().getExecReadRequestTimeout());
118   }
119
120   /**
121    * @see org.continuent.sequoia.controller.requestmanager.distributed.DistributedRequestManager#execRemoteStatementExecuteQuery(org.continuent.sequoia.controller.requests.SelectRequest)
122    */

123   public ControllerResultSet execRemoteStatementExecuteQuery(
124       SelectRequest request) throws SQLException JavaDoc
125   {
126     if (dvdb.isProcessMacroBeforeBroadcast())
127       loadBalancer.handleMacros(request);
128     try
129     {
130       // Iterate over controllers in members list (but us) until someone
131
// successfully executes our request.
132
Iterator JavaDoc i = dvdb.getAllMemberButUs().iterator();
133       SQLException JavaDoc error = null;
134       while (i.hasNext())
135       {
136         Member controller = (Member) i.next();
137         List JavaDoc groupMembers = new ArrayList JavaDoc();
138         groupMembers.add(controller);
139
140         if (logger.isDebugEnabled())
141           logger.debug("Sending request "
142               + request.getSqlShortForm(dvdb.getSqlShortFormLength())
143               + (request.isAutoCommit() ? "" : " transaction "
144                   + request.getTransactionId()) + " to " + controller);
145
146         // Send query to remote controller
147
MulticastResponse responses;
148         responses = dvdb.getMulticastRequestAdapter().multicastMessage(
149             groupMembers,
150             new ExecRemoteStatementExecuteQuery(request),
151             MulticastRequestAdapter.WAIT_ALL,
152             MessageTimeouts.getMinTimeout(dvdb.getMessageTimeouts()
153                 .getExecReadRequestTimeout(), request.getTimeout() * 1000L));
154
155         if (logger.isDebugEnabled())
156           logger.debug("Request "
157               + request.getSqlShortForm(dvdb.getSqlShortFormLength())
158               + " completed.");
159
160         Object JavaDoc ret = responses.getResult(controller);
161         if (ret instanceof ControllerResultSet)
162           return (ControllerResultSet) ret;
163         else if (ret instanceof SQLException JavaDoc)
164           error = (SQLException JavaDoc) ret;
165       }
166
167       if (error == null)
168       {
169         // No one answered, throw
170
throw new NoMoreBackendException(
171             "No answer was received by the controller for remote StatementExecuteQuery");
172       }
173       else
174         throw error;
175     }
176     catch (Exception JavaDoc e)
177     {
178       String JavaDoc msg = "An error occured while executing remote select request "
179           + request.getId();
180       logger.warn(msg, e);
181       if (e instanceof SQLException JavaDoc)
182         throw (SQLException JavaDoc) e;
183       else
184         throw new SQLException JavaDoc(msg + " (" + e + ")");
185     }
186   }
187
188   /**
189    * @see org.continuent.sequoia.controller.requestmanager.distributed.DistributedRequestManager#distributedStatementExecuteUpdate(org.continuent.sequoia.controller.requests.AbstractWriteRequest)
190    */

191   public ExecuteUpdateResult distributedStatementExecuteUpdate(
192       AbstractWriteRequest request) throws SQLException JavaDoc
193   {
194     return executeRequestReturningInt(request,
195         new DistributedStatementExecuteUpdate(request), dvdb
196             .getMessageTimeouts().getExecWriteRequestTimeout());
197   }
198
199   /**
200    * @see org.continuent.sequoia.controller.requestmanager.distributed.DistributedRequestManager#distributedStatementExecuteUpdateWithKeys(org.continuent.sequoia.controller.requests.AbstractWriteRequest)
201    */

202   public GeneratedKeysResult distributedStatementExecuteUpdateWithKeys(
203       AbstractWriteRequest request) throws SQLException JavaDoc
204   {
205     return executeRequestReturningGeneratedKeys(request,
206         new DistributedStatementExecuteUpdateWithKeys(request), dvdb
207             .getMessageTimeouts().getExecWriteRequestWithKeysTimeout());
208   }
209
210   /**
211    * @see org.continuent.sequoia.controller.requestmanager.distributed.DistributedRequestManager#distributedStatementExecute(org.continuent.sequoia.controller.requests.AbstractRequest)
212    */

213   public ExecuteResult distributedStatementExecute(AbstractRequest request)
214       throws SQLException JavaDoc
215   {
216     return executeRequestReturningExecuteResult(request,
217         new DistributedStatementExecute(request), dvdb.getMessageTimeouts()
218             .getExecReadStoredProcedureTimeout());
219   }
220
221   /**
222    * @see org.continuent.sequoia.controller.requestmanager.distributed.DistributedRequestManager#distributedCallableStatementExecuteQuery(StoredProcedure)
223    */

224   public ControllerResultSet distributedCallableStatementExecuteQuery(
225       StoredProcedure proc) throws SQLException JavaDoc
226   {
227     StoredProcedureCallResult result = executeRequestReturningStoredProcedureCallResult(
228         proc, new DistributedCallableStatementExecuteQuery(proc), dvdb
229             .getMessageTimeouts().getExecReadStoredProcedureTimeout());
230     return (ControllerResultSet) result.getResult();
231   }
232
233   /**
234    * @see org.continuent.sequoia.controller.requestmanager.distributed.DistributedRequestManager#distributedCallableStatementExecuteUpdate(org.continuent.sequoia.controller.requests.StoredProcedure)
235    */

236   public ExecuteUpdateResult distributedCallableStatementExecuteUpdate(
237       StoredProcedure proc) throws SQLException JavaDoc
238   {
239     StoredProcedureCallResult result = executeRequestReturningStoredProcedureCallResult(
240         proc, new DistributedCallableStatementExecuteUpdate(proc), dvdb
241             .getMessageTimeouts().getExecWriteStoredProcedureTimeout());
242     return ((ExecuteUpdateResult) result.getResult());
243   }
244
245   /**
246    * @see org.continuent.sequoia.controller.requestmanager.distributed.DistributedRequestManager#distributedCallableStatementExecute(StoredProcedure)
247    */

248   public ExecuteResult distributedCallableStatementExecute(StoredProcedure proc)
249       throws SQLException JavaDoc
250   {
251     StoredProcedureCallResult result = executeRequestReturningStoredProcedureCallResult(
252         proc, new DistributedCallableStatementExecute(proc), dvdb
253             .getMessageTimeouts().getExecReadStoredProcedureTimeout());
254     return (ExecuteResult) result.getResult();
255   }
256
257   /**
258    * Execute a distributed request that returns a GeneratedKeysResult.
259    *
260    * @param request the request to execute
261    * @param requestMsg message to be sent through the group communication
262    * @param messageTimeout group message timeout
263    * @return the corresponding ExecuteResult
264    * @throws SQLException if an error occurs
265    */

266   private ExecuteResult executeRequestReturningExecuteResult(
267       AbstractRequest request, DistributedRequest requestMsg,
268       long messageTimeout) throws SQLException JavaDoc
269   {
270     if (dvdb.isProcessMacroBeforeBroadcast())
271       loadBalancer.handleMacros(request);
272     try
273     {
274       ExecuteResult requestResult = null;
275
276       List JavaDoc groupMembers = dvdb.getAllMembers();
277
278       MulticastResponse responses = multicastRequest(request, requestMsg,
279           messageTimeout, groupMembers);
280
281       // List of controllers that gave a AllBackendsFailedException
282
ArrayList JavaDoc failedOnAllBackends = null;
283       // List of controllers that have no more backends to execute queries
284
ArrayList JavaDoc controllersWithoutBackends = null;
285       SQLException JavaDoc exception = null;
286       int size = groupMembers.size();
287       List JavaDoc successfulControllers = null;
288       // Get the result of each controller
289
for (int i = 0; i < size; i++)
290       {
291         Member member = (Member) groupMembers.get(i);
292         if ((responses.getFailedMembers() != null)
293             && responses.getFailedMembers().contains(member))
294         {
295           logger.warn("Controller " + member + " is suspected of failure.");
296           continue;
297         }
298         Object JavaDoc r = responses.getResult(member);
299         if (r instanceof ExecuteResult)
300         {
301           if (requestResult == null)
302             requestResult = (ExecuteResult) r;
303         }
304         else if (DistributedRequestManager.SUCCESSFUL_COMPLETION.equals(r))
305         {
306           // Remote controller success
307
if (requestResult == null)
308           {
309             if (successfulControllers == null)
310               successfulControllers = new ArrayList JavaDoc();
311             successfulControllers.add(member);
312           }
313         }
314         else if (r instanceof NoMoreBackendException)
315         {
316           if (controllersWithoutBackends == null)
317             controllersWithoutBackends = new ArrayList JavaDoc();
318           controllersWithoutBackends.add(member);
319           if (logger.isDebugEnabled())
320             logger.debug("Controller " + member
321                 + " has no more backends to execute query (" + r + ")");
322         }
323         else if (r instanceof Exception JavaDoc)
324         {
325           if (failedOnAllBackends == null)
326             failedOnAllBackends = new ArrayList JavaDoc();
327           failedOnAllBackends.add(member);
328           String JavaDoc msg = "Request " + request.getId() + " failed on controller "
329               + member + " (" + r + ")";
330           logger.warn(msg);
331           if (r instanceof SQLException JavaDoc)
332             exception = (SQLException JavaDoc) r;
333           else
334           {
335             exception = new SQLException JavaDoc("Internal exception " + r);
336             exception.initCause((Throwable JavaDoc) r);
337           }
338         }
339         else
340         {
341           if (failedOnAllBackends == null)
342             failedOnAllBackends = new ArrayList JavaDoc();
343           failedOnAllBackends.add(member);
344           if (logger.isWarnEnabled())
345             logger.warn("Unexpected answer from controller " + member + " ("
346                 + r + ") for request "
347                 + request.getSqlShortForm(vdb.getSqlShortFormLength()));
348         }
349       }
350
351       if ((requestResult == null) && (successfulControllers != null))
352       { // Local controller could not get the result, ask it to a successful
353
// remote controller
354
try
355         {
356           requestResult = (ExecuteResult) getRequestResultFromFailoverCache(
357               successfulControllers, request.getId());
358         }
359         catch (NoResultAvailableException e)
360         {
361           exception = new SQLException JavaDoc(
362               "Request '"
363                   + request
364                   + "' was successfully executed on remote controllers, but all successful controllers failed before retrieving result");
365         }
366       }
367
368       if ((controllersWithoutBackends != null) || (failedOnAllBackends != null))
369       { // Notify all controllers of completion
370
// Re-create fake stored procedure for proper scheduler notification
371
// (see DistributedStatementExecute#scheduleRequest)
372
StoredProcedure proc = new StoredProcedure(request.getSqlOrTemplate(),
373             request.getEscapeProcessing(), request.getTimeout(), request
374                 .getLineSeparator());
375         proc.setIsAutoCommit(request.isAutoCommit());
376         proc.setTransactionId(request.getTransactionId());
377         proc.setTransactionIsolation(request.getTransactionIsolation());
378         proc.setId(request.getId());
379
380         /*
381          * Notify all controllers where all backend failed (if any) that
382          * completion was 'success'. We determine success from the local result
383          * or the successful remote controllers even though they may have failed
384          * afterwards (in which case requestResult may be null).
385          */

386         boolean success = (requestResult != null || successfulControllers != null);
387
388         notifyRequestCompletion(proc, success, true, failedOnAllBackends);
389
390         // Notify controllers without active backends (if any)
391
notifyRequestCompletion(proc, success, false,
392             controllersWithoutBackends);
393       }
394
395       if (requestResult != null)
396       {
397         if (logger.isDebugEnabled())
398           logger.debug("Request " + request.getId()
399               + " completed successfully.");
400         return requestResult;
401       }
402
403       // At this point, all controllers failed
404

405       if (exception != null)
406         throw exception;
407       else
408       {
409         String JavaDoc msg = "Request '"
410             + request.getSqlShortForm(vdb.getSqlShortFormLength())
411             + "' failed on all controllers";
412         logger.warn(msg);
413         throw new SQLException JavaDoc(msg);
414       }
415     }
416     catch (SQLException JavaDoc e)
417     {
418       String JavaDoc msg = Translate
419           .get("loadbalancer.request.failed", new String JavaDoc[]{
420               request.getSqlShortForm(vdb.getSqlShortFormLength()),
421               e.getMessage()});
422       logger.warn(msg);
423       throw e;
424     }
425   }
426
427   /**
428    * Execute a distributed request that returns a GeneratedKeysResult.
429    *
430    * @param request the request to execute
431    * @param requestMsg message to be sent through the group communication
432    * @param messageTimeout group message timeout
433    * @return the corresponding GeneratedKeysResult
434    * @throws SQLException if an error occurs
435    */

436   private GeneratedKeysResult executeRequestReturningGeneratedKeys(
437       AbstractRequest request, DistributedRequest requestMsg,
438       long messageTimeout) throws SQLException JavaDoc
439   {
440     if (dvdb.isProcessMacroBeforeBroadcast())
441       loadBalancer.handleMacros(request);
442     try
443     {
444       GeneratedKeysResult requestResult = null;
445
446       List JavaDoc groupMembers = dvdb.getAllMembers();
447
448       MulticastResponse responses = multicastRequest(request, requestMsg,
449           messageTimeout, groupMembers);
450
451       // List of controllers that gave a AllBackendsFailedException
452
ArrayList JavaDoc failedOnAllBackends = null;
453       // List of controllers that gave an inconsistent result
454
ArrayList JavaDoc inconsistentControllers = null;
455       // List of controllers that have no more backends to execute queries
456
ArrayList JavaDoc controllersWithoutBackends = null;
457       SQLException JavaDoc exception = null;
458       List JavaDoc successfulControllers = null;
459       int size = groupMembers.size();
460       // Get the result of each controller
461
for (int i = 0; i < size; i++)
462       {
463         Member member = (Member) groupMembers.get(i);
464         if ((responses.getFailedMembers() != null)
465             && responses.getFailedMembers().contains(member))
466         {
467           logger.warn("Controller " + member + " is suspected of failure.");
468           continue;
469         }
470         Object JavaDoc r = responses.getResult(member);
471         if (r instanceof GeneratedKeysResult)
472         {
473           if (requestResult == null)
474           {
475             requestResult = (GeneratedKeysResult) r;
476           }
477           else
478           {
479             if (requestResult.getUpdateCount() != ((GeneratedKeysResult) r)
480                 .getUpdateCount())
481             {
482               if (inconsistentControllers == null)
483                 inconsistentControllers = new ArrayList JavaDoc();
484               inconsistentControllers.add(member);
485               logger
486                   .error("Controller " + member
487                       + " returned an inconsistent results (" + requestResult
488                       + " when expecting " + r + ") for request "
489                       + request.getId());
490             }
491           }
492         }
493         else if (DistributedRequestManager.SUCCESSFUL_COMPLETION.equals(r))
494         {
495           // Remote controller success
496
if (requestResult == null)
497           {
498             if (successfulControllers == null)
499               successfulControllers = new ArrayList JavaDoc();
500             successfulControllers.add(member);
501           }
502         }
503         else if (r instanceof NoMoreBackendException)
504         {
505           if (controllersWithoutBackends == null)
506             controllersWithoutBackends = new ArrayList JavaDoc();
507           controllersWithoutBackends.add(member);
508           if (logger.isDebugEnabled())
509             logger.debug("Controller " + member
510                 + " has no more backends to execute query (" + r + ")");
511         }
512         else if (r instanceof Exception JavaDoc)
513         {
514           if (failedOnAllBackends == null)
515             failedOnAllBackends = new ArrayList JavaDoc();
516           failedOnAllBackends.add(member);
517           String JavaDoc msg = "Request " + request.getId() + " failed on controller "
518               + member + " (" + r + ")";
519           logger.warn(msg);
520           if (r instanceof SQLException JavaDoc)
521             exception = (SQLException JavaDoc) r;
522           else
523           {
524             exception = new SQLException JavaDoc("Internal exception " + r);
525             exception.initCause((Throwable JavaDoc) r);
526           }
527         }
528         else
529         {
530           if (failedOnAllBackends == null)
531             failedOnAllBackends = new ArrayList JavaDoc();
532           failedOnAllBackends.add(member);
533           if (logger.isWarnEnabled())
534             logger.warn("Unexpected answer from controller " + member + " ("
535                 + r + ") for request "
536                 + request.getSqlShortForm(vdb.getSqlShortFormLength()));
537         }
538       }
539
540       if ((requestResult == null) && (successfulControllers != null))
541       { // Local controller could not get the result, ask it to a successful
542
// remote controller
543
try
544         {
545           requestResult = (GeneratedKeysResult) getRequestResultFromFailoverCache(
546               successfulControllers, request.getId());
547         }
548         catch (NoResultAvailableException e)
549         {
550           exception = new SQLException JavaDoc(
551               "Request '"
552                   + request
553                   + "' was successfully executed on remote controllers, but all successful controllers failed before retrieving result");
554         }
555       }
556
557       /*
558        * Notify all controllers where all backend failed (if any) that
559        * completion was 'success'. We determine success from the successful
560        * controllers even though they may have failed afterwards (in which case
561        * requestResult may be null).
562        */

563       boolean success = (requestResult != null || successfulControllers != null);
564       notifyRequestCompletion(request, success, true, failedOnAllBackends);
565
566       // Notify controllers without active backends (if any)
567
notifyRequestCompletion(request, success, false,
568           controllersWithoutBackends);
569
570       if (inconsistentControllers != null)
571       { // Notify all inconsistent controllers to disable their backends
572
notifyControllerInconsistency(request, inconsistentControllers);
573       }
574
575       if (requestResult != null)
576       {
577         if (logger.isDebugEnabled())
578           logger.debug("Request " + request.getId()
579               + " completed successfully.");
580         return requestResult;
581       }
582
583       // At this point, all controllers failed
584

585       if (exception != null)
586         throw exception;
587       else
588       {
589         String JavaDoc msg = "Request '" + request + "' failed on all controllers";
590         logger.warn(msg);
591         throw new SQLException JavaDoc(msg);
592       }
593     }
594     catch (SQLException JavaDoc e)
595     {
596       String JavaDoc msg = Translate
597           .get("loadbalancer.request.failed", new String JavaDoc[]{
598               request.getSqlShortForm(vdb.getSqlShortFormLength()),
599               e.getMessage()});
600       logger.warn(msg);
601       throw e;
602     }
603   }
604
605   /**
606    * Execute a distributed request that returns a ResultSet.
607    *
608    * @param request the request to execute
609    * @param requestMsg message to be sent through the group communication
610    * @param messageTimeout group message timeout
611    * @return the corresponding ResultSet
612    * @throws SQLException if an error occurs
613    */

614   private ExecuteUpdateResult executeRequestReturningInt(
615       AbstractRequest request, DistributedRequest requestMsg,
616       long messageTimeout) throws SQLException JavaDoc
617   {
618     if (dvdb.isProcessMacroBeforeBroadcast())
619       loadBalancer.handleMacros(request);
620     try
621     {
622       ExecuteUpdateResult requestResult = null;
623
624       List JavaDoc groupMembers = dvdb.getAllMembers();
625
626       MulticastResponse responses = multicastRequest(request, requestMsg,
627           messageTimeout, groupMembers);
628
629       // List of controllers that gave a AllBackendsFailedException
630
ArrayList JavaDoc failedOnAllBackends = null;
631       // List of controllers that gave an inconsistent result
632
ArrayList JavaDoc inconsistentControllers = null;
633       // List of controllers that have no more backends to execute queries
634
ArrayList JavaDoc controllersWithoutBackends = null;
635       SQLException JavaDoc exception = null;
636       int size = groupMembers.size();
637       // Get the result of each controller
638
for (int i = 0; i < size; i++)
639       {
640         Member member = (Member) groupMembers.get(i);
641         if ((responses.getFailedMembers() != null)
642             && responses.getFailedMembers().contains(member))
643         {
644           logger.warn("Controller " + member + " is suspected of failure.");
645           continue;
646         }
647         Object JavaDoc r = responses.getResult(member);
648         if (r instanceof ExecuteUpdateResult)
649         {
650           if (requestResult == null)
651             requestResult = (ExecuteUpdateResult) r;
652           else
653           {
654             if (requestResult.getUpdateCount() != ((ExecuteUpdateResult) r)
655                 .getUpdateCount())
656             {
657               if (inconsistentControllers == null)
658                 inconsistentControllers = new ArrayList JavaDoc();
659               inconsistentControllers.add(member);
660               logger.error("Controller " + member
661                   + " returned an inconsistent results ("
662                   + requestResult.getUpdateCount() + " when expecting "
663                   + ((ExecuteUpdateResult) r).getUpdateCount()
664                   + ") for request " + request.getId());
665             }
666           }
667         }
668         else if (r instanceof NoMoreBackendException)
669         {
670           if (controllersWithoutBackends == null)
671             controllersWithoutBackends = new ArrayList JavaDoc();
672           controllersWithoutBackends.add(member);
673           if (logger.isDebugEnabled())
674             logger.debug("Controller " + member
675                 + " has no more backends to execute query (" + r + ")");
676         }
677         else if (r instanceof Exception JavaDoc)
678         {
679           if (failedOnAllBackends == null)
680             failedOnAllBackends = new ArrayList JavaDoc();
681           failedOnAllBackends.add(member);
682           String JavaDoc msg = "Request " + request.getId() + " failed on controller "
683               + member + " (" + r + ")";
684           // This maybe just invalid SQL, see SEQUOIA-809
685
logger.debug(msg);
686           if (r instanceof SQLException JavaDoc)
687             exception = (SQLException JavaDoc) r;
688           else
689           {
690             exception = new SQLException JavaDoc("Internal exception " + r);
691             exception.initCause((Throwable JavaDoc) r);
692           }
693         }
694         else
695         {
696           if (failedOnAllBackends == null)
697             failedOnAllBackends = new ArrayList JavaDoc();
698           failedOnAllBackends.add(member);
699           if (logger.isWarnEnabled())
700             logger.warn("Unexpected answer from controller " + member + " ("
701                 + r + ") for request "
702                 + request.getSqlShortForm(vdb.getSqlShortFormLength()));
703         }
704       }
705
706       int requestUpdateCount = -1;
707       if (requestResult != null)
708         requestUpdateCount = requestResult.getUpdateCount();
709
710       // Notify all controllers where all backends failed (if any) that
711
// completion was 'success'
712
notifyRequestCompletion(request, requestResult != null, true,
713           failedOnAllBackends, requestUpdateCount);
714
715       // Notify controllers without active backends (if any)
716
notifyRequestCompletion(request, requestResult != null, false,
717           controllersWithoutBackends, requestUpdateCount);
718
719       if (inconsistentControllers != null)
720       { // Notify all inconsistent controllers to disable their backends
721
notifyControllerInconsistency(request, inconsistentControllers);
722       }
723
724       if (requestResult != null)
725       {
726         if (logger.isDebugEnabled())
727           logger.debug("Request " + request.getId()
728               + " completed successfully.");
729         return requestResult;
730       }
731
732       // At this point, all controllers failed
733

734       if (exception != null)
735         throw exception;
736       else
737       {
738         String JavaDoc msg = "Request '" + request + "' failed on all controllers";
739         logger.warn(msg);
740         throw new SQLException JavaDoc(msg);
741       }
742     }
743     catch (SQLException JavaDoc e)
744     {
745       String JavaDoc msg = Translate
746           .get("loadbalancer.request.failed", new String JavaDoc[]{
747               request.getSqlShortForm(vdb.getSqlShortFormLength()),
748               e.getMessage()});
749       // This maybe just invalid SQL, see SEQUOIA-809
750
logger.debug(msg);
751       throw e;
752     }
753   }
754
755   /**
756    * Execute a distributed request that returns a ResultSet.
757    *
758    * @param request the request to execute
759    * @param requestMsg message to be sent through the group communication
760    * @param messageTimeout group message timeout
761    * @return the corresponding ResultSet
762    * @throws SQLException if an error occurs
763    */

764   private ControllerResultSet executeRequestReturningResultSet(
765       AbstractRequest request, DistributedRequest requestMsg,
766       long messageTimeout) throws SQLException JavaDoc
767   {
768     if (dvdb.isProcessMacroBeforeBroadcast())
769       loadBalancer.handleMacros(request);
770     try
771     {
772       ControllerResultSet requestResult = null;
773
774       List JavaDoc groupMembers = dvdb.getAllMembers();
775
776       MulticastResponse responses = multicastRequest(request, requestMsg,
777           messageTimeout, groupMembers);
778
779       // List of controllers that gave a AllBackendsFailedException
780
ArrayList JavaDoc failedOnAllBackends = null;
781       // List of controllers that have no more backends to execute queries
782
ArrayList JavaDoc controllersWithoutBackends = null;
783       SQLException JavaDoc exception = null;
784       int size = groupMembers.size();
785       List JavaDoc successfulControllers = null;
786       // Get the result of each controller
787
for (int i = 0; i < size; i++)
788       {
789         Member member = (Member) groupMembers.get(i);
790         if ((responses.getFailedMembers() != null)
791             && responses.getFailedMembers().contains(member))
792         {
793           logger.warn("Controller " + member + " is suspected of failure.");
794           continue;
795         }
796         Object JavaDoc r = responses.getResult(member);
797         if (r instanceof ControllerResultSet)
798         {
799           if (requestResult == null)
800             requestResult = (ControllerResultSet) r;
801         }
802         else if (DistributedRequestManager.SUCCESSFUL_COMPLETION.equals(r))
803         {
804           // Remote controller success
805
if (requestResult == null)
806           {
807             if (successfulControllers == null)
808               successfulControllers = new ArrayList JavaDoc();
809             successfulControllers.add(member);
810           }
811         }
812         else if (r instanceof NoMoreBackendException)
813         {
814           if (controllersWithoutBackends == null)
815             controllersWithoutBackends = new ArrayList JavaDoc();
816           controllersWithoutBackends.add(member);
817           if (logger.isDebugEnabled())
818             logger.debug("Controller " + member
819                 + " has no more backends to execute query (" + r + ")");
820         }
821         else if (r instanceof Exception JavaDoc)
822         {
823           if (failedOnAllBackends == null)
824             failedOnAllBackends = new ArrayList JavaDoc();
825           failedOnAllBackends.add(member);
826           String JavaDoc msg = "Request " + request.getId() + " failed on controller "
827               + member + " (" + r + ")";
828           logger.warn(msg);
829           if (r instanceof SQLException JavaDoc)
830             exception = (SQLException JavaDoc) r;
831           else
832           {
833             exception = new SQLException JavaDoc("Internal exception " + r);
834             exception.initCause((Throwable JavaDoc) r);
835           }
836         }
837         else
838         {
839           if (failedOnAllBackends == null)
840             failedOnAllBackends = new ArrayList JavaDoc();
841           failedOnAllBackends.add(member);
842           if (logger.isWarnEnabled())
843             logger.warn("Unexpected answer from controller " + member + " ("
844                 + r + ") for request "
845                 + request.getSqlShortForm(vdb.getSqlShortFormLength()));
846         }
847       }
848
849       if ((requestResult == null) && (successfulControllers != null))
850       { // Local controller could not get the result, ask it to a successful
851
// remote controller
852
try
853         {
854           requestResult = (ControllerResultSet) getRequestResultFromFailoverCache(
855               successfulControllers, request.getId());
856         }
857         catch (NoResultAvailableException e)
858         {
859           exception = new SQLException JavaDoc(
860               "Request '"
861                   + request
862                   + "' was successfully executed on remote controllers, but all successful controllers failed before retrieving result");
863         }
864       }
865
866       /*
867        * Notify all controllers where all backend failed (if any) that
868        * completion was 'success'. We determine success from the local result or
869        * the successful remote controllers even though they may have failed
870        * afterwards (in which case requestResult may be null).
871        */

872       boolean success = (requestResult != null || successfulControllers != null);
873
874       notifyRequestCompletion(request, success, true, failedOnAllBackends);
875
876       // Notify controllers without active backends (if any)
877
notifyRequestCompletion(request, success, false,
878           controllersWithoutBackends);
879
880       if (requestResult != null)
881       {
882         if (logger.isDebugEnabled())
883           logger.debug("Request " + request.getId()
884               + " completed successfully.");
885         return requestResult;
886       }
887
888       // At this point, all controllers failed
889

890       if (exception != null)
891         throw exception;
892       else
893       {
894         String JavaDoc msg = "Request '" + request + "' failed on all controllers";
895         logger.warn(msg);
896         throw new SQLException JavaDoc(msg);
897       }
898     }
899     catch (SQLException JavaDoc e)
900     {
901       String JavaDoc msg = Translate
902           .get("loadbalancer.request.failed", new String JavaDoc[]{
903               request.getSqlShortForm(vdb.getSqlShortFormLength()),
904               e.getMessage()});
905       logger.warn(msg);
906       throw e;
907     }
908   }
909
910   /**
911    * Execute a distributed request (usually a stored procedure) that returns a
912    * StoredProcedureCallResult.
913    *
914    * @param proc the stored procedure to execute
915    * @param requestMsg message to be sent through the group communication
916    * @param messageTimeout group message timeout
917    * @return the corresponding StoredProcedureCallResult
918    * @throws SQLException if an error occurs
919    */

920   private StoredProcedureCallResult executeRequestReturningStoredProcedureCallResult(
921       StoredProcedure proc, DistributedRequest requestMsg, long messageTimeout)
922       throws SQLException JavaDoc
923   {
924     if (dvdb.isProcessMacroBeforeBroadcast())
925       loadBalancer.handleMacros(proc);
926     try
927     {
928       StoredProcedureCallResult result = null;
929
930       List JavaDoc groupMembers = dvdb.getAllMembers();
931
932       MulticastResponse responses = multicastRequest(proc, requestMsg,
933           messageTimeout, groupMembers);
934
935       // List of controllers that gave a AllBackendsFailedException
936
ArrayList JavaDoc failedOnAllBackends = null;
937       // List of controllers that have no more backends to execute queries
938
ArrayList JavaDoc controllersWithoutBackends = null;
939       SQLException JavaDoc exception = null;
940       int size = groupMembers.size();
941       List JavaDoc successfulControllers = null;
942       // Get the result of each controller
943
for (int i = 0; i < size; i++)
944       {
945         Member member = (Member) groupMembers.get(i);
946         if ((responses.getFailedMembers() != null)
947             && responses.getFailedMembers().contains(member))
948         {
949           logger.warn("Controller " + member + " is suspected of failure.");
950           continue;
951         }
952         Object JavaDoc r = responses.getResult(member);
953         if (r instanceof StoredProcedureCallResult)
954         {
955           if (result == null)
956             result = (StoredProcedureCallResult) r;
957         }
958         else if (DistributedRequestManager.SUCCESSFUL_COMPLETION.equals(r))
959         {
960           // Remote controller success
961
if (result == null)
962           {
963             if (successfulControllers == null)
964               successfulControllers = new ArrayList JavaDoc();
965             successfulControllers.add(member);
966           }
967         }
968         else if (r instanceof NoMoreBackendException)
969         {
970           if (controllersWithoutBackends == null)
971             controllersWithoutBackends = new ArrayList JavaDoc();
972           controllersWithoutBackends.add(member);
973           if (logger.isDebugEnabled())
974             logger.debug("Controller " + member
975                 + " has no more backends to execute query (" + r + ")");
976         }
977         else if (r instanceof Exception JavaDoc)
978         {
979           if (failedOnAllBackends == null)
980             failedOnAllBackends = new ArrayList JavaDoc();
981           failedOnAllBackends.add(member);
982           String JavaDoc msg = "Request " + proc.getId() + " failed on controller "
983               + member + " (" + r + ")";
984           logger.warn(msg);
985           if (r instanceof SQLException JavaDoc)
986             exception = (SQLException JavaDoc) r;
987           else
988           {
989             exception = new SQLException JavaDoc("Internal exception " + r);
990             exception.initCause((Throwable JavaDoc) r);
991           }
992         }
993         else
994         {
995           if (failedOnAllBackends == null)
996             failedOnAllBackends = new ArrayList JavaDoc();
997           failedOnAllBackends.add(member);
998           if (logger.isWarnEnabled())
999             logger.warn("Unexpected answer from controller " + member + " ("
1000                + r + ") for request "
1001                + proc.getSqlShortForm(vdb.getSqlShortFormLength()));
1002        }
1003      }
1004
1005      if ((result == null) && (successfulControllers != null))
1006      { // Local controller could not get the result, ask it to a successful
1007
// remote controller
1008

1009        try
1010        {
1011          result = (StoredProcedureCallResult) getRequestResultFromFailoverCache(
1012              successfulControllers, proc.getId());
1013        }
1014        catch (NoResultAvailableException e)
1015        {
1016          exception = new SQLException JavaDoc(
1017              "Request '"
1018                  + proc
1019                  + "' was successfully executed on remote controllers, but all successful controllers failed before retrieving result");
1020        }
1021
1022      }
1023
1024      /*
1025       * Notify all controllers where all backend failed (if any) that
1026       * completion was 'success'. We determine success from the local result or
1027       * the successful remote controllers even though they may have failed
1028       * afterwards (in which case requestResult may be null).
1029       */

1030      boolean success = (result != null || successfulControllers != null);
1031
1032      notifyRequestCompletion(proc, success, true, failedOnAllBackends);
1033
1034      // Notify controllers without active backends (if any)
1035
notifyRequestCompletion(proc, success, false, controllersWithoutBackends);
1036
1037      if (result != null)
1038      {
1039        proc.copyNamedAndOutParameters(result.getStoredProcedure());
1040        if (logger.isDebugEnabled())
1041          logger.debug("Request " + proc.getId() + " completed successfully.");
1042        return result;
1043      }
1044
1045      // At this point, all controllers failed
1046

1047      if (exception != null)
1048        throw exception;
1049      else
1050      {
1051        String JavaDoc msg = "Request '" + proc + "' failed on all controllers";
1052        logger.warn(msg);
1053        throw new SQLException JavaDoc(msg);
1054      }
1055    }
1056    catch (SQLException JavaDoc e)
1057    {
1058      String JavaDoc msg = Translate.get("loadbalancer.request.failed", new String JavaDoc[]{
1059          proc.getSqlShortForm(vdb.getSqlShortFormLength()), e.getMessage()});
1060      logger.warn(msg);
1061      throw e;
1062    }
1063  }
1064
1065  /**
1066   * Multicast a request to a set of controllers.
1067   *
1068   * @param request the request that is executed
1069   * @param requestMsg the group message to send
1070   * @param messageTimeout timeout on the group message
1071   * @param groupMembers list of controllers to send the message to
1072   * @return the responses to the multicast
1073   * @throws SQLException if an error occurs
1074   */

1075  private MulticastResponse multicastRequest(AbstractRequest request,
1076      Serializable JavaDoc requestMsg, long messageTimeout, List JavaDoc groupMembers)
1077      throws SQLException JavaDoc
1078  {
1079    if (logger.isDebugEnabled())
1080      logger.debug("Broadcasting request "
1081          + request.getSqlShortForm(dvdb.getSqlShortFormLength())
1082          + (request.isAutoCommit() ? "" : " transaction "
1083              + request.getTransactionId()) + " to all controllers ("
1084          + dvdb.getChannel().getLocalMembership() + "->"
1085          + groupMembers.toString() + ")");
1086
1087    // Send the query to everybody including us
1088
MulticastResponse responses;
1089    try
1090    {
1091      // Warning! Message timeouts are in ms but request timeout is in seconds
1092
responses = dvdb.getMulticastRequestAdapter().multicastMessage(
1093          groupMembers,
1094          requestMsg,
1095          MulticastRequestAdapter.WAIT_ALL,
1096          MessageTimeouts.getMinTimeout(messageTimeout,
1097              request.getTimeout() * 1000L));
1098    }
1099    catch (Exception JavaDoc e)
1100    {
1101      String JavaDoc msg = "An error occured while executing distributed request "
1102          + request.getId();
1103      logger.warn(msg, e);
1104      throw new SQLException JavaDoc(msg + " (" + e + ")");
1105    }
1106
1107    if (logger.isDebugEnabled())
1108      logger.debug("Request "
1109          + request.getSqlShortForm(dvdb.getSqlShortFormLength())
1110          + " completed.");
1111
1112    if (responses.getFailedMembers() != null)
1113    { // Some controllers failed ... too bad !
1114
logger.warn(responses.getFailedMembers().size()
1115          + " controller(s) died during execution of request "
1116          + request.getId());
1117    }
1118    return responses;
1119  }
1120
1121  /**
1122   * @see org.continuent.sequoia.controller.requestmanager.distributed.DistributedRequestManager#distributedAbort(String,
1123   * long)
1124   */

1125  public void distributedAbort(String JavaDoc login, long transactionId)
1126      throws SQLException JavaDoc
1127  {
1128    try
1129    {
1130      List JavaDoc groupMembers = dvdb.getAllMembers();
1131
1132      AbstractRequest abortRequest = new UnknownWriteRequest("abort", false, 0,
1133          "\n");
1134      abortRequest.setLogin(login);
1135      abortRequest.setTransactionId(transactionId);
1136      abortRequest.setIsAutoCommit(false);
1137
1138      MulticastResponse responses = multicastRequest(abortRequest,
1139          new DistributedAbort(login, transactionId), dvdb.getMessageTimeouts()
1140              .getRollbackTimeout(), groupMembers);
1141
1142      if (logger.isDebugEnabled())
1143        logger.debug("Abort of transaction " + transactionId + " completed.");
1144
1145      // List of controllers that have no more backends to execute queries
1146
ArrayList JavaDoc controllersWithException = null;
1147      SQLException JavaDoc exception = null;
1148      int size = groupMembers.size();
1149      boolean success = false;
1150      // Get the result of each controller
1151
for (int i = 0; i < size; i++)
1152      {
1153        Member member = (Member) groupMembers.get(i);
1154        if ((responses.getFailedMembers() != null)
1155            && responses.getFailedMembers().contains(member))
1156        {
1157          logger.warn("Controller " + member + " is suspected of failure.");
1158          continue;
1159        }
1160        Object JavaDoc r = responses.getResult(member);
1161        if (r instanceof Boolean JavaDoc)
1162        {
1163          if (((Boolean JavaDoc) r).booleanValue())
1164            success = true;
1165          else
1166            logger.error("Unexpected result for controller " + member);
1167        }
1168        else if (r instanceof Exception JavaDoc)
1169        {
1170          if (controllersWithException == null)
1171            controllersWithException = new ArrayList JavaDoc();
1172          controllersWithException.add(member);
1173          if (logger.isDebugEnabled())
1174            logger.debug("Controller " + member
1175                + " has no more backends to abort transaction "
1176                + transactionId + " (" + r + ")");
1177        }
1178      }
1179
1180      // Notify all controllers that have thrown an exception
1181
notifyRequestCompletion(abortRequest, success, false,
1182          controllersWithException);
1183
1184      if (success)
1185        return; // This is a success if at least one controller has succeeded
1186

1187      if (exception != null)
1188        throw exception;
1189
1190      // At this point, all controllers failed
1191

1192      String JavaDoc msg = "Transaction " + transactionId
1193          + " failed to abort on all controllers";
1194      logger.warn(msg);
1195      throw new SQLException JavaDoc(msg);
1196    }
1197    catch (SQLException JavaDoc e)
1198    {
1199      String JavaDoc msg = "Transaction " + transactionId + " abort failed (" + e + ")";
1200      logger.warn(msg);
1201      throw e;
1202    }
1203  }
1204
1205  /**
1206   * @see org.continuent.sequoia.controller.requestmanager.distributed.DistributedRequestManager#distributedCommit(String,
1207   * long)
1208   */

1209  public void distributedCommit(String JavaDoc login, long transactionId)
1210      throws SQLException JavaDoc
1211  {
1212    try
1213    {
1214      List JavaDoc groupMembers = dvdb.getAllMembers();
1215      AbstractRequest commitRequest = new UnknownWriteRequest("commit", false,
1216          0, "\n");
1217      commitRequest.setTransactionId(transactionId);
1218      commitRequest.setLogin(login);
1219      commitRequest.setIsAutoCommit(false);
1220
1221      MulticastResponse responses = multicastRequest(commitRequest,
1222          new DistributedCommit(login, transactionId), dvdb
1223              .getMessageTimeouts().getCommitTimeout(), groupMembers);
1224
1225      if (logger.isDebugEnabled())
1226        logger.debug("Commit of transaction " + transactionId + " completed.");
1227
1228      // List of controllers that gave a AllBackendsFailedException
1229
ArrayList JavaDoc failedOnAllBackends = null;
1230      // List of controllers that have no more backends to execute queries
1231
ArrayList JavaDoc controllersWithoutBackends = null;
1232      SQLException JavaDoc exception = null;
1233      // get a list that won't change while we go through it
1234
groupMembers = dvdb.getAllMembers();
1235      int size = groupMembers.size();
1236      boolean success = false;
1237      // Get the result of each controller
1238
for (int i = 0; i < size; i++)
1239      {
1240        Member member = (Member) groupMembers.get(i);
1241        if ((responses.getFailedMembers() != null)
1242            && responses.getFailedMembers().contains(member))
1243        {
1244          logger.warn("Controller " + member + " is suspected of failure.");
1245          continue;
1246        }
1247        Object JavaDoc r = responses.getResult(member);
1248        if (r instanceof Boolean JavaDoc)
1249        {
1250          if (((Boolean JavaDoc) r).booleanValue())
1251            success = true;
1252          else
1253            logger.error("Unexpected result for controller " + member);
1254        }
1255        else if (r instanceof NoMoreBackendException)
1256        {
1257          if (controllersWithoutBackends == null)
1258            controllersWithoutBackends = new ArrayList JavaDoc();
1259          controllersWithoutBackends.add(member);
1260          if (logger.isDebugEnabled())
1261            logger.debug("Controller " + member
1262                + " has no more backends to commit transaction "
1263                + transactionId + " (" + r + ")");
1264        }
1265        else if (r instanceof AllBackendsFailedException)
1266        {
1267          if (failedOnAllBackends == null)
1268            failedOnAllBackends = new ArrayList JavaDoc();
1269          failedOnAllBackends.add(member);
1270          if (logger.isDebugEnabled())
1271            logger.debug("Commit failed on all backends of controller "
1272                + member + " (" + r + ")");
1273        }
1274        else if (r instanceof SQLException JavaDoc)
1275        {
1276          if (failedOnAllBackends == null)
1277            failedOnAllBackends = new ArrayList JavaDoc();
1278          failedOnAllBackends.add(member);
1279          String JavaDoc msg = "Commit of transaction " + transactionId
1280              + " failed on controller " + member + " (" + r + ")";
1281          logger.warn(msg);
1282          exception = (SQLException JavaDoc) r;
1283        }
1284      }
1285
1286      // Notify all controllers where all backend failed (if any) that
1287
// completion was 'success'
1288
notifyRequestCompletion(commitRequest, success, true, failedOnAllBackends);
1289
1290      // Notify controllers without active backends (if any)
1291
notifyRequestCompletion(commitRequest, success, false,
1292          controllersWithoutBackends);
1293
1294      if (success)
1295        return; // This is a success if at least one controller has succeeded
1296

1297      // At this point, all controllers failed
1298

1299      if (exception != null)
1300        throw exception;
1301      else
1302      {
1303        String JavaDoc msg = "Transaction " + transactionId
1304            + " failed to commit on all controllers";
1305        logger.warn(msg);
1306        throw new SQLException JavaDoc(msg);
1307      }
1308    }
1309    catch (SQLException JavaDoc e)
1310    {
1311      String JavaDoc msg = "Transaction " + transactionId + " commit failed (" + e
1312          + ")";
1313      logger.warn(msg);
1314      throw e;
1315    }
1316  }
1317
1318  /**
1319   * @see org.continuent.sequoia.controller.requestmanager.distributed.DistributedRequestManager#distributedRollback(String,
1320   * long)
1321   */

1322  public void distributedRollback(String JavaDoc login, long transactionId)
1323      throws SQLException JavaDoc
1324  {
1325    try
1326    {
1327      List JavaDoc groupMembers = dvdb.getAllMembers();
1328
1329      AbstractRequest rollbackRequest = new UnknownWriteRequest("rollback",
1330          false, 0, "\n");
1331      rollbackRequest.setTransactionId(transactionId);
1332      rollbackRequest.setLogin(login);
1333      rollbackRequest.setIsAutoCommit(false);
1334
1335      MulticastResponse responses = multicastRequest(rollbackRequest,
1336          new DistributedRollback(login, transactionId), dvdb
1337              .getMessageTimeouts().getRollbackTimeout(), groupMembers);
1338
1339      if (logger.isDebugEnabled())
1340        logger
1341            .debug("Rollback of transaction " + transactionId + " completed.");
1342
1343      // List of controllers that gave a AllBackendsFailedException
1344
ArrayList JavaDoc failedOnAllBackends = null;
1345      // List of controllers that have no more backends to execute queries
1346
ArrayList JavaDoc controllersWithoutBackends = null;
1347      SQLException JavaDoc exception = null;
1348
1349      // get a list that won't change while we go through it
1350
groupMembers = dvdb.getAllMembers();
1351      int size = groupMembers.size();
1352      boolean success = false;
1353      // Get the result of each controller
1354
for (int i = 0; i < size; i++)
1355      {
1356        Member member = (Member) groupMembers.get(i);
1357        if ((responses.getFailedMembers() != null)
1358            && responses.getFailedMembers().contains(member))
1359        {
1360          logger.warn("Controller " + member + " is suspected of failure.");
1361          continue;
1362        }
1363        Object JavaDoc r = responses.getResult(member);
1364        if (r instanceof Boolean JavaDoc)
1365        {
1366          if (((Boolean JavaDoc) r).booleanValue())
1367            success = true;
1368          else
1369            logger.error("Unexpected result for controller " + member);
1370        }
1371        else if (r instanceof NoMoreBackendException)
1372        {
1373          if (controllersWithoutBackends == null)
1374            controllersWithoutBackends = new ArrayList JavaDoc();
1375          controllersWithoutBackends.add(member);
1376          if (logger.isDebugEnabled())
1377            logger.debug("Controller " + member
1378                + " has no more backends to rollback transaction "
1379                + transactionId + " (" + r + ")");
1380        }
1381        else if (r instanceof AllBackendsFailedException)
1382        {
1383          if (failedOnAllBackends == null)
1384            failedOnAllBackends = new ArrayList JavaDoc();
1385          failedOnAllBackends.add(member);
1386          if (logger.isDebugEnabled())
1387            logger.debug("Rollback failed on all backends of controller "
1388                + member + " (" + r + ")");
1389        }
1390        else if (r instanceof SQLException JavaDoc)
1391        {
1392          if (failedOnAllBackends == null)
1393            failedOnAllBackends = new ArrayList JavaDoc();
1394          failedOnAllBackends.add(member);
1395          String JavaDoc msg = "Rollback of transaction " + transactionId
1396              + " failed on controller " + member + " (" + r + ")";
1397          logger.warn(msg);
1398          exception = (SQLException JavaDoc) r;
1399        }
1400      }
1401
1402      // Notify all controllers where all backend failed (if any) that
1403
// completion was 'success'
1404
notifyRequestCompletion(rollbackRequest, success, true,
1405          failedOnAllBackends);
1406
1407      // Notify controllers without active backends (if any)
1408
notifyRequestCompletion(rollbackRequest, success, false,
1409          controllersWithoutBackends);
1410
1411      if (success)
1412        return; // This is a success if at least one controller has succeeded
1413

1414      if (exception != null)
1415        throw exception;
1416
1417      // At this point, all controllers failed
1418

1419      String JavaDoc msg = "Transaction " + transactionId
1420          + " failed to rollback on all controllers";
1421      logger.warn(msg);
1422      throw new SQLException JavaDoc(msg);
1423    }
1424    catch (SQLException JavaDoc e)
1425    {
1426      String JavaDoc msg = "Transaction " + transactionId + " rollback failed (" + e
1427          + ")";
1428      logger.warn(msg);
1429      throw e;
1430    }
1431  }
1432
1433  /**
1434   * @see org.continuent.sequoia.controller.requestmanager.distributed.DistributedRequestManager#distributedRollback(String,
1435   * long, String)
1436   */

1437  public void distributedRollback(String JavaDoc login, long transactionId,
1438      String JavaDoc savepointName) throws SQLException JavaDoc
1439  {
1440    try
1441    {
1442      List JavaDoc groupMembers = dvdb.getAllMembers();
1443
1444      AbstractRequest rollbackRequest = new UnknownWriteRequest("rollback "
1445          + savepointName, false, 0, "\n");
1446      rollbackRequest.setTransactionId(transactionId);
1447      rollbackRequest.setLogin(login);
1448      rollbackRequest.setIsAutoCommit(false);
1449
1450      MulticastResponse responses = multicastRequest(rollbackRequest,
1451          new DistributedRollbackToSavepoint(transactionId, savepointName),
1452          dvdb.getMessageTimeouts().getRollbackToSavepointTimeout(),
1453          groupMembers);
1454
1455      if (logger.isDebugEnabled())
1456        logger.debug("Rollback to savepoint " + savepointName + " for "
1457            + "transaction " + transactionId + " completed.");
1458
1459      // List of controllers that gave a AllBackendsFailedException
1460
ArrayList JavaDoc failedOnAllBackends = null;
1461      // List of controllers that have no more backends to execute queries
1462
ArrayList JavaDoc controllersWithoutBackends = null;
1463      SQLException JavaDoc exception = null;
1464
1465      // get a list that won't change while we go through it
1466
groupMembers = dvdb.getAllMembers();
1467      int size = groupMembers.size();
1468      boolean success = false;
1469      // Get the result of each controller
1470
for (int i = 0; i < size; i++)
1471      {
1472        Member member = (Member) groupMembers.get(i);
1473        if ((responses.getFailedMembers() != null)
1474            && responses.getFailedMembers().contains(member))
1475        {
1476          logger.warn("Controller " + member + " is suspected of failure.");
1477          continue;
1478        }
1479        Object JavaDoc r = responses.getResult(member);
1480        if (r instanceof Boolean JavaDoc)
1481        {
1482          if (((Boolean JavaDoc) r).booleanValue())
1483            success = true;
1484          else
1485            logger.error("Unexpected result for controller " + member);
1486        }
1487        else if (r instanceof NoMoreBackendException)
1488        {
1489          if (controllersWithoutBackends == null)
1490            controllersWithoutBackends = new ArrayList JavaDoc();
1491          controllersWithoutBackends.add(member);
1492          if (logger.isDebugEnabled())
1493            logger.debug("Controller " + member + " has no more backends to "
1494                + "rollback to savepoint " + savepointName + " for "
1495                + "transaction " + transactionId + " (" + r + ")");
1496        }
1497        else if (r instanceof AllBackendsFailedException)
1498        {
1499          if (failedOnAllBackends == null)
1500            failedOnAllBackends = new ArrayList JavaDoc();
1501          failedOnAllBackends.add(member);
1502          if (logger.isDebugEnabled())
1503            logger.debug("rollback to savepoint failed on all backends of "
1504                + "controller " + member + " (" + r + ")");
1505        }
1506        else if (r instanceof SQLException JavaDoc)
1507        {
1508          if (failedOnAllBackends == null)
1509            failedOnAllBackends = new ArrayList JavaDoc();
1510          failedOnAllBackends.add(member);
1511          String JavaDoc msg = "rollback to savepoint " + savepointName + " for "
1512              + "transaction " + transactionId + " failed on controller "
1513              + member + " (" + r + ")";
1514          logger.warn(msg);
1515          exception = (SQLException JavaDoc) r;
1516        }
1517      }
1518
1519      // Notify all controllers where all backend failed (if any) that
1520
// completion was 'success'
1521
notifyRequestCompletion(rollbackRequest, success, true,
1522          failedOnAllBackends);
1523
1524      // Notify controllers without active backends (if any)
1525
notifyRequestCompletion(rollbackRequest, success, false,
1526          controllersWithoutBackends);
1527
1528      if (success)
1529        return; // This is a success if at least one controller has succeeded
1530

1531      if (exception != null)
1532        throw exception;
1533
1534      // At this point, all controllers failed
1535

1536      if (exception != null)
1537        throw exception;
1538      else
1539      {
1540        String JavaDoc msg = "Rollback to savepoint " + savepointName + " for "
1541            + "transaction " + transactionId + " failed on all controllers";
1542        logger.warn(msg);
1543        throw new SQLException JavaDoc(msg);
1544      }
1545    }
1546    catch (SQLException JavaDoc e)
1547    {
1548      String JavaDoc msg = "Rollback to savepoint " + savepointName + " for "
1549          + "transaction " + transactionId + " failed (" + e + ")";
1550      logger.warn(msg);
1551      throw e;
1552    }
1553  }
1554
1555  /**
1556   * @see org.continuent.sequoia.controller.requestmanager.distributed.DistributedRequestManager#distributedSetSavepoint(String,
1557   * long, String)
1558   */

1559  public void distributedSetSavepoint(String JavaDoc login, long transactionId,
1560      String JavaDoc name) throws SQLException JavaDoc
1561  {
1562    try
1563    {
1564      List JavaDoc groupMembers = dvdb.getAllMembers();
1565
1566      AbstractRequest setSavepointRequest = new UnknownWriteRequest(
1567          "savepoint " + name, false, 0, "\n");
1568      setSavepointRequest.setTransactionId(transactionId);
1569      setSavepointRequest.setLogin(login);
1570      setSavepointRequest.setIsAutoCommit(false);
1571
1572      MulticastResponse responses = multicastRequest(setSavepointRequest,
1573          new DistributedSetSavepoint(login, transactionId, name), dvdb
1574              .getMessageTimeouts().getSetSavepointTimeout(), groupMembers);
1575
1576      if (logger.isDebugEnabled())
1577        logger.debug("Set savepoint " + name + " to transaction "
1578            + transactionId + " completed.");
1579
1580      // List of controllers that gave a AllBackendsFailedException
1581
ArrayList JavaDoc failedOnAllBackends = null;
1582      // List of controllers that have no more backends to execute queries
1583
ArrayList JavaDoc controllersWithoutBackends = null;
1584      SQLException JavaDoc exception = null;
1585
1586      // get a list that won't change while we go through it
1587
groupMembers = dvdb.getAllMembers();
1588      int size = groupMembers.size();
1589      boolean success = false;
1590      // Get the result of each controller
1591
for (int i = 0; i < size; i++)
1592      {
1593        Member member = (Member) groupMembers.get(i);
1594        if ((responses.getFailedMembers() != null)
1595            && responses.getFailedMembers().contains(member))
1596        {
1597          logger.warn("Controller " + member + " is suspected of failure.");
1598          continue;
1599        }
1600        Object JavaDoc r = responses.getResult(member);
1601        if (r instanceof Boolean JavaDoc)
1602        {
1603          if (((Boolean JavaDoc) r).booleanValue())
1604            success = true;
1605          else
1606            logger.error("Unexpected result for controller " + member);
1607        }
1608        else if (r instanceof NoMoreBackendException)
1609        {
1610          if (controllersWithoutBackends == null)
1611            controllersWithoutBackends = new ArrayList JavaDoc();
1612          controllersWithoutBackends.add(member);
1613          if (logger.isDebugEnabled())
1614            logger.debug("Controller " + member + " has no more backends to "
1615                + "set savepoint " + name + " to transaction " + transactionId
1616                + " (" + r + ")");
1617        }
1618        else if (r instanceof AllBackendsFailedException)
1619        {
1620          if (failedOnAllBackends == null)
1621            failedOnAllBackends = new ArrayList JavaDoc();
1622          failedOnAllBackends.add(member);
1623          if (logger.isDebugEnabled())
1624            logger.debug("set savepoint failed on all backends of controller "
1625                + member + " (" + r + ")");
1626        }
1627        else if (r instanceof SQLException JavaDoc)
1628        {
1629          if (failedOnAllBackends == null)
1630            failedOnAllBackends = new ArrayList JavaDoc();
1631          failedOnAllBackends.add(member);
1632          String JavaDoc msg = "set savepoint " + name + " to transaction "
1633              + transactionId + " failed on controller " + member + " (" + r
1634              + ")";
1635          logger.warn(msg);
1636          exception = (SQLException JavaDoc) r;
1637        }
1638      }
1639
1640      // Notify all controllers where all backend failed (if any) that
1641
// completion was 'success'
1642
notifyRequestCompletion(setSavepointRequest, success, true,
1643          failedOnAllBackends);
1644
1645      // Notify controllers without active backends (if any)
1646
notifyRequestCompletion(setSavepointRequest, success, false,
1647          controllersWithoutBackends);
1648
1649      if (success)
1650        return; // This is a success if at least one controller has succeeded
1651

1652      if (exception != null)
1653        throw exception;
1654
1655      // At this point, all controllers failed
1656

1657      if (exception != null)
1658        throw exception;
1659      else
1660      {
1661        String JavaDoc msg = "Set savepoint " + name + " to transaction "
1662            + transactionId + " failed on all controllers";
1663        logger.warn(msg);
1664        throw new SQLException JavaDoc(msg);
1665      }
1666    }
1667    catch (SQLException JavaDoc e)
1668    {
1669      String JavaDoc msg = "Set savepoint " + name + " to transaction " + transactionId
1670          + " failed (" + e + ")";
1671      logger.warn(msg);
1672      throw e;
1673    }
1674  }
1675
1676  /**
1677   * @see org.continuent.sequoia.controller.requestmanager.distributed.DistributedRequestManager#distributedReleaseSavepoint(String,
1678   * long, String)
1679   */

1680  public void distributedReleaseSavepoint(String JavaDoc login, long transactionId,
1681      String JavaDoc name) throws SQLException JavaDoc
1682  {
1683    try
1684    {
1685      List JavaDoc groupMembers = dvdb.getAllMembers();
1686
1687      AbstractRequest releaseSavepointRequest = new UnknownWriteRequest(
1688          "release " + name, false, 0, "\n");
1689      releaseSavepointRequest.setTransactionId(transactionId);
1690      releaseSavepointRequest.setLogin(login);
1691      releaseSavepointRequest.setIsAutoCommit(false);
1692
1693      MulticastResponse responses = multicastRequest(releaseSavepointRequest,
1694          new DistributedReleaseSavepoint(transactionId, name), dvdb
1695              .getMessageTimeouts().getReleaseSavepointTimeout(), groupMembers);
1696
1697      if (logger.isDebugEnabled())
1698        logger.debug("Release savepoint " + name + " from transaction "
1699            + transactionId + " completed.");
1700
1701      // List of controllers that gave a AllBackendsFailedException
1702
ArrayList JavaDoc failedOnAllBackends = null;
1703      // List of controllers that have no more backends to execute queries
1704
ArrayList JavaDoc controllersWithoutBackends = null;
1705      SQLException JavaDoc exception = null;
1706
1707      // get a list that won't change while we go through it
1708
groupMembers = dvdb.getAllMembers();
1709      int size = groupMembers.size();
1710      boolean success = false;
1711      // Get the result of each controller
1712
for (int i = 0; i < size; i++)
1713      {
1714        Member member = (Member) groupMembers.get(i);
1715        if ((responses.getFailedMembers() != null)
1716            && responses.getFailedMembers().contains(member))
1717        {
1718          logger.warn("Controller " + member + " is suspected of failure.");
1719          continue;
1720        }
1721        Object JavaDoc r = responses.getResult(member);
1722        if (r instanceof Boolean JavaDoc)
1723        {
1724          if (((Boolean JavaDoc) r).booleanValue())
1725            success = true;
1726          else
1727            logger.error("Unexpected result for controller " + member);
1728        }
1729        else if (r instanceof NoMoreBackendException)
1730        {
1731          if (controllersWithoutBackends == null)
1732            controllersWithoutBackends = new ArrayList JavaDoc();
1733          controllersWithoutBackends.add(member);
1734          if (logger.isDebugEnabled())
1735            logger.debug("Controller " + member + " has no more backends to "
1736                + "release savepoint " + name + " from transaction "
1737                + transactionId + " (" + r + ")");
1738        }
1739        else if (r instanceof AllBackendsFailedException)
1740        {
1741          if (failedOnAllBackends == null)
1742            failedOnAllBackends = new ArrayList JavaDoc();
1743          failedOnAllBackends.add(member);
1744          if (logger.isDebugEnabled())
1745            logger.debug("release savepoint failed on all backends of "
1746                + "controller " + member + " (" + r + ")");
1747        }
1748        else if (r instanceof SQLException JavaDoc)
1749        {
1750          if (failedOnAllBackends == null)
1751            failedOnAllBackends = new ArrayList JavaDoc();
1752          failedOnAllBackends.add(member);
1753          String JavaDoc msg = "release savepoint " + name + " from transaction "
1754              + transactionId + " failed on controller " + member + " (" + r
1755              + ")";
1756          logger.warn(msg);
1757          exception = (SQLException JavaDoc) r;
1758        }
1759      }
1760
1761      // Notify all controllers where all backend failed (if any) that
1762
// completion was 'success'
1763
notifyRequestCompletion(releaseSavepointRequest, success, true,
1764          failedOnAllBackends);
1765
1766      // Notify controllers without active backends (if any)
1767
notifyRequestCompletion(releaseSavepointRequest, success, false,
1768          controllersWithoutBackends);
1769
1770      if (success)
1771        return; // This is a success if at least one controller has succeeded
1772

1773      if (exception != null)
1774        throw exception;
1775
1776      // At this point, all controllers failed
1777

1778      if (exception != null)
1779        throw exception;
1780      else
1781      {
1782        String JavaDoc msg = "Release savepoint " + name + " from transaction "
1783            + transactionId + " failed on all controllers";
1784        logger.warn(msg);
1785        throw new SQLException JavaDoc(msg);
1786      }
1787    }
1788    catch (SQLException JavaDoc e)
1789    {
1790      String JavaDoc msg = "Release savepoint " + name + " from transaction "
1791          + transactionId + " failed (" + e + ")";
1792      logger.warn(msg);
1793      throw e;
1794    }
1795  }
1796
1797}
Popular Tags