KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > jdbc > standard > StandardXAConnection


1 /*
2  * XAPool: Open Source XA JDBC Pool
3  * Copyright (C) 2003 Objectweb.org
4  * Initial Developer: Lutris Technologies Inc.
5  * Contact: xapool-public@lists.debian-sf.objectweb.org
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20  * USA
21  */

22  package org.enhydra.jdbc.standard;
23
24 import java.sql.Connection JavaDoc;
25 import java.sql.SQLException JavaDoc;
26 import javax.sql.XAConnection JavaDoc;
27 import javax.transaction.xa.XAException JavaDoc;
28 import javax.transaction.xa.XAResource JavaDoc;
29 import javax.transaction.xa.Xid JavaDoc;
30 import javax.naming.NamingException JavaDoc;
31 import javax.naming.Reference JavaDoc;
32 import javax.naming.Referenceable JavaDoc;
33 import javax.naming.StringRefAddr JavaDoc;
34 import javax.transaction.Status JavaDoc;
35 import javax.transaction.TransactionManager JavaDoc;
36
37 /**
38  * Provides a generic wrapper for JDBC 1 drivers. JDBC 1 drivers always
39  * associate a single transaction at every point in time with a physical
40  * connection. J2EE drivers, on the other hand, allow an XAResource (and
41  * therefore an XAConnection with which it has a one to one mapping) to
42  * switch between global transactions.
43  * <P>
44  * To accomodate this, the StandardXADataSource class maintains a list of
45  * Connection objects. When the Transaction Manager associates an XID
46  * with a StandardXAConnection, it looks for a physical connection which
47  * is associated with that transaction.
48  * <P>
49  * The "current" connection (super.con and curCon) is the connection
50  * currently being used by the application (i.e. getConnection has
51  * been called, but not Connection.close()). The current connection
52  * is removed and handed to the data source if it becomes associated
53  * with a global transaction.
54  */

55 public class StandardXAConnection
56     extends StandardPooledConnection
57     implements XAConnection JavaDoc, XAResource JavaDoc, Referenceable JavaDoc, Runnable JavaDoc {
58
59     protected StandardXAStatefulConnection curCon;
60     // the "current" stateful connection, null if none
61
private boolean commitOnPrepare;
62     // true if commit takes place during prepare call
63
boolean isClosed; // true if this connection has been closed
64
private int timeoutSecs; // timeout in seconds
65
private long timeoutPeriod = 60000; // interval in ms to check for timeouts
66
private long nextTimeout; // time when next timeout occurs
67
public Thread JavaDoc timerThread; // the thread that checks for timeouts
68
public TransactionManager JavaDoc transactionManager;
69     public StandardXAConnectionHandle connectionHandle;
70     protected StandardXADataSource xaDataSource;
71     public boolean thisAutoCommit = true;
72
73     /**
74      * Creates the first free connection.
75      */

76     public StandardXAConnection(
77         StandardXADataSource dataSource,
78         String JavaDoc user,
79         String JavaDoc password)
80         throws SQLException JavaDoc {
81         super(dataSource, user, password);
82         // creates the first Connection object
83

84         // Save the constructor parameters.
85
this.xaDataSource = dataSource;
86         curCon = new StandardXAStatefulConnection(dataSource, con);
87         // wrap connection as a stateful connection
88

89         // NOTE - the current connection is not made known to the data source
90
// so it is not eligible for re-use. It only goes on the data source list
91
// if it ever becomes associated with a global transaction.
92

93         /*
94         // get the timer thread
95         if (xaDataSource.getThreadFactory() != null) {
96         dataSource.log.debug("StandardXAConnection: Getting thread from factory");
97         timerThread = xaDataSource.getThreadFactory().getThread(this);
98         dataSource.log.debug("StandardXAConnection: Got thread from factory");
99         } else {
100         dataSource.log.debug("StandardXAConnection: Getting thread from new Thread()");
101         timerThread = new Thread (this); // create the backgroup thread to check for timeouts
102         }
103         
104         timerThread.start(); // start the timer thread
105         //timerThread.suspend(); // and suspend until some timeouts get set up
106         */

107         dataSource.log.debug("StandardXAConnection created");
108     }
109
110     /**
111      * We are required to maintain a 1-1 mapping between an XAConnection
112      * and its corresponding XAResource. We achieve this by implementing
113      * both interfaces in the same class.
114      */

115     public XAResource JavaDoc getXAResource() {
116         return this;
117     }
118
119     /**
120      * Creates a new StandardXAConnectionHandle for use by an application.
121      * If there is already an StandardXAConnectionHandle in use then it is
122      * closed (i.e. the application has the connection withdrawn).
123      * <P>
124      * This method always returns a Connection in the free state (i.e.
125      * (not associated with an Xid). This is necessary since, unless
126      * Start (Xid, flags) gets called, the Connection must do local
127      * transaction processing.
128      */

129     public synchronized Connection JavaDoc getConnection() throws SQLException JavaDoc {
130         dataSource.log.debug("StandardXAConnection:getConnection");
131         if (connectionHandle != null) {
132             // if there's already a delegated connection
133
if (!connectionHandle.isClosed()) // and it hasn't been closed
134
connectionHandle.close(); // close it now
135
}
136         if (curCon == null) { // if there's no current connection
137

138             curCon = xaDataSource.getFreeConnection();
139                         // find or create a free connection
140
con = curCon.con; // save it's Connection
141
}
142
143         // Note that we share the PreparedStatement cache across many physical
144
// connections. This is OK since the connection is used in the lookup key.
145

146         this.newConnectionHandle();
147         dataSource.log.debug(
148             "StandardXAConnection:getConnection return a connection");
149         return connectionHandle;
150     }
151
152     protected void newConnectionHandle() {
153         connectionHandle =
154             new StandardXAConnectionHandle(
155                 this,
156                 dataSource.getMasterPrepStmtCache(),
157                 dataSource.getPreparedStmtCacheSize(),
158                 transactionManager);
159     }
160
161     public void setTransactionManager(TransactionManager JavaDoc tm) {
162         this.transactionManager = tm;
163     }
164
165     /**
166      * Close this XA connection.
167      */

168     public synchronized void close() throws java.sql.SQLException JavaDoc {
169         dataSource.log.debug("StandardXAConnection:close the XAConnection");
170  // if (con != null) { // if we have a current connection
171
// con.close(); // then close it
172
// dataSource.getMasterPrepStmtCache().remove(con.toString());
173
// }
174
//commenented by karthicks - in case of transacted connection curcon will be null and physical connection con will not be null
175
//and physical will be part of freeconnection which would be used by some other instance of XAConnection object at this instant
176
//so only the curCon and its is associated connected should be closed
177
//it will happen fro non transacted connections.
178
//in case of tx connectioins else part will come to play and close any freeconnections
179
if (curCon != null && !curCon.con.isClosed())
180                 { // if we have a current connection
181
curCon.con.close(); // then close it
182
dataSource.getMasterPrepStmtCache().remove(curCon.toString());
183         }
184                 else { // no "current" connection
185
if (xaDataSource.freeConnections.size() > 1) {
186                 // if there are some free connections
187
//curCon.con.setAutoCommit(thisAutoCommit);
188
curCon = xaDataSource.getFreeConnection();
189                 // get one of the free connections
190
curCon.con.close(); // close it
191
dataSource.getMasterPrepStmtCache().remove(
192                     curCon.con.toString());
193             }
194         }
195         curCon = null; // remove stateful connection
196
con = null; // and physical connection
197
xaDataSource.connectionClosed();
198         // tell data source that connection's gone
199

200         isClosed = true; // connection is now closed
201
connectionHandle = null;
202         //timerThread.resume(); // stop the timeout checking
203
nextTimeout = 0; // I don't know how the above line was
204
// supposed to stop the thread but we
205
// should really just set the condition
206
// and let the thread stop itself
207
}
208
209     /**
210      * Does most of the work of the start() call (below). Kept as
211      * a separate method so that subclasses can call it and retain
212      * the curCon property.
213      */

214     public synchronized void doStart(Xid JavaDoc xid, int flags) throws XAException JavaDoc {
215         dataSource.log.debug(
216             "StandardXAConnection:doStart xid='"
217                 + xid
218                 + "' flags='"
219                 + flags
220                 + "'");
221         if (xid == null)
222             throw new XAException JavaDoc(XAException.XAER_INVAL);
223
224         // should only get called after a new/free connection has been made current
225
/* commented by karthick
226         if (curCon == null) {
227             try {
228                 curCon = xaDataSource.getFreeConnection();
229             } catch (Exception e) {
230             }
231             dataSource.log.debug("StandardXAConnection:doStart curCon is null");
232             //throw new XAException (XAException.XAER_PROTO);
233         }
234                 */

235
236         /*
237         if ((curCon.getState() != Status.STATUS_NO_TRANSACTION) && (curCon.xid != xid )){
238             dataSource.log.error("StandardXAConnection:doStart Invalid state:status="
239                     + curCon.getState() + ":id=" + curCon.id);
240             throw new XAException (XAException.XAER_PROTO);
241         }
242         */

243
244         if (flags == TMRESUME
245             || flags == TMJOIN) {
246             // if resuming or joining an existing transaction
247
try {
248                 xaDataSource.processToWait();
249             } catch (Exception JavaDoc e) {
250                 throw new XAException JavaDoc("Exception : " + e.toString());
251             }
252             synchronized (xaDataSource) {
253                             if(curCon != null)
254                             {
255                                 //free connections will be added if this is a new XAConnection object or previously an non transacted connection
256
// so no need to check fori contains any as a precaution
257
//commented by karthicks
258
if(!xaDataSource.freeConnections.contains(curCon))
259                                 {
260                                     xaDataSource.freeConnections.addElement(curCon);
261                                 }
262                             }
263                             // save the current connection
264
}
265             curCon = xaDataSource.getConnection(xid, true);
266             // must find connection handling xid
267
con = curCon.con; // must use correct physical connection
268
} // else {
269
// xaDataSource.getConnection(xid, false);
270
// // must NOT find connection handling xid
271
// }
272
//commented by karthicks -unnecessary fetch
273

274                 //moved by karthicks
275
// should only get called after a new/free which has been called in different tx earlier
276
if (curCon == null) {
277                     try {
278                         curCon = xaDataSource.getFreeConnection();
279                         con = curCon.con;
280                     } catch (Exception JavaDoc e) {
281                         dataSource.log.error("error while gettting connection "+e,e);
282                     }
283                     dataSource.log.debug("StandardXAConnection:doStart curCon is null");
284                     //throw new XAException (XAException.XAER_PROTO);
285
}
286
287
288                 //on suspend all enlisted resource will get called so resetonresume will be set "true" to those StdxaconnHandle
289
//on resume viceversa(deleisted resource ) will get enlisted again so start will get called and current tx will be reset
290
//by - karthicks
291
StandardXAConnectionHandle xad = connectionHandle;
292         try {
293             xad.setGlobalTransaction(true);
294                         if(flags == TMRESUME && xad.resetTxonResume)
295                         {
296                             xad.resetTxonResume = false;
297                             if(transactionManager != null && xad.tx == null)
298                             {
299                                 try
300                                 {
301                                     connectionHandle.tx =transactionManager.getTransaction();
302                                 }
303                                 catch(javax.transaction.SystemException JavaDoc se)
304                                 {
305                                     throw new XAException JavaDoc(se.toString());
306                                 }
307                             }
308                         }
309
310             // delegate must use current physical connection
311
} catch (SQLException JavaDoc e) {
312             throw new XAException JavaDoc(e.toString());
313         }
314
315         if (timeoutSecs != 0) { // if a timeout has been defined
316
curCon.timeout = System.currentTimeMillis() // set the timeout
317
+timeoutSecs * 1000;
318             if (nextTimeout == 0) {
319                 // if there are currently no timeouts set up
320
nextTimeout = curCon.timeout; // set new timeout
321
notify();
322                 //timerThread.resume(); // start checking for timeouts
323
} else { // some timeouts already exist
324
if (curCon.timeout < nextTimeout) {
325                     // if this expires sooner than next timeout
326
nextTimeout = curCon.timeout; // set new timeout
327
}
328             }
329         }
330
331         curCon.xid = xid; // connection now associated with this XID
332
curCon.timedOut = false; // forget about any old timeouts
333
curCon.commitOnPrepare = commitOnPrepare;
334         // tell it when to do a commit
335
if (!xaDataSource.xidConnections.containsKey(xid)) {
336             try {
337                 log.debug("StandardXAConnection:dostart before processToWait");
338                 xaDataSource.processToWait();
339                 log.debug("StandardXAConnection:dostart after processToWait");
340             } catch (Exception JavaDoc e) {
341                 throw new XAException JavaDoc("Exception : " + e.toString());
342             }
343             synchronized (xaDataSource) {
344                 xaDataSource.xidConnections.put(xid, curCon);
345                 // place on allocated list
346
}
347         }
348         curCon.setState(Status.STATUS_ACTIVE); // set new connection state
349
}
350
351     /**
352      * Associates this XAConnection with a global transaction. This
353      * is the only method which can associate the current connection
354      * with a global transaction. It acts only on the current
355      * connection which must have been previously established using
356      * getConnection.
357      */

358     public synchronized void start(Xid JavaDoc xid, int flags) throws XAException JavaDoc {
359         dataSource.log.debug(
360             "StandardXAConnection:start associate the current connection with a global transaction");
361         doStart(xid, flags); // do most of the work
362
curCon = null; // no longer owned by this object
363
//con = null; // ditto
364
}
365
366     /**
367      * Ends a connection's association with a global transaction.
368      * <P>
369      * It need not act on the current transaction. There is an
370      * interval between being returned to the pool manager and
371      * being invoked by the transaction manager during which the
372      * current connection can change.
373      * <P>
374      * Note that the only effect is to change the connection state.
375      */

376     public synchronized void end(Xid JavaDoc xid, int flags)
377         throws XAException JavaDoc { //not tested XS
378
dataSource.log.debug("StandardXAConnection:end");
379         dataSource.log.debug(
380             "StandardXAConnection:end xid='" + xid + "' flags='" + flags + "'");
381
382         if (xid == null)
383             throw new XAException JavaDoc(XAException.XAER_INVAL);
384         StandardXAStatefulConnection statecon =
385             xaDataSource.getConnection(xid, true);
386         // must find connection for this transaction
387
int state = statecon.getState(); // get current state of connection
388
if (state != Status.STATUS_ACTIVE) // must have had start() called
389
throw new XAException JavaDoc(XAException.XAER_PROTO);
390         /*System.out.println("connectionHandle.globalTransaction = false;\n"+
391                 "connectionHandle.setAutoCommit(true);");
392         connectionHandle.globalTransaction = false;
393         try {
394             connectionHandle.setAutoCommit(true);
395         } catch (SQLException sqle) {
396             dataSource.log("StandardXAConnection pb: "+sqle);
397         }*/

398         // try {
399

400                 //on suspend all end of enlisted resource will get called so resetonresume will be set "true" to those StdxaconnHandle
401
//on resume viceversa(deleisted resource ) will get enlisted again so start will get called and current tx will be reset
402
//by - karthicks
403
if(connectionHandle.tx != null)
404                 {
405                     connectionHandle.resetTxonResume =true;
406                 }
407         connectionHandle.tx = null;
408         connectionHandle.globalTransaction = false;
409
410         /* connectionHandle.setGlobalTransaction(false);
411               } catch (SQLException sqle) {
412                   dataSource.log.error("StandardXAConnection:end pb "+sqle);
413               }
414         */

415     }
416
417     /**
418      * Does most of the work of a generic prepare. Kept as a
419      * separate method so that sub-classes can call it and get
420      * the StandardXAStatefulConnection back.
421      */

422     public StandardXAStatefulConnection checkPreparedState(Xid JavaDoc xid)
423         throws XAException JavaDoc {
424         dataSource.log.debug("StandardXAConnection:checkPreparedState");
425         if (xid == null)
426             throw new XAException JavaDoc(XAException.XAER_INVAL);
427         StandardXAStatefulConnection statecon =
428             xaDataSource.getConnection(xid, true);
429         // must find connection for this transaction
430

431         try {
432             if (statecon.commitOnPrepare) { // if early commit is required
433
statecon.con.commit(); // perform the commit operation now
434
statecon.setState(Status.STATUS_PREPARING);
435                 // heuristaclly committed
436
} else {
437                 statecon.setState(Status.STATUS_PREPARED); // prepared
438
}
439         } catch (SQLException JavaDoc e) {
440             dataSource.log.error(
441                 "StandardXAConnection:checkPrepareState Exception on prepare, rolling back");
442             statecon.setState(Status.STATUS_NO_TRANSACTION);
443             // release connection
444
throw new XAException JavaDoc(XAException.XA_RBROLLBACK);
445             // rollback will have been performed
446
}
447
448         return statecon;
449     }
450
451     /**
452      * Prepares to perform a commit. May actually perform a commit
453      * in the flag commitOnPrepare is set to true.
454      */

455     public int prepare(Xid JavaDoc xid) throws XAException JavaDoc {
456         dataSource.log.debug(
457             "StandardXAConnection:prepare prepare to perform a commit");
458         checkPreparedState(xid);
459         return XA_OK;
460     }
461
462     /**
463      * Performs a commit on this resource manager's branch of
464      * the global transaction.
465      */

466     public synchronized void commit(Xid JavaDoc xid, boolean onePhase)
467         throws XAException JavaDoc {
468         dataSource.log.debug("StandardXAConnection:commit perform a commit");
469         if (xid == null)
470             throw new XAException JavaDoc(XAException.XAER_INVAL);
471
472         StandardXAStatefulConnection statecon =
473             xaDataSource.getConnection(xid, true);
474         // must find connection for this transaction
475
dataSource.log.debug("StandardXAConnection:commit case(state)");
476
477         try {
478             switch (statecon.getState()) { // action depends on current state
479
case Status.STATUS_PREPARING : // already commited
480
break; // ...so do nothing
481
case Status.STATUS_PREPARED : // ready to do commit
482
try {
483                         dataSource.log.debug(
484                             "StandardXAConnection:commit try to commit a connection (STATUS_PREPARED)");
485                         statecon.con.commit();
486                         // perform the commit operation now
487
dataSource.log.debug(
488                             "StandardXAConnection:commit commit is ok");
489                     } catch (SQLException JavaDoc e) {
490                         throw new XAException JavaDoc(XAException.XA_RBROLLBACK);
491                         // rollback will have been performed
492
}
493                     break;
494                 case Status.STATUS_COMMITTED : // could be a 1-phase commit
495
case Status.STATUS_ACTIVE :
496                     if (!onePhase) { // if not a one-phase commit
497
throw new XAException JavaDoc(XAException.XAER_PROTO);
498                     }
499
500                     try {
501                         dataSource.log.debug(
502                             "StandardXAConnection:commit try to commit a connection (STATUS_ACTIVE)");
503                         statecon.con.commit();
504                         // perform the commit operation now
505
dataSource.log.debug(
506                             "StandardXAConnection:commit commit is ok");
507                     } catch (SQLException JavaDoc e) {
508                                             throw new XAException JavaDoc(XAException.XA_RBROLLBACK);
509                         // rollback will have been performed
510
}
511                     break;
512                 default :
513                     {
514                         dataSource.log.debug(
515                             "StandardXAConnection:commit UNKNOWN STATUS!:"
516                                 + statecon.getState());
517                         throw new XAException JavaDoc(XAException.XAER_PROTO);
518                     }
519             }
520         } catch (XAException JavaDoc e) {
521             throw e;
522         } finally {
523             try {
524                 dataSource.log.debug(
525                     "StandardXAConnection:commit setAutoCommit to '"
526                         + thisAutoCommit
527                         + "'");
528                 statecon.con.setAutoCommit(thisAutoCommit);
529             } catch (SQLException JavaDoc e) {
530                 dataSource.log.debug(
531                     "StandardXAConnection:commit setAutoCommit problem");
532             }
533                         
534             xaDataSource.freeConnection(xid, false);
535         }
536     }
537
538     /**
539      * PERFORMS a rollback on this resource manager's branch of
540      * the global transaction.
541      */

542     public synchronized void rollback(Xid JavaDoc xid) throws XAException JavaDoc {
543         dataSource.log.debug("StandardXAConnection:rollback");
544         if (xid == null)
545             throw new XAException JavaDoc(XAException.XAER_INVAL);
546
547         StandardXAStatefulConnection statecon =
548             xaDataSource.getConnection(xid, true);
549         // must find connection for this transaction
550

551         try {
552             switch (statecon.getState()) { // action depends on current state
553
case Status.STATUS_PREPARING : // already commited
554
throw new XAException JavaDoc(XAException.XA_HEURCOM);
555                 case Status.STATUS_PREPARED : // ready to do rollback
556
case Status.STATUS_ROLLING_BACK :
557                 case Status.STATUS_ACTIVE :
558                     try {
559                         dataSource.log.debug(
560                             "StandardXAConnection:rollback try to perform the rollback operation");
561                         statecon.con.rollback();
562                         // perform the rollback operation
563
dataSource.log.debug(
564                             "StandardXAConnection:rollback performed the rollback");
565                     } catch (SQLException JavaDoc e) {
566                         throw new XAException JavaDoc(XAException.XA_RBROLLBACK);
567                         // rollback will have been performed
568
}
569                     break;
570                 default :
571                     throw new XAException JavaDoc(XAException.XAER_PROTO);
572             }
573         } catch (XAException JavaDoc e) {
574             throw e;
575         } finally {
576             try {
577                 dataSource.log.debug(
578                     "StandardXAConnection:rollback setAutoCommit to '"
579                         + thisAutoCommit
580                         + "'");
581                 statecon.con.setAutoCommit(thisAutoCommit);
582             } catch (SQLException JavaDoc e) {
583                 dataSource.log.debug(
584                     "StandardXAConnection:rollback setAutoCommit problem");
585             }
586             xaDataSource.freeConnection(xid, false);
587         }
588     }
589
590     public boolean isSameRM(XAResource JavaDoc xares) throws XAException JavaDoc {
591         dataSource.log.debug("StandardXAConnection:isSameRM");
592         if (equals(xares)) { // if the same object
593
dataSource.log.debug("StandardXAConnection:isSameRM isSameRM");
594             return true; // then definitely the same RM
595
}
596         if (!(xares instanceof StandardXAConnection)) {
597             // if it's not one of our wrappers
598
dataSource.log.debug("StandardXAConnection:isSameRM not isSameRM");
599             return false; // then it's definitely not the same RM
600
}
601         StandardXAConnection xac = (StandardXAConnection) xares;
602         // cast to something more convenient
603
if (dataSource.equals(xac.dataSource)) {
604             // if they originate from same data source
605
dataSource.log.debug(
606                 "StandardXAConnection:isSameRM isSameRM (equal datasource)");
607             return true; // then they're the same RM
608
} else {
609             dataSource.log.debug(
610                 "StandardXAConnection:isSameRM not isSameRM (not equal datasource)");
611             return false;
612         }
613     }
614
615     /**
616      * This is called by a TM when the RM has reported a heuristic
617      * completion. It must retain the transaction context until told
618      * to forget about it.
619      */

620     public void forget(Xid JavaDoc xid) throws XAException JavaDoc {
621         dataSource.log.debug("StandardXAConnection:forget forget with Xid");
622         if (xid == null)
623             throw new XAException JavaDoc(XAException.XAER_INVAL);
624
625         //StandardXAStatefulConnection statecon = xaDataSource.getConnection (xid, true);// must find connection for this transaction
626
xaDataSource.freeConnection(xid, false);
627         // finished with this transaction
628
}
629
630     /**
631      * Called by the transaction manager during recovery. If it was the
632      * transaction manager or another compoenent which failed then we
633      * can supply our known Xids. However if we failed then this method
634      * does nothing - we need to know about database internals to do that.
635      */

636     public Xid JavaDoc[] recover(int flag) throws XAException JavaDoc {
637         dataSource.log.debug(
638             "StandardXAConnection:recover recover flag=" + flag);
639         if (flag != TMSTARTRSCAN && flag != TMENDRSCAN && flag != TMNOFLAGS) {
640             throw new XAException JavaDoc(XAException.XAER_INVAL);
641         }
642
643         Xid JavaDoc[] retval = null;
644         retval = xaDataSource.recover(); // get all valid Xids
645
return retval;
646     }
647
648     /**
649      * Accessor methods for timeout.
650      */

651     public boolean setTransactionTimeout(int seconds) {
652         timeoutSecs = seconds;
653         return false;
654     }
655
656     public int getTransactionTimeout() {
657         return timeoutSecs;
658     }
659
660     public void setCommitOnPrepare(boolean commitOnPrepare) {
661         this.commitOnPrepare = commitOnPrepare;
662     }
663
664     public boolean getCommitOnPrepare() {
665         return commitOnPrepare;
666     }
667
668     /**
669      * Periodically checks for timed out connections.
670      */

671     public void run() {
672         //dataSource.log.debug("StandardXAConnection:run check for timed out connections");
673
while (true) { // loop forever
674
/*
675             if (nextTimeout == 0) { // if there are no more timeouts scheduled
676             timerThread.suspend(); // then go to sleep
677             if (isClosed) return; // exit if connection is closed
678             }
679             */

680             try {
681                 synchronized (this) {
682                     while (nextTimeout == 0) {
683                         wait();
684                     }
685                 }
686             } catch (InterruptedException JavaDoc e) {
687             }
688
689             if (isClosed) {
690                 return;
691             }
692
693             try {
694                 Thread.sleep(timeoutPeriod); // sleep for a few seconds
695
if (isClosed)
696                     return; // exit if connection is closed
697
} catch (InterruptedException JavaDoc e) {
698                 e.printStackTrace(); // we don't expect any of these
699
}
700
701             long curTime = System.currentTimeMillis(); // get system time
702
if (curTime < nextTimeout)
703                 continue; // check for time still to go
704

705             // One or more transactions have timeout out.
706
try {
707                 nextTimeout = xaDataSource.checkTimeouts(curTime);
708                 // check to see if connections have timeout out
709
} catch (Exception JavaDoc e) {
710                 e.printStackTrace(); // we don't expect any of these
711
}
712         }
713     }
714
715     public Reference JavaDoc getReference() throws NamingException JavaDoc {
716         // Note that we use getClass().getName() to provide the factory
717
// class name. It is assumed that this class, and all of its
718
// descendants are their own factories.
719
dataSource.log.debug(
720             "StandardXAConnection:getReference return a reference of the object");
721         Reference JavaDoc ref =
722             new Reference JavaDoc(getClass().getName(), getClass().getName(), null);
723         ref.add(
724             new StringRefAddr JavaDoc(
725                 "commitOnPrepare",
726                 String.valueOf(getCommitOnPrepare())));
727         ref.add(
728             new StringRefAddr JavaDoc(
729                 "timeoutSecs",
730                 Integer.toString(getTransactionTimeout())));
731         return ref;
732     }
733
734     public String JavaDoc toString() {
735         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
736         sb.append("StandardXAConnection:\n");
737         sb.append(" commit on prepare =<"+this.commitOnPrepare+">\n");
738         sb.append(" is closed =<"+this.isClosed + ">\n");
739         sb.append(" this autoCommit =<"+this.thisAutoCommit + ">\n");
740         sb.append(" listeners size =<"+this.listeners.size() + ">\n");
741         sb.append(" next timeOut =<"+this.nextTimeout + ">\n");
742         sb.append(" timeOut period =<"+this.timeoutPeriod + ">\n");
743         sb.append(" timeOut secs =<"+this.timeoutSecs + ">\n");
744         sb.append(" transaction manager=<"+this.transactionManager + ">\n");
745         sb.append(this.xaDataSource.toString());
746         sb.append(this.dataSource.toString());
747         if (curCon != null)
748             sb.append(this.curCon.toString());
749         if (connectionHandle != null)
750             sb.append(this.connectionHandle.toString());
751         sb.append(this.con.toString());
752         
753         return sb.toString();
754     
755     }
756 }
757
Popular Tags