User: osh     
  Date: 00/10/18 07:28:53

  Modified:    src/main/org/jboss/tm TxCapsule.java
  Log:
  Fix for possible race on instance reuse.
  More trace information.
  Still outstanding: A problem with invalid XA resource state during
  XA resource calls.
  
  Revision  Changes    Path
  1.15      +132 -36   jboss/src/main/org/jboss/tm/TxCapsule.java
  
  Index: TxCapsule.java
  ===================================================================
  RCS file: /products/cvs/ejboss/jboss/src/main/org/jboss/tm/TxCapsule.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- TxCapsule.java    2000/10/15 19:05:07     1.14
  +++ TxCapsule.java    2000/10/18 14:28:53     1.15
  @@ -43,7 +43,7 @@
    *  @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
    *  @author <a href="mailto:[EMAIL PROTECTED]">Ole Husgaard</a>
    *
  - *  @version $Revision: 1.14 $
  + *  @version $Revision: 1.15 $
    */
   class TxCapsule implements TimeoutTarget
   {
  @@ -87,6 +87,9 @@
      {
         xid = new XidImpl();
         this.tm = tm;
  +
  +      if (trace)
  +         Logger.debug("TxCapsule: Created new instance for tx=" + toString());
      }
   
      /**
  @@ -118,6 +121,9 @@
   
         start = System.currentTimeMillis();
         this.timeout = TimeoutFactory.createTimeout(start+timeout, this);
  +
  +      if (trace)
  +         Logger.debug("TxCapsule: Reused instance for tx=" + toString());
      }
   
      // Public --------------------------------------------------------
  @@ -130,7 +136,8 @@
         try {
            lock();
   
  -         Logger.warning("Transaction " + toString() + " timed out.");
  +         Logger.warning("Transaction " + toString() + " timed out." +
  +                        " status=" + getStringStatus(status));
   
            if (this.timeout == null)
               return; // Don't race with timeout cancellation.
  @@ -167,6 +174,7 @@
               rollbackResources();
               doAfterCompletion();
               gotHeuristic(null, XAException.XA_HEURRB);
  +            instanceDone();
               return;
   
            case Status.STATUS_PREPARING:
  @@ -174,7 +182,8 @@
               return; // commit will fail
   
            default:
  -            Logger.warning("TxCapsule: Unknown status at timeout.");
  +            Logger.warning("TxCapsule: Unknown status at timeout, tx=" +
  +                           toString());
               return;
            }
         } finally {
  @@ -225,8 +234,8 @@
            lock();
   
            if (trace)
  -            Logger.debug("TxCapsule.commit(): Entered, status=" +
  -                         getStringStatus(status));
  +            Logger.debug("TxCapsule.commit(): Entered, tx=" + toString() +
  +                         " status=" + getStringStatus(status));
   
            switch (status) {
            case Status.STATUS_PREPARING:
  @@ -268,7 +277,8 @@
   
            if (trace)
               Logger.debug("TxCapsule.commit(): Before completion done, " +
  -                         "status=" + getStringStatus(status));
  +                         "tx=" + toString() +
  +                         " status=" + getStringStatus(status));
   
            endResources();
   
  @@ -309,8 +319,8 @@
               doAfterCompletion();
               cancelTimeout();
               instanceDone();
  -            throw new RollbackException("Unable to commit, status=" +
  -                                        getStringStatus(status));
  +            throw new RollbackException("Unable to commit, tx=" + toString() +
  +                                        " status=" + getStringStatus(status));
            }
   
            cancelTimeout();
  @@ -319,7 +329,8 @@
            checkHeuristics();
   
            if (trace)
  -            Logger.debug("TxCapsule.commit(): Committed OK.");
  +            Logger.debug("TxCapsule.commit(): Transaction " + toString() +
  +                         " committed OK.");
   
         } finally {
           unlock();
  @@ -340,8 +351,8 @@
            lock();
   
            if (trace)
  -            Logger.debug("TxCapsule.rollback(): Entered, status=" +
  -                         getStringStatus(status));
  +            Logger.debug("TxCapsule.rollback(): Entered, tx=" + toString() +
  +                         " status=" + getStringStatus(status));
   
            switch (status) {
            case Status.STATUS_ACTIVE:
  @@ -361,7 +372,9 @@
               status = Status.STATUS_MARKED_ROLLBACK;
               return; // commit() will do rollback.
            default:
  -            throw new IllegalStateException("Cannot rollback(), status=" +
  +            throw new IllegalStateException("Cannot rollback(), " +
  +                                            "tx=" + toString() +
  +                                            " status=" +
                                               getStringStatus(status));
            }
         } finally {
  @@ -383,8 +396,8 @@
            lock();
   
            if (trace)
  -            Logger.debug("TxCapsule.setRollbackOnly(): Entered, status=" +
  -                         getStringStatus(status));
  +            Logger.debug("TxCapsule.setRollbackOnly(): Entered, tx=" +
  +                         toString() + " status=" + getStringStatus(status));
   
            switch (status) {
            case Status.STATUS_ACTIVE:
  @@ -438,8 +451,8 @@
            lock();
   
            if (trace)
  -            Logger.debug("TxCapsule.delistResource(): Entered, status=" +
  -                         getStringStatus(status));
  +            Logger.debug("TxCapsule.delistResource(): Entered, tx=" +
  +                         toString() + " status=" + getStringStatus(status));
   
            int idx = findResource(xaRes);
   
  @@ -481,6 +494,8 @@
               }
               return true;
            } catch(XAException e) {
  +            Logger.warning("XAException: tx=" + toString() + " errorCode=" +
  +                           getStringXAErrorCode(e.errorCode));
               Logger.exception(e);
               status = Status.STATUS_MARKED_ROLLBACK;
               return false;
  @@ -509,8 +524,8 @@
            lock();
   
            if (trace)
  -            Logger.debug("TxCapsule.enlistResource(): Entered, status=" +
  -                         getStringStatus(status));
  +            Logger.debug("TxCapsule.enlistResource(): Entered, tx=" +
  +                         toString() + " status=" + getStringStatus(status));
   
            switch (status) {
            case Status.STATUS_ACTIVE:
  @@ -569,6 +584,8 @@
               addResource(xaRes);
               return true;
            } catch(XAException e) {
  +            Logger.warning("XAException: tx=" + toString() + " errorCode=" +
  +                           getStringXAErrorCode(e.errorCode));
               Logger.exception(e);
               return false;
            }
  @@ -603,7 +620,8 @@
   
            if (trace)
               Logger.debug("TxCapsule.registerSynchronization(): Entered, " +
  -                         "status=" + getStringStatus(status));
  +                         "tx=" + toString() +
  +                         " status=" + getStringStatus(status));
   
            switch (status) {
            case Status.STATUS_ACTIVE:
  @@ -796,15 +814,76 @@
      }
   
      /**
  +    *  Return a string representation of the given XA error code.
  +    */
  +   private String getStringXAErrorCode(int errorCode) {
  +      switch (errorCode) {
  +         case XAException.XA_HEURCOM:
  +            return "XA_HEURCOM";
  +         case XAException.XA_HEURHAZ:
  +            return "XA_HEURHAZ";
  +         case XAException.XA_HEURMIX:
  +            return "XA_HEURMIX";
  +         case XAException.XA_HEURRB:
  +            return "XA_HEURRB";
  +
  +         case XAException.XA_NOMIGRATE:
  +            return "XA_NOMIGRATE";
  +
  +         case XAException.XA_RBCOMMFAIL:
  +            return "XA_RBCOMMFAIL";
  +         case XAException.XA_RBDEADLOCK:
  +            return "XA_RBDEADLOCK";
  +         case XAException.XA_RBINTEGRITY:
  +            return "XA_RBINTEGRITY";
  +         case XAException.XA_RBOTHER:
  +            return "XA_RBOTHER";
  +         case XAException.XA_RBPROTO:
  +            return "XA_RBPROTO";
  +         case XAException.XA_RBROLLBACK:
  +            return "XA_RBROLLBACK";
  +         case XAException.XA_RBTIMEOUT:
  +            return "XA_RBTIMEOUT";
  +         case XAException.XA_RBTRANSIENT:
  +            return "XA_RBTRANSIENT";
  +
  +         case XAException.XA_RDONLY:
  +            return "XA_RDONLY";
  +         case XAException.XA_RETRY:
  +            return "XA_RETRY";
  +
  +         case XAException.XAER_ASYNC:
  +            return "XAER_ASYNC";
  +         case XAException.XAER_DUPID:
  +            return "XAER_DUPID";
  +         case XAException.XAER_INVAL:
  +            return "XAER_INVAL";
  +         case XAException.XAER_NOTA:
  +            return "XAER_NOTA";
  +         case XAException.XAER_OUTSIDE:
  +            return "XAER_OUTSIDE";
  +         case XAException.XAER_PROTO:
  +            return "XAER_PROTO";
  +         case XAException.XAER_RMERR:
  +            return "XAER_RMERR";
  +         case XAException.XAER_RMFAIL:
  +            return "XAER_RMFAIL";
  + 
  +         default:
  +            return "XA_UNKNOWN(" + errorCode + ")";
  +      }
  +   }
  +
  +   /**
       *  Lock this instance.
       */
      private synchronized void lock()
      {
         if (done)
  -         throw new IllegalStateException("No transaction");
  +         throw new IllegalStateException("Transaction has terminated");
   
         if (locked) {
  -         Logger.warning("TxCapsule: Lock contention."); // Good for debugging.
  +         Logger.warning("TxCapsule: Lock contention, tx=" + toString());
            Thread.currentThread().dumpStack();
   
            long myIncarnation = incarnationCount;
  @@ -813,11 +892,15 @@
               try {
                  wait();
               } catch (InterruptedException ex) {}
  +
  +            // MF FIXME: don't we need a notify() in this case?
  +            // we need to release all the thread waiting on this lock 
   
  -                     // MF FIXME: don't we need a notify() in this case?
  -                     // we need to release all the thread waiting on this lock 
  +            // OSH: notifyAll() is done in instanceDone()
  +            // and notify() is done in unlock().
  +
               if (done || myIncarnation != incarnationCount)
  -              throw new IllegalStateException("No transaction");
  +              throw new IllegalStateException("Transaction has now terminated");
            }
         }
   
  @@ -829,8 +912,11 @@
       */
      private synchronized void unlock()
      {
  -      if (!locked)
  -         Logger.warning("TxCapsule: Unlocking, but not locked.");
  +      if (!locked) {
  +         Logger.warning("TxCapsule: Unlocking, but not locked, tx=" +
  +                        toString());
  +         Logger.exception(new Exception("[Stack trace]"));
  +      }
   
         locked = false;
   
  @@ -918,6 +1004,7 @@
                      ") entered: " + xaRes.toString() +
                      " flags=" + flags);
         unlock();
  +      // OSH FIXME: resourceState could be incorrect during this callout.
         try {
            xaRes.start(xid, flags);
         } finally {
  @@ -935,17 +1022,18 @@
      private void endResource(XAResource xaRes, int flag)
         throws XAException
      {
  -        Logger.debug("TxCapsule.endResource(" + xid.toString() +
  +      Logger.debug("TxCapsule.endResource(" + xid.toString() +
                      ") entered: " + xaRes.toString() +
                      " flag=" + flag);
         unlock();
  +      // OSH FIXME: resourceState could be incorrect during this callout.
         try {
            xaRes.end(xid, flag);
         } finally {
            lock();
  -        Logger.debug("TxCapsule.endResource(" + xid.toString() +
  -                   ") leaving: " + xaRes.toString() +
  -                   " flag=" + flag);
  +         Logger.debug("TxCapsule.endResource(" + xid.toString() +
  +                      ") leaving: " + xaRes.toString() +
  +                      " flag=" + flag);
         }
      }
   
  @@ -978,8 +1066,8 @@
                 resourceState[i] = RS_ENDED;
               }
            } catch(XAException e) {
  -            Logger.debug("endresources: XAException: " + e);
  -            Logger.debug("endresources: XAException: errorCode=" + e.errorCode);
  +            Logger.warning("XAException: tx=" + toString() + " errorCode=" +
  +                           getStringXAErrorCode(e.errorCode));
               Logger.exception(e);
               status = Status.STATUS_MARKED_ROLLBACK;
            }
  @@ -1061,6 +1149,8 @@
               unlock();
               resource.forget(xid);
            } catch (XAException e) {
  +            Logger.warning("XAException at forget(): errorCode=" +
  +                           getStringXAErrorCode(e.errorCode));
               Logger.exception(e);
            } finally {
               lock();
  @@ -1107,6 +1197,10 @@
       */
      private void instanceDone()
      {
  +      // Notify transaction fronts that we are done.
  +      for (int i = 0; i < transactionCount; ++i)
  +        transactions[i].setDone();
  +
         synchronized (this) {
            // Done with this incarnation.
            ++incarnationCount;
  @@ -1119,10 +1213,6 @@
            notifyAll();
         }
   
  -      // Notify transaction fronts that we are done.
  -      for (int i = 0; i < transactionCount; ++i)
  -        transactions[i].setDone();
  -
         // Clear content of collections.
         syncCount = 0;
         transactionCount = 0;
  @@ -1193,6 +1283,8 @@
                     status = Status.STATUS_MARKED_ROLLBACK;
                  break;
               default:
  +               Logger.warning("XAException: tx=" + toString() + " errorCode=" +
  +                              getStringXAErrorCode(e.errorCode));
                  Logger.exception(e);
                  if (status == Status.STATUS_PREPARING)
                     status = Status.STATUS_MARKED_ROLLBACK;
  @@ -1240,6 +1332,8 @@
                  gotHeuristic(resources[i], e.errorCode);
                  break;
               default:
  +               Logger.warning("XAException: tx=" + toString() + " errorCode=" +
  +                              getStringXAErrorCode(e.errorCode));
                  Logger.exception(e);
                  break;
               }
  @@ -1281,6 +1375,8 @@
                  gotHeuristic(resources[i], e.errorCode);
                  break;
               default:
  +               Logger.warning("XAException: tx=" + toString() + " errorCode=" +
  +                              getStringXAErrorCode(e.errorCode));
                  Logger.exception(e);
                  break;
               }
  
  
  

Reply via email to