You are viewing a plain text version of this content. The canonical link for it is here.
Posted to slide-dev@jakarta.apache.org by re...@apache.org on 2001/05/11 05:40:25 UTC
cvs commit: jakarta-slide/src/share/org/apache/slide/transaction SlideTransaction.java SlideTransactionManager.java
remm 01/05/10 20:40:25
Modified: src/share/org/apache/slide/transaction SlideTransaction.java
SlideTransactionManager.java
Log:
- Cleaner handling of status codes + remove entries in the timeout hashtable.
Patch submitted by Erik Olof Stenflo <eRiK at cairnTechnologies.com>
Additional comments by Erik :
I consider the changes to SlideTransactionManager
a fix to a potential memory problem....
the Hashtable "timeouts" could have potentially
grown to be very large, since it's elements were
never removed upon a commit or rollback.
The changes to SlideTransaction are such, that the
getStatus() method will now return
Status.STATUS_MARKED_ROLLBACK when the transaction
is marked for rollback.
Revision Changes Path
1.9 +116 -123 jakarta-slide/src/share/org/apache/slide/transaction/SlideTransaction.java
Index: SlideTransaction.java
===================================================================
RCS file: /home/cvs/jakarta-slide/src/share/org/apache/slide/transaction/SlideTransaction.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- SlideTransaction.java 2001/02/12 04:39:58 1.8
+++ SlideTransaction.java 2001/05/11 03:40:23 1.9
@@ -1,7 +1,7 @@
/*
- * $Header: /home/cvs/jakarta-slide/src/share/org/apache/slide/transaction/SlideTransaction.java,v 1.8 2001/02/12 04:39:58 remm Exp $
- * $Revision: 1.8 $
- * $Date: 2001/02/12 04:39:58 $
+ * $Header: /home/cvs/jakarta-slide/src/share/org/apache/slide/transaction/SlideTransaction.java,v 1.9 2001/05/11 03:40:23 remm Exp $
+ * $Revision: 1.9 $
+ * $Date: 2001/05/11 03:40:23 $
*
* ====================================================================
*
@@ -86,14 +86,14 @@
* JTA Transaction implementation.
*
* @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
- * @version $Revision: 1.8 $
+ * @version $Revision: 1.9 $
*/
public final class SlideTransaction implements Transaction {
-
-
+
+
// ------------------------------------------------------------ Constructor
-
-
+
+
/**
* Constructor.
*/
@@ -107,92 +107,86 @@
+ currentTransactionNumber).getBytes(),
0, new byte[0]);
}
-
-
+
+
// ----------------------------------------------------- Instance Variables
-
-
+
+
/**
* Global transaction id.
*/
private SlideXid xid;
-
-
+
+
/**
* Branches.
* Keyed : branch xid -> resource manager.
*/
private Hashtable branches = new Hashtable();
-
-
+
+
/**
* Active branches.
* Keyed : resource manager -> branches xid.
*/
private Hashtable activeBranches = new Hashtable();
-
-
+
+
/**
* Enlisted resources.
*/
private Vector enlistedResources = new Vector();
-
-
+
+
/**
* Suspended resources.
* Keyed : resource manager -> branches xid.
*/
private Hashtable suspendedResources = new Hashtable();
-
-
+
+
/**
* Transaction status.
*/
private int status = Status.STATUS_ACTIVE;
-
-
- /**
- * Rollback only.
- */
- private boolean rollbackOnly = false;
-
-
+
+
/**
* Synchronization objects.
*/
private Vector synchronizationObjects = new Vector();
-
-
+
+
/**
* Branch counter.
*/
private int branchCounter = 1;
-
-
+
+
/**
* Number of transactions created.
*/
private static int globalCreatedTransactions = 0;
-
-
+
+
/**
* Transaction number.
*/
private int currentTransactionNumber = 0;
-
-
+
+
/**
* Name of the thread bound to the transaction.
*/
private String currentThreadName = null;
-
-
+
+
// ------------------------------------------------------------- Properties
-
-
+
+
// ---------------------------------------------------- Transaction Methods
-
-
+
+
/**
* Complete the transaction represented by this Transaction object.
*
@@ -217,31 +211,31 @@
SystemException {
//System.out.println(this + " COMMIT ");
-
-
- // Check status ACTIVE
- if (status != Status.STATUS_ACTIVE)
- throw new IllegalStateException();
-
- if (rollbackOnly) {
+
+
+ if (status == Status.STATUS_MARKED_ROLLBACK) {
rollback();
return;
}
-
+
+ // Check status ACTIVE
+ if (status != Status.STATUS_ACTIVE)
+ throw new IllegalStateException();
+
// Call synchronized objects beforeCompletion
Enumeration syncList = synchronizationObjects.elements();
while (syncList.hasMoreElements()) {
Synchronization sync = (Synchronization) syncList.nextElement();
sync.beforeCompletion();
}
-
+
Vector exceptions = new Vector();
boolean fail = false;
-
+
Enumeration enum = branches.keys();
-
+
if (enlistedResources.size() == 1) {
-
+
// One phase commit
status = Status.STATUS_COMMITTING;
while (enum.hasMoreElements()) {
@@ -267,9 +261,9 @@
} else {
status = Status.STATUS_ROLLEDBACK;
}
-
+
} else if (enlistedResources.size() != 0) {
-
+
// Prepare each enlisted resource
status = Status.STATUS_PREPARING;
while ((!fail) && (enum.hasMoreElements())) {
@@ -287,10 +281,10 @@
status = Status.STATUS_MARKED_ROLLBACK;
}
}
-
+
if (!fail)
status = Status.STATUS_PREPARED;
-
+
// If fail, rollback
if (fail) {
status = Status.STATUS_ROLLING_BACK;
@@ -326,9 +320,9 @@
}
status = Status.STATUS_COMMITTED;
}
-
+
}
-
+
// Call synchronized objects afterCompletion
syncList = synchronizationObjects.elements();
while (syncList.hasMoreElements()) {
@@ -336,7 +330,7 @@
(Synchronization) syncList.nextElement();
sync.afterCompletion(status);
}
-
+
// Parsing exception and throwing an appropriate exception
enum = exceptions.elements();
if (enum.hasMoreElements()) {
@@ -347,10 +341,10 @@
if ((status == Status.STATUS_COMMITTED) && (fail))
throw new HeuristicMixedException();
}
-
+
}
-
-
+
+
/**
* Delist the resource specified from the current transaction associated
* with the calling thread.
@@ -366,42 +360,42 @@
throws IllegalStateException, SystemException {
//System.out.println(this + " DELIST " + xaRes);
-
+
// Check status ACTIVE
if (status != Status.STATUS_ACTIVE)
throw new IllegalStateException();
-
+
Xid xid = (Xid) activeBranches.get(xaRes);
-
+
if (xid == null)
throw new IllegalStateException();
-
+
activeBranches.remove(xaRes);
-
+
XAException exception = null;
-
+
try {
xaRes.end(xid, flag);
} catch (XAException e) {
exception = e;
}
-
+
if (exception != null) {
// FIXME
System.out.println("Delistment failed(" + this + ") = " + xaRes + " xid: " + xid);
return false;
}
-
+
if (flag == XAResource.TMSUSPEND)
suspendedResources.put(xaRes, xid);
-
+
//System.out.println("Delisted ok(" + this + ") = " + xaRes + " xid: " + xid);
-
+
return true;
-
+
}
-
-
+
+
/**
* Enlist the resource specified with the current transaction context of
* the calling thread.
@@ -419,26 +413,25 @@
throws RollbackException, IllegalStateException, SystemException {
//System.out.println(this + " ENLIST " + xaRes);
-
-
+
+ if (status == Status.STATUS_MARKED_ROLLBACK)
+ throw new RollbackException();
+
// Check status ACTIVE
if (status != Status.STATUS_ACTIVE)
throw new IllegalStateException();
-
- if (rollbackOnly)
- throw new RollbackException();
-
+
// Preventing two branches from being active at the same time on the
// same resource manager
Xid activeXid = (Xid) activeBranches.get(xaRes);
if (activeXid != null)
return false;
-
+
boolean alreadyEnlisted = false;
int flag = XAResource.TMNOFLAGS;
-
+
Xid branchXid = (Xid) suspendedResources.get(xaRes);
-
+
if (branchXid == null) {
Enumeration enum = enlistedResources.elements();
while ((!alreadyEnlisted) && (enum.hasMoreElements())) {
@@ -454,34 +447,34 @@
branchXid = this.xid.newBranch(branchCounter++);
//System.out.println(this + " Creating new branch for " + xaRes);
-
+
} else {
alreadyEnlisted = true;
flag = XAResource.TMRESUME;
suspendedResources.remove(xaRes);
}
-
+
if (!alreadyEnlisted) {
enlistedResources.addElement(xaRes);
}
-
+
try {
//System.out.println("Starting(" + this + ") = " + xaRes + " Branch: " + branchXid + " Flag: " + flag);
-
+
xaRes.start(branchXid, flag);
} catch (XAException e) {
System.out.println("Enlist error(" + this + ") = " + e.errorCode + " " + xaRes+ " Branch: " + branchXid + " Flag: " + flag);
return false;
}
-
+
branches.put(branchXid, xaRes);
activeBranches.put(xaRes, branchXid);
-
+
return true;
-
+
}
-
-
+
+
/**
* Roll back the transaction associated with the current thread. When
* this method completes, the thread becomes associated with no
@@ -496,17 +489,17 @@
*/
public void rollback()
throws SecurityException, IllegalStateException, SystemException {
-
+
//System.out.println(this + " ROLLBACK ");
-
+
// Check status ACTIVE
- if (status != Status.STATUS_ACTIVE)
+ if (status != Status.STATUS_ACTIVE && status != Status.STATUS_MARKED_ROLLBACK)
throw new IllegalStateException();
-
+
Vector exceptions = new Vector();
-
+
Enumeration enum = branches.keys();
-
+
status = Status.STATUS_ROLLING_BACK;
while (enum.hasMoreElements()) {
Xid xid = (Xid) enum.nextElement();
@@ -518,10 +511,10 @@
}
}
status = Status.STATUS_ROLLEDBACK;
-
+
}
-
-
+
+
/**
* Modify the transaction associated with the current thread such that
* the only possible outcome of the transaction is to roll back the
@@ -534,10 +527,10 @@
*/
public void setRollbackOnly()
throws IllegalStateException, SystemException {
- rollbackOnly = true;
+ status = Status.STATUS_MARKED_ROLLBACK;
}
-
-
+
+
/**
* Obtain the status of the transaction associated with the current thread.
*
@@ -550,8 +543,8 @@
throws SystemException {
return status;
}
-
-
+
+
/**
* Register a synchronization object for the transaction currently
* associated with the calling thread. The transction manager invokes the
@@ -570,21 +563,21 @@
*/
public void registerSynchronization(Synchronization sync)
throws RollbackException, IllegalStateException, SystemException {
-
- if (rollbackOnly)
+
+ if (status == Status.STATUS_MARKED_ROLLBACK)
throw new RollbackException();
-
- if (getStatus() != Status.STATUS_ACTIVE)
+
+ if (status != Status.STATUS_ACTIVE)
throw new IllegalStateException();
-
+
synchronizationObjects.addElement(sync);
-
+
}
-
-
+
+
// --------------------------------------------------------- Public Methods
-
-
+
+
/**
* Print the Transaction object in a debugger friendly manner
*/
@@ -594,8 +587,8 @@
(currentThreadName.equals(Thread.currentThread().getName())?"":
" current= " + Thread.currentThread().getName());
}
-
-
+
+
}
1.3 +133 -126 jakarta-slide/src/share/org/apache/slide/transaction/SlideTransactionManager.java
Index: SlideTransactionManager.java
===================================================================
RCS file: /home/cvs/jakarta-slide/src/share/org/apache/slide/transaction/SlideTransactionManager.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- SlideTransactionManager.java 2001/02/12 04:39:59 1.2
+++ SlideTransactionManager.java 2001/05/11 03:40:24 1.3
@@ -1,13 +1,13 @@
/*
- * $Header: /home/cvs/jakarta-slide/src/share/org/apache/slide/transaction/SlideTransactionManager.java,v 1.2 2001/02/12 04:39:59 remm Exp $
- * $Revision: 1.2 $
- * $Date: 2001/02/12 04:39:59 $
+ * $Header: /home/cvs/jakarta-slide/src/share/org/apache/slide/transaction/SlideTransactionManager.java,v 1.3 2001/05/11 03:40:24 remm Exp $
+ * $Revision: 1.3 $
+ * $Date: 2001/05/11 03:40:24 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
- * Copyright (c) 1999 The Apache Software Foundation. All rights
+ * Copyright (c) 1999 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -15,7 +15,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
@@ -23,15 +23,15 @@
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowlegement:
- * "This product includes software developed by the
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
+ * from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
@@ -59,7 +59,7 @@
*
* [Additional notices, if required by prior licensing conditions]
*
- */
+ */
package org.apache.slide.transaction;
@@ -85,176 +85,180 @@
* <li>Does not support nested transactions</li>
* <li>No security</li>
* </ul>
- *
+ *
* @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
- * @version $Revision: 1.2 $
+ * @version $Revision: 1.3 $
*/
public final class SlideTransactionManager implements TransactionManager {
-
-
+
+
// -------------------------------------------------------------- Constants
-
-
+
+
public static final int DEFAULT_TRANSACTION_TIMEOUT = 30;
-
-
+
+
// ------------------------------------------------------------ Constructor
-
-
+
+
// ----------------------------------------------------- Instance Variables
-
-
+
+
/**
* Transaction bindings thread id <-> transaction object.
*/
private Hashtable bindings = new Hashtable();
-
-
+
+
/**
* Transaction bindings thread id <-> transaction timeout.
*/
private Hashtable timeouts = new Hashtable();
-
-
+
+
// ------------------------------------------------------------- Properties
-
-
+
+
// --------------------------------------------------------- Public Methods
-
-
+
+
// --------------------------------------------- TransactionManager Methods
-
-
+
+
/**
* Create a new transaction and associate it with the current thread.
- *
- * @exception NotSupportedException Thrown if the thread is already
- * associated with a transaction and the Transaction Manager
+ *
+ * @exception NotSupportedException Thrown if the thread is already
+ * associated with a transaction and the Transaction Manager
* implementation does not support nested transactions.
* @exception SystemException Thrown if the transaction manager encounters
* an unexpected error condition.
*/
public void begin()
throws NotSupportedException, SystemException {
-
+
Transaction currentTransaction = getTransaction();
if (currentTransaction != null)
throw new NotSupportedException();
-
+
currentTransaction = new SlideTransaction();
bindings.put(Thread.currentThread(), currentTransaction);
-
+
}
-
-
+
+
/**
- * Complete the transaction associated with the current thread. When this
+ * Complete the transaction associated with the current thread. When this
* method completes, the thread becomes associated with no transaction.
- *
- * @exception RollbackException Thrown to indicate that the transaction
+ *
+ * @exception RollbackException Thrown to indicate that the transaction
* has been rolled back rather than committed.
- * @exception HeuristicMixedException Thrown to indicate that a heuristic
- * decision was made and that some relevant updates have been committed
+ * @exception HeuristicMixedException Thrown to indicate that a heuristic
+ * decision was made and that some relevant updates have been committed
* while others have been rolled back.
- * @exception HeuristicRollbackException Thrown to indicate that a
- * heuristic decision was made and that some relevant updates have been
+ * @exception HeuristicRollbackException Thrown to indicate that a
+ * heuristic decision was made and that some relevant updates have been
* rolled back.
- * @exception SecurityException Thrown to indicate that the thread is not
+ * @exception SecurityException Thrown to indicate that the thread is not
* allowed to commit the transaction.
- * @exception IllegalStateException Thrown if the current thread is not
+ * @exception IllegalStateException Thrown if the current thread is not
* associated with a transaction.
* @exception SystemException Thrown if the transaction manager encounters
* an unexpected error condition.
*/
public void commit()
- throws RollbackException, HeuristicMixedException,
+ throws RollbackException, HeuristicMixedException,
HeuristicRollbackException, SecurityException, IllegalStateException,
SystemException {
-
- Transaction currentTransaction = getTransaction();
+
+ Thread currentThread = Thread.currentThread();
+ Transaction currentTransaction =
+ (Transaction) bindings.remove(currentThread);
if (currentTransaction == null)
throw new IllegalStateException();
-
- bindings.remove(Thread.currentThread());
-
+
+ timeouts.remove(currentThread);
+
currentTransaction.commit();
-
+
}
-
-
+
+
/**
- * Roll back the transaction associated with the current thread. When
- * this method completes, the thread becomes associated with no
+ * Roll back the transaction associated with the current thread. When
+ * this method completes, the thread becomes associated with no
* transaction.
- *
- * @exception SecurityException Thrown to indicate that the thread is not
+ *
+ * @exception SecurityException Thrown to indicate that the thread is not
* allowed to commit the transaction.
- * @exception IllegalStateException Thrown if the current thread is not
+ * @exception IllegalStateException Thrown if the current thread is not
* associated with a transaction.
* @exception SystemException Thrown if the transaction manager encounters
* an unexpected error condition.
*/
public void rollback()
throws SecurityException, IllegalStateException, SystemException {
-
- Transaction currentTransaction = getTransaction();
+
+ Thread currentThread = Thread.currentThread();
+ Transaction currentTransaction =
+ (Transaction) bindings.remove(currentThread);
if (currentTransaction == null)
throw new IllegalStateException();
-
- bindings.remove(Thread.currentThread());
-
+
+ timeouts.remove(currentThread);
+
currentTransaction.rollback();
-
+
}
-
-
+
+
/**
- * Modify the transaction associated with the current thread such that
- * the only possible outcome of the transaction is to roll back the
+ * Modify the transaction associated with the current thread such that
+ * the only possible outcome of the transaction is to roll back the
* transaction.
- *
- * @exception IllegalStateException Thrown if the current thread is not
+ *
+ * @exception IllegalStateException Thrown if the current thread is not
* associated with a transaction.
* @exception SystemException Thrown if the transaction manager encounters
* an unexpected error condition.
*/
public void setRollbackOnly()
throws IllegalStateException, SystemException {
-
+
Transaction currentTransaction = getTransaction();
if (currentTransaction == null)
throw new IllegalStateException();
-
+
currentTransaction.setRollbackOnly();
-
+
}
-
-
+
+
/**
* Obtain the status of the transaction associated with the current thread.
- *
+ *
* @exception SystemException Thrown if the transaction manager encounters
* an unexpected error condition.
- * @return The transaction status. If no transaction is associated with
+ * @return The transaction status. If no transaction is associated with
* the current thread, this method returns the Status.NoTransaction value.
*/
public int getStatus()
throws SystemException {
-
+
Transaction currentTransaction = getTransaction();
if (currentTransaction == null)
return Status.STATUS_NO_TRANSACTION;
-
+
return currentTransaction.getStatus();
-
+
}
-
-
+
+
/**
- * Get the transaction object that represents the transaction context of
+ * Get the transaction object that represents the transaction context of
* the calling thread.
- *
- * @return the Transaction object representing the transaction associated
+ *
+ * @return the Transaction object representing the transaction associated
* with the calling thread.
* @exception SystemException Thrown if the transaction manager encounters
* an unexpected error condition.
@@ -263,19 +267,19 @@
throws SystemException {
return (Transaction) bindings.get(Thread.currentThread());
}
-
-
+
+
/**
- * Resume the transaction context association of the calling thread with
- * the transaction represented by the supplied Transaction object. When
- * this method returns, the calling thread is associated with the
+ * Resume the transaction context association of the calling thread with
+ * the transaction represented by the supplied Transaction object. When
+ * this method returns, the calling thread is associated with the
* transaction context specified.
- *
- * @param tobj The Transaction object that represents the transaction to
+ *
+ * @param tobj The Transaction object that represents the transaction to
* be resumed.
- * @exception InvalidTransactionException Thrown if the parameter
+ * @exception InvalidTransactionException Thrown if the parameter
* transaction object contains an invalid transaction.
- * @exception IllegalStateException Thrown if the thread is already
+ * @exception IllegalStateException Thrown if the thread is already
* associated with another transaction.
* @exception SystemException Thrown if the transaction manager encounters
* an unexpected error condition.
@@ -283,60 +287,63 @@
public void resume(Transaction tobj)
throws InvalidTransactionException, IllegalStateException,
SystemException {
-
+
if (getTransaction() != null)
throw new IllegalStateException();
-
+
if (tobj == null)
throw new InvalidTransactionException();
-
+
bindings.put(Thread.currentThread(), tobj);
-
+
}
-
-
+
+
/**
- * Suspend the transaction currently associated with the calling thread
- * and return a Transaction object that represents the transaction
- * context being suspended. If the calling thread is not associated with
- * a transaction, the method returns a null object reference. When this
+ * Suspend the transaction currently associated with the calling thread
+ * and return a Transaction object that represents the transaction
+ * context being suspended. If the calling thread is not associated with
+ * a transaction, the method returns a null object reference. When this
* method returns, the calling thread is associated with no transaction.
- *
+ *
* @return Transaction object representing the suspended transaction.
* @exception SystemException Thrown if the transaction manager encounters
* an unexpected error condition.
*/
public Transaction suspend()
throws SystemException {
-
+
Transaction currentTransaction = getTransaction();
-
- if (currentTransaction != null)
- bindings.remove(Thread.currentThread());
-
+
+ if (currentTransaction != null) {
+ Thread currentThread = Thread.currentThread();
+ bindings.remove(currentThread);
+ timeouts.remove(currentThread);
+ }
+
return currentTransaction;
-
+
}
-
-
+
+
/**
- * Modify the value of the timeout value that is associated with the
- * transactions started by the current thread with the begin method.
+ * Modify the value of the timeout value that is associated with the
+ * transactions started by the current thread with the begin method.
* <p>
- * If an application has not called this method, the transaction service
+ * If an application has not called this method, the transaction service
* uses some default value for the transaction timeout.
- *
- * @param seconds The value of the timeout in seconds. If the value is
+ *
+ * @param seconds The value of the timeout in seconds. If the value is
* zero, the transaction service restores the default value.
* @exception SystemException Thrown if the transaction manager encounters
* an unexpected error condition.
*/
public void setTransactionTimeout(int seconds)
throws SystemException {
-
+
timeouts.put(Thread.currentThread(), new Integer(seconds));
-
+
}
-
-
+
+
}