[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