KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > impl > store > raw > xact > XactXAResourceManager


1 /*
2
3    Derby - Class org.apache.derby.impl.store.raw.xact.XactXAResourceManager
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to you under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derby.impl.store.raw.xact;
23
24 import org.apache.derby.iapi.reference.SQLState;
25
26 import org.apache.derby.iapi.services.context.ContextManager;
27
28 import org.apache.derby.iapi.services.sanity.SanityManager;
29
30 import org.apache.derby.iapi.error.StandardException;
31
32 import org.apache.derby.iapi.store.access.xa.XAResourceManager;
33 import org.apache.derby.iapi.store.access.xa.XAXactId;
34 import org.apache.derby.iapi.store.access.AccessFactoryGlobals;
35
36 import org.apache.derby.iapi.store.raw.GlobalTransactionId;
37 import org.apache.derby.iapi.store.raw.RawStoreFactory;
38 import org.apache.derby.iapi.store.raw.Transaction;
39
40
41 import org.apache.derby.impl.store.raw.xact.GlobalXactId;
42 import org.apache.derby.impl.store.raw.xact.TransactionTable;
43 import org.apache.derby.impl.store.raw.xact.TransactionTableEntry;
44 import org.apache.derby.impl.store.raw.xact.Xact;
45
46 import java.util.Enumeration JavaDoc;
47 import java.util.Hashtable JavaDoc;
48
49 import javax.transaction.xa.Xid JavaDoc;
50 import javax.transaction.xa.XAResource JavaDoc;
51
52 /**
53
54 The XactXAResourceManager implements the Access XAResource interface, which
55 provides offline control over two phase commit transactions. It is expected
56 to be used by TM's (transaction manager's), to recover if systems fail while
57 transactions are still in-doubt (prepared).
58 <P>
59 This interface allows access to commit,prepare,abort global transactions
60 as part of a two phase commit protocol. These interfaces have been chosen
61 to be exact implementations required to implement the XAResource interfaces
62 as part of the JTA standard extension.
63 <P>
64 It is expected that the following interfaces are only used during the
65 recovery portion of 2 phase commit, when the transaction manager is
66 cleaning up after a runtime crash - it is expected that no current context
67 managers exist for the Xid's being operated on. The "online" two phase commit
68 protocol will be implemented by calls directly on a TransactionController.
69 <P>
70 The XAResource interface is a Java mapping of the industry standard XA resource
71 manager interface. Please refer to: X/Open CAE Specification - Distributed
72 Transaction Processing: The XA Specification, X/Open Document No. XO/CAE/91/300
73 or ISBN 1 872630 24 3.
74
75 @see org.apache.derby.iapi.store.access.xa.XAResourceManager
76
77 **/

78
79 public class XactXAResourceManager implements XAResourceManager
80 {
81     /**************************************************************************
82      * Fields of the class
83      **************************************************************************
84      */

85     private TransactionTable transaction_table;
86     private RawStoreFactory rsf;
87
88     /**************************************************************************
89      * Constructors for This class:
90      **************************************************************************
91      */

92     public XactXAResourceManager(
93     RawStoreFactory rsf,
94     TransactionTable tt)
95     {
96         this.rsf = rsf;
97         this.transaction_table = tt;
98     }
99
100     /**************************************************************************
101      * Private/Protected methods of This class:
102      **************************************************************************
103      */

104
105     /**************************************************************************
106      * Public Methods implementing XAResourceManager interface
107      **************************************************************************
108      */

109
110     /**
111      * This method is called to commit the global transaction specified by xid.
112      * <p>
113      * RESOLVE - how do we map to the "right" XAExceptions.
114      * <p>
115      *
116      * @param cm The ContextManager returned from the find() call.
117      * @param xid A global transaction identifier.
118      * @param onePhase If true, the resource manager should use a one-phase
119      * commit protocol to commit the work done on behalf of
120      * xid.
121      *
122      * @exception StandardException Standard exception policy.
123      **/

124     public void commit(
125     ContextManager cm,
126     Xid JavaDoc xid,
127     boolean onePhase)
128         throws StandardException
129     {
130         Transaction rawtran =
131             rsf.findUserTransaction(cm, AccessFactoryGlobals.USER_TRANS_NAME);
132
133         // This may happen if somehow the transaction was committed between
134
// the find() call and now.
135
if (rawtran == null)
136         {
137             throw StandardException.newException(
138                     SQLState.STORE_XA_PROTOCOL_VIOLATION);
139         }
140
141         if (SanityManager.DEBUG)
142         {
143             SanityManager.ASSERT(rawtran != null);
144
145             SanityManager.ASSERT(
146                 (new GlobalXactId(
147                     xid.getFormatId(),
148                     xid.getGlobalTransactionId(),
149                     xid.getBranchQualifier())).equals(rawtran.getGlobalId()));
150         }
151
152         rawtran.xa_commit(onePhase);
153     }
154
155     /**
156      * Find the given Xid in the transaction table.
157      * <p>
158      * This routine is used to find a in-doubt transaction from the list
159      * of Xid's returned from the recover() routine.
160      * <p>
161      * In the current implementation it is up to the calling routine
162      * to make the returned ContextManager the "current" ContextManager
163      * before calls to commit,abort, or forget. The caller is responsible
164      * for error handling, ie. calling cleanupOnError() on the correct
165      * ContextManager.
166      * <p>
167      * If the Xid is not in the system, "null" is returned.
168      * RESOLVE - find out from sku if she wants a exception instead?
169      * <p>
170      *
171      * @param xid A global transaction identifier.
172      *
173      **/

174     public ContextManager find(
175     Xid JavaDoc xid)
176     {
177         return(
178             transaction_table.findTransactionContextByGlobalId(
179                 new GlobalXactId(
180                     xid.getFormatId(),
181                     xid.getGlobalTransactionId(),
182                     xid.getBranchQualifier())));
183     }
184
185     /**
186      * This method is called to remove the given transaction
187      * from the transaction table/log.
188      * <p>
189      * Used to let the store remove all record from log and transaction
190      * table of the given transaction. This should only be used to
191      * clean up heuristically completed transactions, otherwise commit or
192      * abort should be used to act on other transactions.
193      * <p>
194      *
195      * @param cm The ContextManager returned from the find() call.
196      * @param xid A global transaction identifier.
197      *
198      * @exception StandardException Standard exception policy.
199      **/

200     public void forget(
201     ContextManager cm,
202     Xid JavaDoc xid)
203         throws StandardException
204     {
205         Transaction rawtran =
206             rsf.findUserTransaction(cm, AccessFactoryGlobals.USER_TRANS_NAME);
207
208         if (SanityManager.DEBUG)
209         {
210             SanityManager.ASSERT(
211                 new GlobalXactId(
212                     xid.getFormatId(),
213                     xid.getGlobalTransactionId(),
214                     xid.getBranchQualifier()).equals(rawtran.getGlobalId()));
215         }
216
217         // forget should only be called on heuristically completed xacts, which
218
// should not exist in our system.
219
throw StandardException.newException(
220                 SQLState.STORE_XA_PROTOCOL_VIOLATION);
221     }
222
223
224     /**
225      * This method is called to obtain a list of prepared transactions.
226      * <p>
227      * This call returns a complete list of global transactions which are
228      * either prepared or heuristically complete.
229      * <p>
230      * The XAResource interface expects a scan type interface, but our
231      * implementation only returns a complete list of transactions. So to
232      * simulate the scan the following state is maintained. If TMSTARTSCAN
233      * is specified the complete list is returned. If recover is called with
234      * TMNOFLAGS is ever called a 0 length array is returned.
235      *
236      * @return Return a array with 0 or more Xid's which are currently in
237      * prepared or heuristically completed state. If an error occurs
238      * during the operation, an appropriate error is thrown.
239      *
240      * @param flags combination of the following flags
241      * XAResource.{TMSTARTRSCAN,TMENDRSCAN,TMNOFLAGS}.
242      * TMNOFLAGS must be used when no other flags are used.
243      *
244      * @exception StandardException Standard exception policy.
245      **/

246     public Xid JavaDoc[] recover(int flags)
247         throws StandardException
248     {
249         XAXactId[] ret_xid_list;
250
251         if ((flags & XAResource.TMSTARTRSCAN) != 0)
252         {
253             Hashtable JavaDoc trans_hashtable = transaction_table.getTableForXA();
254             XAXactId[] xid_list = new XAXactId[trans_hashtable.size()];
255             int num_prepared = 0;
256
257             // Need to hold sync while linear searching the hash table.
258
synchronized (trans_hashtable)
259             {
260                 int i = 0;
261
262                 for (Enumeration JavaDoc e = trans_hashtable.elements();
263                      e.hasMoreElements(); i++)
264                 {
265                     Xact xact =
266                         ((TransactionTableEntry) e.nextElement()).getXact();
267
268                     if (xact.isPrepared())
269                     {
270                         GlobalTransactionId xa_id = xact.getGlobalId();
271
272                         xid_list[i] =
273                             new XAXactId(
274                                 xa_id.getFormat_Id(),
275                                 xa_id.getGlobalTransactionId(),
276                                 xa_id.getBranchQualifier());
277                         num_prepared++;
278                     }
279                 }
280             }
281
282             // now need to squish the nulls out of the array to return.
283
ret_xid_list = new XAXactId[num_prepared];
284             int ret_index = 0;
285             for (int i = xid_list.length; i-- > 0; )
286             {
287                 if (xid_list[i] != null)
288                     ret_xid_list[ret_index++] = xid_list[i];
289             }
290
291             if (SanityManager.DEBUG)
292             {
293                 SanityManager.ASSERT(ret_index == num_prepared);
294             }
295         }
296         else
297         {
298             ret_xid_list = new XAXactId[0];
299         }
300
301         return(ret_xid_list);
302     }
303
304     /**
305      * rollback the transaction identified by Xid.
306      * <p>
307      * The given transaction is roll'ed back and it's history is not
308      * maintained in the transaction table or long term log.
309      * <p>
310      *
311      * @param cm The ContextManager returned from the find() call.
312      * @param xid A global transaction identifier.
313      *
314      * @exception StandardException Standard exception policy.
315      **/

316     public void rollback(
317     ContextManager cm,
318     Xid JavaDoc xid)
319         throws StandardException
320     {
321         Transaction rawtran =
322             rsf.findUserTransaction(cm, AccessFactoryGlobals.USER_TRANS_NAME);
323
324         // This may happen if somehow the transaction was committed between
325
// the find() call and now.
326
if (rawtran == null)
327         {
328             throw StandardException.newException(
329                     SQLState.STORE_XA_PROTOCOL_VIOLATION);
330         }
331
332         if (SanityManager.DEBUG)
333         {
334
335             SanityManager.ASSERT(
336                 new GlobalXactId(
337                     xid.getFormatId(),
338                     xid.getGlobalTransactionId(),
339                     xid.getBranchQualifier()).equals(rawtran.getGlobalId()));
340         }
341
342         rawtran.xa_rollback();
343     }
344
345     /**************************************************************************
346      * Public Methods of XXXX class:
347      **************************************************************************
348      */

349 }
350
Popular Tags