[jboss-svn-commits] JBL Code SVN: r14945 - in labs/jbosstm/trunk: atsintegration/classes/com/arjuna/ats/jbossatx/jta and 1 other directory.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Sat Sep 8 11:24:22 EDT 2007


Author: jhalliday
Date: 2007-09-08 11:24:21 -0400 (Sat, 08 Sep 2007)
New Revision: 14945

Modified:
   labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/TransactionImple.java
   labs/jbosstm/trunk/atsintegration/classes/com/arjuna/ats/jbossatx/jta/TransactionManagerDelegate.java
Log:
Ported work for JBTM-289 (JBossAS tx locking) from 4.2.3.SP branch to trunk


Modified: labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/TransactionImple.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/TransactionImple.java	2007-09-08 15:08:55 UTC (rev 14944)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/TransactionImple.java	2007-09-08 15:24:21 UTC (rev 14945)
@@ -122,8 +122,10 @@
 		_duplicateResources = new Hashtable();
 		_suspendCount = 0;
 		_xaTransactionTimeoutEnabled = getXATransactionTimeoutEnabled();
-	}
 
+        _txLocalResources = Collections.synchronizedMap(new HashMap());
+    }
+
 	/**
 	 * Overloads Object.equals()
 	 */
@@ -1275,23 +1277,15 @@
 	}
 
 	// get a key-value pair from a transaction specific Map
-	Object getTxLocalResource(Object key)
+	public Object getTxLocalResource(Object key)
 	{
-		if (txLocalResources == null)
-		{
-			return null;
-		}
-		return txLocalResources.get(key);
+		return _txLocalResources.get(key);
 	}
 
 	// store a key-value pair in the scope of the transaction.
-	void putTxLocalResource(Object key, Object value)
+	public void putTxLocalResource(Object key, Object value)
 	{
-		if (txLocalResources == null)
-		{
-			txLocalResources = Collections.synchronizedMap(new HashMap());
-		}
-		txLocalResources.put(key, value);
+		_txLocalResources.put(key, value);
 	}
 
 	protected TransactionImple()
@@ -1786,7 +1780,7 @@
 
 	private final boolean _xaTransactionTimeoutEnabled;
 
-	private Map txLocalResources;
+	private Map _txLocalResources;
 
 	/**
 	 * Count of last resources seen in this transaction.

Modified: labs/jbosstm/trunk/atsintegration/classes/com/arjuna/ats/jbossatx/jta/TransactionManagerDelegate.java
===================================================================
--- labs/jbosstm/trunk/atsintegration/classes/com/arjuna/ats/jbossatx/jta/TransactionManagerDelegate.java	2007-09-08 15:08:55 UTC (rev 14944)
+++ labs/jbosstm/trunk/atsintegration/classes/com/arjuna/ats/jbossatx/jta/TransactionManagerDelegate.java	2007-09-08 15:24:21 UTC (rev 14945)
@@ -1,26 +1,28 @@
 /*
  * JBoss, Home of Professional Open Source
- * Copyright 2006, Red Hat Middleware LLC, and individual contributors 
- * as indicated by the @author tags. 
+ * Copyright 2006, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
  * See the copyright.txt in the distribution for a
- * full listing of individual contributors. 
+ * full listing of individual contributors.
  * This copyrighted material is made available to anyone wishing to use,
  * modify, copy, or redistribute it subject to the terms and conditions
  * of the GNU Lesser General Public License, v. 2.1.
- * This program is distributed in the hope that it will be useful, but WITHOUT A 
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
  * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
  * You should have received a copy of the GNU Lesser General Public License,
  * v.2.1 along with this distribution; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  * MA  02110-1301, USA.
- * 
+ *
  * (C) 2005-2006,
  * @author JBoss Inc.
  */
 package com.arjuna.ats.jbossatx.jta;
 
 import java.util.Hashtable;
+import java.util.Map;
+import java.util.HashMap;
 
 import javax.naming.Context;
 import javax.naming.Name;
@@ -28,18 +30,22 @@
 import javax.transaction.RollbackException;
 import javax.transaction.Status;
 import javax.transaction.SystemException;
+import javax.transaction.Transaction;
 
 import com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple;
+import com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple;
 import com.arjuna.ats.jbossatx.BaseTransactionManagerDelegate;
 import com.arjuna.ats.jbossatx.logging.jbossatxLogger;
 
+import org.jboss.tm.TransactionLocal;
+
 public class TransactionManagerDelegate extends BaseTransactionManagerDelegate implements ObjectFactory
 {
     /**
      * The transaction manager.
      */
     private static final TransactionManagerImple TRANSACTION_MANAGER = new TransactionManagerImple() ;
-    
+
     /**
      * Construct the delegate with the appropriate transaction manager
      */
@@ -47,10 +53,10 @@
     {
         super(getTransactionManager());
     }
-    
+
     /**
      * Get the transaction timeout.
-     * 
+     *
      * @return the timeout in seconds associated with this thread
      * @throws SystemException for any error
      */
@@ -62,13 +68,13 @@
 
     /**
      * Get the time left before transaction timeout
-     * 
+     *
      * @param errorRollback throw an error if the transaction is marked for rollback
      * @return the remaining in the current transaction or -1
      * if there is no transaction
      * @throws RollbackException if the transaction is marked for rollback and
      * errorRollback is true
-     * 
+     *
      * @message com.arjuna.ats.jbossatx.jta.TransactionManagerDelegate.getTimeLeftBeforeTransactionTimeout_1
      * 		[com.arjuna.ats.jbossatx.jta.TransactionManagerDelegate.getTimeLeftBeforeTransactionTimeout_1] - Transaction rolledback
      * @message com.arjuna.ats.jbossatx.jta.TransactionManagerDelegate.getTimeLeftBeforeTransactionTimeout_2
@@ -90,7 +96,7 @@
     	}
         return -1 ;
     }
-    
+
     /**
      * Get the transaction manager from the factory.
      * @param initObj The initialisation object.
@@ -105,7 +111,7 @@
     {
         return this ;
     }
-    
+
     /**
      * Get the transaction manager.
      * @return The transaction manager.
@@ -114,4 +120,174 @@
     {
         return TRANSACTION_MANAGER ;
     }
+
+
+    /////////////////////////
+
+    // TransactionLocalDelegate implementation methods. This part is basically
+    // stateless, we just delegate down to the object storage on the TransactionImple
+
+    /**
+     * Does the specified transaction contain a value for the transaction local.
+     *
+     * @param transactionLocal The associated transaction local.
+     * @param transaction      The associated transaction.
+     * @return true if a value exists within the specified transaction, false otherwise.
+     */
+    public boolean containsValue(final TransactionLocal transactionLocal, final Transaction transaction) {
+        TransactionImple transactionImple = (TransactionImple) transaction;
+        return (transactionImple.getTxLocalResource(transactionLocal) != null ? true : false);
+    }
+
+    /**
+     * Get value of the transaction local in the specified transaction.
+     *
+     * @param transactionLocal The associated transaction local.
+     * @param transaction      The associated transaction.
+     * @return The value of the transaction local.
+     */
+    public Object getValue(final TransactionLocal transactionLocal, final Transaction transaction) {
+        TransactionImple transactionImple = (TransactionImple) transaction;
+        return transactionImple.getTxLocalResource(transactionLocal);
+    }
+
+    /**
+     * Store the value of the transaction local in the specified transaction.
+     *
+     * @param transactionLocal The associated transaction local.
+     * @param transaction      The associated transaction.
+     * @param value            The value of the transaction local.
+     */
+    public void storeValue(final TransactionLocal transactionLocal, final Transaction transaction,
+                           final Object value) {
+        TransactionImple transactionImple = (TransactionImple) transaction;
+        transactionImple.putTxLocalResource(transactionLocal, value);
+    }
+
+    /**
+     * Lock the transaction local in the context of this transaction.
+     *
+     * @throws IllegalStateException if the transaction is not active
+     * @throws InterruptedException  if the thread is interrupted
+     */
+    public void lock(final TransactionLocal local, final Transaction transaction)
+            throws InterruptedException {
+        TransactionLocalLock lock = findLock(local, transaction);
+        lock.lock();
+    }
+
+    /**
+     * Unlock the transaction local in the context of this transaction
+     */
+    public void unlock(final TransactionLocal local, final Transaction transaction) {
+        TransactionLocalLock lock = findLock(local, transaction);
+        lock.unlock();
+    }
+
+    // Lock implementaion: This used to use a Synchronization for lock storage, but
+    // we need to be able to create locks after transactions end, at which point
+    // registration of Synchronizations is no longer permitted. Hence we now
+    // store locks in the general object storage Map on the TransactionImple, using this
+    // as the key under which the map of TransactionLocals to locks is stored.
+    // Bad things will probably happen if users ever use this key themselves
+    private final String LOCKS_MAP = "__LOCKS_MAP";
+
+    // locate and return the lock for a given TransactionLocal+Transaction tuple.
+    // create it if it does not exist.
+    private TransactionLocalLock findLock(final TransactionLocal local, final Transaction transaction) {
+
+        TransactionImple transactionImple = (TransactionImple) transaction;
+        Map<TransactionLocal, TransactionLocalLock> locks;
+        // ideally for performance we should sync on the tx instance itself but that may have nasty
+        // side effects so we use something else as the lock object for the sync block
+        synchronized (LOCKS_MAP) {
+            // ensure there is a holder for lock storage on the given tx instance.
+            locks = (Map) transactionImple.getTxLocalResource(LOCKS_MAP);
+            if (locks == null) {
+                locks = new HashMap<TransactionLocal, TransactionLocalLock>();
+                transactionImple.putTxLocalResource(LOCKS_MAP, locks);
+            }
+        }
+
+        TransactionLocalLock transactionLocalLock;
+        synchronized (locks) {
+            // ensure there is a lock for the specified local+tx tuple
+            transactionLocalLock = locks.get(local);
+            if (transactionLocalLock == null) {
+                transactionLocalLock = new TransactionLocalLock();
+                locks.put(local, transactionLocalLock);
+            }
+        }
+
+        return transactionLocalLock;
+    }
+
+    // A class for the storage of individual lock state:
+
+    private class TransactionLocalLock
+    {
+        /**
+         * The locking thread.
+         */
+        private Thread lockingThread ;
+        /**
+         * The lock count.
+         */
+        private int lockCount ;
+        /**
+         * The lock.
+         */
+        private byte[] lock = new byte[0] ;
+
+        /**
+         * Lock the transaction local within the curren thread context.
+         */
+        public void lock()
+        {
+        	    // The current code in the app server locks the transaction for all, we follow that practice
+        	    synchronized(lock)
+        	    {
+                final Thread currentThread = Thread.currentThread() ;
+                if (currentThread == lockingThread)
+                {
+                    lockCount++ ;
+                    return ;
+                }
+
+                while (lockingThread != null)
+                {
+                    try
+                    {
+                        lock.wait();
+                    }
+                    catch (final InterruptedException ie) {}
+                }
+
+                lockingThread = currentThread ;
+                lockCount ++ ;
+        	    }
+        }
+
+        /**
+         * Unlock the transaction local within the curren thread context.
+         */
+        public void unlock()
+        {
+        	    synchronized(lock)
+        	    {
+                final Thread currentThread = Thread.currentThread() ;
+                if (currentThread != lockingThread)
+                {
+                    throw new IllegalStateException("Unlock called from wrong thread.  Locking thread: " + lockingThread +
+                        ", current thread: " + currentThread) ;
+                }
+
+                if (--lockCount == 0)
+                {
+                    lockingThread = null ;
+                    lock.notify() ;
+                }
+            }
+        }
+    }
 }




More information about the jboss-svn-commits mailing list