ozeigermann 2004/05/18 06:59:13 Modified: transaction/src/java/org/apache/commons/transaction/memory TransactionalMapWrapper.java Log: - more transaction control
- refactored context to be a pure structure Revision Changes Path 1.5 +122 -73 jakarta-commons-sandbox/transaction/src/java/org/apache/commons/transaction/memory/TransactionalMapWrapper.java Index: TransactionalMapWrapper.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/transaction/src/java/org/apache/commons/transaction/memory/TransactionalMapWrapper.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- TransactionalMapWrapper.java 18 May 2004 07:40:29 -0000 1.4 +++ TransactionalMapWrapper.java 18 May 2004 13:59:13 -0000 1.5 @@ -31,6 +31,8 @@ import java.util.Map; import java.util.Set; +import javax.transaction.Status; + /** * Wrapper that adds transactional control to all kinds of maps that implement the [EMAIL PROTECTED] Map} interface. * <br> @@ -44,7 +46,7 @@ * @author <a href="mailto:[EMAIL PROTECTED]">Oliver Zeigermann</a> * @version $Revision$ */ -public class TransactionalMapWrapper implements Map { +public class TransactionalMapWrapper implements Map, Status { protected Map wrapped; @@ -54,6 +56,28 @@ this.wrapped = wrapped; } + public synchronized boolean isReadOnly() { + TxContext txContext = getActiveTx(); + + if (txContext == null) { + throw new IllegalStateException( + "Active thread " + Thread.currentThread() + " not associated with a transaction!"); + } + + return txContext.readOnly; + } + + public synchronized boolean isTransactionMarkedForRollback() { + TxContext txContext = getActiveTx(); + + if (txContext == null) { + throw new IllegalStateException( + "Active thread " + Thread.currentThread() + " not associated with a transaction!"); + } + + return txContext.rollbackOnly; + } + public synchronized void markTransactionForRollback() { TxContext txContext = getActiveTx(); @@ -61,9 +85,9 @@ throw new IllegalStateException( "Active thread " + Thread.currentThread() + " not associated with a transaction!"); } - - txContext.setRollbackOnly(true); - + + txContext.rollbackOnly = true; + } public synchronized TxContext suspendTransaction() { @@ -74,7 +98,7 @@ "Active thread " + Thread.currentThread() + " not associated with a transaction!"); } - activeTx.set(null); + setActiveTx(null); return txContext; } @@ -88,7 +112,16 @@ throw new IllegalStateException("No transaction to resume!"); } - activeTx.set(suspendedTx); + setActiveTx(suspendedTx); + } + + public synchronized int getTransactionState() { + TxContext txContext = getActiveTx(); + + if (txContext == null) { + return Status.STATUS_NO_TRANSACTION; + } + return txContext.status; } public synchronized void startTransaction() { @@ -96,7 +129,7 @@ throw new IllegalStateException( "Active thread " + Thread.currentThread() + " already associated with a transaction!"); } - activeTx.set(new TxContext()); + setActiveTx(new TxContext()); } public synchronized void rollbackTransaction() { @@ -108,7 +141,7 @@ } // simply forget about tx - activeTx.set(null); + setActiveTx(null); } public synchronized void commitTransaction() { @@ -119,23 +152,26 @@ "Active thread " + Thread.currentThread() + " not associated with a transaction!"); } - if (txContext.isRollbackOnly()) { - throw new IllegalStateException( - "Active thread " + Thread.currentThread() + " is marked for rollback!"); + if (txContext.rollbackOnly) { + throw new IllegalStateException("Active thread " + Thread.currentThread() + " is marked for rollback!"); } - for (Iterator it = txContext.getChanges().entrySet().iterator(); it.hasNext();) { + if (txContext.cleared) { + wrapped.clear(); + } + + for (Iterator it = txContext.changes.entrySet().iterator(); it.hasNext();) { Map.Entry entry = (Map.Entry) it.next(); wrapped.put(entry.getKey(), entry.getValue()); } - for (Iterator it = txContext.getDeletes().iterator(); it.hasNext();) { + for (Iterator it = txContext.deletes.iterator(); it.hasNext();) { Object key = it.next(); wrapped.remove(key); } // now forget about tx - activeTx.set(null); + setActiveTx(null); } // @@ -143,8 +179,15 @@ // public synchronized void clear() { - wrapped.clear(); - activeTx.set(null); + TxContext txContext = getActiveTx(); + if (txContext == null) { + wrapped.clear(); + } else { + txContext.readOnly = false; + txContext.cleared = true; + txContext.deletes.clear(); + txContext.changes.clear(); + } } public synchronized int size() { @@ -152,8 +195,11 @@ TxContext txContext = getActiveTx(); if (txContext != null) { - size += txContext.getChanges().size(); size -= txContext.deletes.size(); + if (txContext.cleared) { + size = 0; + } + size += txContext.changes.size(); } return size; @@ -161,7 +207,7 @@ public synchronized boolean isEmpty() { TxContext txContext = getActiveTx(); - if (txContext != null) { + if (txContext == null) { return wrapped.isEmpty(); } else { return (size() > 0); @@ -174,7 +220,9 @@ if (txContext == null) { return wrapped.containsKey(key); } else { - return (!txContext.getDeletes().contains(key) && txContext.getChanges().containsKey(key)); + return ( + (!txContext.cleared && wrapped.containsKey(key) && !txContext.deletes.contains(key)) + || txContext.changes.containsKey(key)); } } @@ -213,16 +261,17 @@ wrapped.putAll(map); } else { try { + txContext.readOnly = false; for (Iterator it = map.entrySet().iterator(); it.hasNext();) { Map.Entry entry = (Map.Entry) it.next(); - txContext.getChanges().put(entry.getKey(), entry.getValue()); - txContext.getDeletes().remove(entry.getKey()); + txContext.changes.put(entry.getKey(), entry.getValue()); + txContext.deletes.remove(entry.getKey()); } } catch (RuntimeException e) { - txContext.setRollbackOnly(true); + txContext.rollbackOnly = true; throw e; } catch (Error e) { - txContext.setRollbackOnly(true); + txContext.rollbackOnly = true; throw e; } @@ -247,36 +296,40 @@ } public synchronized Set keySet() { - Set keySet = wrapped.keySet(); TxContext txContext = getActiveTx(); - if (txContext != null) { - Set deleteSet = txContext.getDeletes(); - keySet.removeAll(deleteSet); - Set changeSet = txContext.getChanges().keySet(); - keySet.addAll(changeSet); + + if (txContext == null) { + return wrapped.keySet(); + } else { + Set keySet = (txContext.cleared ? new HashSet() : wrapped.keySet()); + keySet.removeAll(txContext.deletes); + keySet.addAll(txContext.changes.keySet()); + return keySet; } - return keySet; } public synchronized Object get(Object key) { TxContext txContext = getActiveTx(); if (txContext != null) { - if (txContext.getDeletes().contains(key)) { + if (txContext.deletes.contains(key)) { // reflects that entry has been deleted in this tx return null; } - Object changed = txContext.getChanges().get(key); + Object changed = txContext.changes.get(key); if (changed != null) { // if object has been changed in this tx, get the local one return changed; } } - // as fall back return value from global cache (if present) - return wrapped.get(key); + if (txContext == null || !txContext.cleared) { + // as fall back return value from global cache (if present) + return wrapped.get(key); + } + return null; } public synchronized Object remove(Object key) { @@ -287,14 +340,16 @@ if (txContext == null) { old = wrapped.remove(key); } else { + old = get(key); try { - old = txContext.getChanges().remove(key); - txContext.getDeletes().add(key); + txContext.readOnly = false; + txContext.changes.remove(key); + txContext.deletes.add(key); } catch (RuntimeException e) { - txContext.setRollbackOnly(true); + txContext.rollbackOnly = true; throw e; } catch (Error e) { - txContext.setRollbackOnly(true); + txContext.rollbackOnly = true; throw e; } } @@ -311,13 +366,14 @@ wrapped.put(key, value); } else { try { - txContext.getDeletes().remove(key); - txContext.getChanges().put(key, value); + txContext.readOnly = false; + txContext.deletes.remove(key); + txContext.changes.put(key, value); } catch (RuntimeException e) { - txContext.setRollbackOnly(true); + txContext.rollbackOnly = true; throw e; } catch (Error e) { - txContext.setRollbackOnly(true); + txContext.rollbackOnly = true; throw e; } } @@ -329,33 +385,8 @@ return (TxContext) activeTx.get(); } - public static class TxContext { - protected final Set deletes; - protected final Map changes; - protected boolean rollbackOnly; - - protected TxContext() { - deletes = new HashSet(); - changes = new HashMap(); - rollbackOnly = false; - } - - protected Map getChanges() { - return changes; - } - - protected Set getDeletes() { - return deletes; - } - - protected boolean isRollbackOnly() { - return rollbackOnly; - } - - protected void setRollbackOnly(boolean rollbackOnly) { - this.rollbackOnly = rollbackOnly; - } - + protected void setActiveTx(TxContext txContext) { + activeTx.set(txContext); } // mostly copied from org.apache.commons.collections.map.AbstractHashedMap @@ -402,6 +433,24 @@ public String toString() { return new StringBuffer().append(getKey()).append('=').append(getValue()).toString(); + } + } + + public static class TxContext { + protected final Set deletes; + protected final Map changes; + protected boolean rollbackOnly; + protected int status; + protected boolean cleared; + protected boolean readOnly; + + protected TxContext() { + deletes = new HashSet(); + changes = new HashMap(); + rollbackOnly = false; + status = Status.STATUS_ACTIVE; + cleared = false; + readOnly = true; } } --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]