commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ozeigerm...@apache.org
Subject cvs commit: jakarta-commons-sandbox/transaction/src/java/org/apache/commons/transaction/memory TransactionalMapWrapper.java
Date Thu, 03 Jun 2004 13:34:35 GMT
ozeigermann    2004/06/03 06:34:35

  Modified:    transaction/src/java/org/apache/commons/transaction/memory
                        TransactionalMapWrapper.java
  Log:
  - Fixed wrong calculation of size
  - Made it more reuseable
  
  Revision  Changes    Path
  1.11      +224 -153  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.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- TransactionalMapWrapper.java	2 Jun 2004 21:54:04 -0000	1.10
  +++ TransactionalMapWrapper.java	3 Jun 2004 13:34:35 -0000	1.11
  @@ -25,6 +25,7 @@
   
   import java.util.ArrayList;
   import java.util.Collection;
  +import java.util.HashSet;
   import java.util.Iterator;
   import java.util.Map;
   import java.util.Set;
  @@ -57,39 +58,44 @@
   
       protected ThreadLocal activeTx = new ThreadLocal();
   
  -	protected MapFactory mapFactory;
  -	protected SetFactory setFactory;
  +    protected MapFactory mapFactory;
  +    protected SetFactory setFactory;
   
  -	/**
  -	 * Creates a new transactional map wrapper. Temporary maps and sets to store transactional
  -	 * data will be instances of {@link HashMap} and {@link HashSet}. 
  -	 * 
  -	 * @param wrapped map to be wrapped
  -	 */
  +    /**
  +     * Creates a new transactional map wrapper. Temporary maps and sets to store transactional
  +     * data will be instances of {@link HashMap} and {@link HashSet}. 
  +     * 
  +     * @param wrapped map to be wrapped
  +     */
       public TransactionalMapWrapper(Map wrapped) {
  -    	this(wrapped, new HashMapFactory(), new HashSetFactory());
  +        this(wrapped, new HashMapFactory(), new HashSetFactory());
       }
   
  -	/**
  -	 * Creates a new transactional map wrapper. Temporary maps and sets to store transactional
  -	 * data will be created and disposed using {@link MapFactory} and {@link SetFactory}.
  -	 * 
  -	 * @param wrapped map to be wrapped
  -	 * @param mapFactory factory for temporary maps
  -	 * @param setFactory factory for temporary sets
  -	 */
  -	public TransactionalMapWrapper(Map wrapped, MapFactory mapFactory, SetFactory setFactory)
{
  -		this.wrapped = wrapped;
  -		this.mapFactory = mapFactory;
  -		this.setFactory = setFactory;
  -	}
  +    /**
  +     * Creates a new transactional map wrapper. Temporary maps and sets to store transactional
  +     * data will be created and disposed using {@link MapFactory} and {@link SetFactory}.
  +     * 
  +     * @param wrapped map to be wrapped
  +     * @param mapFactory factory for temporary maps
  +     * @param setFactory factory for temporary sets
  +     */
  +    public TransactionalMapWrapper(
  +        Map wrapped,
  +        MapFactory mapFactory,
  +        SetFactory setFactory) {
  +        this.wrapped = wrapped;
  +        this.mapFactory = mapFactory;
  +        this.setFactory = setFactory;
  +    }
   
       public synchronized boolean isReadOnly() {
           TxContext txContext = getActiveTx();
   
           if (txContext == null) {
               throw new IllegalStateException(
  -                "Active thread " + Thread.currentThread() + " not associated with a transaction!");
  +                "Active thread "
  +                    + Thread.currentThread()
  +                    + " not associated with a transaction!");
           }
   
           return txContext.readOnly;
  @@ -100,7 +106,9 @@
   
           if (txContext == null) {
               throw new IllegalStateException(
  -                "Active thread " + Thread.currentThread() + " not associated with a transaction!");
  +                "Active thread "
  +                    + Thread.currentThread()
  +                    + " not associated with a transaction!");
           }
   
           return txContext.rollbackOnly;
  @@ -111,7 +119,9 @@
   
           if (txContext == null) {
               throw new IllegalStateException(
  -                "Active thread " + Thread.currentThread() + " not associated with a transaction!");
  +                "Active thread "
  +                    + Thread.currentThread()
  +                    + " not associated with a transaction!");
           }
   
           txContext.rollbackOnly = true;
  @@ -123,7 +133,9 @@
   
           if (txContext == null) {
               throw new IllegalStateException(
  -                "Active thread " + Thread.currentThread() + " not associated with a transaction!");
  +                "Active thread "
  +                    + Thread.currentThread()
  +                    + " not associated with a transaction!");
           }
   
           setActiveTx(null);
  @@ -133,7 +145,9 @@
       public synchronized void resumeTransaction(TxContext suspendedTx) {
           if (getActiveTx() != null) {
               throw new IllegalStateException(
  -                "Active thread " + Thread.currentThread() + " already associated with a
transaction!");
  +                "Active thread "
  +                    + Thread.currentThread()
  +                    + " already associated with a transaction!");
           }
   
           if (suspendedTx == null) {
  @@ -155,7 +169,9 @@
       public synchronized void startTransaction() {
           if (getActiveTx() != null) {
               throw new IllegalStateException(
  -                "Active thread " + Thread.currentThread() + " already associated with a
transaction!");
  +                "Active thread "
  +                    + Thread.currentThread()
  +                    + " already associated with a transaction!");
           }
           setActiveTx(new TxContext());
       }
  @@ -165,12 +181,13 @@
   
           if (txContext == null) {
               throw new IllegalStateException(
  -                "Active thread " + Thread.currentThread() + " not associated with a transaction!");
  +                "Active thread "
  +                    + Thread.currentThread()
  +                    + " not associated with a transaction!");
           }
   
           // simply forget about tx
  -		mapFactory.disposeMap(txContext.changes);
  -		setFactory.disposeSet(txContext.deletes);
  +        txContext.dispose();
           setActiveTx(null);
       }
   
  @@ -179,30 +196,20 @@
   
           if (txContext == null) {
               throw new IllegalStateException(
  -                "Active thread " + Thread.currentThread() + " not associated with a transaction!");
  +                "Active thread "
  +                    + Thread.currentThread()
  +                    + " not associated with a transaction!");
           }
   
           if (txContext.rollbackOnly) {
  -            throw new IllegalStateException("Active thread " + Thread.currentThread() +
" is marked for rollback!");
  -        }
  -
  -        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.deletes.iterator(); it.hasNext();) {
  -            Object key = it.next();
  -            wrapped.remove(key);
  +            throw new IllegalStateException(
  +                "Active thread "
  +                    + Thread.currentThread()
  +                    + " is marked for rollback!");
           }
   
  -        // now forget about tx
  -		mapFactory.disposeMap(txContext.changes);
  -        setFactory.disposeSet(txContext.deletes);
  +        txContext.merge();
  +        txContext.dispose();
           setActiveTx(null);
       }
   
  @@ -212,29 +219,20 @@
   
       public synchronized void clear() {
           TxContext txContext = getActiveTx();
  -        if (txContext == null) {
  -            wrapped.clear();
  +        if (txContext != null) {
  +            txContext.clear();
           } else {
  -            txContext.readOnly = false;
  -            txContext.cleared = true;
  -            txContext.deletes.clear();
  -            txContext.changes.clear();
  +            wrapped.clear();
           }
       }
   
       public synchronized int size() {
  -        int size = wrapped.size();
  -
           TxContext txContext = getActiveTx();
           if (txContext != null) {
  -            size -= txContext.deletes.size();
  -            if (txContext.cleared) {
  -                size = 0;
  -            }
  -            size += txContext.changes.size();
  +            return txContext.size();
  +        } else {
  +            return wrapped.size();
           }
  -        return size;
  -
       }
   
       public synchronized boolean isEmpty() {
  @@ -247,15 +245,7 @@
       }
   
       public synchronized boolean containsKey(Object key) {
  -        TxContext txContext = getActiveTx();
  -
  -        if (txContext == null) {
  -            return wrapped.containsKey(key);
  -        } else {
  -            return (
  -                (!txContext.cleared && wrapped.containsKey(key) && !txContext.deletes.contains(key))
  -                    || txContext.changes.containsKey(key));
  -        }
  +        return (get(key) != null);
       }
   
       public synchronized boolean containsValue(Object value) {
  @@ -292,21 +282,13 @@
           if (txContext == null) {
               wrapped.putAll(map);
           } else {
  -            try {
  -                txContext.readOnly = false;
  -                for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
  -                    Map.Entry entry = (Map.Entry) it.next();
  -                    txContext.changes.put(entry.getKey(), entry.getValue());
  -                    txContext.deletes.remove(entry.getKey());
  -                }
  -            } catch (RuntimeException e) {
  -                txContext.rollbackOnly = true;
  -                throw e;
  -            } catch (Error e) {
  -                txContext.rollbackOnly = true;
  -                throw e;
  +            for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
  +                Map.Entry entry = (Map.Entry) it.next();
  +                txContext.put(
  +                    entry.getKey(),
  +                    entry.getValue(),
  +                    wrapped.get(entry.getKey()));
               }
  -
           }
       }
   
  @@ -315,10 +297,9 @@
           if (txContext == null) {
               return wrapped.entrySet();
           } else {
  -            Set entrySet = setFactory.createSet();
  -            Set keySet = keySet();
  +            Set entrySet = new HashSet();
               // XXX expensive :(
  -            for (Iterator it = keySet.iterator(); it.hasNext();) {
  +            for (Iterator it = keySet().iterator(); it.hasNext();) {
                   Object key = it.next();
                   Object value = get(key);
                   entrySet.add(new HashEntry(key, value));
  @@ -328,16 +309,12 @@
       }
   
       public synchronized Set keySet() {
  -
           TxContext txContext = getActiveTx();
   
           if (txContext == null) {
               return wrapped.keySet();
           } else {
  -            Set keySet = (txContext.cleared ? setFactory.createSet() : wrapped.keySet());
  -            keySet.removeAll(txContext.deletes);
  -            keySet.addAll(txContext.changes.keySet());
  -            return keySet;
  +        	return txContext.keys();
           }
       }
   
  @@ -345,72 +322,35 @@
           TxContext txContext = getActiveTx();
   
           if (txContext != null) {
  -            if (txContext.deletes.contains(key)) {
  -                // reflects that entry has been deleted in this tx 
  -                return null;
  -            }
  -
  -            Object changed = txContext.changes.get(key);
  -            if (changed != null) {
  -                // if object has been changed in this tx, get the local one
  -                return changed;
  -            }
  -        }
  -
  -        if (txContext == null || !txContext.cleared) {
  -            // as fall back return value from global cache (if present)
  +            return txContext.get(key);
  +        } else {
               return wrapped.get(key);
           }
  -        return null;
       }
   
       public synchronized Object remove(Object key) {
           TxContext txContext = getActiveTx();
   
  -        Object old = null;
  -
           if (txContext == null) {
  -            old = wrapped.remove(key);
  +            return wrapped.remove(key);
           } else {
  -            old = get(key);
  -            try {
  -                txContext.readOnly = false;
  -                txContext.changes.remove(key);
  -                txContext.deletes.add(key);
  -            } catch (RuntimeException e) {
  -                txContext.rollbackOnly = true;
  -                throw e;
  -            } catch (Error e) {
  -                txContext.rollbackOnly = true;
  -                throw e;
  -            }
  +            Object oldValue = get(key);
  +            txContext.remove(key);
  +            return oldValue;
           }
  -
  -        return old;
       }
   
       public synchronized Object put(Object key, Object value) {
           TxContext txContext = getActiveTx();
   
  -        Object old = get(key);
  -
           if (txContext == null) {
  -            wrapped.put(key, value);
  +            return wrapped.put(key, value);
           } else {
  -            try {
  -                txContext.readOnly = false;
  -                txContext.deletes.remove(key);
  -                txContext.changes.put(key, value);
  -            } catch (RuntimeException e) {
  -                txContext.rollbackOnly = true;
  -                throw e;
  -            } catch (Error e) {
  -                txContext.rollbackOnly = true;
  -                throw e;
  -            }
  +            Object oldValue = get(key);
  +            txContext.put(key, value, oldValue);
  +            return oldValue;
           }
   
  -        return old;
       }
   
       protected TxContext getActiveTx() {
  @@ -455,22 +395,33 @@
                   return false;
               }
               Map.Entry other = (Map.Entry) obj;
  -            return (getKey() == null ? other.getKey() == null : getKey().equals(other.getKey()))
  -                && (getValue() == null ? other.getValue() == null : getValue().equals(other.getValue()));
  +            return (
  +                getKey() == null
  +                    ? other.getKey() == null
  +                    : getKey().equals(other.getKey()))
  +                && (getValue() == null
  +                    ? other.getValue() == null
  +                    : getValue().equals(other.getValue()));
           }
   
           public int hashCode() {
  -            return (getKey() == null ? 0 : getKey().hashCode()) ^ (getValue() == null ?
0 : getValue().hashCode());
  +            return (getKey() == null ? 0 : getKey().hashCode())
  +                ^ (getValue() == null ? 0 : getValue().hashCode());
           }
   
           public String toString() {
  -            return new StringBuffer().append(getKey()).append('=').append(getValue()).toString();
  +            return new StringBuffer()
  +                .append(getKey())
  +                .append('=')
  +                .append(getValue())
  +                .toString();
           }
       }
   
       public class TxContext {
  -        protected final Set deletes;
  -        protected final Map changes;
  +        protected Set deletes;
  +        protected Map changes;
  +        protected Map adds;
           protected boolean rollbackOnly;
           protected int status;
           protected boolean cleared;
  @@ -479,10 +430,130 @@
           protected TxContext() {
               deletes = setFactory.createSet();
               changes = mapFactory.createMap();
  +            adds = mapFactory.createMap();
               rollbackOnly = false;
               status = Status.STATUS_ACTIVE;
               cleared = false;
               readOnly = true;
  +        }
  +
  +        protected Set keys() {
  +            Set keySet = (cleared ? new HashSet() : wrapped.keySet());
  +            keySet.removeAll(deletes);
  +            keySet.addAll(adds.keySet());
  +            return keySet;
  +
  +        }
  +
  +        protected Object get(Object key) {
  +
  +            if (deletes.contains(key)) {
  +                // reflects that entry has been deleted in this tx 
  +                return null;
  +            }
  +
  +            Object changed = changes.get(key);
  +            if (changed != null) {
  +                return changed;
  +            }
  +
  +            Object added = adds.get(key);
  +            if (added != null) {
  +                return added;
  +            }
  +
  +            if (cleared) {
  +                return null;
  +            } else {
  +                // not modified in this tx
  +                return wrapped.get(key);
  +            }
  +        }
  +
  +        protected void put(Object key, Object value, Object oldValue) {
  +            try {
  +                readOnly = false;
  +                deletes.remove(key);
  +                if (oldValue != null) {
  +                    changes.put(key, value);
  +                } else {
  +                    adds.put(key, value);
  +                }
  +            } catch (RuntimeException e) {
  +                rollbackOnly = true;
  +                throw e;
  +            } catch (Error e) {
  +                rollbackOnly = true;
  +                throw e;
  +            }
  +        }
  +
  +        protected void remove(Object key) {
  +
  +            try {
  +                readOnly = false;
  +                adds.remove(key);
  +                changes.remove(key);
  +                deletes.add(key);
  +            } catch (RuntimeException e) {
  +                rollbackOnly = true;
  +                throw e;
  +            } catch (Error e) {
  +                rollbackOnly = true;
  +                throw e;
  +            }
  +        }
  +
  +        protected int size() {
  +            int size = (cleared ? 0 : wrapped.size());
  +
  +            size -= deletes.size();
  +            size += adds.size();
  +
  +            return size;
  +        }
  +
  +        protected void clear() {
  +            readOnly = false;
  +            cleared = true;
  +            deletes.clear();
  +            changes.clear();
  +            adds.clear();
  +        }
  +
  +        protected void merge() {
  +            if (!readOnly) {
  +
  +                if (cleared) {
  +                    wrapped.clear();
  +                }
  +
  +                for (Iterator it = changes.entrySet().iterator();
  +                    it.hasNext();
  +                    ) {
  +                    Map.Entry entry = (Map.Entry) it.next();
  +                    wrapped.put(entry.getKey(), entry.getValue());
  +                }
  +
  +                for (Iterator it = adds.entrySet().iterator(); it.hasNext();) {
  +                    Map.Entry entry = (Map.Entry) it.next();
  +                    wrapped.put(entry.getKey(), entry.getValue());
  +                }
  +
  +                for (Iterator it = deletes.iterator(); it.hasNext();) {
  +                    Object key = it.next();
  +                    wrapped.remove(key);
  +                }
  +            }
  +        }
  +
  +        protected void dispose() {
  +            setFactory.disposeSet(deletes);
  +            deletes = null;
  +            mapFactory.disposeMap(changes);
  +            changes = null;
  +            mapFactory.disposeMap(adds);
  +            adds = null;
           }
       }
   
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Mime
View raw message