KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > jts > CosTransactions > TopCoordinator


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24 /*
25  * Copyright 2004-2005 Sun Microsystems, Inc. All rights reserved.
26  * Use is subject to license terms.
27  */

28
29 //----------------------------------------------------------------------------
30
//
31
// Module: TopCoordinator.java
32
//
33
// Description: Top-level transaction Coordinator object implementation.
34
//
35
// Product: com.sun.jts.CosTransactions
36
//
37
// Author: Simon Holdsworth
38
//
39
// Date: March, 1997
40
//
41
// Copyright (c): 1995-1997 IBM Corp.
42
//
43
// The source code for this program is not published or otherwise divested
44
// of its trade secrets, irrespective of what has been deposited with the
45
// U.S. Copyright Office.
46
//
47
// This software contains confidential and proprietary information of
48
// IBM Corp.
49
//----------------------------------------------------------------------------
50

51 package com.sun.jts.CosTransactions;
52
53 import java.util.*;
54
55 import org.omg.CORBA.*;
56 import org.omg.CosTransactions.*;
57
58 import com.sun.jts.otsidl.*;
59 import com.sun.jts.jtsxa.OTSResourceImpl;
60 //import com.sun.jts.otsidl.JCoordinatorHelper;
61
//import com.sun.jts.otsidl.JCoordinatorOperations;
62
//import java.io.PrintStream;
63
//import java.util.Vector;
64

65 //import com.sun.enterprise.transaction.OTSResourceImpl;
66
//import com.sun.enterprise.transaction.SynchronizationImpl;
67

68 import com.sun.jts.trace.*;
69
70 import java.util.logging.Logger JavaDoc;
71 import java.util.logging.Level JavaDoc;
72 import com.sun.logging.LogDomains;
73 import com.sun.jts.utils.LogFormatter;
74
75 /**
76  * The TopCoordinator interface is our implementation of the standard
77  * Coordinator interface that is used for top-level transactions. It allows
78  * Resources to be registered for participation in a top-level transaction.
79  * In addition the TopCoordinator recovery interface can be used if the
80  * connection to a superior Coordinator is lost after a transaction is
81  * prepared. As an instance of this class may be accessed from multiple
82  * threads within a process, serialisation for thread-safety is necessary in
83  * the implementation. The information managed should be reconstructible in
84  * the case of a failure.
85  *
86  * @version 0.02
87  *
88  * @author Simon Holdsworth, IBM Corporation
89  *
90  * @see
91  */

92
93 //----------------------------------------------------------------------------
94
// CHANGE HISTORY
95
//
96
// Version By Change Description
97
// 0.01 SAJH Initial implementation.
98
// 0.02 GDH Gordon Hutchison April 1998
99
// Some improvements to the way the additional tran states in
100
// OTS 1.1 (vs 1.0) are handled and also improvements to logic
101
// used in recovery.
102
// 0.03 GDH Gordon 27th Jan 1999
103
// Changes marked by COPDEF1 to fix two defects in COP work.
104
// 0.04 GDH Gordon 28th Jan 1999
105
// Change marked by COPDEF2, in COP if resource voted rb
106
// our code set state to COB_RB twice which is invalid:
107
// first state change removed as unnecessary.
108
//-----------------------------------------------------------------------------
109

110 public class TopCoordinator extends CoordinatorImpl {
111     String JavaDoc name = null;
112     RegisteredResources participants = null;
113     RegisteredSyncs synchronizations = null;
114     SuperiorInfo superInfo = null;
115     NestingInfo nestingInfo = null;
116     TransactionState tranState = null;
117     CoordinatorLog logRecord = null;
118     CompletionHandler terminator = null;
119     boolean registered = false;
120     boolean registeredSync = false;
121     boolean root = true;
122     boolean rollbackOnly = false;
123     boolean dying = false;
124     boolean temporary = false;
125     int hash = 0;
126
127     /*
128         Logger to log transaction messages
129     */

130       static Logger JavaDoc _logger = LogDomains.getLogger(LogDomains.TRANSACTION_LOGGER);
131     // added (Ram J) for memory Leak fix.
132
Vector recoveryCoordinatorList = null;
133     CoordinatorSynchronizationImpl coordSyncImpl = null;
134
135    // added (sankar) for delegated recovery support
136
boolean delegated = false;
137    String JavaDoc logPath = null;
138
139     /**
140      * Default TopCoordinator constructor.
141      *
142      * @param
143      *
144      * @return
145      *
146      * @see
147      */

148     TopCoordinator() {
149         // No persistent reference is created in this case.
150
}
151
152     /**
153      * Creates and initialises a new root TopCoordinator,
154      * and returns the global identifier for the transaction.
155      * The timeout value, if non-zero, is used
156      * to establish a time-out for the transaction. A CoordinatorLog object is
157      * created at this time if the log is available.
158      *
159      * @param timeOut The time-out value for the transaction.
160      *
161      * @return
162      *
163      * @exception LogicErrorException An internal logic error occurred.
164      *
165      * @see
166      */

167     TopCoordinator(int timeOut) throws LogicErrorException {
168
169         // If this execution of the process is recoverable, then create a
170
// CoordinatorLog object for the top-level transaction. Each of the
171
// implementation classes that use the CoordinatorLog have been written
172
// to be able to work with or without a CoordinatorLog reference.
173

174         if (Configuration.isRecoverable()) {
175         // get a CoordinatorLog object from the cache
176
// instead of instantiating a new one Arun 9/27/99
177
logRecord = CoordinatorLogPool.getCoordinatorLog();
178         } else {
179             logRecord = null;
180         }
181
182         // Allocate a new global identifier for the transaction.
183

184         tranState = new TransactionState(logRecord);
185
186         // Store information about the superior, ancestors and
187
// participants of the new transaction.
188

189         superInfo = new SuperiorInfo(tranState.localTID, tranState.globalTID,
190                                      null, logRecord);
191
192         // Cache the name - create a buffer and print the global XID into it.
193

194         // name = superInfo.globalTID.toString();
195

196         // Cache the hash value of the Coordinator.
197

198         hash = superInfo.globalTID.hashCode();
199
200         // Zero out the RegisteredResources, NestingInfo and RegisteredSyncs
201
// references. These will be created when they are required.
202

203         nestingInfo = null;
204         participants = null;
205         synchronizations = null;
206
207         // Set other instance variables.
208

209         root = true;
210         registered = true;
211         registeredSync = true;
212         rollbackOnly = false;
213         dying = false;
214         temporary = false;
215         terminator = null;
216
217         if (!tranState.setState(TransactionState.STATE_ACTIVE)) {
218
219             // Set the state of the transaction to active before making
220
// it visible to the TransactionManager.
221

222             LogicErrorException exc =
223                 new LogicErrorException(
224                     LogFormatter.getLocalizedMessage(_logger,
225                     "jts.invalid_state_change"));
226             throw exc;
227
228         } else {
229
230             // Inform the RecoveryManager of the existence of this transaction.
231
if (!RecoveryManager.addCoordinator(tranState.globalTID,
232                                                 tranState.localTID,
233                                                 this,
234                                                 timeOut)) {
235                 LogicErrorException exc =
236                     new LogicErrorException(
237                         LogFormatter.getLocalizedMessage(_logger,
238                         "jts.transaction_id_already_in_use"));
239                 throw exc;
240             }
241         }
242     }
243
244     /**
245      * Creates and initialises a subordinate TopCoordinator, given the global
246      * identifier and superior Coordinator reference, and returns the local
247      * identifier for the transaction. The timeout value, if non-zero, is used
248      * to establish a time-out for the subordinate transaction. The temporary
249      * flag indicates whether the TopCoordinator was created as a temporary
250      * ancestor.
251      *
252      * @param timeOut The timeout value for the transaction.
253      * @param globalTID The global identifier for the transaction.
254      * @param superior The superior Coordinator.
255      * @param temporary The temporary indicator.
256      *
257      * @return
258      *
259      * @exception LogicErrorException An internal logic error occurred.
260      *
261      * @see
262      */

263     TopCoordinator(int timeOut, GlobalTID globalTID, Coordinator superior,
264             boolean temporary) throws LogicErrorException {
265
266         // If this execution of the process is recoverable, then create a
267
// CoordinatorLog object for the top-level transaction. Each of the
268
// implementation classes that use the CoordinatorLog have been written
269
// to be able to work with or without a CoordinatorLog reference.
270

271         if (Configuration.isRecoverable()) {
272         // get a CoordinatorLog object from the cache
273
// instead of instantiating a new one Arun 9/27/99
274
logRecord = CoordinatorLogPool.getCoordinatorLog();
275         } else {
276             logRecord = null;
277         }
278
279         // Allocate a new local identifier for the transaction.
280
// If one cannot be allocated, raise an exception as the
281
// transaction cannot be started.
282

283         tranState = new TransactionState(globalTID,logRecord);
284
285         // Store information about the superior, ancestors and participants
286
// of the new subordinate transaction.
287

288         superInfo = new SuperiorInfo(tranState.localTID, tranState.globalTID,
289                                      superior, logRecord);
290
291         // Cache the name - create a buffer and print the global XID into it.
292

293         // name = superInfo.globalTID.toString();
294

295         // Cache the hash value of the Coordinator.
296

297         hash = superInfo.globalTID.hashCode();
298
299         // Zero out the RegisteredResources, NestingInfo and RegisteredSyncs
300
// references. These will be created when they are required.
301

302         nestingInfo = null;
303         participants = null;
304         synchronizations = null;
305
306         // Set other instance variables.
307

308         root = false;
309         registered = false;
310         registeredSync = false;
311         rollbackOnly = false;
312         dying = false;
313         this.temporary = temporary;
314         terminator = null;
315
316         // Set the state of the transaction to active before making it
317
// visible to the RecoveryManager.
318

319         if (!tranState.setState(TransactionState.STATE_ACTIVE)) {
320             LogicErrorException exc =
321                 new LogicErrorException(
322                     LogFormatter.getLocalizedMessage(_logger,
323                     "jts.invalid_state_change"));
324             throw exc;
325         } else {
326             if (!RecoveryManager.addCoordinator(globalTID, tranState.localTID,
327                                                 this, timeOut)) {
328                 LogicErrorException exc =
329                     new LogicErrorException(
330                         LogFormatter.getLocalizedMessage(_logger,
331                         "jts.transaction_id_already_in_use"));
332                 throw exc;
333             }
334         }
335     }
336
337     /**
338      * Cleans up the objects state.
339      *
340      * @param
341      *
342      * @return
343      *
344      * @see
345      */

346     synchronized public void finalize() {
347
348         // Set the flag to indicate that the coordinator is being destroyed.
349

350         dying = true;
351
352         // What we do when destroyed depends on the transaction's state.
353
// We assume that temporary Coordinators have rolled bak at this point.
354

355         int state = TransactionState.STATE_ROLLED_BACK;
356         if (tranState != null && !temporary) {
357             state = tranState.state;
358         }
359
360         switch (state) {
361
362         // If the transaction is active it should be rolled back. This
363
// will result in the TopCoordinator self-destructing at the
364
// end of two-phase commit.
365

366         case TransactionState.STATE_ACTIVE :
367             try {
368                 rollback(true);
369             } catch (Throwable JavaDoc exc) {}
370
371             break;
372
373         // For committed or rolled-back, we really need to destroy the
374
// object. Also for prepared_readonly.
375

376         case TransactionState.STATE_PREPARED_READONLY :
377         case TransactionState.STATE_COMMITTED :
378         case TransactionState.STATE_ROLLED_BACK :
379         case TransactionState.STATE_COMMITTED_ONE_PHASE_OK :
380         case TransactionState.STATE_COMMIT_ONE_PHASE_ROLLED_BACK :
381
382             if (tranState != null) {
383                 tranState.finalize();
384             }
385
386             if (superInfo != null) {
387                 superInfo.finalize();
388             }
389
390             if (nestingInfo != null) {
391                 nestingInfo.finalize();
392             }
393
394             if (participants != null) {
395                 participants.finalize();
396             }
397
398             if (synchronizations != null) {
399                 synchronizations.finalize();
400             }
401
402             tranState = null;
403             superInfo = null;
404             nestingInfo = null;
405             participants = null;
406             synchronizations = null;
407             logRecord = null;
408             terminator = null;
409             name = null;
410             break;
411
412         // For any other state, the transaction is completing, so the
413
// TopCoordinator will eventually self-destruct. We do nothing here.
414

415         default :
416             break;
417         }
418     }
419
420     /**
421      * Directs the TopCoordinator to recover its state after a failure,
422      * based on the given CoordinatorLog object.
423      * If the TopCoordinator has already been defined or recovered,
424      * the operation returns immediately. Otherwise the
425      * TopCoordinator restores the state of its internal objects using their
426      * recovery operations, which in turn recover their state from the
427      * CoordinatorLog object.
428      *
429      * @param log The CoordinatorLog object which contains the Coordinators
430      * state.
431      * @return
432      *
433      * @see
434      */

435     synchronized void reconstruct(CoordinatorLog log) {
436
437         // Set up instance variables.
438

439         rollbackOnly = false;
440         registered = false;
441         registeredSync = false;
442         root = false;
443         dying = false;
444         temporary = false;
445         terminator = null;
446         logRecord = log;
447         name = null;
448
449         // Zero out NestingInfo and Synchronizations references. These won't be
450
// needed for a recovered transaction.
451

452         nestingInfo = null;
453         synchronizations = null;
454
455         // Use the result of the TransactionState reconstruction to
456
// decide whether to continue with recovery of this transaction.
457

458         tranState = new TransactionState();
459         int state = tranState.reconstruct(log);
460         if (state == TransactionState.STATE_NONE ||
461                 state == TransactionState.STATE_COMMITTED ||
462                 // state == TransactionState.STATE_COMMITTED_ONE_PHASE_OK ||
463
// state == TransactionState.STATE_COMMIT_ONE_PHASE_ROLLED_BACK ||
464
state == TransactionState.STATE_ROLLED_BACK) {
465
466             // If the transaction is discarded, then ensure that
467
// the log record is discarded.
468

469             CoordinatorLog.removeLog(log.localTID);
470             destroy();
471
472         } else {
473
474             // Otherwise continue with reconstruction.
475
participants = new RegisteredResources(this);
476             participants.reconstruct(log);
477
478             // Reconstruct the SuperiorInfo object. This will result in a
479
// call to RecoveryManager.addCoordinator (which is done
480
// because reconstruction of the object references in the
481
// SuperiorInfo requires the Coordinator to
482
// already be known to the RecoveryManager).
483

484             superInfo = new SuperiorInfo();
485             superInfo.reconstruct(log, this);
486
487             // Cache the name - create a buffer and print the
488
// global XID into it.
489

490             name = superInfo.globalTID.toString();
491
492             // Cache the hash value of the Coordinator.
493

494             hash = superInfo.globalTID.hashCode();
495         }
496     }
497
498     /**
499      * Directs the TopCoordinator to recover its state after a failure,
500      * based on the given CoordinatorLog object for the given logpath.
501      * If the TopCoordinator has already been defined or recovered,
502      * the operation returns immediately. Otherwise the
503      * TopCoordinator restores the state of its internal objects using their
504      * recovery operations, which in turn recover their state from the
505      * CoordinatorLog object.
506      *
507      * @param log The CoordinatorLog object which contains the Coordinators
508      * state.
509      *
510      * @param logPath Location of the log file
511      * @return
512      *
513      * @see
514      */

515     synchronized void delegated_reconstruct(CoordinatorLog log, String JavaDoc logPath ) {
516
517         // Set up instance variables.
518

519         rollbackOnly = false;
520         registered = false;
521         registeredSync = false;
522         root = false;
523         dying = false;
524         temporary = false;
525         terminator = null;
526         logRecord = log;
527         name = null;
528
529         // Zero out NestingInfo and Synchronizations references. These won't be
530
// needed for a recovered transaction.
531

532         nestingInfo = null;
533         synchronizations = null;
534
535         delegated = true;
536         this.logPath = logPath;
537
538         // Use the result of the TransactionState reconstruction to
539
// decide whether to continue with recovery of this transaction.
540

541         tranState = new TransactionState();
542         // int state = tranState.delegated_reconstruct(log);
543
int state = tranState.reconstruct(log);
544         if (state == TransactionState.STATE_NONE ||
545                 state == TransactionState.STATE_COMMITTED ||
546                 // state == TransactionState.STATE_COMMITTED_ONE_PHASE_OK ||
547
// state == TransactionState.STATE_COMMIT_ONE_PHASE_ROLLED_BACK ||
548
state == TransactionState.STATE_ROLLED_BACK) {
549
550             // If the transaction is discarded, then ensure that
551
// the log record is discarded.
552

553             CoordinatorLog.removeLog(log.localTID, logPath);
554             destroy();
555
556         } else {
557
558             // Otherwise continue with reconstruction.
559
participants = new RegisteredResources(this);
560             participants.reconstruct(log);
561
562             // Reconstruct the SuperiorInfo object. This will result in a
563
// call to RecoveryManager.addCoordinator (which is done
564
// because reconstruction of the object references in the
565
// SuperiorInfo requires the Coordinator to
566
// already be known to the RecoveryManager).
567

568             superInfo = new SuperiorInfo();
569             superInfo.delegated_reconstruct(log, this, logPath);
570
571             // Cache the name - create a buffer and print the
572
// global XID into it.
573

574             name = superInfo.globalTID.toString();
575
576             // Cache the hash value of the Coordinator.
577

578             hash = superInfo.globalTID.hashCode();
579         }
580     }
581
582     /**
583      * Directs the TopCoordinator to perform recovery actions based on its
584      * reconstructed state after a failure, or after an in-doubt timeout has
585      * occurred.
586      * This method is called by the RecoveryManager during recovery, in
587      * which case there is no terminator object, or during normal operation
588      * if the transaction commit retry interval has been
589      * exceeded for the transaction.
590      * If this method is called more times than the retry limit specified in
591      * COMMITRETRY, then the global outcome of the transaction is taken from
592      * the value of HEURISTICDIRECTION.
593      *
594      * @param isRoot A 1-element array which will be filled in with the
595      * root flag.
596      *
597      * @return The state of the recovered transaction.
598      *
599      * @see
600      */

601     synchronized Status recover(boolean[/*1*/] isRoot) {
602
603         Status result;
604
605         // Determine the global outcome using the transactions state for a root
606
// Coordinator, or the RecoveryCoordinator for a subordinate.
607

608         if (superInfo.recovery != null) {
609
610             // For a subordinate, first check whether the global
611
// outcome is known locally.
612

613
614             // GDH COP For the commit_one_phase operations we need to do the
615
// following ultimately. However for all c-o-p operations
616
// We know that the CLIENT/Superior chose to COMMIT.
617
// Also for all c-o-p operations that are 'past tense'
618
// the direction (commit or rolled back) is not really
619
// important as we are using c-o-p for single resources
620
// not last agent in CORBA CosTransactions.
621
//
622
// For clarity, all c-o-p states return a commited direction,
623
// This is counter intuative but logicaly correct (unimportant)
624
// even for COMMIT_ONE_PHASE_ROLLED_BACK.
625
// A well behaved resource will not contact us in any of the
626
// 'past tense' c-o-p states anyway as they have already returned
627
// from a c-o-p op and can expect no further flows
628
// (apart from forget perhaps).
629
// When it comes to real resource flows we must be careful to
630
// cause the following actions based on state:
631
//
632
// STATE_COMMITTING_ONE_PHASE
633
// (We only ever enter this state if we have one resource
634
// even if the c-o-p method was called on our CoordinatorResource)
635
// The transaction was partway through a commit_one_phase
636
// operation when the server failed.
637
// So the commit_one_phase needs to be called again.
638
// STATE COMMITTED_ONE_PHASE
639
// STATE COMMITTED_ONE_PHASE_ROLLEDBACK
640
// The transaction had just completed a commit_one_phase operation.
641
// Therefore all of the work for the downstream part of the
642
// transaction is over. The only work to do is to possibly report
643
// outcome to superior.
644
// STATE COMMIT_ONE_PHASE_HEURISTIC_MIXED
645
// STATE COMMIT_ONE_PHASE_HEURISTIC_HAZARD
646
// Part of the tree has made a heuristic decision. The forget
647
// message must flow to all subordinate coordinators to allow them
648
// to end.
649

650             switch (tranState.state) {
651
652             // GDH Due to the possibility of recovery being attempted
653
// on more than one thread we must cover the case where
654
// the transaction has actually COMMITTED already.
655

656             case TransactionState.STATE_COMMITTED :
657                 // GDH (added)
658
case TransactionState.STATE_COMMITTED_ONE_PHASE_OK :
659                 // GDH (added)
660
case TransactionState.STATE_COMMITTING_ONE_PHASE :
661                 // GDH (added)
662
case TransactionState.STATE_COMMIT_ONE_PHASE_ROLLED_BACK :
663                 // GDH (added)
664
case TransactionState.STATE_COMMITTING :
665                 result = Status.StatusCommitted;
666                 break;
667
668             // GDH Due to the possibility of recovery being attempted
669
// on more than one thread we must cover the case where
670
// the transaction has actually ROLLED_BACK already.
671

672             case TransactionState.STATE_ROLLED_BACK : // GDH (added)
673
case TransactionState.STATE_ROLLING_BACK :
674                 // GDH Note we do not need C-O-P_ROLLED_BACK Here as the actual
675
// resource rolling back will be done already so it's academic.
676
result = Status.StatusRolledBack;
677                 break;
678
679             // For a subordinate, the replay_completion method is invoked on
680
// the superior's RecoveryCoordinator. We may need to create a
681
// CoordinatorResource object to give to the superior in the case
682
// where we are in recovery. If the number of times
683
// the replay_completion has bee retried is greater than the value
684
// specified by COMMITRETRY, then HEURISTICDIRECTION is used
685
// to determine the transaction outcome.
686

687             default :
688
689                 boolean attemptRetry = true;
690                 // String commitRetryVar;
691
// int commitRetries = 0;
692

693                 // If COMMITRETRY is not set, then retry is infinite.
694
// Otherwise check that
695
// the current number of retries is less than the limit.
696

697                /**
698                 commitRetryVar = Configuration.
699                     getPropertyValue(Configuration.COMMIT_RETRY);
700                 if (commitRetryVar != null) {
701                     try {
702                         commitRetries = Integer.parseInt(commitRetryVar);
703                     } catch( NumberFormatException exc ) {}
704
705                     if (superInfo.resyncRetries() >= commitRetries) {
706                         attemptRetry = false;
707                     }
708                 }
709                 **/

710                 int commitRetries = Configuration.getRetries();
711                 if (commitRetries >= 0 && (superInfo.resyncRetries() >= commitRetries))
712                     attemptRetry = false;
713
714
715                 if (!attemptRetry) {
716
717                     // If we are not to attempt a retry of the
718
// replay_completion method, then the HEURISTICDIRECTION
719
// environment variable is used to get the global outcome.
720

721                     String JavaDoc heuristicVar;
722                     boolean commitTransaction = false;
723                     result = Status.StatusRolledBack;
724
725                     heuristicVar =
726                         Configuration.getPropertyValue(
727                             Configuration.HEURISTIC_DIRECTION);
728
729                     if (heuristicVar != null) {
730                         commitTransaction = (heuristicVar.charAt(0) == '1');
731                     }
732
733                     if (commitTransaction) {
734                         result = Status.StatusCommitted;
735                     }
736
737                 } else {
738
739                     // Otherwise, use the RecoveryCoordinator to get
740
// the global outcome. Get the global outcome
741
// from the superior's RecoveryCoordinator.
742

743                     try {
744                         if(_logger.isLoggable(Level.FINE))
745                         {
746                             _logger.logp(Level.FINE,"TopCoordinator","recover",
747                                     "Before invoking replay_completion on Superior Coordinator");
748                         }
749                         if (!delegated) {
750                             result = superInfo.recovery.
751                                         replay_completion(superInfo.resource);
752                         } else {
753                             result = ((RecoveryCoordinatorImpl)(superInfo.recovery)).
754                                         replay_completion(superInfo.resource, logPath);
755                         }
756
757                         // GDH
758
// If the global result is returned as COMMITTING we
759
// know the outcome of the global transaction
760
// is COMMITTED.
761

762                         if (result == Status.StatusCommitting) {
763                             result = Status.StatusCommitted;
764                         }
765                     } catch (Throwable JavaDoc exc) {
766                         // If the exception is neither TRANSIENT or
767
// COMM_FAILURE, it isunexpected, so display a message
768
// and assume that the transaction has rolled back.
769

770                         if (!(exc instanceof COMM_FAILURE) &&
771                                 !(exc instanceof TRANSIENT)) {
772                             result = Status.StatusRolledBack;
773                         } else {
774                             // For TRANSIENT or COMM_FAILURE, the outcome
775
// is unknown.
776
result = Status.StatusUnknown;
777                         }
778                     }
779                 }
780
781                 break;
782             }
783
784             // Clear the root Coordinator flag to indicate that
785
// this is not the root.
786

787             root = false;
788
789         } else {
790
791             // For a top-level Coordinator, we will generally only
792
// recover in the case where we have successfully prepared.
793
// If the state is not prepared_success,
794
// then assume it is rollback.
795

796             if (tranState.state == TransactionState.STATE_PREPARED_SUCCESS) {
797                 result = Status.StatusCommitted;
798             } else {
799                 result = Status.StatusRolledBack;
800             }
801
802             // Set the root Coordinator flag to indicate that this is the root.
803

804             root = true;
805         }
806
807         isRoot[0] = root;
808
809         return result;
810     }
811
812     /**
813      * Returns the local status of the target transaction.
814      *
815      * @param
816      *
817      * @return The status of the transaction.
818      *
819      * @see
820      */

821     public Status get_status() {
822
823         Status result = Status.StatusUnknown;
824
825         if (tranState != null) {
826
827             switch (tranState.state) {
828
829             // If active, return active or marked rollback-only
830
// if the flag is set.
831

832             case TransactionState.STATE_ACTIVE :
833                 if( rollbackOnly )
834                     result = Status.StatusMarkedRollback;
835                 else
836                     result = Status.StatusActive;
837                 break;
838
839             // If prepared, (successfully or otherwise), return prepared.
840
// If committing return prepared (may want to block in this case).
841

842             case TransactionState.STATE_PREPARED_SUCCESS :
843             case TransactionState.STATE_PREPARED_FAIL :
844             case TransactionState.STATE_PREPARED_READONLY :
845                 result = Status.StatusPrepared;
846                 break;
847
848             // If we have no internal state, return that fact.
849
// All of these states map directly to the OMG values.
850

851             case TransactionState.STATE_NONE :
852                 result = Status.StatusNoTransaction;
853                 break;
854             case TransactionState.STATE_PREPARING :
855             case TransactionState.STATE_COMMITTING_ONE_PHASE :
856                 result = Status.StatusPreparing;
857                 break;
858             case TransactionState.STATE_COMMITTING :
859                 result = Status.StatusCommitting;
860                 break;
861             case TransactionState.STATE_COMMITTED :
862             case TransactionState.STATE_COMMITTED_ONE_PHASE_OK :
863             case TransactionState.STATE_COMMIT_ONE_PHASE_HEURISTIC_HAZARD :
864             case TransactionState.STATE_COMMIT_ONE_PHASE_HEURISTIC_MIXED :
865                 result = Status.StatusCommitted;
866                 break;
867             case TransactionState.STATE_ROLLING_BACK :
868             case TransactionState.STATE_COMMIT_ONE_PHASE_ROLLED_BACK :
869                 result = Status.StatusRollingBack;
870                 break;
871             case TransactionState.STATE_ROLLED_BACK :
872                 result = Status.StatusRolledBack;
873                 break;
874
875             // Any other state, return unknown.
876
// GDH Including c-o-p heuristic states
877

878             default :
879                 result = Status.StatusUnknown;
880                 break;
881             }
882         } else {
883             INVALID_TRANSACTION exc = new INVALID_TRANSACTION(
884                                             MinorCode.Completed,
885                                             CompletionStatus.COMPLETED_NO);
886           throw exc;
887         }
888
889         return result;
890     }
891
892     /**
893      * Gets the local state of the transaction.
894      * For a top-level transaction this operation is equivalent
895      * to the get_status method.
896      * This operation references no instance variables and so can be
897      * implemented locally in the proxy class.
898      *
899      * @param
900      *
901      * @return The status of the transaction.
902      *
903      * @see
904      */

905     public Status get_parent_status() {
906         Status result = get_status();
907         return result;
908     }
909
910     /**
911      * Gets the local state of the transaction.
912      * For a top-level transaction this operation is equivalent
913      * to the get_status method.
914      * This operation references no instance variables and so can be
915      * implemented locally in a proxy class.
916      *
917      * @param
918      *
919      * @return The status of the transaction.
920      *
921      * @see
922      */

923     public Status get_top_level_status() {
924
925         Status result = get_status();
926         return result;
927     }
928
929     /**
930      * Compares the given Coordinator object with the target,
931      * and returns TRUE if they represent the same transaction.
932      * This operation needs to be implemented in an efficient manner,
933      * without any cross-process calls. This could be achieved by
934      * including the global identifier in the Coordinator references
935      * and comparing them.
936      * This operation references no instance variables and so can be
937      * implemented locally in a proxy class.
938      *
939      * @param other The other Coordinator to be compared.
940      *
941      * @return Indicates equality of the transactions the objects
942      * represent.
943      *
944      * @exception SystemException The other Coordinator could not be reached.
945      *
946      * @see
947      */

948 /**
949     removed synchronization at method level since only tranState requires
950     locking
951 */

952     public boolean is_same_transaction(Coordinator other)
953             throws SystemException {
954
955         boolean result = false;
956
957         // Get the names of the two transactions and compare them.
958

959         if (tranState != null) {
960             if (name == null)
961                 name = superInfo.globalTID.toString();
962             result = name.equals(other.get_transaction_name());
963         } else {
964             INVALID_TRANSACTION exc = new INVALID_TRANSACTION(
965                                             MinorCode.Completed,
966                                             CompletionStatus.COMPLETED_NO);
967             throw exc;
968         }
969
970         return result;
971     }
972
973     /**
974      * Determines whether the target TopCoordinator is related to
975      * the given Coordinator (i.e. is a member of the same transaction family).
976      * For a top-level transaction returns TRUE if and only if
977      * the transaction associated with the parameter object is a
978      * descendant of the transaction associated with the target object.
979      * This operation references no instance variables and so can be
980      * implemented locally in a proxy class.
981      *
982      * @param other The other Coordinator.
983      *
984      * @return Indicates the relationship.
985      *
986      * @exception SystemException The other Coordinator could not be reached.
987      *
988      * @see
989      */

990     public boolean is_related_transaction(Coordinator other)
991             throws SystemException {
992
993         boolean result = false;
994
995         if (tranState != null) {
996             result = other.is_descendant_transaction(this.object());
997         } else {
998             INVALID_TRANSACTION exc = new INVALID_TRANSACTION(
999                                             MinorCode.Completed,
1000                                            CompletionStatus.COMPLETED_NO);
1001            throw exc;
1002        }
1003
1004        return result;
1005    }
1006
1007    /**
1008     * Determines whether this TopCoordinator is the root TopCoordinator.
1009     * the given Coordinator (i.e. is a member of the same transaction family).
1010     * For a root transaction, this method returns TRUE. Otherwise it
1011     * returns FALSE.
1012     *
1013     * @return Indicates if this is the root TopCoordinator.
1014     *
1015     * @see
1016     */

1017    public boolean is_root_transaction() {
1018
1019        boolean result = root;
1020
1021        return result;
1022    }
1023
1024    /**
1025     * Determines whether the target TopCoordinator is an ancestor
1026     * of the given Coordinator.
1027     * For a top-level transaction returns TRUE if and only if
1028     * the transaction associated with the target object is an ancestor
1029     * of the transaction associated with the parameter object.
1030     * This operation references no instance variables and so can be
1031     * implemented locally in a proxy class.
1032     *
1033     * @param other The other Coordinator.
1034     *
1035     * @return Indicates the relationship.
1036     *
1037     * @exception SystemException The other Coordinator could not be reached.
1038     *
1039     * @see
1040     */

1041    public boolean is_ancestor_transaction(Coordinator other)
1042            throws SystemException {
1043
1044        boolean result = false;
1045        if (tranState != null) {
1046          result = other.is_descendant_transaction(this.object());
1047        } else {
1048            INVALID_TRANSACTION exc = new INVALID_TRANSACTION(
1049                                            MinorCode.Completed,
1050                                            CompletionStatus.COMPLETED_NO);
1051            throw exc;
1052        }
1053
1054        return result;
1055    }
1056
1057    /**
1058     * Determines whether the target TopCoordinator is a descendant
1059     * of the given Coordinator.
1060     * For a top-level transaction returns TRUE if and only if
1061     * the transaction associated with the target object is the same as
1062     * the transaction associated with the parameter object.
1063     * This operation references no instance variables and so can be
1064     * implemented locally in a proxy class.
1065     *
1066     * @param other The other Coordinator.
1067     *
1068     * @return Indicates the relationship.
1069     *
1070     * @exception SystemException The other Coordinator could not be reached.
1071     *
1072     * @see
1073     */

1074    public boolean is_descendant_transaction(Coordinator other)
1075            throws SystemException {
1076
1077        boolean result = false;
1078        if (tranState != null) {
1079            result = is_same_transaction(other);
1080        } else {
1081            INVALID_TRANSACTION exc = new INVALID_TRANSACTION(
1082                                            MinorCode.Completed,
1083                                            CompletionStatus.COMPLETED_NO);
1084            throw exc;
1085        }
1086
1087        return result;
1088    }
1089
1090    /**
1091     * Determines whether the target TopCoordinator represents a top-level
1092     * (non-nested) transaction.
1093     * <p>
1094     * For a top-level transaction returns TRUE.
1095     * <p>
1096     * This operation references no instance variables and so can be
1097     * implemented locally in a proxy class.
1098     *
1099     * @param
1100     *
1101     * @return Indicates this is a top-level transaction.
1102     *
1103     * @see
1104     */

1105    public boolean is_top_level_transaction() {
1106
1107        boolean result = true;
1108        return result;
1109    }
1110
1111    /**
1112     * Returns a hash value based on the transaction associated with the target
1113     * object.
1114     * This operation references only the global TID, and so can be
1115     * implemented locally in a proxy class.
1116     *
1117     * @param
1118     *
1119     * @return The hash value for the transaction.
1120     *
1121     * @see
1122     */

1123/**
1124    removed synchronization at method level since only tranState requires
1125    locking
1126*/

1127    public int hash_transaction() {
1128
1129        int result = hash;
1130
1131        if (tranState == null) {
1132            INVALID_TRANSACTION exc = new INVALID_TRANSACTION(
1133                                            MinorCode.Completed,
1134                                            CompletionStatus.COMPLETED_NO);
1135            throw exc;
1136        }
1137
1138        return result;
1139    }
1140
1141    /**
1142     * Returns a hash value based on the top-level ancestor of the transaction
1143     * associated with the target object.
1144     * This operation references only the global TID, and so can be
1145     * implemented locally in a proxy class.
1146     *
1147     * @param
1148     *
1149     * @return The hash value for the transaction.
1150     *
1151     * @see
1152     */

1153    synchronized public int hash_top_level_tran() {
1154
1155        int result = hash;
1156
1157        if (tranState == null) {
1158            INVALID_TRANSACTION exc = new INVALID_TRANSACTION(
1159                                            MinorCode.Completed,
1160                                            CompletionStatus.COMPLETED_NO);
1161
1162            throw exc;
1163        }
1164
1165        return result;
1166    }
1167
1168    /**
1169     * Enables a Resource to be registered as a participant in the completion
1170     * of the top-level transaction represented by the TopCoordinator.
1171     * If the TopCoordinator is a subordinate, and has not registered with its
1172     * superior, it creates a CoordinatorResource and registers it. The
1173     * RecoveryCoordinator that is returned is stored in the SuperiorInfo.
1174     *
1175     * @param res The Resource to be registered.
1176     *
1177     * @return The RecoveryCoordinator object from the
1178     * registration with the top-level ancestor.
1179     *
1180     * @exception Inactive The Coordinator is completing the transaction and
1181     * cannot accept this registration.
1182     * @exception TRANSACTION_ROLLEDBACK The transaction which the Coordinator
1183     * represents has already been rolled back, or has been marked
1184     * rollback-only.
1185     *
1186     * @see
1187     */

1188    synchronized public RecoveryCoordinator register_resource(Resource res)
1189            throws Inactive, TRANSACTION_ROLLEDBACK {
1190
1191        RecoveryCoordinator result = null;
1192
1193        // First check the state of the transaction. If it is not active,
1194
// do not allow the registration.
1195

1196        if (tranState == null || tranState.state !=
1197                TransactionState.STATE_ACTIVE) {
1198          Inactive exc = new Inactive();
1199          throw exc;
1200        }
1201
1202        // Check whether the transaction has been marked rollback-only.
1203

1204        if (rollbackOnly) {
1205            TRANSACTION_ROLLEDBACK exc =
1206                new TRANSACTION_ROLLEDBACK(0, CompletionStatus.COMPLETED_NO);
1207            throw exc;
1208        }
1209
1210        // If not previously registered, a CoordinatorResource object must be
1211
// registered with our superior. Note that root TopCoordinators are
1212
// created with the registration flag set, so we do not need to
1213
// check whether we are the root TopCoordinator here.
1214

1215        if (!registered) {
1216
1217            // Initialise the CoordinatorResource with the local id,
1218
// our reference, and a flag to indicate that it does not
1219
// represent a subtransaction.
1220

1221            CoordinatorResourceImpl cImpl =
1222                new CoordinatorResourceImpl(superInfo.globalTID, this, false);
1223
1224            try {
1225
1226                // Register the CoordinatorResource with the superior
1227
// Coordinator, and store the resulting RecoveryCoordinator
1228
// reference.
1229

1230                CoordinatorResource cRes = cImpl.object();
1231                RecoveryCoordinator superRecovery =
1232                    superInfo.superior.register_resource(cRes);
1233                superInfo.setRecovery(superRecovery);
1234                superInfo.setResource(cRes);
1235                registered = true;
1236                if(_logger.isLoggable(Level.FINEST))
1237                {
1238                    _logger.logp(Level.FINEST,"TopCoordinator","register_resource()",
1239                            "CoordinatorResource " + cImpl +
1240                            " has been registered with (Root)TopCoordinator"+
1241                            superInfo.globalTID.toString());
1242                }
1243
1244            } catch (Exception JavaDoc exc) {
1245
1246                // If an exception was raised, do not store the
1247
// RecoveryCoordinator or set the registration flag.
1248
// Throw an internal exception.
1249

1250                cImpl.destroy();
1251
1252                if (exc instanceof OBJECT_NOT_EXIST) {
1253
1254                    // If the exception is a system exception, then allow it
1255
// to percolate to the caller.
1256
TRANSACTION_ROLLEDBACK ex2 =
1257                        new TRANSACTION_ROLLEDBACK(
1258                            0, CompletionStatus.COMPLETED_NO);
1259                    ex2.initCause(exc);
1260                    throw ex2;
1261                }
1262
1263                if (exc instanceof Inactive) {
1264                    throw (Inactive)exc;
1265                }
1266
1267                if (exc instanceof SystemException) {
1268                    throw (SystemException)exc;
1269                }
1270
1271                // Otherwise throw an internal exception.
1272

1273                INTERNAL ex2 = new INTERNAL(MinorCode.NotRegistered,
1274                                            CompletionStatus.COMPLETED_NO);
1275                ex2.initCause(exc);
1276                throw ex2;
1277            }
1278        }
1279
1280        // If the set has not already been created, create it now.
1281

1282        if (participants == null) {
1283            participants = new RegisteredResources(logRecord, this);
1284        }
1285
1286        // Add a duplicate of the reference to the set. This is done
1287
// because if the registration is for a remote object, the proxy
1288
// will be freed when the registration request returns.
1289

1290        // COMMENT(Ram J) if the res object is a local servant, there is
1291
// no proxy involved. Also, the instanceof operator could be replaced
1292
// by a is_local() method if this class implements the CORBA local
1293
// object contract.
1294
int numRes = 0;
1295        if (res instanceof OTSResourceImpl) {
1296            numRes = participants.addRes(res);
1297            if(_logger.isLoggable(Level.FINEST))
1298            {
1299                _logger.logp(Level.FINEST,"TopCoordinator","register_resource()",
1300                        "OTSResource " + res +" has been registered"+"GTID is:"+
1301                        superInfo.globalTID.toString());
1302            }
1303
1304        } else {
1305            numRes = participants.addRes((Resource)res._duplicate());
1306        }
1307
1308        temporary = false;
1309
1310        // Create, initialise and return a RecoveryCoordinator
1311
// object to the caller.
1312

1313        // COMMENT(Ram J) a RecoveryCoordinator object need not be
1314
// created for local resources.
1315
if (!(res instanceof OTSResourceImpl)) {
1316            RecoveryCoordinatorImpl rcImpl = null;
1317            try {
1318                rcImpl = new RecoveryCoordinatorImpl(
1319                                            superInfo.globalTID, numRes);
1320                result = rcImpl.object();
1321            } catch (Exception JavaDoc exc) {
1322
1323                // If the RecoveryCoordinator could not be created,
1324
// report the exception.
1325

1326                INTERNAL ex2 = new INTERNAL(MinorCode.RecCoordCreateFailed,
1327                                            CompletionStatus.COMPLETED_NO);
1328                throw ex2;
1329            }
1330
1331            // ADD(Ram J) memory leak fix. All Recovery Coordinators need
1332
// to be cleanedup when the transaction completes.
1333
if (recoveryCoordinatorList == null) {
1334                recoveryCoordinatorList = new Vector();
1335            }
1336            recoveryCoordinatorList.add(rcImpl);
1337        }
1338
1339        return result;
1340    }
1341
1342    /**
1343     * Enables a SubtransactionAwareResource to be registered as a
1344     * participant in the completion of a subtransaction.
1345     * For a top-level transaction this raises the NotSubtransaction exception.
1346     *
1347     * @param sares The SubtransactionAwareResource to be registered.
1348     *
1349     * @return
1350     *
1351     * @exception NotSubtransaction The Coordinator represents a top-level
1352     * transaction and cannot accept the registration.
1353     *
1354     * @see
1355     */

1356    synchronized public void register_subtran_aware(
1357            SubtransactionAwareResource sares) throws NotSubtransaction {
1358
1359        NotSubtransaction exc = new NotSubtransaction();
1360        throw exc;
1361    }
1362
1363    /**
1364     * Ensures that the transaction represented by the target TopCoordinator
1365     * cannot be committed.
1366     *
1367     * @param
1368     *
1369     * @return
1370     *
1371     * @exception Inactive The Coordinator is already completing the
1372     * transaction.
1373     * @see
1374     */

1375     public void rollback_only() throws Inactive {
1376
1377        if (tranState == null ||
1378                tranState.state != TransactionState.STATE_ACTIVE) {
1379            Inactive exc = new Inactive();
1380            throw exc;
1381        } else {
1382            // Set the rollback-only flag.
1383
rollbackOnly = true;
1384        }
1385    }
1386
1387    /**
1388     * Returns a printable string that represents the TopCoordinator.
1389     * This operation references only the global TID, and so can be
1390     * implemented locally in a proxy class.
1391     *
1392     * @param
1393     *
1394     * @return The transaction name.
1395     *
1396     * @see
1397     */

1398/**
1399    removed synchronization at method level since only tranState requires
1400    locking
1401*/

1402    public String JavaDoc get_transaction_name() {
1403
1404        String JavaDoc result = null;
1405        if (tranState != null) {
1406            if (name == null)
1407                name = superInfo.globalTID.toString();
1408            result = new String JavaDoc(name);
1409        } else {
1410            INVALID_TRANSACTION exc = new INVALID_TRANSACTION(
1411                                            MinorCode.Completed,
1412                                            CompletionStatus.COMPLETED_NO);
1413            throw exc;
1414        }
1415
1416        return result;
1417    }
1418
1419    /**
1420     * Creates a subtransaction and returns a Control object that represents
1421     * the child transaction.
1422     *
1423     * @param
1424     *
1425     * @return The Control object for the new child transaction.
1426     *
1427     * @exception Inactive The Coordinator is completing the subtransaction
1428     * and cannot create a new child.
1429     *
1430     * @see
1431     */

1432    synchronized public Control create_subtransaction() throws Inactive {
1433
1434        Control result = null;
1435
1436        // First check the state of the transaction. If it is not active,
1437
// do not allow the subtransaction to be created.
1438

1439        if (tranState == null ||
1440                tranState.state != TransactionState.STATE_ACTIVE) {
1441            Inactive exc = new Inactive();
1442            throw exc;
1443        }
1444
1445        // Set up the sequence of ancestors to hold the single reference
1446
// and global identifier of the top-level
1447
// TopCoordinator as there are no ancestors.
1448
// We do not need to make a copy of the global TID as this is done
1449
// by the factory when it creates the child.
1450

1451        CoordinatorImpl[] ancestors = new CoordinatorImpl[1];
1452        ancestors[0] = this;
1453
1454        // Create a new SubCoordinator, and initialise it with the given
1455
// identifiers and ancestry. If the operation fails,
1456
// return a NULL Control object, and
1457
// the SubtransactionsUnavailable exception. Note that the
1458
// ancestor sequence is not copied by the creation operation.
1459

1460        SubCoordinator child = null;
1461        TerminatorImpl terminator = null;
1462        try {
1463            child = new SubCoordinator(superInfo.globalTID,
1464                                       superInfo.localTID,
1465                                       ancestors);
1466
1467            // Create a Terminator object, and initialise it with the
1468
// SubCoordinator reference and a flag to indicate that it
1469
// represents a subtransaction.
1470

1471            terminator = new TerminatorImpl(child,true);
1472
1473            // Create a Control object, and initialise it with the Terminator,
1474
// SubCoordinator and global OMGtid.
1475

1476            result = new ControlImpl(terminator, child,
1477                                     new GlobalTID(child.getGlobalTID()),
1478                                     new Long JavaDoc(child.getLocalTID())
1479                                    ).object();
1480        } catch (Throwable JavaDoc exc) {
1481            Inactive ex2 = new Inactive();
1482            throw ex2;
1483        }
1484
1485        // If the operation succeeded, add the new child to the set
1486
// of children. Ensure that the NestingInfo object is set up.
1487

1488        if (nestingInfo == null) {
1489            nestingInfo = new NestingInfo();
1490        }
1491
1492        nestingInfo.addChild(child);
1493
1494        return result;
1495    }
1496
1497    /**
1498     * Returns a global identifier that represents the TopCoordinator's
1499     * transaction. <p>
1500     * This operation references only the global identifier, and so can be
1501     * implemented locally in a proxy class.
1502     * <p>
1503     * This method is currently not synchronized because that causes a deadlock
1504     * in resync. I don't think this is a problem as the global identifier is
1505     * allocated in the constructor and then never changes.
1506     *
1507     * @param
1508     *
1509     * @return The global transaction identifier.
1510     *
1511     * @see
1512     */

1513    public otid_t getGlobalTID() {
1514
1515        otid_t result = superInfo.globalTID.realTID;
1516        return result;
1517    }
1518
1519    public GlobalTID getGlobalTid() {
1520        return superInfo.globalTID;
1521    }
1522
1523    public int getParticipantCount() {
1524        if (participants == null) {
1525            return 0;
1526        }
1527        return participants.numRegistered();
1528    }
1529    
1530    /**
1531     * Returns the internal identifier for the transaction.
1532     * This method is currently not synchronized because that causes a deadlock
1533     * in resync.
1534     *
1535     * @param
1536     *
1537     * @return The local identifier.
1538     *
1539     * @see
1540     */

1541    public long getLocalTID() {
1542
1543        long result = superInfo.localTID.longValue();
1544        return result;
1545    }
1546
1547    /**
1548     * Indicates that a method reply is being sent and requests
1549     * the TopCoordinator's action.
1550     * If the Coordinator has active children, which are not
1551     * registered with their superior (includes root Coordinators)
1552     * then this method returns activeChildren.
1553     * If it has already been registered, the method returns doNothing.
1554     * Otherwise the TopCoordinator returns forgetMe.
1555     *
1556     * @param action A 1-element array to hold the reply action.
1557     *
1558     * @return The parent coordinator if any.
1559     *
1560     * @exception SystemException An error occurred. The minor code indicates
1561     * the reason for the exception.
1562     *
1563     * @see
1564     */

1565    synchronized CoordinatorImpl replyAction(int[/*1*/] action)
1566            throws SystemException {
1567
1568        CoordinatorImpl result = null;
1569        action[0] = CoordinatorImpl.doNothing;
1570
1571        // If this Coordinator is not a root, and there are active children,
1572
// report that fact to the caller. If the NestingInfo instance variable
1573
// has not been set up, there are no children.
1574

1575        if (!root && nestingInfo != null && nestingInfo.replyCheck()) {
1576
1577            action[0] = CoordinatorImpl.activeChildren;
1578
1579            // If there are no active children, then check whether this
1580
// transaction needs to be destroyed, or registered on reply.
1581

1582        } else {
1583
1584            // If there are participants, and we have not registered,
1585
// raise an exception.
1586

1587            if (!registered) {
1588                if (participants != null && participants.involved()) {
1589
1590                    INTERNAL ex2 = new INTERNAL(MinorCode.NotRegistered,
1591                                                CompletionStatus.COMPLETED_NO);
1592                    throw ex2;
1593                } else if (!registeredSync) {
1594                    action[0] = forgetMe;
1595                }
1596            }
1597
1598            // If there are synchronization objects, and we have not
1599
// registered, raise an exception.
1600

1601            if (!registeredSync) {
1602                if (synchronizations != null && synchronizations.involved()) {
1603
1604                    INTERNAL ex2 = new INTERNAL(MinorCode.NotRegistered,
1605                                                CompletionStatus.COMPLETED_NO);
1606                    throw ex2;
1607                } else if (action[0] == doNothing && !registered) {
1608                    // If we are not registered, and have no participants,
1609
// we have no reason to exist, so tell the caller to
1610
// forget about us. The TransactionManager will take
1611
// care of cleaning everything else up when
1612
// it receives the forgetMe response.
1613
action[0] = forgetMe;
1614                }
1615            }
1616        }
1617
1618        // Default action is do nothing when we are registered.
1619

1620        result = null;
1621
1622        return result;
1623    }
1624
1625    /**
1626     * Marks the TopCoordinator as permanent.
1627     *
1628     * @param
1629     *
1630     * @return The local transaction identifier.
1631     *
1632     * @see
1633     */

1634    synchronized Long JavaDoc setPermanent() {
1635
1636        Long JavaDoc result = superInfo.localTID;
1637        temporary = false;
1638        return result;
1639    }
1640
1641    /**
1642     * Checks whether the TopCoordinator is marked rollback-only.
1643     *
1644     * @param
1645     *
1646     * @return Indicates whether the transaction is rollback-only.
1647     *
1648     * @see
1649     */

1650    synchronized public boolean isRollbackOnly() {
1651
1652        boolean result = rollbackOnly;
1653        return result;
1654    }
1655
1656    /**
1657     * Checks whether the TopCoordinator is active.
1658     *
1659     * @param
1660     *
1661     * @return Indicates the transaction is active.
1662     *
1663     * @see
1664     */

1665    synchronized boolean isActive() {
1666
1667        boolean result = (tranState.state == TransactionState.STATE_ACTIVE);
1668        return result;
1669    }
1670
1671    /**
1672     * Checks whether the TopCoordinator has registered with its superior.
1673     *
1674     * @param
1675     *
1676     * @return Indicates the registration status.
1677     *
1678     * @see
1679     */

1680    synchronized boolean hasRegistered() {
1681
1682        boolean result = registered || registeredSync;
1683        return result;
1684    }
1685
1686    /**
1687     * Returns the sequence of ancestors of the transaction.
1688     *
1689     * @param
1690     *
1691     * @return The sequence of ancestors.
1692     *
1693     * @see
1694     */

1695    synchronized public TransIdentity[] getAncestors() {
1696        return null;
1697    }
1698
1699    /**
1700     * Adds the given Coordinator reference to the set of children of the
1701     * target TopCoordinator.
1702     *
1703     * @param child The child Coordinator.
1704     *
1705     * @return Indicates success of the operation.
1706     *
1707     * @see
1708     */

1709    synchronized boolean addChild(CoordinatorImpl child) {
1710
1711        boolean result;
1712
1713        // Make sure the NestingInfo instance variables is set up
1714
// before adding the child.
1715

1716        if (nestingInfo == null) {
1717            nestingInfo = new NestingInfo();
1718        }
1719
1720        result = nestingInfo.addChild(child);
1721
1722        return result;
1723    }
1724
1725    /**
1726     * Removes the given Coordinator from the set of children of the
1727     * target TopCoordinator.
1728     * If the TopCoordinator is a temporary ancestor, and has no
1729     * recoverable state after the child is removed, it destroys itself.
1730     *
1731     * @param child The child Coordinator.
1732     *
1733     * @return Indicates success of the operation.
1734     *
1735     * @see
1736     */

1737    synchronized boolean removeChild(CoordinatorImpl child) {
1738
1739        boolean result = false;
1740
1741        // Remove the child from the set of children. If the NestingInfo
1742
// instance variable has not been set up, then the child cannot
1743
// be removed.
1744

1745        if (nestingInfo != null) {
1746            result = nestingInfo.removeChild(child);
1747        }
1748
1749        // If the removal results in an empty, temporary Coordinator, then this
1750
// Coordinator must be cleaned up. The RecoveryManager is called to
1751
// clean up the transaction.
1752

1753        if (temporary && !registered &&
1754                !(participants != null && participants.involved()) &&
1755                !(synchronizations != null && synchronizations.involved()) &&
1756                !(nestingInfo != null && nestingInfo.numChildren() > 0)) {
1757            cleanUpEmpty(null);
1758        }
1759
1760        return result;
1761    }
1762
1763    static String JavaDoc[] resultName = { "Commit"/*#Frozen*/, "Rollback"/*#Frozen*/, "Read-only"/*#Frozen*/ };
1764
1765    /**
1766     * Directs the TopCoordinator to prepare to commit.
1767     * The TopCoordinator directs all registered Resources to prepare, and
1768     * returns the result to the caller. The TopCoordinator must
1769     * guarantee that each Resource object registered with it receives
1770     * at most one prepare request (This includes the case where the
1771     * Recoverable Server registers the same Resource twice).
1772     *
1773     * @param
1774     *
1775     * @return The consolidated vote.
1776     *
1777     * @exception INVALID_TRANSACTION The transaction is not in a state to
1778     * commit, due to outstanding work.
1779     * @exception HeuristicMixed Indicates that a participant voted
1780     * to roll the transaction back, but one or more others
1781     * have already heuristically committed.
1782     * @exception HeuristicHazard Indicates that a participant voted to roll
1783     * the transaction back, but one or more others may have already
1784     * heuristically committed.
1785     *
1786     * @see
1787     */

1788    Vote prepare()
1789            throws INVALID_TRANSACTION, HeuristicMixed, HeuristicHazard {
1790
1791        Vote result = Vote.VoteRollback;
1792
1793        // Until we actually distribute prepare flows, synchronize the method.
1794

1795        synchronized(this) {
1796
1797            // First check for active children, before getting too far into
1798
// the prepare. This is only done for the root Coordinator as for
1799
// any others it is too late.
1800

1801            if (root && nestingInfo != null &&
1802                    nestingInfo.numChildren() != 0) {
1803                INVALID_TRANSACTION exc =
1804                    new INVALID_TRANSACTION(
1805                        MinorCode.UnfinishedSubtransactions,
1806                        CompletionStatus.COMPLETED_NO);
1807                throw exc;
1808            }
1809
1810            // If the TopCoordinator is in the wrong state, return immediately.
1811

1812            if (!tranState.setState(TransactionState.STATE_PREPARING)) {
1813                return Vote.VoteRollback;
1814            }
1815
1816            // Check for marked rollback-only.
1817

1818            if (rollbackOnly) {
1819
1820                // Try to set the state to prepared fail.
1821

1822                if (!tranState.
1823                        setState(TransactionState.STATE_PREPARED_FAIL)) {
1824                    // empty
1825
}
1826
1827                return Vote.VoteRollback;
1828            }
1829
1830            // Release the lock prior to distributing the prepare operations.
1831
// This is to allow the transaction to be marked rollback-only
1832
// (by resources)
1833

1834        } // synchronised bit
1835

1836        // Get the RegisteredResources to distribute prepare operations.
1837
// If a heuristic exception is thrown, then set the state
1838
// to rolled back.
1839

1840        Vote overallResult = Vote.VoteReadOnly;
1841        Throwable JavaDoc heuristicExc = null;
1842
1843        if (participants != null) {
1844
1845            try {
1846
1847                overallResult = participants.distributePrepare();
1848        if (overallResult == Vote.VoteCommit ||
1849                overallResult == Vote.VoteReadOnly) {
1850            
1851            if (participants.getLAOResource() != null) {
1852                    if (logRecord == null) {
1853                            if (!(LogDBHelper.getInstance().addRecord(
1854                  tranState.localTID.longValue(),
1855                                  tranState.globalTID.toTidBytes()))) {
1856                                overallResult = Vote.VoteRollback;
1857                            }
1858            }
1859            if (overallResult != Vote.VoteRollback) {
1860                            participants.getLAOResource().commit();
1861                }
1862            }
1863        }
1864            } catch (Throwable JavaDoc exc) {
1865
1866                // If a heuristic exception was thrown, change the state of
1867
// the Coordinator to rolled back and clean up before throwing
1868
// the exception to the caller.
1869

1870                if (exc instanceof HeuristicMixed ||
1871                        exc instanceof HeuristicHazard) {
1872
1873                    if (!tranState.
1874                            setState(TransactionState.STATE_ROLLED_BACK)) {
1875                        // empty
1876
}
1877
1878                    /* comented out (Ram J) for memory leak fix.
1879                    // Discard the Coordinator if there is no after completion.
1880                    // Root Coordinators and those with registered
1881                    // Synchronization objects always have after completion
1882                    // flows. Otherwise remove the RecoveryManager associations
1883                    // and destroy the Coordinator.
1884
1885                    if (!root &&
1886                            (synchronizations == null ||
1887                             !synchronizations.involved())
1888                            ) {
1889                        RecoveryManager.removeCoordinator(superInfo.globalTID,
1890                                                          superInfo.localTID,
1891                                                          false);
1892                        destroy();
1893                    }
1894                    */

1895
1896                    // added (Ram J) for memory leak fix
1897
// if subordinate, send out afterCompletion. This will
1898
// destroy the CoordinatorSynchronization and coordinator.
1899
if (!root) {
1900                        afterCompletion(Status.StatusRolledBack);
1901                    }
1902
1903                    /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
1904                    /* NO INSTANCE VARIABLES MAY BE */
1905                    /* ACCESSED FROM THIS POINT ON.*/
1906                    /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
1907
1908                    if (heuristicExc instanceof HeuristicMixed) {
1909                        throw (HeuristicMixed)heuristicExc;
1910                    } else {
1911                        throw (HeuristicHazard)heuristicExc;
1912                    }
1913                }
1914
1915                // For any other exception, change the vote to rollback
1916

1917                overallResult = Vote.VoteRollback;
1918
1919            } // catch for except
1920

1921        } // if block
1922

1923        // The remainder of the method needs to be synchronized.
1924

1925        synchronized(this) {
1926
1927            // If the transaction has been marked rollback-only during
1928
// this process, change the vote.
1929

1930            if (rollbackOnly) {
1931                overallResult = Vote.VoteRollback;
1932            }
1933
1934
1935            // Set the state depending on the result of the prepare operation.
1936
// For read-only, we can throw away the Coordinator if there are no
1937
// synchronization objects, otherwise the Coordinator will
1938
// be destroyed after synchronization.
1939
// Set the state to prepared, read-only.
1940

1941            if (overallResult == Vote.VoteReadOnly) {
1942
1943                if (!tranState.
1944                        setState(TransactionState.STATE_PREPARED_READONLY)) {
1945                    overallResult = Vote.VoteRollback;
1946                }
1947
1948                /* commented out (Ram J) for memory leak fix.
1949                // When voting readonly, discard the Coordinator if there is
1950                // no after completion. Root Coordinators and those with
1951                // registered Synchronization objects always have after
1952                // completion flows. Otherwise remove the
1953                // RecoveryManager associations and destroy the Coordinator.
1954
1955                if (!root &&
1956                        (synchronizations == null ||
1957                         !synchronizations.involved())
1958                        ) {
1959                    RecoveryManager.removeCoordinator(superInfo.globalTID,
1960                                                      superInfo.localTID,
1961                                                      false);
1962                    destroy();
1963                }
1964                */

1965
1966                // added (Ram J) for memory leak fix
1967
// if subordinate, send out afterCompletion. This will
1968
// destroy the CoordinatorSynchronization and coordinator.
1969
// Note: the after_completion status is "unknown", since
1970
// at this point we do not know if the tx completed sucessfully,
1971
// as the sync objects are being called before the root
1972
// actually completes.
1973
if (!root) {
1974                    afterCompletion(Status.StatusUnknown);
1975                }
1976            } else if (overallResult == Vote.VoteCommit) {
1977
1978                // For commit, change any active timeout and change the state.
1979

1980                int timeoutType = TimeoutManager.NO_TIMEOUT;
1981
1982                // In the root, there is no need for an in-doubt timeout,
1983
// so cancel the timeout so that the transaction is
1984
// not rolled back. Otherwise set an
1985
// in-doubt timeout of 60 seconds.
1986

1987                if (!root) {
1988                    timeoutType = TimeoutManager.IN_DOUBT_TIMEOUT;
1989                }
1990
1991                TimeoutManager.setTimeout(superInfo.localTID, timeoutType, 60);
1992
1993                // Set the state to prepared_success.
1994

1995                if (!tranState.
1996                        setState(TransactionState.STATE_PREPARED_SUCCESS)) {
1997                    overallResult = Vote.VoteRollback;
1998                }
1999            } else {
2000
2001                // By default, assume rollback. We do not need to cancel
2002
// the timeout as it does not matter
2003
// if the transaction is subsequently rolled back.
2004

2005                if (!tranState.
2006                        setState(TransactionState.STATE_PREPARED_FAIL)) {
2007                    overallResult = Vote.VoteRollback;
2008                }
2009            }
2010        }
2011
2012        return overallResult;
2013    }
2014
2015    /**
2016     * Directs the TopCoordinator to commit the transaction.
2017     * The TopCoordinator directs all registered Resources to commit. If any
2018     * Resources raise Heuristic exceptions, the information is recorded,
2019     * and the Resources are directed to forget the transaction before the
2020     * Coordinator returns a heuristic exception to its caller.
2021     *
2022     * @param
2023     *
2024     * @return
2025     *
2026     * @exception HeuristicMixed A Resource has taken an heuristic decision
2027     * which has resulted in part of the transaction being rolled back.
2028     * @exception HeuristicHazard Indicates that heuristic decisions may have
2029     * been taken which have resulted in part of the transaction
2030     * being rolled back.
2031     * @exception NotPrepared The transaction has not been prepared.
2032     *
2033     * @see
2034     */

2035    void commit() throws HeuristicMixed, HeuristicHazard, NotPrepared {
2036
2037        // Until we actually distribute prepare flows, synchronize the method.
2038

2039
2040        synchronized(this) {
2041            if(_logger.isLoggable(Level.FINE))
2042            {
2043                _logger.logp(Level.FINE,"TopCoordinator","commit()",
2044                        "Within TopCoordinator.commit()"+"GTID is :"+
2045                        superInfo.globalTID.toString());
2046            }
2047
2048            // If the TopCoordinator voted readonly,
2049
// produce a warning and return.
2050

2051            if (tranState.state == TransactionState.STATE_PREPARED_READONLY) {
2052                return;
2053            }
2054
2055            // GDH
2056
// If the TopCoordinator has already completed due to recovery
2057
// resync thread, return. (Note there is no
2058
// need to deal with state ROLLED_BACK here as nothing should have
2059
// caused us to enter that state and subsequently receive a commit.
2060
// However the opposite cannot be said to be true as presumed abort
2061
// can cause a rollback to occur when
2062
// replay_completion is called on a transaction that
2063
// has gone away already.
2064

2065            if (tranState.state == TransactionState.STATE_COMMITTED) {
2066                return;
2067            }
2068
2069            // If the TopCoordinator is in the wrong state, return immediately.
2070

2071            if (!tranState.setState(TransactionState.STATE_COMMITTING)) {
2072                _logger.log(Level.SEVERE,"jts.transaction_wrong_state","commit");
2073                 String JavaDoc msg = LogFormatter.getLocalizedMessage(_logger,
2074                                        "jts.transaction_wrong_state",
2075                                        new java.lang.Object JavaDoc[] { "commit"});
2076                 throw new org.omg.CORBA.INTERNAL JavaDoc(msg);
2077                //NotPrepared exc = new NotPrepared();
2078
//Commented out as code is never executed
2079
//throw exc;
2080
}
2081
2082            // Release the lock before proceeding with commit.
2083

2084        }
2085
2086        // Commit all participants. If a fatal error occurs during
2087
// this method, then the process must be ended with a fatal error.
2088

2089        Throwable JavaDoc heuristicExc = null;
2090        if (participants != null) {
2091            try {
2092                participants.distributeCommit();
2093            } catch (Throwable JavaDoc exc) {
2094                if (exc instanceof HeuristicMixed ||
2095                        exc instanceof HeuristicHazard) {
2096                    heuristicExc = exc;
2097                }
2098
2099                // ADDED(Ram J) percolate any system exception
2100
// back to the caller.
2101
if (exc instanceof INTERNAL) {
2102                    throw (INTERNAL) exc;
2103                }
2104            }
2105        }
2106
2107        // The remainder of the method needs to be synchronized.
2108

2109        synchronized(this) {
2110
2111            // Record that objects have been told to commit.
2112

2113            // Set the state
2114

2115            if (!tranState.setState(TransactionState.STATE_COMMITTED)) {
2116                _logger.log(Level.SEVERE,"jts.transaction_wrong_state","commit");
2117                 String JavaDoc msg = LogFormatter.getLocalizedMessage(_logger,
2118                                        "jts.transaction_wrong_state",
2119                                        new java.lang.Object JavaDoc[] { "commit"});
2120                 throw new org.omg.CORBA.INTERNAL JavaDoc(msg);
2121            }
2122
2123            // Clean up the TopCoordinator after a commit. In the case where
2124
// the TopCoordinator is a root, the CoordinatorTerm object must be
2125
// informed that the transaction has completed so that if another
2126
// caller has committed the transaction the object normally
2127
// responsible for terminating the transaction can take the
2128
// appropriate action. NOTE: This may DESTROY the TopCoordinator
2129
// object so NO INSTANCE VARIABLES should be referenced after the
2130
// call. In the case where the TopCoordinator is a subordinate, the
2131
// CoordinatorResource object must be informed that the transaction
2132
// has been completed so that it can handle any subsequent requests
2133
// for the transaction.
2134

2135            if (terminator != null) {
2136                terminator.setCompleted(false, heuristicExc != null);
2137            }
2138
2139            /* commented out (Ram J) for memory leak fix.
2140            // If there are no registered Synchronization objects,
2141            // there is nothing left to do, so get the RecoveryManager
2142            // to forget about us, then self-destruct.
2143
2144            if (!root && (synchronizations == null ||
2145                          !synchronizations.involved())
2146                         ) {
2147                RecoveryManager.removeCoordinator(superInfo.globalTID,
2148                                                  superInfo.localTID,
2149                                                  false);
2150                destroy();
2151            }
2152            */

2153
2154             // added (Ram J) for memory leak fix
2155
// if subordinate, send out afterCompletion. This will
2156
// destroy the CoordinatorSynchronization and coordinator.
2157
if (!root) {
2158                afterCompletion(Status.StatusCommitted);
2159             }
2160
2161
2162            /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
2163            /* NO INSTANCE VARIABLES MAY BE ACCESSED FROM THIS POINT ON. */
2164            /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
2165
2166            // If there was heuristic damage, report it.
2167

2168            if (heuristicExc != null) {
2169                if (heuristicExc instanceof HeuristicMixed) {
2170                    throw (HeuristicMixed) heuristicExc;
2171                } else {
2172                    throw (HeuristicHazard) heuristicExc;
2173                }
2174            }
2175        }
2176    }
2177
2178    /**
2179     * Directs the TopCoordinator to roll back the transaction.
2180     * The TopCoordinator directs all registered Resources to rollback.
2181     * If any Resources raise Heuristic exceptions,
2182     * the information is recorded, and the Resources are directed
2183     * to forget the transaction before the
2184     * Coordinator returns a heuristic exception to its caller.
2185     *
2186     * @param force Indicates that the transaction must rollback regardless.
2187     *
2188     * @return
2189     *
2190     * @exception HeuristicMixed A Resource has taken an heuristic decision
2191     * which has resulted in part of the transaction being committed.
2192     * @exception HeuristicHazard Indicates that heuristic decisions may
2193     * have been taken which have resulted in part of the transaction
2194     * being rolled back.
2195     * @see
2196     */

2197    void rollback(boolean force) throws HeuristicMixed, HeuristicHazard {
2198
2199        // Until we actually distribute prepare flows, synchronize the method.
2200

2201        synchronized(this){
2202        if(_logger.isLoggable(Level.FINE))
2203        {
2204            _logger.logp(Level.FINE,"TopCoordinator","rollback()",
2205                    "Within TopCoordinator.rollback() :"+"GTID is : "+
2206                    superInfo.globalTID.toString());
2207        }
2208
2209            // If the transaction has already been rolled back, just return.
2210

2211            if (tranState == null) {
2212                return;
2213            }
2214
2215            // GDH
2216
// If the TopCoordinator has already completed (eg due to
2217
// recovery resync thread and this is now running on
2218
// the 'main' one) we can safely ignore the error
2219

2220            if (tranState.state == TransactionState.STATE_ROLLED_BACK) {
2221                return;
2222            }
2223
2224            // GDH
2225
// The state could even be commited, which can be OK if it was
2226
// committed, and thus completed, when the recovery thread asked
2227
// the superior about the txn. The superior would
2228
// no longer had any knowledge of it. In this case, due to presumed
2229
// abort, the recovery manager would then
2230
// now default to aborting it.
2231
// In this case if the TopCoordinator has committed already
2232
// we should also just return ignoring the error.
2233

2234            if (tranState.state == TransactionState.STATE_COMMITTED) {
2235                return;
2236            }
2237
2238            // If this is not a forced rollback and the coordinator
2239
// has prepared or is in an inappropriate state, do not continue
2240
// and return FALSE.
2241

2242            if (!force && ((tranState.state ==
2243                                TransactionState.STATE_PREPARED_SUCCESS) ||
2244                           (!tranState.setState(
2245                                TransactionState.STATE_ROLLING_BACK))
2246                          )) {
2247                return;
2248            }
2249
2250            // We do not care about invalid state changes as we are
2251
// rolling back anyway. If the TopCoordinator is
2252
// temporary, we do not change state as this would
2253
// cause a log force in a subordinate, which is not required.
2254

2255            if( !temporary &&
2256                    !tranState.setState(TransactionState.STATE_ROLLING_BACK)) {
2257                // empty
2258
}
2259
2260            // Rollback outstanding children. If the NestingInfo instance
2261
// variable has not been created, there are no
2262
// children to rollback.
2263

2264            if (nestingInfo != null) {
2265                nestingInfo.rollbackFamily();
2266            }
2267
2268            // Release the lock before proceeding with rollback.
2269

2270        }
2271
2272        // Roll back all participants. If a fatal error occurs during
2273
// this method, then the process must be ended with a fatal error.
2274

2275        Throwable JavaDoc heuristicExc = null;
2276        if (participants != null) {
2277            try {
2278                participants.distributeRollback(false);
2279            } catch(Throwable JavaDoc exc) {
2280
2281                if (exc instanceof HeuristicMixed ||
2282                        exc instanceof HeuristicHazard) {
2283                    heuristicExc = exc;
2284                }
2285
2286                // ADDED (Ram J) percolate up any system exception.
2287
if (exc instanceof INTERNAL) {
2288                    throw (INTERNAL) exc;
2289                }
2290            }
2291        }
2292
2293        // The remainder of the method needs to be synchronized.
2294

2295        synchronized(this) {
2296
2297            // Set the state. Only bother doing this if the coordinator
2298
// is not temporary.
2299

2300            if (!temporary &&
2301                    !tranState.setState(TransactionState.STATE_ROLLED_BACK)) {
2302                // empty
2303
}
2304
2305            // Clean up the TopCoordinator after a rollback.
2306
// In the case where the TopCoordinator is a root,
2307
// the CoordinatorTerm object must be informed that the transaction
2308
// has completed so that if another caller has rolled back
2309
// the transaction (time-out for example) the object normally
2310
// responsible for terminating the transaction can take the
2311
// appropriate action. NOTE: This may DESTROY
2312
// the TopCoordinator object so NO INSTANCE VARIABLES
2313
// should be referenced after the call. In the case where
2314
// the TopCoordinator is a subordinate, the CoordinatorResource
2315
// object must be informed that the transaction has been
2316
// completed so that it can handle any subsequent requests for the
2317
// transaction.
2318

2319            if (terminator != null) {
2320                terminator.setCompleted(true, heuristicExc != null);
2321            }
2322
2323            /* commented out (Ram J) for memory leak fix.
2324            // If there are no registered Synchronization objects, there is
2325            // nothing left to do, so get the RecoveryManager to forget
2326            // about us, then self-destruct.
2327
2328            if (!root && (synchronizations == null ||
2329                          !synchronizations.involved())
2330                         ) {
2331                RecoveryManager.removeCoordinator(superInfo.globalTID,
2332                                                  superInfo.localTID,
2333                                                  true);
2334
2335                if (!dying) {
2336                    destroy();
2337                }
2338            }
2339            */

2340            // added (Ram J) for memory leak fix
2341
// if subordinate, send out afterCompletion. This will
2342
// destroy the CoordinatorSynchronization and coordinator.
2343
if (!root) {
2344                afterCompletion(Status.StatusRolledBack);
2345            }
2346
2347            /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
2348            /* NO INSTANCE VARIABLES MAY BE ACCESSED FROM THIS POINT ON. */
2349            /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
2350
2351            // If there was heuristic damage, report it.
2352

2353            if (heuristicExc != null) {
2354                if (heuristicExc instanceof HeuristicMixed) {
2355                    throw (HeuristicMixed) heuristicExc;
2356                } else {
2357                    throw (HeuristicHazard) heuristicExc;
2358                }
2359            }
2360        }
2361
2362        // Otherwise return normally.
2363
}
2364
2365    /**
2366     * Informs the TopCoordinator that the given object requires
2367     * synchronization before and after completion of the transaction.
2368     * If possible, a CoordinatorSync object is registered
2369     * with the superior Coordinator. Otherwise this
2370     * Coordinator becomes the root of a sub-tree for
2371     * synchronization.
2372     *
2373     * @param sync The Synchronization object to be registered.
2374     *
2375     * @return
2376     *
2377     * @exception Inactive The Coordinator is in the process of completing the
2378     * transaction and cannot accept this registration.
2379     * @exception SynchronizationUnavailable The transaction service
2380     * cannot support synchronization.
2381     * @exception SystemException The operation failed.
2382     *
2383     * @see
2384     */

2385    synchronized public void register_synchronization(Synchronization sync)
2386            throws SystemException, Inactive, SynchronizationUnavailable {
2387
2388        // First check the state of the transaction. If it is not active,
2389
// do not allow the registration.
2390

2391        if (tranState == null ||
2392                tranState.state != TransactionState.STATE_ACTIVE) {
2393              Inactive exc = new Inactive();
2394              throw exc;
2395        }
2396
2397        // If not previously registered, a CoordinatorSync object must be
2398
// registered with our superior. Note that root TopCoordinators
2399
// are created with the registration flag set, so we do not need to
2400
// check whether we are the root TopCoordinator here.
2401

2402        if (!registeredSync) {
2403
2404            // Initialise the CoordinatorSync with the local id, our reference,
2405
// and a flag to indicate that does not represent a subtransaction.
2406

2407            CoordinatorSynchronizationImpl sImpl =
2408                new CoordinatorSynchronizationImpl(this);
2409
2410            // Register the CoordinatorSync with the superior CoordinatorImpl.
2411

2412            try {
2413                Synchronization subSync = sImpl.object();
2414                superInfo.superior.register_synchronization(subSync);
2415                registeredSync = true;
2416
2417                // added (Ram J) for memory leak fix.
2418
this.coordSyncImpl = sImpl;
2419                if(_logger.isLoggable(Level.FINER))
2420                {
2421                    _logger.logp(Level.FINER,"TopCoordinator",
2422                            "register_synchronization()",
2423                            "CoordinatorSynchronizationImpl :" + sImpl +
2424                            " has been registered with (Root)TopCoordinator"+
2425                            "GTID is: "+ superInfo.globalTID.toString());
2426                }
2427
2428            } catch (Exception JavaDoc exc) {
2429                // If an exception was raised, dont set the registration flag.
2430
sImpl.destroy();
2431
2432                // If the exception is a system exception, then allow it
2433
// to percolate to the caller.
2434

2435                if (exc instanceof OBJECT_NOT_EXIST) {
2436                    TRANSACTION_ROLLEDBACK ex2 =
2437                        new TRANSACTION_ROLLEDBACK(
2438                            0, CompletionStatus.COMPLETED_NO);
2439                    throw ex2;
2440                }
2441
2442                if (exc instanceof Inactive) {
2443                    throw (Inactive)exc;
2444                }
2445
2446                if (exc instanceof SystemException) {
2447                    throw (SystemException) exc;
2448                }
2449
2450                // Otherwise throw an internal exception.
2451

2452                INTERNAL ex2 = new INTERNAL(MinorCode.NotRegistered,
2453                                            CompletionStatus.COMPLETED_NO);
2454                throw ex2;
2455            }
2456        }
2457
2458        // Make sure the RegisteredSyncs instance variable has been set up.
2459

2460        if (synchronizations == null) {
2461            synchronizations = new RegisteredSyncs();
2462        }
2463
2464        // Add a duplicate of the reference to the set. This is done
2465
// because if the registration is for a remote object,
2466
// the proxy will be freed
2467
// when the registration request returns.
2468

2469        // COMMENT(Ram J) if the sync object is a local servant, there is
2470
// no proxy involved. Also the instanceof operator could be replaced
2471
// by a is_local() method if this class implements the CORBA local
2472
// object contract.
2473
if (sync instanceof com.sun.jts.jta.SynchronizationImpl) {
2474            synchronizations.addSync(sync);
2475
2476            if(_logger.isLoggable(Level.FINER))
2477            {
2478                _logger.logp(Level.FINER,"TopCoordinator",
2479                        "register_synchronization()",
2480                        "SynchronizationImpl :" + sync +
2481                        " has been registeredwith TopCoordinator :"+
2482                        "GTID is : "+ superInfo.globalTID.toString().toString());
2483            }
2484
2485        } else {
2486            synchronizations.addSync((Synchronization) sync._duplicate());
2487        }
2488
2489        temporary = false;
2490    }
2491
2492    /**
2493     * Informs the TopCoordinator that the transaction is about to complete.
2494     * The TopCoordinator informs all Synchronization objects registered with
2495     * it that the transaction is about to complete and waits for all of the
2496     * replies before this operation completes.
2497     *
2498     * @param
2499     *
2500     * @return
2501     *
2502     * @exception INVALID_TRANSACTION The transaction is not in a state to
2503     * commit, due to outstanding work.
2504     *
2505     * @see
2506     */

2507    synchronized void beforeCompletion() throws INVALID_TRANSACTION {
2508
2509        // First check for active children, before getting too far in.
2510
// This is only done for the root Coordinator as for any
2511
// others its too late.
2512

2513        if (root && nestingInfo != null && nestingInfo.numChildren() != 0) {
2514            INVALID_TRANSACTION exc = new INVALID_TRANSACTION(
2515                                        MinorCode.UnfinishedSubtransactions,
2516                                        CompletionStatus.COMPLETED_NO);
2517            throw exc;
2518        }
2519
2520        // If there are registered Synchronization objects, tell them
2521
// the transaction is about to prepare.
2522

2523        if (synchronizations != null) {
2524
2525            // Tell the RegisteredSyncs to distribute the before completion
2526
// messages. If an exception is raised, then mark the transaction
2527
// rollback-only.
2528

2529            if (!synchronizations.distributeBefore()) {
2530                rollbackOnly = true;
2531            }
2532        }
2533    }
2534
2535    /**
2536     * Informs the TopCoordinator that the transaction has completed.
2537     * The TopCoordinator informs all Synchronization objects registered with
2538     * it that the transaction has completed. It does not need to wait for all
2539     * responses before returning.
2540     *
2541     * @param status Indicates whether the transaction committed or aborted.
2542     *
2543     * @return
2544     *
2545     * @see
2546     */

2547    synchronized void afterCompletion(Status status) {
2548
2549        // If the Coordinator is still active, set it to read only to prevent
2550
// the Coordinator from actually rolling back when it is destroyed.
2551

2552        if (tranState.state == TransactionState.STATE_ACTIVE) {
2553            tranState.setState(TransactionState.STATE_PREPARING);
2554            tranState.setState(TransactionState.STATE_PREPARED_READONLY);
2555        }
2556
2557        // If there are registered Synchronization objects,
2558
// tell them the transaction has completed.
2559

2560        if (synchronizations != null) {
2561
2562            // Tell the RegisteredSyncs to distribute the after completion
2563
// messages. If an exception occurs, just report it.
2564

2565            // synchronizations.distributeAfter(get_status());
2566
synchronizations.distributeAfter(status);
2567        }
2568
2569        // At this point, there is nothing left to do, so destroy ourselves
2570
// before returning.
2571
boolean aborted = true;
2572        if (status == Status.StatusCommitted) {
2573            aborted = false;
2574        }
2575        if (!delegated) {
2576            RecoveryManager.removeCoordinator(superInfo.globalTID,
2577                                       superInfo.localTID,
2578                                       aborted);
2579        } else {
2580            DelegatedRecoveryManager.removeCoordinator(superInfo.globalTID,
2581                                       superInfo.localTID,
2582                                       aborted, logPath);
2583        }
2584
2585        // memory leak fix (Ram J) - cleanup the Recovery Coordinator objs.
2586
if (recoveryCoordinatorList != null) {
2587            for (int i = 0; i < recoveryCoordinatorList.size(); i++) {
2588                RecoveryCoordinatorImpl rcImpl = (RecoveryCoordinatorImpl)
2589                    recoveryCoordinatorList.elementAt(i);
2590                rcImpl.destroy();
2591            }
2592            recoveryCoordinatorList = null;
2593        }
2594
2595        // memory leak fix (Ram J)
2596
// destroy the CoordinatorSynchronization object.
2597
if (this.coordSyncImpl != null) {
2598            this.coordSyncImpl.destroy();
2599        }
2600        this.synchronizations = null;
2601
2602        // destroy the coordinator object.
2603
destroy();
2604    }
2605
2606    /**
2607     * Informs the TopCoordinator of the identity of the
2608     * object that is normally responsible for directing
2609     * it through termination. The CoordinatorTerm /
2610     * CoordinatorResource object is informed by the Coordinator when the
2611     * transaction aborts so that they can cope with asynchronous aborts.
2612     *
2613     * @param term The object normally responsible for terminating the
2614     * Coordinator.
2615     * @return
2616     *
2617     * @see
2618     */

2619    synchronized void setTerminator(CompletionHandler term) {
2620        terminator = term;
2621    }
2622
2623    /**
2624     * Gets the parent coordinator of the transaction. As this is a top level
2625     * coordinator, a parent does not exist so NULL is returned.
2626     *
2627     * @param
2628     *
2629     * @return The parent Coordinator, null.
2630     *
2631     * @see
2632     */

2633    Coordinator getParent() {
2634
2635        Coordinator result = null;
2636        return result;
2637    }
2638
2639    /**
2640     * Gets the superior Coordinator for this transaction.
2641     *
2642     * @param
2643     *
2644     * @return The superior Coordinator
2645     *
2646     * @see
2647     */

2648    Coordinator getSuperior() {
2649
2650        Coordinator result = superInfo.superior;
2651        return result;
2652    }
2653
2654    /**
2655     * Returns the Resource objects and their states.
2656     *
2657     * @param resources The object which will contain the Resources
2658     * @param states The object which will contain the states.
2659     *
2660     * @return
2661     *
2662     * @see
2663     */

2664    /* COMMENT(Ram J) only Admin package needs this.
2665    public void getResources(ResourceSequenceHolder resources,
2666                             ResourceStatusSequenceHolder states) {
2667        if (participants != null) {
2668            participants.getResources(resources,states);
2669
2670            // Validate each of the Resource objects in the list
2671            // before returning it.
2672
2673            for (int i = 0; i < resources.value.length; i++) {
2674                if (resources.value[i]._non_existent()) {
2675                    resources.value[i] = null;
2676                }
2677            }
2678        } else {
2679            resources.value = new Resource[0];
2680            states.value = new ResourceStatus[0];
2681        }
2682    }
2683    */

2684
2685    /**
2686     * Gets the object normally responsible for terminating this Coordinator.
2687     *
2688     * @param
2689     *
2690     * @return The object normally responsible for terminating
2691     * the Coordinator.
2692     *
2693     * @see
2694     */

2695    CompletionHandler getTerminator() {
2696
2697        CompletionHandler result = terminator;
2698        return result;
2699    }
2700
2701    /**
2702     * Registers the given Resource object with the Coordinator with no regard
2703     * for the state of the transaction or registration with the superior.
2704     * <p>
2705     * This is intended to be used during recovery to enable XA Resource
2706     * Managers to participate in resync without needing the XA Resource
2707     * objects to have persistent references.
2708     * <p>
2709     * The Resource object parameter should only refer to a local object.
2710     *
2711     * @param res The Resource to be directly registered.
2712     *
2713     * @return
2714     *
2715     * @see
2716     */

2717    void directRegisterResource(Resource res) {
2718
2719        // If the set has not already been created, create it now.
2720
// Note that we do notpass the CoordinatorLog object to the
2721
// RegisteredResources as we do not want to do anything
2722
// with it here. Generally participants will not be null
2723
// as this method will be called diring recovery.
2724

2725        if (participants == null) {
2726            participants = new RegisteredResources(null, this);
2727        }
2728
2729        // Add the reference to the set. The reference is not duplicated,
2730
// as this operation should only be called for local Resource objects.
2731

2732        participants.addRes(res);
2733        if(_logger.isLoggable(Level.FINE))
2734        {
2735            _logger.logp(Level.FINE,"TopCoordinator","directRegisterResource()",
2736                    "Registered resource :" + res );
2737        }
2738
2739    }
2740
2741    private static Any emptyData = null;
2742
2743    /**
2744     * Creates a PropagationContext which contains the information which would
2745     * normally be passed implicitly via the CosTSPropagation interfaces.
2746     *
2747     * @param
2748     *
2749     * @return The transaction context.
2750     *
2751     * @exception Inactive The Coordinator is in the process of completing the
2752     * transaction and cannot return the information.
2753     *
2754     * @see
2755     */

2756    synchronized public PropagationContext get_txcontext() throws Unavailable {
2757
2758        // First check the state of the transaction. If it is not active,
2759
// do not allow the registration.
2760

2761        if (tranState == null ||
2762                tranState.state != TransactionState.STATE_ACTIVE ||
2763                rollbackOnly ) {
2764            Unavailable exc = new Unavailable();
2765            throw exc;
2766        }
2767
2768        // Work out the timeout value to pass, if any.
2769
// Note that only top-level transactions have timeouts.
2770
// We do not check for timeouts if the Coordinator is remote.
2771
// If the Coordinator does not have a timeout defined, the
2772
// TimeoutManager will return a negative value.
2773
// If the transaction has timed out, the value will be zero.
2774

2775        long timeLeft = TimeoutManager.timeLeft(superInfo.localTID);
2776        int timeout = 0;
2777        if (timeLeft > 0) {
2778
2779            timeout = (int)timeLeft/1000;
2780
2781        } else if (timeLeft == 0) {
2782
2783            // If the timeout has expired, then do not return a context,
2784
// but roll the transaction back and
2785
// throw the TRANSACTION_ROLLEDBACK exception.
2786

2787            TimeoutManager.timeoutCoordinator(superInfo.localTID,
2788                                              TimeoutManager.ACTIVE_TIMEOUT);
2789            TRANSACTION_ROLLEDBACK exc = new TRANSACTION_ROLLEDBACK(
2790                                            0, CompletionStatus.COMPLETED_NO);
2791            throw exc;
2792        }
2793
2794        // Fill in the context with the current transaction information,
2795
// and the ancestor information.
2796

2797        TransIdentity current = new TransIdentity(this.object(),
2798                                                  null,
2799                                                  superInfo.globalTID.realTID);
2800
2801        // Ensure that the implementation specific data is filled with a value.
2802

2803        if (emptyData == null){
2804            emptyData = Configuration.getORB().create_any();
2805            emptyData.insert_boolean(false);
2806        }
2807
2808        PropagationContext result = new PropagationContext(
2809                                            timeout, current,
2810                                            new TransIdentity[0], emptyData);
2811        if(_logger.isLoggable(Level.FINEST))
2812        {
2813            _logger.logp(Level.FINEST,"TopCoordinator","get_txcontext()",
2814                    "Obtained PropagationContext"+"GTID is: "+
2815                    superInfo.globalTID.toString());
2816        }
2817
2818        return result;
2819    }
2820
2821    /**
2822     * Cleans up an empty Coordinator.
2823     *
2824     * @param parent The parent Coordinator
2825     * (always null for a TopCoordinator).
2826     * @return
2827     *
2828     * @see
2829     */

2830    void cleanUpEmpty(CoordinatorImpl parent) {
2831
2832        // Roll the transaction back, ignoring any exceptions.
2833

2834        try {
2835            rollback(true);
2836        } catch( Throwable JavaDoc exc ) {}
2837    }
2838
2839    //-------------------------------------------------------------------------
2840
// Method: TopCoordinator.commmitOnePhase
2841
//
2842
// Comments: This method is called by CoordinatorResource when
2843
// this Coordinator is a subordinate coordinator. If any
2844
// Resources raise Heuristic exceptions, the information is
2845
// recorded, and the Resources are directed to forget the
2846
// transaction before the Coordinator returns a heuristic
2847
// exception to its caller.
2848
//-------------------------------------------------------------------------
2849

2850    /**
2851     * commitOnePhase
2852     *
2853     * @param none
2854     * @return boolean indicating success or whether two phase commit
2855     * should be tried.
2856     * @see
2857     */

2858    boolean commitOnePhase() throws HeuristicMixed, HeuristicHazard {
2859
2860        synchronized (this) {
2861
2862            // First check for active children, before getting too far
2863
// into the prepare. This is only done for
2864
// the root Coordinator as for any others it is too late.
2865

2866            if (root && nestingInfo != null &&
2867                    nestingInfo.numChildren() != 0) {
2868                INVALID_TRANSACTION exc =
2869                    new INVALID_TRANSACTION(
2870                        MinorCode.UnfinishedSubtransactions,
2871                        CompletionStatus.COMPLETED_NO);
2872                throw exc;
2873            }
2874
2875
2876            // If the Coordinator has > 1 resource return smoothly
2877

2878            if (participants != null && participants.numRegistered() > 1) {
2879                // GDH COPDEF1
2880
return false;
2881            }
2882
2883            // If the TopCoordinator is in the wrong state, return immediately.
2884

2885            if (!tranState.
2886                setState(TransactionState.STATE_COMMITTING_ONE_PHASE)) {
2887                return false;
2888            }
2889
2890            // Check for marked rollback-only, if we are then we can drive
2891
// the rollback directly from the 2PC process so return false
2892
// this will cause use to enter prepare (which will do nothing as
2893
// it checks the same flag
2894
// thence directly into rollback
2895

2896            if (rollbackOnly) {
2897                return false;
2898            }
2899
2900            int timeoutType = TimeoutManager.NO_TIMEOUT;
2901
2902            // In the root, there is no need for an in-doubt timeout,
2903
// so cancel the timeout so that the transaction is
2904
// not rolled back. Otherwise set anin-doubt timeout of 60 seconds.
2905

2906            if (root) {
2907                TimeoutManager.setTimeout(superInfo.localTID,
2908                                          TimeoutManager.NO_TIMEOUT,
2909                                          60);
2910            }
2911            else {
2912                TimeoutManager.setTimeout(superInfo.localTID,
2913                                          TimeoutManager.IN_DOUBT_TIMEOUT,
2914                                          60);
2915            }
2916
2917
2918            //
2919
// Contact the resource (note: participants can exist with
2920
// no resourcesafter recovery)
2921
//
2922

2923        } // first synchronised bit ends now to allow possible callbacks.
2924

2925
2926        if ((participants != null) && (participants.numRegistered() == 1)) {
2927            Throwable JavaDoc heuristicExc = null;
2928            boolean rolled_back = false;
2929            try {
2930                participants.commitOnePhase();
2931            } catch (Throwable JavaDoc exc) {
2932
2933                if (exc instanceof HeuristicMixed) {
2934                    // IASRI START 4722886
2935
// heuristicExc = exc;
2936
// IASRI END 4722886
2937
if (!tranState.setState(
2938                            TransactionState.
2939                                STATE_COMMIT_ONE_PHASE_HEURISTIC_MIXED)) {
2940                                _logger.log(Level.SEVERE,"jts.transaction_wrong_state",
2941                                       "COMMIT_ONE_PHASE (1)");
2942                                 String JavaDoc msg = LogFormatter.getLocalizedMessage(_logger,
2943                                                        "jts.transaction_wrong_state",
2944                                                        new java.lang.Object JavaDoc[]
2945                                                        { "COMMIT_ONE_PHASE (1)"});
2946                                  throw new org.omg.CORBA.INTERNAL JavaDoc(msg);
2947                    }
2948                    // IASRI START 4722886
2949
throw (HeuristicMixed)exc;
2950                    // IASRI END 4722886
2951
} else if (exc instanceof HeuristicHazard) {
2952                    // IASRI START 4722886
2953
// heuristicExc = exc;
2954
// IASRI END 4722886
2955
if (!tranState.setState(
2956                            TransactionState.
2957                                STATE_COMMIT_ONE_PHASE_HEURISTIC_HAZARD)) {
2958                                _logger.log(Level.SEVERE,"jts.transaction_wrong_state",
2959                                        "COMMIT_ONE_PHASE (2)");
2960                                 String JavaDoc msg = LogFormatter.getLocalizedMessage(_logger,
2961                                                        "jts.transaction_wrong_state",
2962                                                        new java.lang.Object JavaDoc[]
2963                                                        { "COMMIT_ONE_PHASE (2)"});
2964                                  throw new org.omg.CORBA.INTERNAL JavaDoc(msg);
2965                    }
2966                    // IASRI START 4722886
2967
throw (HeuristicHazard)exc;
2968                    // IASRI END 4722886
2969
} else if (exc instanceof TRANSACTION_ROLLEDBACK) {
2970                    rolled_back = true;
2971
2972                    // GDH COPDEF2 Removed code below that changesd state to
2973
// COMMIT_ONE_PHASE_ROLLED_BACK this was unnecessary
2974
// as setting the rolled_back flag is picked up just below
2975
// where the state is changed. Prior to this change we
2976
// tried to set the state to COP_RB twice
2977
// in a row which is an error.
2978
} else if (exc instanceof INTERNAL) {
2979                    // ADDED (Ram J) percolate up any system exception.
2980
throw (INTERNAL) exc;
2981                } // end else if cascade on the exception types
2982

2983                // (Other exceptions are not passed back
2984
// by RegisteredResources)
2985

2986            } // end of catch block for exceptions
2987

2988            // (GDH COPDEF1 was after if-else block below)
2989

2990            // Set the final state now
2991
if (rolled_back) {
2992
2993                // GDH COPDEF1 Changed state movement to be via COP_RB
2994
// even though possible to go direct to RB
2995

2996                // Change state in two steps - this is traced and only the
2997
// first change would need a forced log write traditionaly
2998
if (!tranState.setState(
2999                        TransactionState.
3000                            STATE_COMMIT_ONE_PHASE_ROLLED_BACK)) {
3001                                _logger.log(Level.SEVERE,"jts.transaction_wrong_state",
3002                                       "COMMIT_ONE_PHASE (4)");
3003                                 String JavaDoc msg = LogFormatter.getLocalizedMessage(_logger,
3004                                                        "jts.transaction_wrong_state",
3005                                                        new java.lang.Object JavaDoc[]
3006                                                        { "COMMIT_ONE_PHASE (4)"});
3007                                  throw new org.omg.CORBA.INTERNAL JavaDoc(msg);
3008                    }
3009                  /**
3010
3011                if (!tranState.setState(TransactionState.STATE_ROLLED_BACK)) {
3012                    _logger.log(Level.SEVERE,"jts.transaction_wrong_state",
3013                            "COMMIT_ONE_PHASE (5)");
3014                     String msg = LogFormatter.getLocalizedMessage(_logger,
3015                                        "jts.transaction_wrong_state",
3016                                        new java.lang.Object[] { "COMMIT_ONE_PHASE (5)"});
3017                      throw new org.omg.CORBA.INTERNAL(msg);
3018                }
3019                   **/

3020            } else { // we commited
3021

3022                // GDH COPDEF1 Changed state movement to be via COP_OK
3023
// this is needed by the state tables as the first
3024
// state change should ideall be a forced log write.
3025

3026                // We do the state change in two jumps for better trace
3027
// and to log the fact that a COP_OK represents a successful
3028
// prepare - only the fist state changed needs a flushed write.
3029
if (!tranState.setState(TransactionState.
3030                                            STATE_COMMITTED_ONE_PHASE_OK)) {
3031                    _logger.log(Level.SEVERE,"jts.transaction_wrong_state",
3032                            "COMMIT_ONE_PHASE (6)");
3033                     String JavaDoc msg = LogFormatter.getLocalizedMessage(_logger,
3034                                        "jts.transaction_wrong_state",
3035                                        new java.lang.Object JavaDoc[] { "COMMIT_ONE_PHASE (6)"});
3036                      throw new org.omg.CORBA.INTERNAL JavaDoc(msg);
3037                }
3038                /**
3039
3040                // Now set this coord to commited finally.
3041                if (!tranState.setState(TransactionState.STATE_COMMITTED)) {
3042                    _logger.log(Level.SEVERE,"jts.transaction_wrong_state",
3043                            "COMMIT_ONE_PHASE (7)");
3044                     String msg = LogFormatter.getLocalizedMessage(_logger,
3045                                        "jts.transaction_wrong_state",
3046                                        new java.lang.Object[] { "COMMIT_ONE_PHASE (7)"});
3047                      throw new org.omg.CORBA.INTERNAL(msg);
3048                }
3049                 **/

3050            } // else we did not rollback
3051

3052
3053            // The remainder of the method needs to be synchronized too!
3054

3055            synchronized (this) {
3056
3057                // Clean up the TopCoordinator after a commit. In the case
3058
// where the TopCoordinator is a root,
3059
// the CoordinatorTerm object must be informed that
3060
// the transaction has completed so that if another
3061
// caller has committed the transaction the object
3062
// normally responsible for terminating the
3063
// transaction can take the appropriate action. NOTE: This may
3064
// DESTROY the TopCoordinator object so NO INSTANCE VARIABLES
3065
// should be referenced after the call.
3066
// In the case where the TopCoordinator is a subordinate, the
3067
// CoordinatorResource object must be informed that the
3068
// transaction has been completed so that it can
3069
// handle any subsequent requests for the
3070
// transaction.
3071

3072                if (terminator != null) {
3073                    terminator.setCompleted(false, heuristicExc != null);
3074                }
3075
3076                /* commented out (Ram J) for memory leak fix.
3077                // If there are no registered Synchronization objects,
3078                // there is nothing left to do, so get the RecoveryManager
3079                // to forget about us, then self-destruct.
3080
3081                if (!root && (synchronizations == null ||
3082                              !synchronizations.involved())
3083                             ) {
3084                    RecoveryManager.removeCoordinator(superInfo.globalTID,
3085                                                      superInfo.localTID,
3086                                                      false);
3087                    destroy();
3088                }
3089                */

3090
3091                // added (Ram J) for memory leak fix
3092
// if subordinate, send out afterCompletion. This will
3093
// destroy the CoordinatorSynchronization and coordinator.
3094
if (!root) {
3095                    afterCompletion(Status.StatusCommitted);
3096                }
3097
3098                /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
3099                /* NO INSTANCE VARIABLES MAY BE ACCESSED FROM THIS POINT ON. */
3100                /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
3101
3102                // If there was heuristic damage, report it.
3103

3104                if (heuristicExc != null) {
3105                    if (heuristicExc instanceof HeuristicMixed) {
3106                        throw (HeuristicMixed)heuristicExc;
3107                    } else {
3108                        throw (HeuristicHazard)heuristicExc;
3109                    }
3110                }
3111
3112                // If the resource rolled back throw TRANSACTION_ROLLEDBACK
3113

3114                if (rolled_back) {
3115                    TRANSACTION_ROLLEDBACK exc =
3116                        new TRANSACTION_ROLLEDBACK(
3117                            0, CompletionStatus.COMPLETED_YES);
3118                    throw exc;
3119                }
3120
3121            } //end of any synchronised work
3122

3123            // Otherwise return normally.
3124

3125            return true;
3126
3127        } else {
3128            // GDH COPDEF1
3129
// No resources at all - just complete state as for commited
3130

3131            // We do the state change in two jumps for better trace and to
3132
// log the fact that a COP_OK represents a successful prepare,
3133
// only the fist state changed needs a flushed write.
3134
// (Can't turn of NTFS file caching in Java anyway but the
3135
// intention is in that direction)
3136
if (!tranState.
3137                    setState(TransactionState.STATE_COMMITTED_ONE_PHASE_OK)) {
3138                    _logger.log(Level.SEVERE,"jts.transaction_wrong_state",
3139                            "COMMIT_ONE_PHASE (8)");
3140                     String JavaDoc msg = LogFormatter.getLocalizedMessage(_logger,
3141                                        "jts.transaction_wrong_state",
3142                                        new java.lang.Object JavaDoc[] { "COMMIT_ONE_PHASE (8)"});
3143                      throw new org.omg.CORBA.INTERNAL JavaDoc(msg);
3144            }
3145
3146            // Now set this coord to commited finally.
3147
/*
3148            if (!tranState.setState(TransactionState.STATE_COMMITTED)) {
3149                _logger.log(Level.SEVERE,"jts.transaction_wrong_state",
3150                        "COMMIT_ONE_PHASE (9)");
3151                 String msg = LogFormatter.getLocalizedMessage(_logger,
3152                                    "jts.transaction_wrong_state",
3153                                    new java.lang.Object[] { "COMMIT_ONE_PHASE (9)"});
3154                  throw new org.omg.CORBA.INTERNAL(msg);
3155            }
3156            */

3157        } // end of else clause if no resources
3158

3159        return true;
3160    }
3161
3162    /**
3163     * Returns a hash code for the object.
3164     * <p>
3165     * This very basic method is used by the trace facility and
3166     * should not call any method which is traced.
3167     *
3168     * @param
3169     *
3170     * @return The hash code for the object.
3171     *
3172     * @see
3173     */

3174    public int hashCode() {
3175        if (hash == 0 && superInfo != null && superInfo.globalTID != null) {
3176            hash = superInfo.globalTID.hashCode();
3177        }
3178
3179        return hash;
3180    }
3181
3182    /**
3183     * Determines equality of the object with the parameter.
3184     *
3185     * @param other The other object.
3186     *
3187     * @return Indicates equality.
3188     *
3189     * @see
3190     */

3191    public boolean equals(java.lang.Object JavaDoc other) {
3192
3193        // Do a quick check on the object references.
3194

3195        if( this == other ) return true;
3196
3197        // Obtain the global identifier for the other Coordinator.
3198

3199        otid_t otherTID = null;
3200
3201        // For local Coordinator objects which are really instances of the
3202
// CoordinatorImpl class, get the global TID via a private method call.
3203

3204        if (other instanceof CoordinatorImpl) {
3205            if (other instanceof TopCoordinator) {
3206                otherTID = ((TopCoordinator) other).
3207                                superInfo.globalTID.realTID;
3208            }
3209        } else if (other instanceof org.omg.CORBA.Object JavaDoc) {
3210
3211            // For remote Coordinator objects which are instances of
3212
// the JCoordinator class, use the getGlobalTID method remotely.
3213

3214            try {
3215                JCoordinator jcoord = JCoordinatorHelper.
3216                                        narrow((org.omg.CORBA.Object JavaDoc) other);
3217                otherTID = jcoord.getGlobalTID();
3218            } catch (BAD_PARAM exc) {
3219
3220                // For remote Coordinator objects which are not
3221
// instances of the JCoordinator class, use the propagation
3222
// context to compare the Coordinators. This relies on the
3223
// availability of the propagation
3224
// context from the target Coordinator.
3225

3226                try {
3227                    Coordinator coord =
3228                        CoordinatorHelper.narrow((org.omg.CORBA.Object JavaDoc) other);
3229                    PropagationContext pc = coord.get_txcontext();
3230                    otherTID = pc.current.otid;
3231                } catch (BAD_PARAM ex2) {
3232                    // If the other object is not actually a Coordinator,
3233
// then the objects are not the same.
3234
} catch (Unavailable ex2) {
3235                    // If the other Coordinator is inactive, then there is
3236
// nothing we can do to get the global identifier for the
3237
// transaction, so we cannot compare the
3238
// Coordinator objects.
3239
INVALID_TRANSACTION ex3 = new INVALID_TRANSACTION(
3240                                                MinorCode.CompareFailed,
3241                                                CompletionStatus.COMPLETED_NO);
3242                    throw ex3;
3243                }
3244            }
3245        }
3246
3247        // Compare the global identifiers.
3248

3249        if (otherTID != null) {
3250            return superInfo.globalTID.equals(otherTID);
3251        }
3252
3253        return false;
3254    }
3255}
3256
Popular Tags