User: mulder  
  Date: 00/10/20 22:20:24

  Modified:    src/main/org/jboss/tm TransactionImpl.java TxCapsule.java
                        XidImpl.java
  Log:
  Make jBoss work with Oracle XADataSource driver.
  Not yet a very elegant solution - we need to be able to use a different
      Xid implementation class per pool for this to really work right.
  
  The requirements of the Oracle driver were:
   - Xid must be instanceof OracleXid
   - Global and Branch IDs must be exactly 64 bytes
   - RM that end is called on must be *exactly* the same as start
        was called on (XAConnection.getXAResource returns a different
        instance each time *despite* the documented 1-to-1 relation)
   - Can't execute DDL (create/drop table, etc) within a transaction
  
  Haven't tested this well with multiple data sources - that's next.
  
  Revision  Changes    Path
  1.10      +8 -8      jboss/src/main/org/jboss/tm/TransactionImpl.java
  
  Index: TransactionImpl.java
  ===================================================================
  RCS file: /products/cvs/ejboss/jboss/src/main/org/jboss/tm/TransactionImpl.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- TransactionImpl.java      2000/09/28 21:10:11     1.9
  +++ TransactionImpl.java      2000/10/21 05:20:23     1.10
  @@ -35,7 +35,7 @@
    *  @author Rickard �berg ([EMAIL PROTECTED])
    *  @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
    *  @author <a href="mailto:[EMAIL PROTECTED]">Ole Husgaard</a>
  - *  @version $Revision: 1.9 $
  + *  @version $Revision: 1.10 $
    */
   public class TransactionImpl
      implements Transaction, Serializable
  @@ -44,17 +44,17 @@
   
      // Attributes ----------------------------------------------------
   
  -   XidImpl xid; // Transaction ID.
  -   
  +   Xid xid; // Transaction ID.
  +
      // Constructors --------------------------------------------------
  -   
  -   TransactionImpl(TxCapsule txCapsule, XidImpl xid)
  +
  +   TransactionImpl(TxCapsule txCapsule, Xid xid)
      {
         this.txCapsule = txCapsule;
  -      this.xid = xid; 
  +      this.xid = xid;
         travelled = false;
      }
  -   
  +
      // Public --------------------------------------------------------
   
      // In the following methods we synchronize to avoid races with transaction
  @@ -153,7 +153,7 @@
   
      public int hashCode()
      {
  -      return xid.hash;
  +      return xid.hashCode();
      }
   
      public String toString()
  
  
  
  1.17      +64 -29    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.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- TxCapsule.java    2000/10/20 03:14:56     1.16
  +++ TxCapsule.java    2000/10/21 05:20:23     1.17
  @@ -7,6 +7,7 @@
   package org.jboss.tm;
   
   import java.io.Serializable;
  +import java.lang.reflect.Constructor;
   import java.util.ArrayList;
   import java.util.Set;
   import java.util.HashSet;
  @@ -43,14 +44,16 @@
    *  @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
    *  @author <a href="mailto:[EMAIL PROTECTED]">Ole Husgaard</a>
    *
  - *  @version $Revision: 1.16 $
  + *  @version $Revision: 1.17 $
    */
   class TxCapsule implements TimeoutTarget
   {
      // Constants -----------------------------------------------------
   
      // Trace enabled flag
  -   static private final boolean trace = true;
  +   static private final boolean trace = false;
  +   // Constructor for Xid instances
  +   private static Constructor xidConstructor = null;
   
      // Code meaning "no heuristics seen", must not be XAException.XA_HEURxxx
      static private final int HEUR_NONE     = XAException.XA_RETRY;
  @@ -85,7 +88,7 @@
       */
      private TxCapsule(TxManager tm)
      {
  -      xid = new XidImpl();
  +      xid = createXid();
         this.tm = tm;
   
         if (trace)
  @@ -114,7 +117,7 @@
         done = false;
         resourcesEnded = false;
   
  -      xid = new XidImpl();
  +      xid = createXid();
   
         status = Status.STATUS_ACTIVE;
         heuristicCode = HEUR_NONE;
  @@ -194,7 +197,7 @@
   
      // Package protected ---------------------------------------------
   
  -   XidImpl getXid()
  +   Xid getXid()
      {
          return xid;
      }
  @@ -732,7 +735,7 @@
      /**
       *  The ID of this transaction.
       */
  -   private XidImpl xid; // Transaction id
  +   private Xid xid; // Transaction id
   
      /**
       *  Status of this transaction.
  @@ -803,7 +806,7 @@
               return "STATUS_MARKED_ROLLBACK";
            case Status.STATUS_ACTIVE:
               return "STATUS_ACTIVE";
  - 
  +
            default:
               return "STATUS_UNKNOWN(" + status + ")";
         }
  @@ -864,7 +867,7 @@
               return "XAER_RMERR";
            case XAException.XAER_RMFAIL:
               return "XAER_RMFAIL";
  - 
  +
            default:
               return "XA_UNKNOWN(" + errorCode + ")";
         }
  @@ -890,7 +893,7 @@
               } 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 
  +            // we need to release all the thread waiting on this lock
   
               // OSH: notifyAll() is done in instanceDone()
               // and notify() is done in unlock().
  @@ -942,14 +945,16 @@
      /**
       *  Return index of XAResource, or <code>-1</code> if not found.
       */
  -   private int findResource(XAResource xaRes)
  -   {
  -      for (int i = 0; i < resourceCount; ++i)
  -         if (resources[i] == xaRes)
  -            return i;
  +    private int findResource(XAResource xaRes) {
  +        int pos = -1;
  +        for (int i = 0; i < resourceCount; ++i)
  +            try { // FIXME: Do we need to join if there's more than one?
  +                if(resources[i].isSameRM(xaRes))
  +                    pos = i;
  +            } catch(XAException e) {}
   
  -      return -1;
  -   }
  +        return pos;
  +    }
   
      /**
       *  Add a resource, expanding tables if needed.
  @@ -996,18 +1001,20 @@
      private void startResource(XAResource xaRes, int flags)
         throws XAException
      {
  -        Logger.debug("TxCapsule.startResource(" + xid.toString() +
  -                   ") entered: " + xaRes.toString() +
  -                   " flags=" + flags);
  +        if(trace)
  +            Logger.debug("TxCapsule.startResource(" + xid.toString() +
  +                         ") entered: " + xaRes.toString() +
  +                         " flags=" + flags);
         unlock();
         // OSH FIXME: resourceState could be incorrect during this callout.
         try {
            xaRes.start(xid, flags);
         } finally {
            lock();
  -        Logger.debug("TxCapsule.startResource(" + xid.toString() +
  -                   ") leaving: " + xaRes.toString() +
  -                   " flags=" + flags);
  +         if(trace)
  +            Logger.debug("TxCapsule.startResource(" + xid.toString() +
  +                         ") leaving: " + xaRes.toString() +
  +                         " flags=" + flags);
         }
      }
   
  @@ -1018,18 +1025,20 @@
      private void endResource(XAResource xaRes, int flag)
         throws XAException
      {
  -      Logger.debug("TxCapsule.endResource(" + xid.toString() +
  -                   ") entered: " + xaRes.toString() +
  -                   " flag=" + flag);
  +      if(trace)
  +          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);
  +         if(trace)
  +             Logger.debug("TxCapsule.endResource(" + xid.toString() +
  +                          ") leaving: " + xaRes.toString() +
  +                          " flag=" + flag);
         }
      }
   
  @@ -1304,7 +1313,9 @@
         status = Status.STATUS_COMMITTING;
   
         for (int i = 0; i < resourceCount; i++) {
  -        Logger.debug("TxCapsule.commitResources(): 
resourceStates["+i+"]="+resourceState[i]);
  +         if(trace) {
  +            Logger.debug("TxCapsule.commitResources(): 
resourceStates["+i+"]="+resourceState[i]);
  +         }
            if (!onePhase && resourceState[i] != RS_VOTE_OK)
              continue;
   
  @@ -1376,11 +1387,35 @@
                  Logger.exception(e);
                  break;
               }
  +            try {
  +                resources[i].forget(xid);
  +            } catch(XAException forgetEx) {}
            }
         }
   
         status = Status.STATUS_ROLLEDBACK;
      }
  +
  +    private Xid createXid() {
  +        String name = System.getProperty("jboss.xa.xidclass", 
"org.jboss.tm.XidImpl");
  +        if(xidConstructor == null) {
  +            try {
  +                Class cls = Class.forName(name);
  +                xidConstructor = cls.getConstructor(new Class[]{Integer.TYPE, 
byte[].class, byte[].class});
  +            } catch(Exception e) {
  +                System.out.println("Unable to load Xid class '"+name+"'");
  +            }
  +        }
  +        try {
  +            Object xid = xidConstructor.newInstance(new Object[]{new 
Integer(XidImpl.getJbossFormatId()),
  +                                                                 
XidImpl.getGlobalIdString(XidImpl.getNextId()),
  +                                                                 
XidImpl.noBranchQualifier});
  +            return (Xid)xid;
  +        } catch(Exception e) {
  +            System.out.println("Unable to create an Xid (reverting to default 
impl): "+e);
  +            return new XidImpl(XidImpl.getJbossFormatId(), 
XidImpl.getGlobalIdString(XidImpl.getNextId()), XidImpl.noBranchQualifier);
  +        }
  +    }
   
      // Inner classes -------------------------------------------------
   }
  
  
  
  1.5       +36 -20    jboss/src/main/org/jboss/tm/XidImpl.java
  
  Index: XidImpl.java
  ===================================================================
  RCS file: /products/cvs/ejboss/jboss/src/main/org/jboss/tm/XidImpl.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- XidImpl.java      2000/09/28 21:10:11     1.4
  +++ XidImpl.java      2000/10/21 05:20:23     1.5
  @@ -18,13 +18,13 @@
    *  @see TransactionImpl
    *  @author Rickard �berg ([EMAIL PROTECTED])
    *  @author <a href="mailto:[EMAIL PROTECTED]">Ole Husgaard</a>
  - *  @version $Revision: 1.4 $
  + *  @version $Revision: 1.5 $
    */
   class XidImpl
      implements Xid, java.io.Serializable
   {
      // Constants -----------------------------------------------------
  -    
  +
      // Attributes ----------------------------------------------------
   
      /**
  @@ -42,7 +42,7 @@
       *  This identifies the branch of a transaction.
       */
      byte[] branchId;
  -    
  +
      // Static --------------------------------------------------------
   
      /**
  @@ -66,7 +66,7 @@
               hostName = "localhost/";
            }
         }
  - 
  +
         return hostName;
      }
   
  @@ -78,7 +78,7 @@
      /**
       *  Return a new unique transaction id to use on this host.
       */
  -   static private synchronized int getNextId()
  +   static synchronized int getNextId()
      {
         return nextId++;
      }
  @@ -86,18 +86,22 @@
      /**
       *  Singleton for no branch qualifier.
       */
  -   static private byte[] noBranchQualifier = new byte[0];
  +    static byte[] noBranchQualifier = new byte[MAXBQUALSIZE];
  +    static {
  +        for(int i=0; i<noBranchQualifier.length; i++)
  +            noBranchQualifier[i] = 0;
  +    }
   
      // Constructors --------------------------------------------------
   
      /**
       *  Create a new unique branch qualifier.
       */
  -   public XidImpl()
  +   public XidImpl(int formatId, byte[] globalId, byte[] branchId)
      {
  -      hash = getNextId();
  -      this.globalId = getGlobalIdString().getBytes();
  -      this.branchId = noBranchQualifier;
  +      this.hash = getNextId();
  +      this.globalId = globalId;
  +      this.branchId = branchId;
      }
   
      /**
  @@ -109,9 +113,9 @@
         this.globalId = xid.globalId;
         this.branchId = branchId;
      }
  -   
  +
      // Public --------------------------------------------------------
  -   
  +
      // Xid implementation --------------------------------------------
   
      /**
  @@ -121,7 +125,7 @@
      {
         return (byte[])globalId.clone();
      }
  -   
  +
      /**
       *  Return the branch qualifier of this transaction.
       */
  @@ -139,7 +143,11 @@
       *  The format identifier augments the global id and specifies
       *  how the global id and branch qualifier should be interpreted.
       */
  -   public int getFormatId()
  +   public int getFormatId() {
  +       return getJbossFormatId();
  +   }
  +
  +   public static int getJbossFormatId()
      {
         // The id we return here should be different from all other transaction
         // implementations.
  @@ -150,7 +158,7 @@
         //         OSI TP do have the same id format.)
         // 0xBB14: Used by JONAS
         // 0xBB20: Used by JONAS
  -      return 1;
  +      return 0x0101;
      }
   
      /**
  @@ -185,18 +193,26 @@
   
      public String toString()
      {
  -      return "XidImpl:" + getGlobalIdString();
  +      return "XidImpl:" + getGlobalTransactionId();
      }
   
      // Package protected ---------------------------------------------
  -    
  +
      // Protected -----------------------------------------------------
  -    
  +
      // Private -------------------------------------------------------
   
  -   private String getGlobalIdString()
  +   static byte[] getGlobalIdString(int hash)
      {
  -      return getHostName() + hash;
  +      String value;
  +      String s = getHostName();
  +      String h = Integer.toString(hash);
  +      if(s.length() + h.length() > 64) {
  +          value = s.substring(0, 64-h.length())+h;
  +      } else value = s+h;
  +      byte b[] = new byte[MAXGTRIDSIZE];
  +      System.arraycopy(value.getBytes(), 0, b, 0, value.length());
  +      return b;
      }
   
      // Inner classes -------------------------------------------------
  
  
  

Reply via email to