commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ozeigerm...@apache.org
Subject svn commit: r149190 - in jakarta/commons/proper/transaction/trunk: RELEASE-NOTES.txt src/java/org/apache/commons/transaction/memory/OptimisticMapWrapper.java
Date Mon, 31 Jan 2005 00:12:32 GMT
Author: ozeigermann
Date: Sun Jan 30 16:12:31 2005
New Revision: 149190

URL: http://svn.apache.org/viewcvs?view=rev&rev=149190
Log:
OptimisticMapWrapper now uses a read/write lock to guarantee 
no other operations are being executed while
commiting.

Before this it was possible that conflicts that arose during the process of  
committing remained undetected

Modified:
    jakarta/commons/proper/transaction/trunk/RELEASE-NOTES.txt
    jakarta/commons/proper/transaction/trunk/src/java/org/apache/commons/transaction/memory/OptimisticMapWrapper.java

Modified: jakarta/commons/proper/transaction/trunk/RELEASE-NOTES.txt
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/transaction/trunk/RELEASE-NOTES.txt?view=diff&r1=149189&r2=149190
==============================================================================
--- jakarta/commons/proper/transaction/trunk/RELEASE-NOTES.txt (original)
+++ jakarta/commons/proper/transaction/trunk/RELEASE-NOTES.txt Sun Jan 30 16:12:31 2005
@@ -65,6 +65,9 @@
 - Fixed deadlock hazard in deadlock detection caused by interleaving access to locks set
of an owner
 - Fixed timeout that in certain scenarios did not work
 - GenericLock test method released all locks held by the testing owner - fixed
+- OptimisticMapWrapper now uses a read/write lock to guarantee no other operations are being
executed while
+  commiting; before it was possible that conflicts that arose during the process of 
+  committing remained undetected
 
 ENHANCEMENTS FROM 1.0 beta1
 -----------------------

Modified: jakarta/commons/proper/transaction/trunk/src/java/org/apache/commons/transaction/memory/OptimisticMapWrapper.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/transaction/trunk/src/java/org/apache/commons/transaction/memory/OptimisticMapWrapper.java?view=diff&r1=149189&r2=149190
==============================================================================
--- jakarta/commons/proper/transaction/trunk/src/java/org/apache/commons/transaction/memory/OptimisticMapWrapper.java
(original)
+++ jakarta/commons/proper/transaction/trunk/src/java/org/apache/commons/transaction/memory/OptimisticMapWrapper.java
Sun Jan 30 16:12:31 2005
@@ -1,7 +1,7 @@
 /*
  * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//transaction/src/java/org/apache/commons/transaction/memory/OptimisticMapWrapper.java,v
1.1 2004/11/18 23:27:18 ozeigermann Exp $
  * $Revision: 1.1 $
- * $Date: 2004/11/18 23:27:18 $
+ * $Date$
  *
  * ====================================================================
  *
@@ -23,12 +23,17 @@
 
 package org.apache.commons.transaction.memory;
 
+import java.io.PrintWriter;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
 import java.util.Collections;
 
+import org.apache.commons.transaction.locking.ReadWriteLock;
+import org.apache.commons.transaction.util.LoggerFacade;
+import org.apache.commons.transaction.util.PrintWriterLogger;
+
 /**
  * Wrapper that adds transactional control to all kinds of maps that implement the {@link
Map} interface. By using
  * a naive optimistic transaction control this wrapper has better isolation than {@link TransactionalMapWrapper},
but
@@ -52,8 +57,15 @@
  */
 public class OptimisticMapWrapper extends TransactionalMapWrapper {
 
+    protected static final int COMMIT_TIMEOUT = 1000 * 60; // 1 minute
+    protected static final int ACCESS_TIMEOUT = 1000 * 30; // 30 seconds
+
     protected Set activeTransactions;
 
+    protected LoggerFacade logger;
+    
+    protected ReadWriteLock commitLock;
+    
     /**
      * Creates a new optimistic transactional map wrapper. Temporary maps and sets to store
transactional
      * data will be instances of {@link java.util.HashMap} and {@link java.util.HashSet}.

@@ -73,10 +85,28 @@
      * @param setFactory factory for temporary sets
      */
     public OptimisticMapWrapper(Map wrapped, MapFactory mapFactory, SetFactory setFactory)
{
+        this(wrapped, mapFactory, setFactory, new PrintWriterLogger(new PrintWriter(System.out),
+                OptimisticMapWrapper.class.getName(), false));
+    }
+
+    /**
+     * Creates a new optimistic 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
+     * @param logger
+     *            generic logger used for all kinds of logging
+     */
+    public OptimisticMapWrapper(Map wrapped, MapFactory mapFactory, SetFactory setFactory,
LoggerFacade logger) {
         super(wrapped, mapFactory, setFactory);
         activeTransactions = Collections.synchronizedSet(new HashSet());
+        this.logger = logger;
+        commitLock = new ReadWriteLock("COMMIT", logger);
     }
-
+    
+    
     public void startTransaction() {
         if (getActiveTx() != null) {
             throw new IllegalStateException(
@@ -99,7 +129,7 @@
 
     public void commitTransaction(boolean force) throws ConflictException {
         TxContext txContext = getActiveTx();
-
+        
         if (txContext == null) {
             throw new IllegalStateException(
                 "Active thread " + Thread.currentThread() + " not associated with a transaction!");
@@ -108,19 +138,28 @@
         if (txContext.status == STATUS_MARKED_ROLLBACK) {
             throw new IllegalStateException("Active thread " + Thread.currentThread() + "
is marked for rollback!");
         }
-
-        if (!force) {
-            Object conflictKey = checkForConflicts();
-            if (conflictKey != null) {
-                throw new ConflictException(conflictKey);
+        
+        try {
+            // in this final commit phase we need to be the only one access the map
+            // to make sure no one adds an entry after we checked for conflicts
+            commitLock.acquireWrite(txContext, COMMIT_TIMEOUT);
+
+            if (!force) {
+                Object conflictKey = checkForConflicts();
+                if (conflictKey != null) {
+                    throw new ConflictException(conflictKey);
+                }
             }
-        }
-
-        // be sure commit is atomic
-        synchronized (this) {
+    
             activeTransactions.remove(txContext);
             copyChangesToConcurrentTransactions();
             super.commitTransaction();
+            
+        } catch (InterruptedException e) {
+            // XXX a bit dirty ;)
+            throw new ConflictException(e);
+        } finally {
+            commitLock.release(txContext);
         }
     }
 
@@ -208,76 +247,139 @@
         }
 
         protected Set keys() {
-            Set keySet = super.keys();
-            keySet.removeAll(externalDeletes);
-            keySet.addAll(externalAdds.keySet());
-            return keySet;
-        }
-
-        protected Object get(Object key) {
-
-            if (deletes.contains(key)) {
-                // reflects that entry has been deleted in this tx 
+            try {
+                commitLock.acquireRead(this, ACCESS_TIMEOUT);
+                Set keySet = super.keys();
+                keySet.removeAll(externalDeletes);
+                keySet.addAll(externalAdds.keySet());
+                return keySet;
+            } catch (InterruptedException e) {
                 return null;
+            } finally {
+                commitLock.release(this);
             }
+        }
 
-            Object changed = changes.get(key);
-            if (changed != null) {
-                return changed;
-            }
-
-            Object added = adds.get(key);
-            if (added != null) {
-                return added;
-            }
+        protected Object get(Object key) {
+            try {
+                commitLock.acquireRead(this, ACCESS_TIMEOUT);
 
-            if (cleared) {
-                return null;
-            } else {
-                if (externalDeletes.contains(key)) {
+                if (deletes.contains(key)) {
                     // reflects that entry has been deleted in this tx 
                     return null;
                 }
-
-                changed = externalChanges.get(key);
+    
+                Object changed = changes.get(key);
                 if (changed != null) {
                     return changed;
                 }
-
-                added = externalAdds.get(key);
+    
+                Object added = adds.get(key);
                 if (added != null) {
                     return added;
                 }
+    
+                if (cleared) {
+                    return null;
+                } else {
+                    if (externalDeletes.contains(key)) {
+                        // reflects that entry has been deleted in this tx 
+                        return null;
+                    }
+    
+                    changed = externalChanges.get(key);
+                    if (changed != null) {
+                        return changed;
+                    }
+    
+                    added = externalAdds.get(key);
+                    if (added != null) {
+                        return added;
+                    }
+    
+                    // not modified in this tx
+                    return wrapped.get(key);
+                }
+            } catch (InterruptedException e) {
+                return null;
+            } finally {
+                commitLock.release(this);
+            }
+        }
 
-                // not modified in this tx
-                return wrapped.get(key);
+        protected void put(Object key, Object value) {
+            try {
+                commitLock.acquireRead(this, ACCESS_TIMEOUT);
+                super.put(key, value);
+            } catch (InterruptedException e) {
+            } finally {
+                commitLock.release(this);
+            }
+        }
+        
+        protected void remove(Object key) {
+            try {
+                commitLock.acquireRead(this, ACCESS_TIMEOUT);
+                super.remove(key);
+            } catch (InterruptedException e) {
+            } finally {
+                commitLock.release(this);
             }
         }
 
         protected int size() {
-            int size = super.size();
-
-            size -= externalDeletes.size();
-            size += externalAdds.size();
-
-            return size;
+            try {
+                commitLock.acquireRead(this, ACCESS_TIMEOUT);
+                int size = super.size();
+    
+                size -= externalDeletes.size();
+                size += externalAdds.size();
+    
+                return size;
+            } catch (InterruptedException e) {
+                return -1;
+            } finally {
+                commitLock.release(this);
+            }
         }
 
         protected void clear() {
-            super.clear();
-            externalDeletes.clear();
-            externalChanges.clear();
-            externalAdds.clear();
+            try {
+                commitLock.acquireRead(this, ACCESS_TIMEOUT);
+                super.clear();
+                externalDeletes.clear();
+                externalChanges.clear();
+                externalAdds.clear();
+            } catch (InterruptedException e) {
+            } finally {
+                commitLock.release(this);
+            }
         }
 
+        protected void merge() {
+            try {
+                commitLock.acquireRead(this, ACCESS_TIMEOUT);
+                super.merge();
+            } catch (InterruptedException e) {
+            } finally {
+                commitLock.release(this);
+            }
+        }
+        
         protected void dispose() {
-            super.dispose();
-            setFactory.disposeSet(externalDeletes);
-            externalDeletes = null;
-            mapFactory.disposeMap(externalChanges);
-            externalChanges = null;
-            mapFactory.disposeMap(externalAdds);
-            externalAdds = null;
+            try {
+                commitLock.acquireRead(this, ACCESS_TIMEOUT);
+                super.dispose();
+                setFactory.disposeSet(externalDeletes);
+                externalDeletes = null;
+                mapFactory.disposeMap(externalChanges);
+                externalChanges = null;
+                mapFactory.disposeMap(externalAdds);
+                externalAdds = null;
+            } catch (InterruptedException e) {
+            } finally {
+                commitLock.release(this);
+            }
         }
 
         protected void finalize() throws Throwable {



---------------------------------------------------------------------
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