KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > jca > PoolItem


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.jca;
31
32 import com.caucho.log.Log;
33 import com.caucho.util.Alarm;
34 import com.caucho.util.L10N;
35
36 import javax.resource.NotSupportedException JavaDoc;
37 import javax.resource.ResourceException JavaDoc;
38 import javax.resource.spi.ConnectionEvent JavaDoc;
39 import javax.resource.spi.ConnectionEventListener JavaDoc;
40 import javax.resource.spi.ConnectionRequestInfo JavaDoc;
41 import javax.resource.spi.LocalTransaction JavaDoc;
42 import javax.resource.spi.ManagedConnection JavaDoc;
43 import javax.resource.spi.ManagedConnectionFactory JavaDoc;
44 import javax.security.auth.Subject JavaDoc;
45 import javax.transaction.xa.XAException JavaDoc;
46 import javax.transaction.xa.XAResource JavaDoc;
47 import javax.transaction.xa.Xid JavaDoc;
48 import java.util.logging.Level JavaDoc;
49 import java.util.logging.Logger JavaDoc;
50
51 /**
52  * Implementation of the connection manager manager.
53  */

54 class PoolItem implements ConnectionEventListener JavaDoc, XAResource JavaDoc {
55   private static final L10N L = new L10N(PoolItem.class);
56   private static final Logger JavaDoc log = Log.open(PoolItem.class);
57
58   private ConnectionPool _cm;
59   
60   private ManagedConnectionFactory JavaDoc _mcf;
61   private ManagedConnection JavaDoc _mConn;
62
63   private UserTransactionImpl _transaction;
64
65   private String JavaDoc _id;
66
67   private XAResource JavaDoc _xaResource;
68   private LocalTransaction JavaDoc _localTransaction;
69   private int _defaultTransactionTimeout;
70   private int _transactionTimeout;
71
72   private Subject JavaDoc _subject;
73   private ConnectionRequestInfo JavaDoc _requestInfo;
74
75   final Object JavaDoc _shareLock = new Object JavaDoc();
76   
77   // The head shared connection for transaction
78
// The UserPoolItem code is responsible for this field
79
UserPoolItem _shareHead;
80   
81   // The other pool items joined transaction
82
private PoolItem _xaHead;
83   private PoolItem _xaNext;
84   
85   private boolean _hasConnectionError;
86
87   private long _poolStartTime;
88   private long _poolEventTime;
89
90   private Xid JavaDoc _xid;
91   private int _endFlags = -1;
92
93   // flag forcing an XA transaction (for the local transaction optimization)
94
private boolean _isXATransaction = true;
95     
96   // true if in local transaction
97
private boolean _isLocalTransaction;
98
99   private IllegalStateException JavaDoc _allocationStackTrace;
100
101   public PoolItem(ConnectionPool cm,
102           ManagedConnectionFactory JavaDoc mcf,
103           ManagedConnection JavaDoc conn)
104   {
105     _cm = cm;
106
107     _id = _cm.generateId();
108
109     _mcf = mcf;
110     _mConn = conn;
111
112     _poolStartTime = Alarm.getCurrentTime();
113     _poolEventTime = Alarm.getCurrentTime();
114
115     // Gets the resource object from the driver
116
try {
117       if (cm.isXATransaction()) {
118     XAResource JavaDoc xaResource = conn.getXAResource();
119
120     try {
121       _defaultTransactionTimeout = xaResource.getTransactionTimeout();
122     } catch (Throwable JavaDoc e) {
123       log.log(Level.FINE, e.toString(), e);
124     }
125     
126     _xaResource = xaResource;
127       }
128     } catch (NotSupportedException JavaDoc e) {
129       _cm.setXATransaction(false);
130       log.log(Level.FINER, e.toString(), e);
131     } catch (Exception JavaDoc e) {
132       log.log(Level.FINE, e.toString(), e);
133     }
134
135     if (_xaResource == null)
136       _isXATransaction = false;
137
138     // Gets the local transaction from the driver
139
try {
140       if (_cm.isLocalTransaction())
141     _localTransaction = conn.getLocalTransaction();
142     } catch (NotSupportedException JavaDoc e) {
143       _cm.setLocalTransaction(false);
144       log.log(Level.FINE, e.toString(), e);
145     } catch (Exception JavaDoc e) {
146       log.log(Level.FINE, e.toString(), e);
147     }
148     
149     _mConn.addConnectionEventListener(this);
150
151     if (log.isLoggable(Level.FINE))
152       log.fine("create: " + this +
153            "(active:" + _cm.getConnectionActiveCount() +
154            ", total:" + _cm.getConnectionCount() + ")");
155   }
156
157   /**
158    * Sets the subject.
159    */

160   public void setSubject(Subject JavaDoc subject)
161   {
162     _subject = subject;
163   }
164
165   /**
166    * Sets the info.
167    */

168   public void setInfo(ConnectionRequestInfo JavaDoc info)
169   {
170     _requestInfo = info;
171   }
172
173   /**
174    * Returns true if the connection is active.
175    */

176   public boolean isActive()
177   {
178     return _shareHead != null;
179   }
180
181   /**
182    * Returns true if the connection is dead
183    */

184   public boolean isDead()
185   {
186     return _mConn == null;
187   }
188
189   /**
190    * Returns the time of the last event.
191    */

192   public long getEventTime()
193   {
194     return _poolEventTime;
195   }
196
197   /**
198    * Returns the time the connection was first used.
199    */

200   public long getStartTime()
201   {
202     return _poolStartTime;
203   }
204
205   /**
206    * Sets the item's transaction.
207    */

208   void setTransaction(UserTransactionImpl transaction)
209   {
210     _transaction = transaction;
211   }
212
213   /**
214    * Make this connection active.
215    *
216    * @return true if the pool item is valid, false if it should be removed.
217    */

218   synchronized UserPoolItem toActive(Subject JavaDoc subject,
219                      ConnectionRequestInfo JavaDoc info,
220                      UserPoolItem userPoolItem)
221     throws ResourceException JavaDoc
222   {
223     long now = Alarm.getCurrentTime();
224
225     long maxIdleTime = _cm.getMaxIdleTime();
226     long maxPoolTime = _cm.getMaxPoolTime();
227
228     if (_hasConnectionError)
229       return null;
230     else if (0 < maxIdleTime && _poolEventTime + maxIdleTime < now) {
231       return null;
232     }
233     else if (0 < maxPoolTime && _poolStartTime + maxPoolTime < now)
234       return null;
235     else if (_shareHead != null)
236       throw new IllegalStateException JavaDoc(L.l("trying to activate active pool item."));
237
238     _poolEventTime = now;
239     _isXATransaction = _xaResource != null; // disable LT-optim by default
240

241     if (userPoolItem != null) {
242       Object JavaDoc uConn = userPoolItem.getUserConnection();
243
244       if (uConn != null)
245     _mConn.associateConnection(uConn);
246
247       userPoolItem.associatePoolItem(this);
248     }
249     else
250       userPoolItem = new UserPoolItem(_cm, this);
251     
252     if (! isValid(subject, info, userPoolItem))
253       return null;
254
255     _subject = subject;
256     _requestInfo = info;
257     userPoolItem.associate(this, _mcf, subject, info);
258
259     if (log.isLoggable(Level.FINE))
260       log.fine("allocate " + this);
261
262     if (_cm.getSaveAllocationStackTrace())
263       _allocationStackTrace = new IllegalStateException JavaDoc(L.l("Connection {0} allocation stack trace", this));
264
265     return userPoolItem;
266   }
267
268   /**
269    * Checks if the pool item is still valid.
270    *
271    * @return true if the pool item is valid, false if it should be removed.
272    */

273   synchronized boolean isValid()
274   {
275     long now = Alarm.getCurrentTime();
276
277     long maxIdleTime = _cm.getMaxIdleTime();
278     long maxPoolTime = _cm.getMaxPoolTime();
279     long maxActiveTime = _cm.getMaxActiveTime();
280
281     boolean isActive = isActive() || _xid != null;
282     boolean isDead = false;
283
284     if (! isActive && _hasConnectionError) {
285       isDead = true;
286       log.fine("closing pool item from connection error:" + this);
287     }
288     else if (! isActive &&
289          0 < maxIdleTime && _poolEventTime + maxIdleTime < now) {
290       isDead = true;
291       log.fine("closing pool item from idle timeout:" + this);
292     }
293     else if (! isActive &&
294          0 < maxPoolTime && _poolStartTime + maxPoolTime < now) {
295       isDead = true;
296       log.fine("closing pool item from pool timeout:" + this);
297     }
298     else if (isActive &&
299          0 < maxActiveTime && _poolEventTime + maxActiveTime < now) {
300       isDead = true;
301       log.warning("closing pool item from active timeout:" + this);
302     }
303
304     if (isDead) {
305       _hasConnectionError = true;
306       return false;
307     }
308     else
309       return true;
310   }
311   
312   /**
313    * Use the item only if it's already been used for the current transaction
314    * and is available. allocateXA returns the same connection for the
315    * following case:
316    *
317    * <pre>
318    * UserTransaction.begin();
319    *
320    * conn = ds.getConnection();
321    * ...
322    * conn.close();
323    *
324    * conn = ds.getConnection();
325    * ...
326    * conn.close();
327    * </pre>
328    *
329    * <p>Nested connections are not reused.
330    *
331    * @param xid the current transaction id
332    *
333    * @return true if the pool item has been allocated
334    */

335   UserPoolItem allocateXA(ManagedConnectionFactory JavaDoc mcf,
336               Subject JavaDoc subject,
337               ConnectionRequestInfo JavaDoc info)
338   {
339     if (_mConn == null) // already closed
340
return null;
341     else if (_subject != subject)
342       return null;
343     else if (_requestInfo != info)
344       return null;
345     else if (_mcf != mcf)
346       return null;
347     else if (_shareHead != null && ! _cm.isShareable()) // is currently in use
348
return null;
349     else if (_hasConnectionError) // had a fatal error
350
return null;
351     
352     if (log.isLoggable(Level.FINER))
353       log.finer("sharing xa-pool item: " + this);
354
355     UserPoolItem userPoolItem = new UserPoolItem(_cm);
356     userPoolItem.associate(this, _mcf, _subject, _requestInfo);
357
358     return userPoolItem;
359   }
360
361   /**
362    * Returns true if the tested pool item is the Xid leader.
363    */

364   boolean isJoin(PoolItem item)
365   {
366     if (this == item)
367       return false;
368     else if (_xid != item._xid)
369       return false;
370     else if (_mcf != item._mcf)
371       return false;
372     else
373       return true;
374   }
375
376   /**
377    * Try to share the connection.
378    */

379   boolean share(UserPoolItem userPoolItem)
380   {
381     if (this == userPoolItem.getOwnPoolItem())
382       return true;
383     else if (_mConn == null) // already closed
384
return false;
385     else if (! _cm.isShareable()) // not shareable
386
return false;
387     else if (_mcf != userPoolItem.getManagedConnectionFactory())
388       return false;
389     else if (_subject != userPoolItem.getSubject())
390       return false;
391     else if (_requestInfo != userPoolItem.getInfo())
392       return false;
393     else if (_hasConnectionError) // had a fatal error
394
return false;
395
396     // skip for now
397
if (true)
398       return false;
399     
400     userPoolItem.associate(this, _mcf, _subject, _requestInfo);
401
402     return true;
403   }
404
405   /**
406    * Returns the managed connection.
407    */

408   ManagedConnection JavaDoc getManagedConnection()
409   {
410     return _mConn;
411   }
412
413   /**
414    * Returns the user connection.
415    */

416   /*
417   Object getUserConnection()
418     throws ResourceException
419   {
420     return _userPoolItem.getUserConnection();
421   }
422   */

423
424   /**
425    * Returns the user connection.
426    */

427   Object JavaDoc allocateConnection()
428     throws ResourceException JavaDoc
429   {
430     return _mConn.getConnection(_subject, _requestInfo);
431   }
432
433   /**
434    * Returns true for a valid connection.
435    */

436   boolean isValid(Subject JavaDoc subject,
437           ConnectionRequestInfo JavaDoc requestInfo,
438           UserPoolItem userPoolItem)
439   {
440     try {
441       ManagedConnection JavaDoc mConn = getManagedConnection();
442
443       if (mConn == null)
444     return false;
445
446       Object JavaDoc userConn = userPoolItem.getUserConnection();
447
448       if (userConn == null) {
449     userConn = mConn.getConnection(subject, requestInfo);
450
451     userPoolItem.setUserConnection(userConn);
452       }
453
454       return userConn != null;
455     } catch (ResourceException JavaDoc e) {
456       log.log(Level.WARNING, e.toString(), e);
457
458       return false;
459     }
460   }
461
462   /**
463    * Returns the XA resource.
464    */

465   void enableLocalTransactionOptimization(boolean enableOptimization)
466   {
467     if (_xaResource == null)
468       _isXATransaction = false;
469     else if (_localTransaction == null)
470       _isXATransaction = true;
471     else if (! _cm.isLocalTransactionOptimization())
472       _isXATransaction = true;
473     else if (! _cm.isShareable())
474       _isXATransaction = true;
475     else
476       _isXATransaction = ! enableOptimization;
477   }
478
479   /**
480    * Returns true if the pooled connection supports transactions.
481    */

482   boolean supportsTransaction()
483   {
484     // server/164j
485
return _xaResource != null || _localTransaction != null;
486   }
487
488   /**
489    * Returns the XA resource.
490    */

491   XAResource JavaDoc getXAResource()
492   {
493     return _xaResource;
494   }
495
496   /**
497    * Returns the Xid resource.
498    */

499   Xid JavaDoc getXid()
500   {
501     return _xid;
502   }
503
504   /**
505    * Notifies that an application has closed the connection.
506    */

507   public void connectionClosed(ConnectionEvent JavaDoc event)
508   {
509     boolean addIdle = false;
510
511     Object JavaDoc handle = event.getConnectionHandle();
512
513     if (! _hasConnectionError && handle == null && _shareHead != null) {
514       log.fine(L.l("JCA close event '{0}' for {1} did not have a connection handle. Please notify the JCA resource provider.",
515           event, _mConn));
516     }
517
518     if (_shareHead == null) {
519       toIdle();
520       return;
521     }
522     
523     UserPoolItem userPoolItem = _shareHead;
524
525     while (userPoolItem != null) {
526       UserPoolItem next = userPoolItem.getShareNext();
527
528       Object JavaDoc userConn = userPoolItem.getUserConnection();
529
530       if (userConn == handle || handle == null)
531     userPoolItem.close();
532
533       userPoolItem = next;
534     }
535   }
536   
537   /**
538    * Notifies that a local transaction has started.
539    */

540   public void localTransactionStarted(ConnectionEvent JavaDoc event)
541   {
542     if (_isLocalTransaction || _xid != null)
543       throw new IllegalStateException JavaDoc(L.l("attempted to start local transaction while transaction is in progress."));
544     
545     if (_localTransaction != null) {
546       try {
547     _localTransaction.begin();
548     _isLocalTransaction = true;
549       } catch (ResourceException JavaDoc e) {
550     log.log(Level.WARNING, e.toString(), e);
551       }
552     }
553   }
554   
555   /**
556    * Notifies that a local transaction has committed.
557    */

558   public void localTransactionCommitted(ConnectionEvent JavaDoc event)
559   {
560     if (_xid != null)
561       throw new IllegalStateException JavaDoc(L.l("attempted to commit() local transaction from an active XA transaction."));
562     else if (! _isLocalTransaction)
563       throw new IllegalStateException JavaDoc(L.l("attempted to commit() with no active local transaction."));
564     
565     if (_localTransaction != null && _isLocalTransaction) {
566       try {
567     _isLocalTransaction = false;
568     _localTransaction.commit();
569       } catch (ResourceException JavaDoc e) {
570     log.log(Level.WARNING, e.toString(), e);
571       }
572     }
573   }
574   
575   /**
576    * Notifies that a local transaction has rolled back.
577    */

578   public void localTransactionRolledback(ConnectionEvent JavaDoc event)
579   {
580     if (_xid != null)
581       throw new IllegalStateException JavaDoc(L.l("attempted to rollback() local transaction from an active XA transaction."));
582     else if (! _isLocalTransaction)
583       throw new IllegalStateException JavaDoc(L.l("attempted to rollback() with no active local transaction."));
584     
585     if (_localTransaction != null) {
586       try {
587     _isLocalTransaction = false;
588     _localTransaction.rollback();
589       } catch (ResourceException JavaDoc e) {
590     log.log(Level.WARNING, e.toString(), e);
591       }
592     }
593   }
594   
595   /**
596    * Notifies that a connection error has occurred.
597    */

598   public void connectionErrorOccurred(ConnectionEvent JavaDoc event)
599   {
600     _hasConnectionError = true;
601   }
602   
603   /**
604    * Notifies that a connection error has occurred.
605    */

606   public void setConnectionError()
607   {
608     _hasConnectionError = true;
609   }
610
611   /**
612    * Returns true if there was a connection error.
613    */

614   public boolean isConnectionError()
615   {
616     return _hasConnectionError;
617   }
618
619   /**
620    * Returns the allocation stack trace.
621    */

622   public IllegalStateException JavaDoc getAllocationStackTrace()
623   {
624     return _allocationStackTrace;
625   }
626
627   /**
628    * Returns true if there is a connection error.
629    */

630
631   // XAResource stuff
632

633   /**
634    * identity of resources
635    */

636   public boolean isSameRM(XAResource JavaDoc resource)
637     throws XAException JavaDoc
638   {
639     if (! (resource instanceof PoolItem))
640       return false;
641
642     PoolItem poolItem = (PoolItem) resource;
643     
644     //if (_cm == poolItem._cm)
645
// return true;
646

647     if (_xaResource == null)
648       return false;
649
650     boolean isSameRM = _xaResource.isSameRM(poolItem._xaResource);
651     
652     if (log.isLoggable(Level.FINER))
653       log.finer("isSameRM->" + isSameRM + " " + _xaResource);
654
655     return isSameRM;
656   }
657   
658   /**
659    * starts work on a transaction branch
660    */

661   public void start(Xid JavaDoc xid, int flags)
662     throws XAException JavaDoc
663   {
664     if (_xid != null) {
665       if (log.isLoggable(Level.FINER))
666         log.finer("connection pool start XA: rejoin " + this);
667       
668       return;
669     }
670
671     if (flags == TMJOIN && _xid == null) {
672       // TMJOIN means the resource manager is managing more than one
673
// connection. The delegates tie the PoolItems managed by
674
// the same resource manager together.
675

676       _xid = xid;
677       
678       UserTransactionImpl trans = _cm.getTransaction();
679
680       if (trans != null) {
681     PoolItem xaHead = trans.findJoin(this);
682
683     if (xaHead != null) {
684       _xaNext = xaHead._xaNext;
685       _xaHead = xaHead;
686       xaHead._xaNext = this;
687     }
688       }
689       
690       /* XXX: is this still an issue?
691       if (_xaDelegate != this)
692         throw new IllegalStateException("pool state exception");
693       
694       PoolItem delegate = _cm.getDelegatePoolItem(xid);
695
696       // set to the delegate
697       _xaDelegate = delegate._xaDelegate;
698       
699       // single link list of parents
700       _xaDelegateNext = _xaDelegate._xaDelegateNext;
701       _xaDelegate._xaDelegateNext = this;
702       */

703
704       /*
705       if (log.isLoggable(Level.FINER))
706         log.finer("start XA: using delegate " + _xaDelegate + " for XID " + xid);
707       return;
708       */

709     }
710
711     // local transaction optimization
712
if (! _isXATransaction && flags != TMJOIN && _localTransaction != null) {
713       try {
714     if (log.isLoggable(Level.FINER))
715       log.finer("begin-local-XA: " + _localTransaction);
716
717     _localTransaction.begin();
718       } catch (ResourceException JavaDoc e) {
719     throw new XAExceptionWrapper(e);
720       }
721
722       _xid = xid;
723
724       return;
725     }
726
727     
728     if (_xaResource != null) {
729       if (log.isLoggable(Level.FINER))
730     log.finer("start-XA: " + xid + " " + _xaResource);
731
732       try {
733     _xaResource.start(xid, flags);
734       } catch (XAException JavaDoc e) {
735     throw e;
736       }
737     }
738     else {
739       if (log.isLoggable(Level.FINER))
740     log.finer("start-XA with non XA resource: " + xid + " " + _xaResource);
741     }
742     
743     _xid = xid;
744   }
745   
746   /**
747    * Sets the transaction timeout
748    */

749   public boolean setTransactionTimeout(int seconds)
750     throws XAException JavaDoc
751   {
752     if (seconds == _transactionTimeout)
753       return true;
754
755     XAResource JavaDoc xaResource = _xaResource;
756     
757     _transactionTimeout = seconds;
758
759     if (xaResource == null)
760       return true;
761     else if (seconds == 0)
762       return xaResource.setTransactionTimeout(_defaultTransactionTimeout);
763     else
764       return xaResource.setTransactionTimeout(seconds);
765   }
766
767   /**
768    * Returns the timeout of the underlying resource.
769    */

770   public int getTransactionTimeout()
771     throws XAException JavaDoc
772   {
773     return _transactionTimeout;
774   }
775
776   /**
777    * forget about the transaction
778    */

779   public void forget(Xid JavaDoc xid)
780     throws XAException JavaDoc
781   {
782     try {
783       if (_isXATransaction)
784     _xaResource.forget(xid);
785     } finally {
786       clearXid();
787     }
788   }
789
790   /**
791    * Vote using phase-1 of the 2-phase commit.
792    */

793   public int prepare(Xid JavaDoc xid)
794     throws XAException JavaDoc
795   {
796     if (_endFlags != -1) {
797       int endFlags = _endFlags;
798       _endFlags = -1;
799
800       if (_isXATransaction)
801     endResource(xid, endFlags);
802     }
803
804     if (_isXATransaction) {
805       try {
806     if (log.isLoggable(Level.FINER))
807       log.finer("prepare-XA: " + xid + " " + _xaResource);
808
809     return _xaResource.prepare(xid);
810       } catch (XAException JavaDoc e) {
811     if (log.isLoggable(Level.FINER))
812       log.finer("failed prepare-XA: " + xid + " " + _xaResource + " " + e);
813
814     throw e;
815       }
816     }
817     else
818       return XA_OK;
819   }
820
821   /**
822    * recover the transaction
823    */

824   public Xid JavaDoc[]recover(int flag)
825     throws XAException JavaDoc
826   {
827     if (_isXATransaction)
828       return _xaResource.recover(flag);
829     else
830       return null;
831   }
832   
833   /**
834    * Ends work with the resource. Called before commit/rollback.
835    */

836   public void end(Xid JavaDoc xid, int flags)
837     throws XAException JavaDoc
838   {
839     /* XXX:
840     if (_xid == null)
841       throw new IllegalStateException("ending with no transaction");
842     */

843
844     //if (log.isLoggable(Level.FINER))
845
// log.finer("connection pool end XA: " + this + " xa=" + xid + " flags=" + flags);
846

847     _endFlags = flags;
848
849     // XXX: In theory, drop the _xid. The underlying XADataSource
850
// can handle combining the connections itself.
851

852     // Don't call the underlying _xaResource.end. The commit or rollback
853
// will handle that automatically.
854
}
855   
856   /**
857    * rollback the resource
858    */

859   public void rollback(Xid JavaDoc xid)
860     throws XAException JavaDoc
861   {
862     try {
863       if (_endFlags != -1) {
864     try {
865       int endFlags = _endFlags;
866       _endFlags = -1;
867
868       if (_isXATransaction)
869         endResource(xid, endFlags);
870     } catch (Throwable JavaDoc e) {
871       log.log(Level.WARNING, e.toString(), e);
872       if (_isXATransaction)
873         _xaResource.rollback(xid);
874       return;
875     }
876       }
877     
878       if (log.isLoggable(Level.FINER))
879     log.finer("connection pool rollback XA: " + this);
880
881       if (_isXATransaction)
882     _xaResource.rollback(xid);
883       else if (_localTransaction != null) {
884     try {
885       _isLocalTransaction = false;
886       _localTransaction.rollback();
887     } catch (ResourceException JavaDoc e) {
888       throw new XAExceptionWrapper(e);
889     }
890       }
891     } finally {
892       if (_xaResource != null)
893     _isXATransaction = true;
894       
895       clearXid();
896     }
897   }
898   
899   /**
900    * commit the resource
901    */

902   public void commit(Xid JavaDoc xid, boolean onePhase)
903     throws XAException JavaDoc
904   {
905     boolean logFiner = log.isLoggable(Level.FINER);
906     
907     try {
908       if (_endFlags != -1) {
909     try {
910       int endFlags = _endFlags;
911       _endFlags = -1;
912
913       if (_isXATransaction)
914         endResource(xid, endFlags);
915     } catch (XAException JavaDoc e) {
916       log.log(Level.WARNING, e.toString(), e);
917       _xaResource.rollback(xid);
918       throw e;
919     } catch (Throwable JavaDoc e) {
920       log.log(Level.WARNING, e.toString(), e);
921       _xaResource.rollback(xid);
922       throw new XAException JavaDoc(XAException.XA_RBOTHER);
923     }
924       }
925
926       if (_isXATransaction) {
927     if (logFiner) {
928       log.finer("commit-XA" + (onePhase ? "-1p: " : ": ")
929             + xid + " " + _xaResource);
930     }
931
932     try {
933       _xaResource.commit(xid, onePhase);
934     } catch (XAException JavaDoc e) {
935       if (logFiner)
936         log.finer("commit-XA failed: " + _xaResource + " " + e);
937       
938       throw e;
939     }
940       }
941       else if (_localTransaction != null) {
942     if (logFiner)
943       log.finer("commit-local: " + _localTransaction);
944       
945     try {
946       _isLocalTransaction = false;
947       _localTransaction.commit();
948     } catch (ResourceException JavaDoc e) {
949       if (logFiner)
950         log.finer("commit failed: " + _localTransaction + " " + e);
951       
952       throw new XAExceptionWrapper(e);
953     }
954       }
955       else {
956     if (logFiner)
957       log.finer("commit for resource with no XA support: " + this);
958       }
959     } finally {
960       if (_xaResource != null)
961     _isXATransaction = true;
962       
963       clearXid();
964     }
965   }
966
967   /**
968    * Ends the resource.
969    */

970   private void endResource(Xid JavaDoc xid, int flags)
971     throws XAException JavaDoc
972   {
973     PoolItem xaPtr = this;
974
975     for (; xaPtr != null; xaPtr = xaPtr._xaNext) {
976       if (xaPtr._xaResource != null)
977     xaPtr._xaResource.end(xid, flags);
978     }
979   }
980   
981   /**
982    * Restores the delegation for the entire chain.
983    */

984   private void clearXid()
985   {
986     _xid = null;
987     
988     UserPoolItem shareHead = _shareHead;
989     // _shareHead is nullified at end for timing reasons
990

991     PoolItem xaPtr = _xaNext;
992     _xaHead = null;
993     _xaNext = null;
994
995     boolean isClosed = true;
996
997     UserPoolItem ptr = shareHead;
998     while (ptr != null) {
999       UserPoolItem next = ptr.getShareNext();
1000      
1001      if (ptr.getOwnPoolItem() == this)
1002    isClosed = false;
1003
1004      try {
1005    ptr.reassociatePoolItem();
1006      } catch (Throwable JavaDoc e) {
1007    log.log(Level.WARNING, e.toString(), e);
1008      }
1009
1010      ptr = next;
1011    }
1012
1013    while (xaPtr != null) {
1014      PoolItem next = xaPtr._xaNext;
1015      xaPtr._xaNext = null;
1016      xaPtr._xaHead = null;
1017
1018      xaPtr.clearXid();
1019
1020      xaPtr = next;
1021    }
1022
1023    if (! isClosed) {
1024    }
1025    else if (_hasConnectionError) {
1026      toDead();
1027    }
1028    else {
1029      toIdle();
1030    }
1031  }
1032
1033  /**
1034   * Changes the state to idle.
1035   */

1036  void toIdle()
1037  {
1038    if (_shareHead != null)
1039      return;
1040    else if (_xid != null || _isLocalTransaction)
1041      return;
1042    else if (_hasConnectionError) {
1043      toDead();
1044      return;
1045    }
1046
1047    UserTransactionImpl transaction = _transaction;
1048    _transaction = null;
1049      
1050    if (transaction != null) {
1051      try {
1052    transaction.delistPoolItem(this, XAResource.TMSUCCESS);
1053      } catch (Throwable JavaDoc e) {
1054    log.log(Level.FINE, e.toString(), e);
1055      }
1056    }
1057
1058    _isLocalTransaction = false;
1059
1060    if (log.isLoggable(Level.FINE))
1061      log.fine("idle " + this);
1062
1063    _poolEventTime = Alarm.getCurrentTime();
1064    _cm.toIdle(this);
1065  }
1066
1067  /**
1068   * Closes the connection.
1069   */

1070  void abortConnection()
1071  {
1072    toDead();
1073  }
1074
1075  /**
1076   * Kills the connection.
1077   */

1078  private void toDead()
1079  {
1080    _cm.toDead(this);
1081  }
1082
1083  /**
1084   * Closes the connection.
1085   */

1086  void destroy()
1087    throws ResourceException JavaDoc
1088  {
1089    ManagedConnection JavaDoc mConn = _mConn;
1090    _mConn = null;
1091
1092    UserTransactionImpl transaction = _transaction;
1093    _transaction = null;
1094
1095    if (mConn == null)
1096      return;
1097
1098    UserPoolItem userItem = _shareHead;
1099
1100    if (log.isLoggable(Level.FINE))
1101      log.fine("connection pool destroy " + this);
1102
1103    try {
1104      while (userItem != null) {
1105    UserPoolItem next = userItem.getShareNext();
1106
1107    userItem.close();
1108
1109    userItem = next;
1110      }
1111    
1112      if (transaction != null)
1113    transaction.delistPoolItem(this, XAResource.TMFAIL);
1114    } catch (Throwable JavaDoc e) {
1115      log.log(Level.FINE, e.toString(), e);
1116    }
1117
1118    mConn.destroy();
1119  }
1120
1121  public String JavaDoc toString()
1122  {
1123    return "PoolItem[" + _cm.getName() + "," + _id + "," + _mConn + "]";
1124  }
1125}
1126
Popular Tags