KickJava   Java API By Example, From Geeks To Geeks.

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


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  * @(#)SubCoordinator.java 1.10 00/11/09
30  *
31  * Copyright 1995-1999 Sun Microsystems, Inc. All Rights Reserved.
32  *
33  * This software is the proprietary information of Sun Microsystems, Inc.
34  * Use is subject to license terms.
35  *
36  */

37
38 //----------------------------------------------------------------------------
39
//
40
// Module: SubCoordinator.java
41
//
42
// Description: Nested transaction Coordinator object implementation.
43
//
44
// Product: com.sun.jts.CosTransactions
45
//
46
// Author: Simon Holdsworth
47
//
48
// Date: March, 1997
49
//
50
// Copyright (c): 1995-1997 IBM Corp.
51
//
52
// The source code for this program is not published or otherwise divested
53
// of its trade secrets, irrespective of what has been deposited with the
54
// U.S. Copyright Office.
55
//
56
// This software contains confidential and proprietary information of
57
// IBM Corp.
58
//----------------------------------------------------------------------------
59

60 package com.sun.jts.CosTransactions;
61
62 import java.util.*;
63
64 import org.omg.CORBA.*;
65 import org.omg.CosTransactions.*;
66
67 import com.sun.jts.otsidl.*;
68 import java.util.logging.Logger JavaDoc;
69 import java.util.logging.Level JavaDoc;
70 import com.sun.logging.LogDomains;
71 import com.sun.jts.utils.LogFormatter;
72
73 /**
74  * The SubCoordinator interface is our implementation of the standard
75  * Coordinator interface that is used for subtransactions. It allows
76  * SubtransactionAwareResources to be registered for participation in a
77  * subtransaction. As an instance of this class may be accessed from multiple
78  * threads within a process, serialisation for thread-safety is necessary in
79  * the implementation. The information managed does not need to be
80  * reconstructible in the case of a failure as subtransactions are not
81  * durable.
82  *
83  * @version 0.01
84  *
85  * @author Simon Holdsworth, IBM Corporation
86  *
87  * @see
88  */

89
90 //----------------------------------------------------------------------------
91
// CHANGE HISTORY
92
//
93
// Version By Change Description
94
// 0.01 SAJH Initial implementation.
95
//----------------------------------------------------------------------------
96

97 class SubCoordinator extends CoordinatorImpl {
98     String JavaDoc name = null;
99     RegisteredResources participants = null;
100     SuperiorInfo superInfo = null;
101     NestingInfo nestingInfo = null;
102     TransactionState tranState = null;
103     CompletionHandler terminator = null;
104     boolean registered = false;
105     boolean root = true;
106     boolean rollbackOnly = false;
107     boolean dying = false;
108     boolean temporary = false;
109     int hash = 0;
110     /*
111         Logger to log transaction messages
112     */

113     static Logger JavaDoc _logger = LogDomains.getLogger(LogDomains.TRANSACTION_LOGGER);
114
115
116     /**
117      * Creates and initialises a SubCoordinator, given the parent's local
118      * and global identifiers and the sequence of ancestors.
119      *
120      * @param parentGlobalTID The parent's global transaction identifier.
121      * @param parentLocalTID The parent's local transaction identifier.
122      * @param ancestors This transactions's ancestors (includes parent).
123      *
124      * @return
125      *
126      * @exception LogicErrorException An internal logic error occurred.
127      *
128      * @see
129      */

130     SubCoordinator(GlobalTID parentGlobalTID, Long JavaDoc parentLocalTID,
131             CoordinatorImpl[] ancestors) throws LogicErrorException {
132
133         // Allocate a new global identifier for the subtransaction.
134
// If one cannot be allocated, raise an exception as the
135
// subtransaction cannot be started.
136

137         tranState = new TransactionState(parentLocalTID, parentGlobalTID);
138
139         // Store information about the superior, ancestors and participants
140
// of the new subtransaction.
141

142         superInfo = new SuperiorInfo(tranState.localTID,
143                                      tranState.globalTID, null, null);
144
145         // Cache the name - create a buffer and print the global XID into it.
146

147         name = superInfo.globalTID.toString();
148
149         // Cache the hash code.
150

151         hash = superInfo.globalTID.hashCode();
152
153         // Create the nesting info object to record the ancestors.
154

155         nestingInfo = new NestingInfo(ancestors);
156
157         // Zero out the RegisteredResources reference as it will be
158
// created when needed.
159

160         participants = null;
161
162         // Set other instance variables.
163

164         root = true;
165         registered = true;
166         rollbackOnly = false;
167         dying = false;
168         temporary = false;
169         terminator = null;
170
171         // Set the state of the subtransaction to active before making it
172
// visible to the RecoveryManager.
173

174         if (!tranState.setState(TransactionState.STATE_ACTIVE)) {
175             LogicErrorException exc =
176                 new LogicErrorException(
177                      LogFormatter.getLocalizedMessage(_logger,
178                      "jts.invalid_state_change"));
179             throw exc;
180         } else {
181             // Inform the RecoveryManager of the existence of this transaction.
182
RecoveryManager.addCoordinator(tranState.globalTID,
183                                            tranState.localTID, this, 0);
184         }
185     }
186
187     /**
188      * Creates and initialises a subordinate SubCoordinator, given the global
189      * identifier, a reference to the superior SubCoordinator,
190      * and the ancestors of the transaction.
191      * The temporary subordinate indicator is used for the case where a parent
192      * Coordinator is created when a subtransaction enters a process for the
193      * first time. If the request returns and the subtransaction has no
194      * participants, it is destroyed, along with any temporary ancestors.
195      *
196      * @param globalTID The global identifier for the transaction.
197      * @param superior The superior Coordinator.
198      * @param temporary The temporary flag.
199      * @param ancestors The ancestors of the transaction.
200      *
201      * @return
202      *
203      * @exception LogicErrorException An internal logic error occurred.
204      *
205      * @see
206      */

207     SubCoordinator(GlobalTID globalTID, Coordinator superior,
208             boolean temporary, CoordinatorImpl[] ancestors)
209             throws LogicErrorException {
210
211         // Allocate a new local identifier for the transaction. If one cannot
212
// be allocated, raise an exception as the transaction
213
// cannot be started.
214

215         tranState = new TransactionState(globalTID,null);
216
217         // Store information about the superior, ancestors and participants of
218
// the new subordinate transaction.
219

220         superInfo = new SuperiorInfo(tranState.localTID,
221                                      globalTID, superior, null);
222
223         // Cache the name - create a buffer and print the global XID into it.
224

225         name = superInfo.globalTID.toString();
226
227         // Cache the hash code.
228

229         hash = superInfo.globalTID.hashCode();
230
231         // Create the nesting info object to record the ancestors.
232

233         nestingInfo = new NestingInfo(ancestors);
234
235         // Zero out the RegisteredResources reference,
236
// as it will be created when needed.
237

238         participants = null;
239
240         // Set other instance variables.
241

242         root = false;
243         registered = false;
244         rollbackOnly = false;
245         dying = false;
246         this.temporary = temporary;
247         terminator = null;
248
249         // Set the state of the transaction to active before making it visible
250
// to the TransactionManager.
251

252         if (!tranState.setState(TransactionState.STATE_ACTIVE)) {
253             LogicErrorException exc =
254                 new LogicErrorException(
255                     LogFormatter.getLocalizedMessage(_logger,
256                     "jts.invalid_state_change"));
257             throw exc;
258         } else if (!RecoveryManager.addCoordinator(globalTID,
259                                                    tranState.localTID,
260                                                    this, 0)) {
261             LogicErrorException exc =
262                 new LogicErrorException(
263                     LogFormatter.getLocalizedMessage(_logger,
264                     "jts.transaction_id_already_in_use"));
265             throw exc;
266         }
267     }
268
269     /**
270      * Cleans up the state of the object.
271      *
272      * @param
273      *
274      * @return
275      *
276      * @see
277      */

278     public void finalize() {
279
280         // Set the flag to indicate that the coordinator is being destroyed.
281

282         dying = true;
283
284         // What we do when destroyed depends on the transaction's state.
285
// We assume that temporary Coordinators have rolled bak at this point.
286

287         int state = TransactionState.STATE_ROLLED_BACK;
288         if (tranState != null && !temporary) {
289             state = tranState.state;
290         }
291
292         switch (state) {
293
294         // If the transaction is active it should be rolled back. This
295
// will result in the TopCoordinator self-destructing at the
296
// end of two-phase commit.
297

298         case TransactionState.STATE_ACTIVE :
299             rollback(true);
300             break;
301
302         // For committed or rolled-back, we really need to destroy the object
303

304         case TransactionState.STATE_COMMITTED :
305         case TransactionState.STATE_ROLLED_BACK :
306             if( tranState != null ) tranState.finalize();
307             if( superInfo != null ) superInfo.finalize();
308             if( nestingInfo != null ) nestingInfo.finalize();
309             if( participants != null ) participants.finalize();
310
311             tranState = null;
312             superInfo = null;
313             nestingInfo = null;
314             participants = null;
315             terminator = null;
316             name = null;
317             break;
318
319         // For any other state, the transaction is completing, so the
320
// TopCoordinator will eventually self-destruct. We do nothing here.
321

322         default :
323             break;
324         }
325     }
326
327     /**
328      * Returns the local status of the target transaction.
329      *
330      * @param
331      *
332      * @return The status of the transaction.
333      *
334      * @see
335      */

336     synchronized public Status get_status() {
337
338         Status result = Status.StatusUnknown;
339
340         if (tranState != null) {
341
342             switch (tranState.state) {
343
344             // If active, return active or marked rollback-only
345
// if the flag is set.
346

347             case TransactionState.STATE_ACTIVE :
348                 if (rollbackOnly) {
349                     result = Status.StatusMarkedRollback;
350                 } else {
351                     result = Status.StatusActive;
352                 }
353                 break;
354
355             // If prepared, (successfully or otherwise), return prepared.
356
// If committing return prepared (may want to block in this case).
357

358             case TransactionState.STATE_PREPARED_SUCCESS :
359             case TransactionState.STATE_PREPARED_FAIL :
360             case TransactionState.STATE_PREPARED_READONLY :
361                 result = Status.StatusPrepared;
362                 break;
363
364             // If we have no internal state, return that fact.
365
// All of these states map directly to the OMG values.
366

367             case TransactionState.STATE_NONE :
368                 result = Status.StatusNoTransaction;
369                 break;
370             case TransactionState.STATE_PREPARING :
371                 result = Status.StatusPreparing;
372                 break;
373             case TransactionState.STATE_COMMITTING :
374                 result = Status.StatusCommitting;
375                 break;
376             case TransactionState.STATE_COMMITTED :
377                 result = Status.StatusCommitted;
378                 break;
379             case TransactionState.STATE_ROLLING_BACK :
380                 result = Status.StatusRollingBack;
381                 break;
382             case TransactionState.STATE_ROLLED_BACK :
383                 result = Status.StatusRolledBack;
384                 break;
385
386             // Any other state, return unknown.
387

388             default :
389                 result = Status.StatusUnknown;
390                 break;
391             }
392         } else {
393             INVALID_TRANSACTION exc = new INVALID_TRANSACTION(
394                 MinorCode.Completed, CompletionStatus.COMPLETED_NO);
395             throw exc;
396         }
397
398         return result;
399     }
400
401     /**
402      * Gets the local state of the parent transaction.
403      * This operation references no instance variables and so can be
404      * implemented locally in the proxy class.
405      *
406      * @param
407      *
408      * @return The parent transaction's status.
409      *
410      * @exception SystemException The parent could not be reached.
411      *
412      * @see
413      */

414     synchronized public Status get_parent_status() throws SystemException {
415
416         Status result = Status.StatusNoTransaction;
417
418         // Return the parents status. If there is none, this is an error;
419
// return no transaction status (may want to raise a LogicError here).
420

421         if (tranState != null) {
422             CoordinatorImpl parent = nestingInfo.getParent(false);
423             if (parent != null) {
424                 result = parent.get_status();
425             }
426         } else {
427             INVALID_TRANSACTION exc = new INVALID_TRANSACTION(
428                 MinorCode.Completed, CompletionStatus.COMPLETED_NO);
429             throw exc;
430         }
431
432         return result;
433     }
434
435     /**
436      * Gets the local state of the top-level transaction.
437      * This operation references no instance variables and so can be
438      * implemented locally in a proxy class.
439      *
440      * @param
441      *
442      * @return The top-level transaction status.
443      *
444      * @exception SystemException The top-level ancestor could not be reached.
445      *
446      * @see
447      */

448     synchronized public Status get_top_level_status() throws SystemException {
449
450         // Return the top-level status. If there is none, this is an error;
451
// return no transaction status (may want to raise a LogicError here).
452

453         Status result = Status.StatusNoTransaction;
454
455         if (tranState != null) {
456             CoordinatorImpl topLevel = nestingInfo.getTopLevel();
457             if (topLevel != null) {
458                 result = topLevel.get_status();
459             }
460         } else {
461             INVALID_TRANSACTION exc = new INVALID_TRANSACTION(
462                 MinorCode.Completed, CompletionStatus.COMPLETED_NO);
463             throw exc;
464         }
465
466         return result;
467     }
468
469     /**
470      * Compares the given Coordinator object with the target,
471      * and returns TRUE if they represent the same transaction.
472      * This operation needs to be implemented in an efficient manner, without
473      * any cross-process calls. This could be achieved by including the
474      * global identifier in the Coordinator references and comparing them.
475      * This operation references no instance variables and so can be
476      * implemented locally in a proxy class.
477      *
478      * @param other The other Coordinator to be compared.
479      *
480      * @return Indicates equality of the transactions the objects
481      * represent.
482      *
483      * @exception SystemException The other Coordinator could not be reached.
484      *
485      * @see
486      */

487     synchronized public boolean is_same_transaction(Coordinator other)
488             throws SystemException {
489
490         boolean result = false;
491
492         // Get the names of the two transactions and compare them.
493

494         if (name != null) {
495           result = name.equals(other.get_transaction_name());
496         } else {
497             INVALID_TRANSACTION exc = new INVALID_TRANSACTION(
498                 MinorCode.Completed, CompletionStatus.COMPLETED_NO);
499             throw exc;
500         }
501
502         return result;
503     }
504
505     /**
506      * Determines whether the target SubCoordinator is related to
507      * the given Coordinator (i.e. is a member of the same transaction family).
508      * For a subtransaction this is equivalent to saying that the transaction
509      * associated with the parameter object is a descendant of the top-level
510      * ancestor of the transaction associated with the target object.
511      * This operation references no instance variables and so can be
512      * implemented locally in a proxy class.
513      *
514      * @param other The other Coordinator.
515      *
516      * @return Indicates the relationship.
517      *
518      * @exception SystemException The other Coordinator could not be reached.
519      *
520      * @see
521      */

522     synchronized public boolean is_related_transaction(Coordinator other)
523             throws SystemException {
524
525         // Check whether the given transaction is a descendant of our top-level
526
// transaction.
527

528         boolean result = false;
529         if (tranState != null) {
530             CoordinatorImpl topLevel = nestingInfo.getTopLevel();
531             if (topLevel != null) {
532                 result = other.is_descendant_transaction(topLevel.object());
533             }
534         } else {
535             INVALID_TRANSACTION exc = new INVALID_TRANSACTION(
536                 MinorCode.Completed, CompletionStatus.COMPLETED_NO);
537             throw exc;
538         }
539
540         return result;
541     }
542
543     /**
544      * Determines whether the target SubCoordinator is an ancestor
545      * of the given Coordinator.
546      * This operation references no instance variables and so can be
547      * implemented locally in a proxy class.
548      *
549      * @param other The other Coordinator.
550      *
551      * @return Indicates the relationship.
552      *
553      * @exception SystemException The other Coordinator could not be reached.
554      *
555      * @see
556      */

557     public boolean is_ancestor_transaction(Coordinator other)
558             throws SystemException {
559
560         boolean result = false;
561         if (tranState != null) {
562             result = other.is_descendant_transaction(this.object());
563         } else {
564             INVALID_TRANSACTION exc = new INVALID_TRANSACTION(
565                 MinorCode.Completed, CompletionStatus.COMPLETED_NO);
566             throw exc;
567         }
568
569         return result;
570     }
571
572     /**
573      * Determines whether the target SubCoordinator is a descendant
574      * of the given Coordinator.
575      * This operation references no instance variables and so can be
576      * implemented locally in a proxy class.
577      *
578      * @param other The other Coordinator.
579      *
580      * @return Indicates the relationship.
581      *
582      * @exception SystemException The other Coordinator could not be reached.
583      *
584      * @see
585      */

586     synchronized public boolean is_descendant_transaction(Coordinator other)
587             throws SystemException {
588
589         // A transaction is considered to be a descendant of itself, so if the
590
// two transactions are the same, return TRUE.
591

592         boolean result = false;
593         if (tranState != null) {
594             if (is_same_transaction(other)) {
595                 result = true;
596             } else {
597             // Otherwise, go through our ancestors, comparing
598
// them with the given transaction.
599
result = nestingInfo.isDescendant(other);
600             }
601         } else {
602             INVALID_TRANSACTION exc = new INVALID_TRANSACTION(
603                 MinorCode.Completed, CompletionStatus.COMPLETED_NO);
604             throw exc;
605         }
606
607         return result;
608     }
609
610     /**
611      * Determines whether the target SubCoordinator represents a top-level
612      * (non-nested) transaction.
613      * <p>
614      * For a subtransaction returns FALSE.
615      * <p>
616      * This operation references no instance variables and so can be
617      * implemented locally in a proxy class.
618      *
619      * @param
620      *
621      * @return Indicates the transaction is top-level.
622      *
623      * @see
624      */

625     public boolean is_top_level_transaction() {
626
627         boolean result = false;
628         if (tranState == null) {
629             INVALID_TRANSACTION exc = new INVALID_TRANSACTION(
630                 MinorCode.Completed, CompletionStatus.COMPLETED_NO);
631             throw exc;
632         }
633
634         return result;
635     }
636
637     /**
638      * Returns a hash value based on the transaction associated with the target
639      * object.
640      *
641      * @param
642      *
643      * @return The hash value for the transaction.
644      *
645      * @see
646      */

647     synchronized public int hash_transaction() {
648
649         int result = hash;
650
651         if (tranState == null) {
652             INVALID_TRANSACTION exc = new INVALID_TRANSACTION(
653                 MinorCode.Completed, CompletionStatus.COMPLETED_NO);
654             throw exc;
655         }
656
657         return result;
658     }
659
660     /**
661      * Returns a hash value based on the top-level ancestor of the transaction
662      * associated with the target object.
663      *
664      * @param
665      *
666      * @return The hash value for the top-level ancestor.
667      *
668      * @exception SystemException The other Coordinator could not be reached.
669      *
670      * @see
671      */

672     synchronized public int hash_top_level_tran() throws SystemException {
673
674         int result = 0;
675         if (tranState != null) {
676             CoordinatorImpl topLevel = nestingInfo.getTopLevel();
677             if (topLevel != null) {
678                 result = topLevel.hash_transaction();
679             }
680         } else {
681             INVALID_TRANSACTION exc = new INVALID_TRANSACTION(
682                 MinorCode.Completed, CompletionStatus.COMPLETED_NO);
683             throw exc;
684         }
685
686         return result;
687     }
688
689     /**
690      * Enables a Resource to be registered as a participant in the completion
691      * of the subtransaction represented by the SubCoordinator.
692      * If the Resource is a SubtransactionAwareResource, it is registered
693      * with the SubCoordinator; if the SubCoordinator has not registered
694      * with is superior, it creates a CoordinatorResource and registers it
695      * with the superior. The registration is passed on to the top-level
696      * Coordinator in any case.
697      *
698      * @param res The Resource to be registered.
699      *
700      * @return The RecoveryCoordinator object from the
701      * registration with the top-level ancestor.
702      *
703      * @exception Inactive The Coordinator is completing the transaction and
704      * cannot accept this registration.
705      * @exception TRANSACTION_ROLLEDBACK The transaction which the Coordinator
706      * represents has already been rolled back, or been marked
707      * rollback-only.
708      * @exception SystemException The operation failed.
709      *
710      * @see
711      */

712     synchronized public RecoveryCoordinator register_resource(Resource res)
713             throws SystemException, Inactive, TRANSACTION_ROLLEDBACK {
714
715         RecoveryCoordinator result = null;
716
717         // First check the state of the transaction. If it is not active,
718
// do not allow the registration.
719

720         if (tranState == null ||
721                 tranState.state != TransactionState.STATE_ACTIVE) {
722             Inactive exc = new Inactive();
723             throw exc;
724         }
725
726         // Check whether the transaction has been marked rollback-only.
727

728         if (rollbackOnly) {
729             TRANSACTION_ROLLEDBACK exc =
730                 new TRANSACTION_ROLLEDBACK(0,CompletionStatus.COMPLETED_NO);
731             throw exc;
732         }
733
734         // Register the given Resource with the top-level
735
// Coordinator first, and remember the RecoveryCoordinator object
736
// that is returned by the top-level Coordinator.
737

738         CoordinatorImpl topLevel = nestingInfo.getTopLevel();
739
740         // If the top-level Coordinator raises an exception, then do not
741
// proceed with the registration, and return the exception.
742

743         try {
744             result = topLevel.register_resource(res);
745         } catch (SystemException exc) {
746             throw (SystemException) exc.fillInStackTrace();
747         } catch (Inactive exc) {
748             throw (Inactive) exc.fillInStackTrace();
749         }
750
751         // Find out whether the Resource is actually a
752
// SubtransactionAwareResource.
753

754         boolean subAwareRes =
755             res._is_a(SubtransactionAwareResourceHelper.id());
756
757         // If the Resource is actually a SubtransactionAwareResource,
758
// then it needs to be registered for participation in completion
759
// of the subtransaction as well as the top level transaction.
760

761         if (subAwareRes) {
762
763             // If not previously registered, a CoordinatorResource object
764
// must be registered with our superior. Note that root
765
// SubCoordinators are created with the registration flag set,
766
// so we do not need to check
767
// whether we are the root SubCoordinator here.
768

769             if (!registered) {
770
771                 // Initialise the CoordinatorResource with the local id,
772
// our reference, and a flag to indicate that it does
773
// not represent a subtransaction.
774

775                 CoordinatorResourceImpl cImpl =
776                     new CoordinatorResourceImpl(superInfo.globalTID,
777                                                 this, true);
778
779                 // Register the CoordinatorResource with superior Coordinator,
780
// and store the resulting RecoveryCoordinator reference.
781

782                 try {
783                     CoordinatorResource cRes = cImpl.object();
784                     superInfo.superior.register_subtran_aware(cRes);
785                     superInfo.setResource(cRes);
786                     registered = true;
787                 } catch (Throwable JavaDoc exc) {
788                     // If an exception was raised, do not set the
789
// registration flag, and destroy the object.
790
cImpl.destroy();
791
792                     // If the exception is a system exception,
793
// then allow it to percolate to the caller.
794

795                     if (exc instanceof OBJECT_NOT_EXIST) {
796                         TRANSACTION_ROLLEDBACK ex2 =
797                             new TRANSACTION_ROLLEDBACK(
798                                 0, CompletionStatus.COMPLETED_NO);
799                         throw ex2;
800                     }
801
802                     if (exc instanceof Inactive) {
803                         throw (Inactive) exc;
804                     }
805
806                     if (exc instanceof SystemException) {
807                         throw (SystemException) exc;
808                     }
809
810                     // Otherwise throw an internal exception.
811

812                     INTERNAL ex2 = new INTERNAL(MinorCode.NotRegistered,
813                                                 CompletionStatus.COMPLETED_NO);
814                     throw ex2;
815                 }
816             }
817
818             // Add the SubtransactionAwareResource to the set of participants.
819
// Make sure the RegisteredResources instance variable has been
820
// set up.
821

822             if (participants == null) {
823                 participants = new RegisteredResources(null, this);
824             }
825
826             // Add a duplicate of the reference to the set. This is done
827
// because if the registration is for a remote object, the proxy
828
// will be freed when the registration request returns.
829

830             participants.addRes((Resource)res._duplicate());
831             temporary = false;
832         }
833
834         return result;
835     }
836
837     /**
838      * Enables a SubtransactionAwareResource to be registered as a participant
839      * in the completion of a subtransaction.
840      * <p>
841      * If the SubCoordinator has not registered with is superior, it creates a
842      * CoordinatorResource and registers it with the superior.
843      *
844      * @param sares The SubtransactionAwareResource to be registered.
845      *
846      * @return
847      *
848      * @exception Inactive The Coordinator is completing the transaction and
849      * cannot accept this registration.
850      * @exception TRANSACTION_ROLLEDBACK The transaction which the Coordinator
851      * represents has already been rolled back, or has been marked
852      * rollback-only.
853      * @exception SystemException The operation failed.
854      *
855      * @see
856      */

857     synchronized public void register_subtran_aware(
858             SubtransactionAwareResource sares)
859             throws SystemException, Inactive, TRANSACTION_ROLLEDBACK {
860
861         // First check the state of the transaction. If it is not active,
862
// do not allow the registration.
863

864         if (tranState == null ||
865                 tranState.state != TransactionState.STATE_ACTIVE) {
866             Inactive exc = new Inactive();
867             throw exc;
868         }
869
870         // Check whether the transaction has been marked rollback-only.
871

872         if (rollbackOnly) {
873             TRANSACTION_ROLLEDBACK exc =
874                 new TRANSACTION_ROLLEDBACK(0, CompletionStatus.COMPLETED_NO);
875             throw exc;
876         }
877
878         // If not previously registered, a CoordinatorResource object must be
879
// registered with our superior. Note that root SubCoordinators
880
// are created with the registration flag set, so we do not need
881
// to check whether we are the root SubCoordinator here.
882

883         if (!registered) {
884
885             // Initialise the CoordinatorResource with the local id,
886
// our reference, and a
887
// flag to indicate that it does not represent a subtransaction.
888

889             CoordinatorResourceImpl cImpl =
890                 new CoordinatorResourceImpl(superInfo.globalTID, this, true);
891
892             // Register the CoordinatorResource with the superior Coordinator,
893
// and store the resulting RecoveryCoordinator reference.
894

895             try {
896                 CoordinatorResource cRes = cImpl.object();
897                 superInfo.superior.register_subtran_aware(cRes);
898                 superInfo.setResource(cRes);
899                 registered = true;
900             } catch(Throwable JavaDoc exc) {
901                 // If an exception was raised, do not set the registration flag.
902
cImpl.destroy();
903
904                 // If the exception is a system exception, then allow
905
// it to percolate to the caller.
906

907                 if (exc instanceof OBJECT_NOT_EXIST) {
908                     TRANSACTION_ROLLEDBACK ex2 =
909                         new TRANSACTION_ROLLEDBACK(
910                             0, CompletionStatus.COMPLETED_NO);
911                     throw ex2;
912                 }
913
914                 if (exc instanceof Inactive) {
915                     throw (Inactive) exc;
916                 }
917
918                 if (exc instanceof SystemException) {
919                     throw (SystemException) exc;
920                 }
921
922                 // Otherwise throw an internal exception.
923

924                 INTERNAL ex2 = new INTERNAL(MinorCode.NotRegistered,
925                                             CompletionStatus.COMPLETED_NO);
926                 throw ex2;
927             }
928         }
929
930         // Add the SubtransactionAwareResource to the set of participants.
931
// Make sure the RegisteredResources instance variable has been set up.
932

933         if (participants == null) {
934             participants = new RegisteredResources(null, this);
935         }
936
937         // Add a duplicate of the reference to the set.
938
// This is done because if the registration is for a remote
939
// object, the proxy will be freed when the
940
// registration request returns.
941

942         participants.addRes((Resource)sares._duplicate());
943         temporary = false;
944     }
945
946     /**
947      * Ensures that the transaction represented by the target SubCoordinator
948      * cannot be committed.
949      *
950      * @param
951      *
952      * @return
953      *
954      * @exception Inactive The Coordinator is already completing the
955      * transaction.
956      * @see
957      */

958     synchronized public void rollback_only() throws Inactive {
959
960         if (tranState.state != TransactionState.STATE_ACTIVE) {
961             Inactive exc = new Inactive();
962             throw exc;
963         } else {
964             // Set the rollback-only flag.
965
rollbackOnly = true;
966         }
967     }
968
969     /**
970      * Returns a printable string that represents the SubCoordinator.
971      * This operation references only the global TID, and so can be
972      * implemented locally in a proxy class.
973      *
974      * @param
975      *
976      * @return The transaction name.
977      *
978      * @see
979      */

980     synchronized public String JavaDoc get_transaction_name() {
981
982         String JavaDoc result = null;
983         if (tranState != null) {
984             result = new String JavaDoc(name);
985         } else {
986             INVALID_TRANSACTION exc = new INVALID_TRANSACTION(
987                                         MinorCode.Completed,
988                                         CompletionStatus.COMPLETED_NO);
989
990             throw exc;
991         }
992
993         return result;
994     }
995
996     /**
997      * Creates a subtransaction and returns a Control object that
998      * represents the child transaction.
999      *
1000     * @param
1001     *
1002     * @return The Control object for the new child transaction.
1003     *
1004     * @exception Inactive The Coordinator is completing the
1005     * subtransaction and cannot create a new child.
1006     *
1007     * @see
1008     */

1009    synchronized public Control create_subtransaction() throws Inactive {
1010
1011        Control result = null;
1012
1013        // First check the state of the transaction. If it is not active,
1014
// do not allow the subtransaction to be created.
1015

1016        if (tranState == null ||
1017                tranState.state != TransactionState.STATE_ACTIVE) {
1018            Inactive exc = new Inactive();
1019            throw exc;
1020        }
1021
1022        // Set up the sequence of ancestors to hold the single reference
1023
// and global identifier of the top-level SubCoordinator
1024
// as there are no ancestors. We do not need to make a copy of the
1025
// global TID as this is done by the factory when it creates the child.
1026

1027        CoordinatorImpl[] thisAncestors = nestingInfo.getAncestors();
1028        CoordinatorImpl[] ancestors =
1029            new CoordinatorImpl[thisAncestors.length + 1];
1030        System.arraycopy(thisAncestors, 0, ancestors, 1, thisAncestors.length);
1031        ancestors[0] = this;
1032
1033        // Create a new SubCoordinator, and initialise it with the given
1034
// identifiers and ancestry. If the operation fails, return a
1035
// NULL Control object, and the SubtransactionsUnavailable exception.
1036
// Note that the ancestor sequence is not copied by the creation
1037
// operation.
1038

1039        SubCoordinator child = null;
1040        TerminatorImpl terminator = null;
1041        try {
1042            child = new SubCoordinator(superInfo.globalTID,
1043                                       superInfo.localTID, ancestors);
1044
1045            // Create a Terminator object, and initialise it with
1046
// the SubCoordinator reference and a flag to indicate that
1047
// it represents a subtransaction.
1048

1049            terminator = new TerminatorImpl(child, true);
1050
1051            // Create a Control object, and initialise it with the Terminator,
1052
// SubCoordinator and global OMGtid.
1053

1054            result = new ControlImpl(terminator, child,
1055                                     new GlobalTID(child.getGlobalTID()),
1056                                     new Long JavaDoc(child.getLocalTID())).object();
1057        } catch (Throwable JavaDoc exc) {
1058            Inactive ex2 = new Inactive();
1059            throw ex2;
1060        }
1061
1062        // If the operation succeeded, add the new child
1063
// to the set of children.
1064

1065        nestingInfo.addChild(child);
1066
1067        return result;
1068    }
1069
1070    /**
1071     * Returns a global identifier that represents the SubCoordinator's
1072     * transaction. <p>
1073     * This operation references only the global identifier, and so can be
1074     * implemented locally in a proxy class.
1075     * <p>
1076     * This method is currently not synchronized because that causes a
1077     * deadlock in resync. I don't think this is a problem as the global
1078     * identifier is allocated in the constructor and then never changes.
1079     *
1080     * @param
1081     *
1082     * @return The global identifier for the transaction.
1083     *
1084     * @see
1085     */

1086    public otid_t getGlobalTID() {
1087
1088        otid_t result = null;
1089        result = superInfo.globalTID.realTID;
1090
1091        return result;
1092    }
1093
1094    /**
1095     * Returns the internal identifier for the transaction.
1096     * This method is currently not synchronized because that causes a deadlock
1097     * in resync.
1098     *
1099     * @param
1100     *
1101     * @return The local transaction identifier.
1102     *
1103     * @see
1104     */

1105    public long getLocalTID() {
1106
1107        long result = superInfo.localTID.longValue();
1108        return result;
1109    }
1110
1111    /**
1112     * Indicates that a method reply is being sent and requests the
1113     * SubCoordinator's action.
1114     * If the Coordinator has active children, which are not registered with
1115     * their superior (includes root Coordinators) then this method returns
1116     * activeChildren.
1117     * If it has already been registered, the method returns doNothing.
1118     * Otherwise the SubCoordinator returns forgetMe.
1119     *
1120     * @param action A 1-element array to hold the reply action.
1121     *
1122     * @return The parent coordinator if any.
1123     *
1124     * @exception SystemException An error occurred. The minor code indicates
1125     * the reason for the exception.
1126     *
1127     * @see
1128     */

1129    synchronized CoordinatorImpl replyAction(int[/*1*/] action)
1130            throws SystemException {
1131
1132        CoordinatorImpl result = null;
1133        action[0] = CoordinatorImpl.doNothing;
1134
1135        // If this Coordinator is not a root, and there are active children,
1136
// report that fact to the caller. If the NestingInfo instance
1137
// variable has not been set up, there are no children.
1138

1139        if (!root && nestingInfo.replyCheck()) {
1140          action[0] = CoordinatorImpl.activeChildren;
1141
1142        // If there are no active children, then check whether this
1143
// transaction needs to be destroyed, or registered on reply.
1144

1145        } else {
1146
1147            // If there are participants, and we have not registered,
1148
// raise an exception.
1149

1150            if (!registered) {
1151                if (participants != null && participants.involved()) {
1152                    INTERNAL ex2 = new INTERNAL(MinorCode.NotRegistered,
1153                                                CompletionStatus.COMPLETED_NO);
1154                    throw ex2;
1155                } else {
1156                    action[0] = forgetMe;
1157                }
1158            }
1159
1160            // If we are not registered, and have no participants,
1161
// we have no reason to exist, so tell the caller to
1162
// forget about us. The TransactionManager will take care of
1163
// cleaning everything else up whenit receives the forgetMe
1164
// response.
1165

1166            if (action[0] == doNothing && !registered)
1167                action[0] = forgetMe;
1168        }
1169
1170        // Default action is do nothing when we are registered.
1171

1172        result = null;
1173
1174        return result;
1175    }
1176
1177    /**
1178     * Marks the SubCoordinator as permanent.
1179     *
1180     * @param
1181     *
1182     * @return The local transaction identifier.
1183     *
1184     * @see
1185     */

1186    synchronized Long JavaDoc setPermanent() {
1187
1188        Long JavaDoc result = superInfo.localTID;
1189        temporary = false;
1190
1191        return result;
1192    }
1193
1194    /**
1195     * Checks whether the SubCoordinator is marked rollback-only.
1196     *
1197     * @param
1198     *
1199     * @return Indicates whether the transaction is rollback-only.
1200     *
1201     * @see
1202     */

1203    synchronized public boolean isRollbackOnly() {
1204
1205        boolean result = rollbackOnly;
1206        return result;
1207    }
1208
1209    /**
1210     * Checks whether the SubCoordinator is active.
1211     *
1212     * @param
1213     *
1214     * @return Indicates the transaction is active.
1215     *
1216     * @see
1217     */

1218    synchronized boolean isActive() {
1219
1220        boolean result = (tranState.state == TransactionState.STATE_ACTIVE);
1221        return result;
1222    }
1223
1224    /**
1225     * Checks whether the SubCoordinator has registered with its superior.
1226     *
1227     * @param
1228     *
1229     * @return Indicates the registration status.
1230     *
1231     * @see
1232     */

1233    synchronized boolean hasRegistered() {
1234
1235        boolean result = registered;
1236        return result;
1237    }
1238
1239    /**
1240     * Returns the sequence of ancestors of the transaction.
1241     *
1242     * @param
1243     *
1244     * @return The sequence of ancestors.
1245     *
1246     * @see
1247     */

1248    synchronized public TransIdentity[] getAncestors() {
1249
1250        CoordinatorImpl[] coords = nestingInfo.getAncestors();
1251
1252        TransIdentity[] result = new TransIdentity[coords.length];
1253        for (int i = 0; i < coords.length; i++) {
1254            try {
1255                result[i] = new TransIdentity(coords[i].object(), null,
1256                                              coords[i].getGlobalTID());
1257            } catch (Throwable JavaDoc exc) {}
1258        }
1259
1260        return result;
1261    }
1262
1263    /**
1264     * Adds the given Coordinator reference to the set of children
1265     * of the target SubCoordinator.
1266     *
1267     * @param child The child Coordinator.
1268     *
1269     * @return Indicates success of the operation.
1270     *
1271     * @see
1272     */

1273    synchronized boolean addChild(CoordinatorImpl child) {
1274
1275        boolean result = nestingInfo.addChild(child);
1276        return result;
1277    }
1278
1279    /**
1280     * Removes the given Coordinator from the set of children of the target
1281     * SubCoordinator.
1282     * If the SubCoordinator is a temporary ancestor, and has no
1283     * recoverable state after the child is removed, it destroys itself.
1284     *
1285     * @param child The child Coordinator.
1286     *
1287     * @return Indicates success of the operation.
1288     *
1289     * @see
1290     */

1291    synchronized boolean removeChild(CoordinatorImpl child) {
1292
1293        boolean result = false;
1294
1295        // Remove the child from the set of children. If the NestingInfo
1296
// instance variable has not been set up, then the child
1297
// cannot be removed.
1298

1299        result = nestingInfo.removeChild(child);
1300
1301        // If the removal results in an empty, temporary Coordinator, then this
1302
// Coordinator must be cleaned up. The RecoveryManager is called to
1303
// clean up the transaction.
1304

1305        if (temporary && !registered &&
1306                !(participants != null && participants.involved()) &&
1307                !(nestingInfo != null && nestingInfo.numChildren() > 0)) {
1308
1309            // We pass the parent Coordinator to the RecoveryManager
1310
// so that it can remove the child from the parent's set of
1311
// children after the child is rolled back.
1312

1313            CoordinatorImpl parent = nestingInfo.getParent(true);
1314            cleanUpEmpty(parent);
1315        }
1316
1317        return result;
1318    }
1319
1320    /**
1321     * Directs the SubCoordinator to prepare to commit.
1322     * The SubCoordinator checks that the subtransaction can be committed.
1323     * It does not distribute prepare operations to the participants.
1324     *
1325     * @param
1326     *
1327     * @return The consolidated vote.
1328     *
1329     * @exception INVALID_TRANSACTION The transaction is not in a
1330     * state to commit, due to outstanding work.
1331     *
1332     * @see
1333     */

1334    static String JavaDoc[] resultName = { "Commit"/*#Frozen*/, "Rollback"/*#Frozen*/, "Read-only"/*#Frozen*/ };
1335
1336    synchronized Vote prepare() throws INVALID_TRANSACTION {
1337
1338        Vote result = Vote.VoteRollback;
1339        int newState = TransactionState.STATE_PREPARED_FAIL;
1340
1341        // Record that the Coordinator is about to prepare.
1342

1343        // First check for active children, before getting too far
1344
// into the prepare. This is only done for the root Coordinator
1345
// as for any others it is too late.
1346

1347        if (root && nestingInfo.numChildren() != 0) {
1348            INVALID_TRANSACTION exc =
1349                new INVALID_TRANSACTION(MinorCode.UnfinishedSubtransactions,
1350                                        CompletionStatus.COMPLETED_NO);
1351                throw exc;
1352        }
1353
1354        // If the SubCoordinator is in the wrong state, return immediately.
1355

1356        if (!tranState.setState(TransactionState.STATE_PREPARING)) {
1357            return Vote.VoteRollback;
1358        }
1359
1360        // Check for marked rollback-only.
1361

1362        if (rollbackOnly) {
1363
1364            // Record that the Coordinator is deciding to rollback.
1365
// Try to set the state to prepared fail.
1366

1367            if (!tranState.setState(TransactionState.STATE_PREPARED_FAIL)) {
1368                return Vote.VoteRollback;
1369            }
1370        } else {
1371            newState = TransactionState.STATE_PREPARED_SUCCESS;
1372            result = Vote.VoteCommit;
1373        }
1374
1375        // Record that prepare is complete.
1376
// Set the state.
1377

1378        if (!tranState.setState(newState)) {
1379            result = Vote.VoteRollback;
1380        }
1381
1382        return result;
1383    }
1384
1385    /**
1386     * Directs the SubCoordinator to commit the transaction.
1387     * The SubCoordinator directs all registered Resources to commit.
1388     *
1389     * @param
1390     *
1391     * @return
1392     *
1393     * @see
1394     */

1395    void commit() {
1396
1397        Coordinator parent = null;
1398
1399        // Record that the Coordinator is about to commit.
1400
// Until we actually distribute commit flows, synchronize the method.
1401

1402        synchronized (this) {
1403
1404            // If the SubCoordinator is in the wrong state, return immediately.
1405

1406            if (!tranState.setState(TransactionState.STATE_COMMITTING)) {
1407                    _logger.log(Level.SEVERE,"jts.transaction_wrong_state",
1408                            "commit");
1409                     String JavaDoc msg = LogFormatter.getLocalizedMessage(_logger,
1410                                            "jts.transaction_wrong_state",
1411                                            new java.lang.Object JavaDoc[] {
1412                                            "commit"});
1413                     throw new org.omg.CORBA.INTERNAL JavaDoc(msg);
1414            }
1415
1416            // Get the reference of the parent Coordinator.
1417

1418            parent = nestingInfo.getParent(false).object();
1419
1420            // Release the lock before proceeding with commit.
1421

1422        }
1423
1424        // Commit all participants. If a fatal error occurs during this
1425
// method, then the process must be ended with a fatal error.
1426

1427        if (participants != null) {
1428            try {
1429                participants.distributeSubcommit(parent);
1430            } catch (Throwable JavaDoc exc) {
1431                _logger.log(Level.SEVERE,"jts.exception_on_resource_operation",
1432                        new java.lang.Object JavaDoc[] { exc.toString(),
1433                        "commit"});
1434                 String JavaDoc msg = LogFormatter.getLocalizedMessage(_logger,
1435                                            "jts.exception_on_resource_operation",
1436                                            new java.lang.Object JavaDoc[]
1437                                            {exc.toString(),
1438                                            "commit"});
1439                 throw new org.omg.CORBA.INTERNAL JavaDoc(msg);
1440            }
1441        }
1442
1443        // The remainder of the method needs to be synchronized.
1444

1445        synchronized (this) {
1446
1447            // Record that objects have been told to commit.
1448
// Set the state
1449

1450            if (!tranState.setState(TransactionState.STATE_COMMITTED)) {
1451                    _logger.log(Level.SEVERE,"jts.transaction_wrong_state",
1452                            "commit");
1453                     String JavaDoc msg = LogFormatter.getLocalizedMessage(_logger,
1454                                            "jts.transaction_wrong_state",
1455                                            new java.lang.Object JavaDoc[] {
1456                                            "commit"});
1457                     throw new org.omg.CORBA.INTERNAL JavaDoc(msg);
1458            }
1459
1460            // Remove our reference from the parents set of children
1461

1462            nestingInfo.removeFromParent(this);
1463
1464            // Clean up the SubCoordinator after a commit.
1465
// In the case where the SubCoordinator is a root,
1466
// the CoordinatorTerm object must be informed that the
1467
// transaction has completed so that if another
1468
// caller has committed the transaction the object
1469
// normally responsible for terminating the transaction
1470
// can take the appropriate action. NOTE: This may DESTROY
1471
// the SubCoordinator object so NO INSTANCE VARIABLES
1472
// should be referenced after the call.
1473
// In the case where the SubCoordinator is a subordinate, the
1474
// CoordinatorResource object must be informed that the transaction
1475
// has been completed so that it can handle any subsequent requests
1476
// for the transaction.
1477

1478            if (terminator != null) {
1479                terminator.setCompleted(false, false);
1480            }
1481
1482            // As subtransactions do not have synchronization,
1483
// there is nothing left to do, so get the
1484
//RecoveryManager to forget about us, then self-destruct.
1485

1486            RecoveryManager.removeCoordinator(superInfo.globalTID,
1487                                              superInfo.localTID, false);
1488            destroy();
1489
1490            /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
1491            /* NO INSTANCE VARIABLES MAY BE ACCESSED FROM THIS POINT ON. */
1492            /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
1493
1494        }
1495    }
1496
1497    /**
1498     * Directs the SubCoordinator to roll back the transaction.
1499     * The SubCoordinator directs all registered Resources to rollback.
1500     *
1501     * @param force
1502     *
1503     * @return
1504     *
1505     * @see
1506     */

1507    void rollback(boolean force) {
1508
1509        // Until we actually distribute rollback flows, synchronize the method.
1510

1511        synchronized (this) {
1512
1513            // If the transaction has already been rolled back, just return.
1514

1515            if (tranState == null) {
1516                return;
1517            }
1518
1519            // If this is not a forced rollback and the
1520
// coordinator has prepared or is in an
1521
// inappropriate state, do not continue and return FALSE.
1522

1523            if (!force &&
1524                    ((tranState.state ==
1525                        TransactionState.STATE_PREPARED_SUCCESS) ||
1526                     (!tranState.setState(TransactionState.STATE_ROLLING_BACK))
1527                    )) {
1528                return;
1529            }
1530
1531            // We do not care about invalid state changes as we are
1532
// rolling back anyway. If the SubCoordinator is temporary,
1533
// we do not change state as this would
1534
// cause a log force in a subordinate, which is not required.
1535

1536            if (!temporary &&
1537                    !tranState.setState(TransactionState.STATE_ROLLING_BACK)) {
1538                // empty
1539
}
1540
1541            // Rollback outstanding children. If the NestingInfo instance
1542
// variable has not been created, there are no children
1543
// to roll back.
1544

1545            if (nestingInfo != null) {
1546                nestingInfo.rollbackFamily();
1547            }
1548
1549            // Release the lock before proceeding with rollback.
1550

1551        }
1552
1553        // Roll back all participants. If a fatal error occurs during
1554
// this method, then the process must be ended with a fatal error.
1555

1556        if (participants != null) {
1557            participants.distributeSubrollback();
1558        }
1559
1560        // The remainder of the method needs to be synchronized.
1561

1562        synchronized(this) {
1563
1564            // Set the state to rolled back.
1565

1566            // Remove our reference from the parents set of children
1567
if (!temporary &&
1568                    !tranState.setState(TransactionState.STATE_ROLLED_BACK)) {
1569                // empty
1570
}
1571
1572            nestingInfo.removeFromParent(this);
1573
1574            // Clean up the SubCoordinator after a rollback.
1575
// In the case where the SubCoordinator is a root,
1576
// the CoordinatorTerm object must be informed that
1577
// the transaction has completed so that if another caller has
1578
// rolled back the transaction (time-out for example) the object
1579
// normally responsible for terminating the transaction can
1580
// take the appropriate action.
1581
// NOTE: This may DESTROY the SubCoordinator object
1582
// so NO INSTANCE VARIABLES should be referenced after the call.
1583
// In the case where the SubCoordinator is a subordinate, the
1584
// CoordinatorResource object must be informed that the transaction
1585
// has been completed so that it can handle any subsequent
1586
// requests for the transaction.
1587

1588            if (terminator != null) {
1589                terminator.setCompleted(true, false);
1590            }
1591
1592            // As subtransactions do not have synchronization,
1593
// there is nothing left to do, so get the RecoveryManager
1594
// to forget about us, then self-destruct.
1595

1596            RecoveryManager.removeCoordinator(superInfo.globalTID,
1597                                              superInfo.localTID, false);
1598
1599            if (!dying) {
1600                destroy();
1601            }
1602
1603            /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
1604            /* NO INSTANCE VARIABLES MAY BE ACCESSED FROM THIS POINT ON. */
1605            /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
1606        }
1607    }
1608
1609    /**
1610     * Informs the SubCoordinator that the given object
1611     * requires synchronization before and after completion
1612     * of the top-level ancestor transaction.
1613     * The registration is passed directly to the top-level ancestor.
1614     *
1615     * @param sync The Synchronization object to be registered.
1616     *
1617     * @return
1618     *
1619     * @exception Inactive The Coordinator is in the process of completing the
1620     * transaction and cannot accept this registration.
1621     * @exception SynchronizationUnavailable The transaction service
1622     * cannot support synchronization.
1623     *
1624     * @see
1625     */

1626    synchronized public void register_synchronization(Synchronization sync)
1627            throws Inactive, SynchronizationUnavailable {
1628
1629        // First check the state of the transaction. If it is not active,
1630
// do not allow the registration.
1631

1632        if (tranState == null ||
1633                tranState.state != TransactionState.STATE_ACTIVE) {
1634              Inactive exc = new Inactive();
1635              throw exc;
1636          }
1637
1638        // Register the Synchronization object with the top-level Coordinator.
1639
// Allow any exception to percolate to the caller.
1640

1641        CoordinatorImpl topLevel = nestingInfo.getTopLevel();
1642        topLevel.register_synchronization(sync);
1643    }
1644
1645    /**
1646     * Informs the SubCoordinator of the identity of the
1647     * object that is normally responsible for directing
1648     * it through termination. The CoordinatorTerm/
1649     * CoordinatorResource object is informed by the Coordinator when the
1650     * transaction aborts so that they can cope with asynchronous aborts.
1651     *
1652     * @param term The object normally responsible for terminating the
1653     * Coordinator.
1654     *
1655     * @return
1656     *
1657     * @see
1658     */

1659    synchronized void setTerminator(CompletionHandler term) {
1660        terminator = term;
1661    }
1662
1663    /**
1664     * Gets the parent coordinator of the transaction.
1665     *
1666     * @param
1667     *
1668     * @return The parent Coordinator
1669     *
1670     * @see
1671     */

1672    Coordinator getParent() {
1673
1674        Coordinator result = nestingInfo.getParent(false).object();
1675        return result;
1676    }
1677
1678    /**
1679     * Gets the superior Coordinator for this transaction.
1680     *
1681     * @param
1682     *
1683     * @return The superior Coordinator
1684     *
1685     * @see
1686     */

1687    Coordinator getSuperior() {
1688
1689        Coordinator result = superInfo.superior;
1690        return result;
1691    }
1692
1693   /**
1694    * Returns the Resource objects and their states.
1695    *
1696    * @param resources The object which will contain the Resources
1697    * @param states The object which will contain the states.
1698    *
1699    * @return
1700    *
1701    * @see
1702    */

1703    /* COMMENT(Ram J) only Admin package needs this.
1704    public void getResources(ResourceSequenceHolder resources,
1705            ResourceStatusSequenceHolder states) {
1706
1707        if (participants != null) {
1708            participants.getResources(resources, states);
1709
1710            // Validate each of the Resource objects in
1711            // the list before returning it.
1712
1713            for (int i = 0; i < resources.value.length; i++) {
1714                if (resources.value[i]._non_existent()) {
1715                    resources.value[i] = null;
1716                }
1717            }
1718        } else {
1719            resources.value = null;
1720            states.value = null;
1721        }
1722    }
1723    */

1724    
1725    /**
1726     * Gets the object normally responsible for terminating this Coordinator.
1727     *
1728     * @param
1729     *
1730     * @return The object normally responsible for terminating
1731     * the Coordinator.
1732     *
1733     * @see
1734     */

1735    CompletionHandler getTerminator() {
1736
1737        CompletionHandler result = terminator;
1738        return result;
1739    }
1740
1741    private static Any emptyData = null;
1742
1743    /**
1744     * Creates a PropagationContext which contains the information which would
1745     * normally be passed implicitly via the CosTSPropagation interfaces.
1746     *
1747     * @param
1748     *
1749     * @return The transaction context.
1750     *
1751     * @exception Inactive The Coordinator is in the process of completing the
1752     * transaction and cannot return the information.
1753     *
1754     * @see
1755     */

1756    synchronized public PropagationContext get_txcontext() throws Unavailable {
1757
1758        // First check the state of the transaction. If it is not active,
1759
// do not allow the operation.
1760

1761        if (tranState == null ||
1762                tranState.state != TransactionState.STATE_ACTIVE ||
1763                rollbackOnly) {
1764            Unavailable exc = new Unavailable();
1765            throw exc;
1766        }
1767
1768        // Work out the timeout value to pass, if any.
1769
// Note that only top-level transactions have timeouts.
1770
// We do not check for timeouts if the Coordinator is remote.
1771
// If the Coordinator does not have a timeout defined, the
1772
// TimeoutManager will return a negative value.
1773
// If the transaction has timed out, the value will be
1774
// zero.
1775

1776        long timeLeft = TimeoutManager.timeLeft(superInfo.localTID);
1777        int timeout = 0;
1778        if (timeLeft > 0) {
1779          timeout = (int) timeLeft / 1000;
1780        } else if (timeLeft == 0) {
1781            // If the timeout has expired, then do not return a context,
1782
// but roll the transaction back and throw
1783
// the TRANSACTION_ROLLEDBACK exception.
1784

1785            TimeoutManager.timeoutCoordinator(superInfo.localTID,
1786                                              TimeoutManager.ACTIVE_TIMEOUT);
1787            TRANSACTION_ROLLEDBACK exc =
1788                new TRANSACTION_ROLLEDBACK(0,CompletionStatus.COMPLETED_NO);
1789            throw exc;
1790        }
1791
1792        // Fill in the context with the current transaction information,
1793
// and the ancestor information.
1794

1795        TransIdentity current = new TransIdentity(this.object(),
1796                                                  null,
1797                                                  superInfo.globalTID.realTID);
1798        TransIdentity[] parents = getAncestors();
1799
1800        // Ensure that the implementation specific data is filled with a value.
1801

1802        if (emptyData == null) {
1803            emptyData = Configuration.getORB().create_any();
1804            emptyData.insert_boolean(false);
1805        }
1806
1807        PropagationContext result = new PropagationContext(timeout, current,
1808                                                           parents, emptyData);
1809
1810        return result;
1811    }
1812
1813    /**
1814     * Cleans up an empty Coordinator.
1815     *
1816     * @param parent The parent Coordinator, if any.
1817     *
1818     * @return
1819     *
1820     * @see
1821     */

1822    void cleanUpEmpty(CoordinatorImpl parent) {
1823
1824        // Roll the transaction back, ignoring any exceptions.
1825

1826        try {
1827            rollback(true);
1828        } catch (Throwable JavaDoc exc) {}
1829
1830        // If the transaction is a subtransaction, remove the
1831
// child from the parent's set of children.
1832
// If the parent is temporary, this will cause the parent
1833
// to call cleanup_empty_coordinator, and so-on until all
1834
// empty ancestors are cleaned up.
1835

1836        if (parent != null) {
1837            parent.removeChild(this);
1838        }
1839    }
1840
1841    /**
1842     * Directs the SubCoordinator to commit the transaction in one phase
1843     * The SubCoordinator directs all registered Resources to commit.
1844     *
1845     * @param
1846     *
1847     * @return
1848     *
1849     * @see
1850     */

1851    boolean commitOnePhase() {
1852
1853        // The commit of a subtransaction is always a one phase commit.
1854
// The implementation of the prepare/commit methods simply
1855
// split this up into two parts: the prepare checks the state and
1856
// the commit calls the resources. Therefore commit_one_phase can
1857
// simply call these methods directly.
1858
// Also we let any exception pass up through.
1859

1860        Vote v = this.prepare();
1861
1862        if (v == Vote.VoteCommit) {
1863           this.commit();
1864        } else if (v == Vote.VoteReadOnly) {
1865            // Nothing to do
1866
} else {
1867            this.rollback(true);
1868        }
1869
1870        return true;
1871    }
1872
1873    /**
1874     * Returns a hash code for the object.
1875     * This very basic method is used by the trace facility and should
1876     * not call any method which is traced.
1877     *
1878     * @param
1879     *
1880     * @return The hash code for the object.
1881     *
1882     * @see
1883     */

1884    public int hashCode() {
1885        return hash;
1886    }
1887
1888    /**
1889     * Determines equality of the object with the parameter.
1890     * <p>
1891     * This relies on the availability of the propagation context from the
1892     * target Coordinator.
1893     * <p>
1894     * If the other Coordinator is remote, and not a JCoordinator,
1895     * and is in the process of ending the transaction,
1896     * then this operation will fail; in this
1897     * case we throw the INVALID_TRANSACTION exception with a minor code that
1898     * indicates the cause of the failure.
1899     * <p>
1900     * Unfortunately this is the best we can do with the OMG interfaces when
1901     * interoperating with a different OTS implementation.
1902     *
1903     * @param other The other object.
1904     *
1905     * @return Indicates equality.
1906     *
1907     * @see
1908     */

1909    public boolean equals(java.lang.Object JavaDoc other) throws INVALID_TRANSACTION {
1910
1911        // Do a quick check on the object references.
1912

1913        if (this == other) {
1914            return true;
1915        }
1916
1917        // Obtain the global identifier for the other Coordinator.
1918

1919        otid_t otherTID = null;
1920
1921        if (other instanceof CoordinatorImpl) {
1922            // For local Coordinator objects which are really instances of the
1923
// CoordinatorImpl class, get the global TID via a private
1924
// method call.
1925
if (other instanceof SubCoordinator) {
1926                otherTID = ((SubCoordinator)other).superInfo.globalTID.realTID;
1927            }
1928        } else if (other instanceof org.omg.CORBA.Object JavaDoc) {
1929
1930            // For remote Coordinator objects which are instances of the
1931
// JCoordinator class, use the getGlobalTID method remotely.
1932

1933            try {
1934                JCoordinator jcoord =
1935                    JCoordinatorHelper.narrow((org.omg.CORBA.Object JavaDoc) other);
1936                otherTID = jcoord.getGlobalTID();
1937            } catch (BAD_PARAM exc) {
1938
1939                // For remote Coordinator objects which are not instances of
1940
// the JCoordinator class, use the
1941
// propagation context to compare the Coordinators.
1942
// This relies on the availability of the propagation context
1943
// from the target Coordinator.
1944

1945                try {
1946                    Coordinator coord =
1947                        CoordinatorHelper.narrow((org.omg.CORBA.Object JavaDoc)other);
1948                    PropagationContext pc = coord.get_txcontext();
1949                    otherTID = pc.current.otid;
1950                } catch (BAD_PARAM ex2) {
1951                    // If the other object is not actually a Coordinator,
1952
// then the objects are not the same.
1953
} catch (Unavailable ex2) {
1954                    // If the other Coordinator is inactive, then there is
1955
// nothing we can do to get the global identifier for the
1956
// transaction, so we cannot compare the Coordinator
1957
// objects.
1958

1959                    INVALID_TRANSACTION ex3 =
1960                        new INVALID_TRANSACTION(MinorCode.CompareFailed,
1961                                                CompletionStatus.COMPLETED_NO);
1962                    throw ex3;
1963                }
1964            }
1965        }
1966
1967        // Compare the global identifiers.
1968

1969        if (otherTID != null) {
1970            return superInfo.globalTID.equals(otherTID);
1971        }
1972
1973        return false;
1974    }
1975}
1976
Popular Tags