Author: ozeigermann
Date: Sun Jul 22 08:16:04 2007
New Revision: 558494

URL: http://svn.apache.org/viewvc?view=rev&rev=558494
Log:
Major refeactoring to
- allow for new type of lock manager
- allow operations on multiple transaction resource managers inside a single 
transaction

Added:
    
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/ManageableResourceManager.java
    
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/TransactionException.java
    
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/TransactionImpl.java
    
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/HierarchicalRWLockManager.java
    
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/RWLockManager.java
    
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/BasicTxMap.java
      - copied, changed from r558031, 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/TxMap.java
    
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/test/org/apache/commons/transaction/TransactionImplTest.java
Removed:
    
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/GenericLockManager.java
    
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/IntrinsicLockManager.java
    
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/ReadWriteLockManager.java
Modified:
    
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/AbstractTransactionalResourceManager.java
    
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/Transaction.java
    
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/TransactionalResourceManager.java
    
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/HierarchicalLockManager.java
    
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/LockException.java
    
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/LockManager.java
    
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/OptimisticTxMap.java
    
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/PessimisticTxMap.java
    
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/TxMap.java

Modified: 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/AbstractTransactionalResourceManager.java
URL: 
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/AbstractTransactionalResourceManager.java?view=diff&rev=558494&r1=558493&r2=558494
==============================================================================
--- 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/AbstractTransactionalResourceManager.java
 (original)
+++ 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/AbstractTransactionalResourceManager.java
 Sun Jul 22 08:16:04 2007
@@ -16,37 +16,44 @@
  */
 package org.apache.commons.transaction;
 
+import java.util.Map;
 import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.ReadWriteLock;
 
 import org.apache.commons.transaction.locking.LockException;
-import org.apache.commons.transaction.locking.ReadWriteLockManager;
-import org.apache.commons.transaction.locking.LockException.Code;
+import org.apache.commons.transaction.locking.LockManager;
 
 /**
  * Not thread-safe. FIXME: Should it be?
- *  
+ * 
  * @author olli
- *
+ * 
  * @param <T>
  */
-public abstract class AbstractTransactionalResourceManager<T extends 
AbstractTransactionalResourceManager.AbstractTxContext> implements 
TransactionalResourceManager {
+public abstract class AbstractTransactionalResourceManager<T extends 
AbstractTransactionalResourceManager.AbstractTxContext>
+        implements ManageableResourceManager {
     protected ThreadLocal<T> activeTx = new ThreadLocal<T>();
 
+    private LockManager<Object, String> lm;
+
+    private String name;
+
     protected abstract T createContext();
 
-    /**
-     * Checks whether this transaction has been marked to allow a rollback as
-     * the only valid outcome. This can be set my method
-     * [EMAIL PROTECTED] #markTransactionForRollback()} or might be set 
internally be any
-     * fatal error. Once a transaction is marked for rollback there is no way 
to
-     * undo this. A transaction that is marked for rollback can not be
-     * committed, also rolled back.
-     * 
-     * @return <code>true</code> if this transaction has been marked for a
-     *         roll back
-     * @see #markTransactionForRollback()
-     */
+    public AbstractTransactionalResourceManager() {
+    }
+
+    public AbstractTransactionalResourceManager(String name) {
+        this.name = name;
+    }
+
+    // can be used to share a lock manager with other transactinal resource
+    // managers
+    public AbstractTransactionalResourceManager(String name, 
LockManager<Object, String> lm) {
+        this.name = name;
+        this.lm = lm;
+    }
+
+    @Override
     public boolean isTransactionMarkedForRollback() {
         T txContext = getActiveTx();
 
@@ -59,13 +66,14 @@
     }
 
     @Override
-    public void startTransaction() {
+    public void startTransaction(long timeout, TimeUnit unit) {
         if (getActiveTx() != null) {
             throw new IllegalStateException("Active thread " + 
Thread.currentThread()
                     + " already associated with a transaction!");
         }
-        T txContent = createContext();
-        setActiveTx(txContent);
+        T txContext = createContext();
+        txContext.start(timeout, unit);
+        setActiveTx(txContext);
 
     }
 
@@ -83,7 +91,7 @@
     }
 
     @Override
-    public void commitTransaction() {
+    public boolean commitTransaction() {
         T txContext = getActiveTx();
 
         if (txContext == null) {
@@ -99,32 +107,7 @@
         txContext.commit();
         txContext.dispose();
         setActiveTx(null);
-    }
-
-    /**
-     * Prepares the changes done inside this transaction reasource.
-     *  
-     */
-    public boolean prepareTransaction() {
-        T txContext = getActiveTx();
-
-        if (txContext == null) {
-            throw new IllegalStateException("Active thread " + 
Thread.currentThread()
-                    + " not associated with a transaction!");
-        }
-        return txContext.prepare();
-    }
-
-    @Override
-    public void setTransactionTimeout(long mSecs) {
-        T txContext = getActiveTx();
-
-        if (txContext == null) {
-            throw new IllegalStateException("Active thread " + 
Thread.currentThread()
-                    + " not associated with a transaction!");
-        }
-        
-        txContext.setTimeout(mSecs);
+        return true;
     }
 
     protected T getActiveTx() {
@@ -135,130 +118,114 @@
         activeTx.set(txContext);
     }
 
-    public boolean isTransactionPrepared() {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
     public boolean isReadOnlyTransaction() {
-        // TODO Auto-generated method stub
-        return false;
-    }
+        T txContext = getActiveTx();
 
-    /**
-     * Marks the current transaction to allow only a rollback as valid outcome.
-     * 
-     * @see #isTransactionMarkedForRollback()
-     */
-    public void markTransactionForRollback() {
-        // TODO Auto-generated method stub
-        
+        if (txContext == null) {
+            throw new IllegalStateException("Active thread " + 
Thread.currentThread()
+                    + " not associated with a transaction!");
+        }
+
+        return (txContext.isReadOnly());
     }
 
     public abstract class AbstractTxContext {
-        private long timeout = -1L;
+        private boolean readOnly = true;
 
-        private long startTime = -1L;
+        private boolean markedForRollback = false;
 
-        private boolean readOnly = true;
+        private LockManager<Object, String> lm;
         
-        private boolean prepared = false;
-        private boolean markedForRollback = false;
+        public AbstractTxContext() {
+        }
         
-        private ReadWriteLockManager lm = new ReadWriteLockManager();
+        public LockManager<Object, String> getLm() {
+            if (this.lm != null) return this.lm;
+            else return AbstractTransactionalResourceManager.this.lm;
+        }
 
-        public AbstractTxContext() {
-            startTime = System.currentTimeMillis();
+
+        public void join(LockManager lm) {
+            this.lm = lm;
         }
 
-        protected long getRemainingTimeout() {
-            long now = System.currentTimeMillis();
-            return (getStartTime()- now + timeout);
+        public void start(long timeout, TimeUnit unit) {
+            getLm().startWork(timeout, unit);
         }
 
         public void dispose() {
-            Iterable<ReadWriteLock> locks = getLm().getAllForCurrentThread();
-
-            for (ReadWriteLock lock : locks) {
-                lock.readLock().unlock();
-                lock.writeLock().unlock();
-            }
+            getLm().endWork();
         }
 
         public boolean isReadOnly() {
             return readOnly;
         }
 
-        public boolean prepare() {
-            prepared = true;
-            return true;
+        public void setReadOnly(boolean readOnly) {
+            this.readOnly = readOnly;
         }
 
-        public long getStartTime() {
-            return startTime;
+        public void readLock(Object id) throws LockException {
+            getLm().lock(getName(), id, false);
         }
 
-        public void setStartTime(long startTimeMSecs) {
-            this.startTime = startTimeMSecs;
+        public void writeLock(Object id) throws LockException {
+            getLm().lock(getName(), id, true);
         }
 
-        public long getTimeout() {
-            return timeout;
+        public boolean isMarkedForRollback() {
+            return markedForRollback;
         }
 
-        public void setTimeout(long timeoutMSecs) {
-            this.timeout = timeoutMSecs;
-        }
-        
-        public void setReadOnly(boolean readOnly) {
-            this.readOnly = readOnly;
+        public void markForRollback() {
+            markedForRollback = true;
         }
 
-        public ReadWriteLockManager getLm() {
-            return lm;
-        }
+        public void commit() {
 
-        protected ReadWriteLock initLock(Object id) {
-            return getLm().putIfAbsent(id, getLm().create());
         }
+    }
 
-        public void readLock(Object id) throws LockException {
-            try {
-                boolean locked = 
initLock(id).readLock().tryLock(getRemainingTimeout(), TimeUnit.MILLISECONDS);
-                if (!locked) {
-                    throw new LockException(Code.TIMED_OUT, id);
-                }
-            } catch (InterruptedException e) {
-                throw new LockException(Code.INTERRUPTED, id);
-            }
-        }
-
-        public void writeLock(Object id)throws LockException  {
-            try {
-                boolean locked = 
initLock(id).writeLock().tryLock(getRemainingTimeout(), TimeUnit.MILLISECONDS);
-                if (!locked) {
-                    throw new LockException(Code.TIMED_OUT, id);
-                }
-            } catch (InterruptedException e) {
-                throw new LockException(Code.INTERRUPTED, id);
-            }
-        }
+    public LockManager<Object, String> getLm() {
+        return lm;
+    }
 
-        public boolean isMarkedForRollback() {
-            return markedForRollback;
-        }
+    public void setLm(LockManager<Object, String> lm) {
+        this.lm = lm;
+    }
 
-        public boolean isPrepared() {
-            return prepared;
-        }
+    public String getName() {
+        return name;
+    }
 
-        public void markForRollback() {
-            markedForRollback = true;
+    public void setName(String name) {
+        this.name = name;
+    }
+    
+    public abstract boolean commitCanFail();
+
+    @Override
+    public void joinTransaction(LockManager lm) {
+        if (getActiveTx() != null) {
+            throw new IllegalStateException("Active thread " + 
Thread.currentThread()
+                    + " already associated with a transaction!");
         }
+        T txContext = createContext();
+        txContext.join(lm);
+        setActiveTx(txContext);
 
-        public void commit() {
-            
+    }
+
+    public void setRollbackOnly() {
+        T txContext = getActiveTx();
+
+        if (txContext == null) {
+            throw new IllegalStateException("Active thread " + 
Thread.currentThread()
+                    + " not associated with a transaction!");
         }
+        txContext.markForRollback();
+
     }
+
 
 }

Added: 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/ManageableResourceManager.java
URL: 
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/ManageableResourceManager.java?view=auto&rev=558494
==============================================================================
--- 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/ManageableResourceManager.java
 (added)
+++ 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/ManageableResourceManager.java
 Sun Jul 22 08:16:04 2007
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.transaction;
+
+import org.apache.commons.transaction.locking.LockManager;
+
+
+public interface ManageableResourceManager extends 
TransactionalResourceManager {
+    void setRollbackOnly();
+    boolean commitCanFail();
+    /**
+     * Checks whether this transaction has been marked to allow a rollback as
+     * the only valid outcome. This can be set my method
+     * [EMAIL PROTECTED] #markTransactionForRollback()} or might be set 
internally be any
+     * fatal error. Once a transaction is marked for rollback there is no way 
to
+     * undo this. A transaction that is marked for rollback can not be
+     * committed, also rolled back.
+     * 
+     * @return <code>true</code> if this transaction has been marked for a
+     *         roll back
+     * @see #markTransactionForRollback()
+     */
+    public boolean isTransactionMarkedForRollback();
+
+
+    public boolean isReadOnlyTransaction();
+    
+    public void joinTransaction(LockManager lm);
+
+    
+
+}

Modified: 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/Transaction.java
URL: 
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/Transaction.java?view=diff&rev=558494&r1=558493&r2=558494
==============================================================================
--- 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/Transaction.java
 (original)
+++ 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/Transaction.java
 Sun Jul 22 08:16:04 2007
@@ -16,12 +16,19 @@
  */
 package org.apache.commons.transaction;
 
-public interface Transaction {
-    public void setTransactionTimeout(long mSecs);
-
-    public void start();
+import java.util.concurrent.TimeUnit;
 
-    void setRollbackOnly();
+/**
+ * A managed transaction meant as interface to the user. Meant to operate on 
more than one resource manager.
+ * This is a light weight replacement for a complex 2PC xa transaction.
+ * 
+ * @author olli
+ *
+ * 
+ */
+// TODO: We need a manager for such a transaction (or at least an 
implementation)
+public interface Transaction {
+    public void start(long timeout, TimeUnit unit);
 
     boolean isRollbackOnly();
 
@@ -29,6 +36,6 @@
 
     public void commit();
 
-    boolean enlistResourceManager(TransactionalResourceManager 
resourceManager);
+    void enlistResourceManager(ManageableResourceManager resourceManager);
 
 }

Added: 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/TransactionException.java
URL: 
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/TransactionException.java?view=auto&rev=558494
==============================================================================
--- 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/TransactionException.java
 (added)
+++ 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/TransactionException.java
 Sun Jul 22 08:16:04 2007
@@ -0,0 +1,38 @@
+package org.apache.commons.transaction;
+
+
+
+public class TransactionException extends RuntimeException {
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 7650329971392401844L;
+
+    public enum Code {
+        COMMIT_FAILED,
+        ROLLBACK_ONLY
+    }
+
+    protected Code code;
+
+    public TransactionException(Throwable cause, Code code) {
+        super(cause);
+        this.code = code;
+    }
+
+    public TransactionException(Code code) {
+        this.code = code;
+    }
+    
+    /**
+     * Returns the formal reason for the exception.
+     * 
+     * @return the reason code
+     */
+    public Code getCode() {
+        return code;
+    }
+
+
+}

Added: 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/TransactionImpl.java
URL: 
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/TransactionImpl.java?view=auto&rev=558494
==============================================================================
--- 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/TransactionImpl.java
 (added)
+++ 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/TransactionImpl.java
 Sun Jul 22 08:16:04 2007
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.transaction;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.commons.transaction.locking.LockManager;
+
+/**
+ * A managed transaction meant as interface to the user. Meant to operate on
+ * more than one resource manager. This is a light weight replacement for a
+ * complex 2PC xa transaction.
+ * 
+ * @author olli
+ * 
+ * 
+ */
+public class TransactionImpl implements Transaction {
+
+    protected LockManager lm;
+
+    protected List<ManageableResourceManager> rms;
+
+    public TransactionImpl(LockManager lm) {
+        this.lm = lm;
+        this.rms = new LinkedList<ManageableResourceManager>();
+    }
+
+    public void commit() throws TransactionException {
+        lm.endWork();
+        if (isRollbackOnly()) {
+            throw new 
TransactionException(TransactionException.Code.ROLLBACK_ONLY);
+        }
+        for (ManageableResourceManager manager : rms) {
+            if (!manager.isReadOnlyTransaction()) {
+                try {
+                    if (!manager.commitTransaction()) {
+                        throw new 
TransactionException(TransactionException.Code.COMMIT_FAILED);
+                    }
+                } catch (Exception e) {
+                    throw new TransactionException(e, 
TransactionException.Code.COMMIT_FAILED);
+                } catch (Error e) {
+                    // is this really a good idea?
+                    rollback();
+                    throw e;
+                }
+            }
+        }
+    }
+
+    public void enlistResourceManager(ManageableResourceManager 
resourceManager) {
+        // if the manager might fail upon commit, tried it as early as possible
+        if (resourceManager.commitCanFail()) {
+            rms.add(0, resourceManager);
+        } else {
+            rms.add(resourceManager);
+        }
+    }
+
+    public boolean isRollbackOnly() {
+        for (ManageableResourceManager manager : rms) {
+            if (manager.isTransactionMarkedForRollback())
+                return true;
+        }
+        return false;
+    }
+
+    public void rollback() {
+        lm.endWork();
+        for (ManageableResourceManager manager : rms) {
+            if (!manager.isReadOnlyTransaction()) {
+                manager.rollbackTransaction();
+            }
+        }
+    }
+
+    public void start(long timeout, TimeUnit unit) {
+        for (ManageableResourceManager manager : rms) {
+            manager.joinTransaction(lm);
+        }
+        lm.startWork(timeout, unit);
+    }
+
+}

Modified: 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/TransactionalResourceManager.java
URL: 
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/TransactionalResourceManager.java?view=diff&rev=558494&r1=558493&r2=558494
==============================================================================
--- 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/TransactionalResourceManager.java
 (original)
+++ 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/TransactionalResourceManager.java
 Sun Jul 22 08:16:04 2007
@@ -16,20 +16,16 @@
  */
 package org.apache.commons.transaction;
 
+import java.util.concurrent.TimeUnit;
+
 
 /**
  * Interface for something that makes up a transactional resource manager.
+ * Comparable to an XA resource.
  * 
  */
 public interface TransactionalResourceManager {
     /**
-     * TODO
-     * 
-     * @param mSecs
-     */
-    public void setTransactionTimeout(long mSecs);
-
-    /**
      * Starts a new transaction and associates it with the current thread. All
      * subsequent changes in the same thread made to the map are invisible from
      * other threads until [EMAIL PROTECTED] #commitTransaction()} is called. 
Use
@@ -43,14 +39,13 @@
      * @see #commitTransaction()
      * @see #rollbackTransaction()
      */
-    public void startTransaction();
-
+    public void startTransaction(long timeout, TimeUnit unit);
 
     /**
      * Discards all changes made in the current transaction and deletes the
      * association between the current thread and the transaction.
      * 
-     * @see #startTransaction()
+     * @see #startTransaction(long, TimeUnit)
      * @see #commitTransaction()
      */
     public void rollbackTransaction();
@@ -59,9 +54,8 @@
      * Commits all changes made in the current transaction and deletes the
      * association between the current thread and the transaction.
      * 
-     * @see #startTransaction()
+     * @see #startTransaction(long, TimeUnit)
      * @see #rollbackTransaction()
      */
-    public void commitTransaction();
-
+    public boolean commitTransaction();
 }

Modified: 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/HierarchicalLockManager.java
URL: 
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/HierarchicalLockManager.java?view=diff&rev=558494&r1=558493&r2=558494
==============================================================================
--- 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/HierarchicalLockManager.java
 (original)
+++ 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/HierarchicalLockManager.java
 Sun Jul 22 08:16:04 2007
@@ -2,6 +2,7 @@
 
 
 // Takes care of hierarchical locking with folders and resources
-public class HierarchicalLockManager extends ReadWriteLockManager {
-
+public interface HierarchicalLockManager<M> extends LockManager<String, M> {
+    public void lockAsFolder(String path, boolean exclusive) throws 
LockException;
+    public void lockAsResource(String path, boolean exclusive) throws 
LockException;
 }

Added: 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/HierarchicalRWLockManager.java
URL: 
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/HierarchicalRWLockManager.java?view=auto&rev=558494
==============================================================================
--- 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/HierarchicalRWLockManager.java
 (added)
+++ 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/HierarchicalRWLockManager.java
 Sun Jul 22 08:16:04 2007
@@ -0,0 +1,15 @@
+package org.apache.commons.transaction.locking;
+
+public class HierarchicalRWLockManager<M> extends RWLockManager<String, M> 
implements
+        HierarchicalLockManager<M> {
+
+    public void lockAsFolder(String path, boolean exclusive) throws 
LockException {
+        // TODO Auto-generated method stub
+        
+    }
+
+    public void lockAsResource(String path, boolean exclusive) throws 
LockException {
+        // TODO Auto-generated method stub
+        
+    }
+}

Modified: 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/LockException.java
URL: 
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/LockException.java?view=diff&rev=558494&r1=558493&r2=558494
==============================================================================
--- 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/LockException.java
 (original)
+++ 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/LockException.java
 Sun Jul 22 08:16:04 2007
@@ -87,6 +87,10 @@
         super(cause);
     }
 
+    public LockException(Code code) {
+        this.code = code;
+    }
+
     public LockException(Throwable cause, Code code) {
         super(cause);
         this.code = code;

Modified: 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/LockManager.java
URL: 
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/LockManager.java?view=diff&rev=558494&r1=558493&r2=558494
==============================================================================
--- 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/LockManager.java
 (original)
+++ 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/LockManager.java
 Sun Jul 22 08:16:04 2007
@@ -1,18 +1,41 @@
 package org.apache.commons.transaction.locking;
 
+import java.util.concurrent.TimeUnit;
 
+/**
+ * 
+ * @author olli
+ * 
+ * 
+ * 
+ * @param <K>
+ */
+public interface LockManager<K, M> {
+    /**
+     * Starts a block of work for which a certain set of locks is required.
+     * 
+     * @param timeout
+     *            the maximum time for the whole work to take before it times
+     *            out
+     * @param unit
+     *            the time unit of the [EMAIL PROTECTED] timeout} argument
+     */
+    public void startWork(long timeout, TimeUnit unit);
 
-public interface LockManager<K, L> {
-    public L get(K key);
+    /**
+     * Ends a block of work that has been started in
+     * [EMAIL PROTECTED] #startWork(long, TimeUnit)}. All locks acquired will 
be released.
+     * All registered locks will be unregistered from this lock manager.
+     * 
+     */
+    public void endWork();
 
-    public L putIfAbsent(K key, L lock);
+    public boolean isWorking();
 
-    public L remove(K key);
-    
-    public L create();
-    
-    public Iterable<L> getAll();
-    
-    public Iterable<L> getAllForCurrentThread();
+    /**
+     * @param managedResource
+     *            resource for on which this block of work shall be done
+     */
+    public void lock(M managedResource, K key, boolean exclusive) throws 
LockException;
 
 }

Added: 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/RWLockManager.java
URL: 
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/RWLockManager.java?view=auto&rev=558494
==============================================================================
--- 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/RWLockManager.java
 (added)
+++ 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/RWLockManager.java
 Sun Jul 22 08:16:04 2007
@@ -0,0 +1,169 @@
+package org.apache.commons.transaction.locking;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import org.apache.commons.transaction.locking.LockException.Code;
+
+public class RWLockManager<K, M> implements LockManager<K, M> {
+
+    protected ConcurrentHashMap<KeyEntry<K, M>, ReadWriteLock> locks = new 
ConcurrentHashMap<KeyEntry<K, M>, ReadWriteLock>();
+
+    protected Map<Thread, Set<ReadWriteLock>> locksForThreads = new 
ConcurrentHashMap<Thread, Set<ReadWriteLock>>();
+
+    protected Map<ReadWriteLock, Set<Thread>> threadsForLocks = new 
ConcurrentHashMap<ReadWriteLock, Set<Thread>>();
+
+    protected Map<Thread, Long> effectiveGlobalTimeouts = new 
ConcurrentHashMap<Thread, Long>();
+
+    // TODO
+    public static Iterable<ReadWriteLock> orderLocks() {
+        return null;
+
+    }
+
+    // TODO
+    public void lockAll(Iterable<ReadWriteLock> locks) {
+    }
+
+    @Override
+    public void endWork() {
+        Set<ReadWriteLock> locks = locksForThreads.get(Thread.currentThread());
+        // graceful reaction...
+        if (locks == null) {
+            return;
+        }
+        for (ReadWriteLock lock : locks) {
+            try {
+                lock.readLock().unlock();
+            } catch (IllegalMonitorStateException imse) {
+                // we do not care
+            }
+            try {
+                lock.writeLock().unlock();
+            } catch (IllegalMonitorStateException imse) {
+                // we do not care
+            }
+
+            // FIXME: We need to do this atomically
+            Set<Thread> threadsForThisLock = threadsForLocks.get(lock);
+            if (threadsForThisLock != null) {
+                threadsForThisLock.remove(Thread.currentThread());
+                if (threadsForThisLock.isEmpty()) {
+                    threadsForLocks.remove(lock);
+                    locks.remove(lock);
+                }
+            }
+        }
+
+        locksForThreads.remove(Thread.currentThread());
+    }
+
+    @Override
+    public void startWork(long timeout, TimeUnit unit) {
+        if (isWorking()) {
+            throw new IllegalStateException("work has already been started");
+        }
+        locksForThreads.put(Thread.currentThread(), new 
HashSet<ReadWriteLock>());
+
+        long timeoutMSecs = unit.toMillis(timeout);
+        long now = System.currentTimeMillis();
+        long effectiveTimeout = now + timeoutMSecs;
+        effectiveGlobalTimeouts.put(Thread.currentThread(), effectiveTimeout);
+    }
+
+    // TODO
+    protected boolean checkForDeadlock() {
+        return false;
+
+    }
+
+    protected long computeRemainingTime() {
+        long timeout = effectiveGlobalTimeouts.get(Thread.currentThread());
+        long now = System.currentTimeMillis();
+        long remaining = timeout - now;
+        return remaining;
+    }
+
+    protected final ReadWriteLock putIfAbsent(KeyEntry<K, M> entry, 
ReadWriteLock lock) {
+        ReadWriteLock existingLock = locks.get(entry);
+        if (existingLock == null) {
+            ReadWriteLock concurrentlyInsertedLock = locks.putIfAbsent(entry, 
lock);
+            if (concurrentlyInsertedLock != null)
+                lock = concurrentlyInsertedLock;
+        }
+        return lock;
+
+    }
+
+    protected ReadWriteLock create() {
+        return new ReentrantReadWriteLock();
+    }
+
+    protected static class KeyEntry<K, M> {
+
+        private K k;
+
+        private M m;
+
+        public KeyEntry(K k, M m) {
+            this.k = k;
+            this.m = m;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj)
+                return true;
+            if (obj instanceof KeyEntry) {
+                KeyEntry otherEntry = (KeyEntry) obj;
+                return (otherEntry.k.equals(k) && otherEntry.m.equals(m));
+            }
+            return false;
+        }
+
+        public int hashCode() {
+            return k.hashCode() + m.hashCode();
+        }
+    }
+
+    @Override
+    public void lock(M managedResource, K key, boolean exclusive) throws 
LockException {
+        long remainingTime = computeRemainingTime();
+        if (remainingTime < 0) {
+            throw new LockException(LockException.Code.TIMED_OUT);
+        }
+
+        KeyEntry<K, M> entry = new KeyEntry<K, M>(key, managedResource);
+
+        ReadWriteLock rwlock = putIfAbsent(entry, create());
+        Set<ReadWriteLock> locks = locksForThreads.get(Thread.currentThread());
+        if (locks == null) {
+            throw new IllegalStateException("lock() can only be called after 
startWork()");
+        }
+        locks.add(rwlock);
+
+        Lock lock = exclusive ? rwlock.writeLock() : rwlock.readLock();
+
+        try {
+            boolean locked = lock.tryLock(remainingTime, 
TimeUnit.MILLISECONDS);
+            if (!locked) {
+                throw new LockException(Code.TIMED_OUT, key);
+            }
+        } catch (InterruptedException e) {
+            throw new LockException(Code.INTERRUPTED, key);
+        }
+
+    }
+
+    @Override
+    public boolean isWorking() {
+        return locksForThreads.get(Thread.currentThread()) != null;
+    }
+
+}

Copied: 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/BasicTxMap.java
 (from r558031, 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/TxMap.java)
URL: 
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/BasicTxMap.java?view=diff&rev=558494&p1=jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/TxMap.java&r1=558031&p2=jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/BasicTxMap.java&r2=558494
==============================================================================
--- 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/TxMap.java
 (original)
+++ 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/BasicTxMap.java
 Sun Jul 22 08:16:04 2007
@@ -28,6 +28,7 @@
 import org.apache.commons.transaction.AbstractTransactionalResourceManager;
 import org.apache.commons.transaction.TransactionalResourceManager;
 import 
org.apache.commons.transaction.AbstractTransactionalResourceManager.AbstractTxContext;
+import org.apache.commons.transaction.locking.LockManager;
 
 /**
  * Wrapper that adds transactional control to all kinds of maps that implement
@@ -49,12 +50,15 @@
  * @see OptimisticTxMap
  * @see PessimisticTxMap
  */
-public class TxMap<K, V> extends
-        AbstractTransactionalResourceManager<TxMap.MapTxContext> implements 
Map<K, V>,
-        TransactionalResourceManager {
+public class BasicTxMap<K, V> extends 
AbstractTransactionalResourceManager<BasicTxMap.MapTxContext> implements
+        TxMap<K, V> {
 
     protected Map<K, V> wrapped = new ConcurrentHashMap<K, V>();
 
+    public BasicTxMap(String name) {
+        super(name);
+    }
+
     //
     // Map methods
     // 
@@ -419,6 +423,11 @@
             }
         }
 
+    }
+
+    @Override
+    public boolean commitCanFail() {
+        return false;
     }
 
 }

Modified: 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/OptimisticTxMap.java
URL: 
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/OptimisticTxMap.java?view=diff&rev=558494&r1=558493&r2=558494
==============================================================================
--- 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/OptimisticTxMap.java
 (original)
+++ 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/OptimisticTxMap.java
 Sun Jul 22 08:16:04 2007
@@ -27,11 +27,12 @@
 
 import org.apache.commons.transaction.TransactionalResourceManager;
 import org.apache.commons.transaction.locking.LockException;
+import org.apache.commons.transaction.locking.LockManager;
 
 /**
  * Wrapper that adds transactional control to all kinds of maps that implement
  * the [EMAIL PROTECTED] Map} interface. By using a naive optimistic 
transaction control
- * this wrapper has better isolation than [EMAIL PROTECTED] TxMap}, but
+ * this wrapper has better isolation than [EMAIL PROTECTED] BasicTxMap}, but
  * may also fail to commit.
  * 
  * <br>
@@ -50,11 +51,10 @@
  * around.
  * 
  * @version $Id: OptimisticMapWrapper.java 493628 2007-01-07 01:42:48Z joerg $
- * @see TxMap
+ * @see BasicTxMap
  * @see PessimisticTxMap
  */
-public class OptimisticTxMap<K, V> extends TxMap<K, V> implements Map<K, V>,
-TransactionalResourceManager {
+public class OptimisticTxMap<K, V> extends BasicTxMap<K, V> implements 
TxMap<K, V> {
 
     private Set<CopyingTxContext> activeTransactions = new 
HashSet<CopyingTxContext>();
     private ReadWriteLock commitLock = new ReentrantReadWriteLock();
@@ -68,11 +68,16 @@
         activeTransactions.remove(txContext);
     }
 
-    public void commitTransaction() throws LockException {
-        commitTransaction(false);
+    public OptimisticTxMap(String name) {
+        super(name);
     }
 
-    public void commitTransaction(boolean force) throws LockException {
+
+    public boolean commitTransaction() throws LockException {
+        return commitTransaction(false);
+    }
+
+    public boolean commitTransaction(boolean force) throws LockException {
         MapTxContext txContext = getActiveTx();
         
         if (txContext == null) {
@@ -99,8 +104,7 @@
     
             activeTransactions.remove(txContext);
             copyChangesToConcurrentTransactions();
-            super.commitTransaction();
-            
+            return super.commitTransaction();
         } catch (InterruptedException e) {
             throw new LockException(e);
         } finally {
@@ -337,4 +341,10 @@
     public void setCommitTimeout(long commitTimeout) {
         this.commitTimeout = commitTimeout;
     }
+    
+    @Override
+    public boolean commitCanFail() {
+        return true;
+    }
+
 }

Modified: 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/PessimisticTxMap.java
URL: 
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/PessimisticTxMap.java?view=diff&rev=558494&r1=558493&r2=558494
==============================================================================
--- 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/PessimisticTxMap.java
 (original)
+++ 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/PessimisticTxMap.java
 Sun Jul 22 08:16:04 2007
@@ -22,11 +22,12 @@
 import java.util.Set;
 
 import org.apache.commons.transaction.TransactionalResourceManager;
+import org.apache.commons.transaction.locking.LockManager;
 
 /**
  * Wrapper that adds transactional control to all kinds of maps that implement
  * the [EMAIL PROTECTED] Map} interface. By using pessimistic transaction 
control (blocking
- * locks) this wrapper has better isolation than [EMAIL PROTECTED] TxMap},
+ * locks) this wrapper has better isolation than [EMAIL PROTECTED] BasicTxMap},
  * but also has less possible concurrency and may even deadlock. A commit,
  * however, will never fail. <br>
  * Start a transaction by calling [EMAIL PROTECTED] #startTransaction()}. Then 
perform the
@@ -41,14 +42,17 @@
  * <code>SERIALIZABLE</code>.
  * 
  * @version $Id: PessimisticMapWrapper.java 493628 2007-01-07 01:42:48Z joerg $
- * @see TxMap
+ * @see BasicTxMap
  * @see OptimisticTxMap
  */
-public class PessimisticTxMap<K, V> extends TxMap<K, V> implements Map<K, V>,
-TransactionalResourceManager {
+public class PessimisticTxMap<K, V> extends BasicTxMap<K, V> implements 
TxMap<K, V> {
 
     protected static final Object GLOBAL_LOCK = "GLOBAL";
 
+    public PessimisticTxMap(String name) {
+        super(name);
+    }
+
     public Collection values() {
         assureGlobalReadLock();
         return super.values();
@@ -142,6 +146,10 @@
             super.clear();
         }
 
+    }
+    @Override
+    public boolean commitCanFail() {
+        return false;
     }
 
 }

Modified: 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/TxMap.java
URL: 
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/TxMap.java?view=diff&rev=558494&r1=558493&r2=558494
==============================================================================
--- 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/TxMap.java
 (original)
+++ 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/TxMap.java
 Sun Jul 22 08:16:04 2007
@@ -16,409 +16,9 @@
  */
 package org.apache.commons.transaction.memory;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
 import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
 
-import org.apache.commons.transaction.AbstractTransactionalResourceManager;
-import org.apache.commons.transaction.TransactionalResourceManager;
-import 
org.apache.commons.transaction.AbstractTransactionalResourceManager.AbstractTxContext;
-
-/**
- * Wrapper that adds transactional control to all kinds of maps that implement
- * the [EMAIL PROTECTED] Map} interface. This wrapper has rather weak 
isolation, but is
- * simply, neven blocks and commits will never fail for logical reasons. <br>
- * Start a transaction by calling [EMAIL PROTECTED] #startTransaction()}. Then 
perform the
- * normal actions on the map and finally either call
- * [EMAIL PROTECTED] #commitTransaction()} to make your changes permanent or
- * [EMAIL PROTECTED] #rollbackTransaction()} to undo them. <br>
- * <em>Caution:</em> Do not modify values retrieved by [EMAIL PROTECTED] 
#get(Object)} as
- * this will circumvent the transactional mechanism. Rather clone the value or
- * copy it in a way you see fit and store it back using
- * [EMAIL PROTECTED] #put(Object, Object)}. <br>
- * <em>Note:</em> This wrapper guarantees isolation level
- * <code>READ COMMITTED</code> only. I.e. as soon a value is committed in one
- * transaction it will be immediately visible in all other concurrent
- * transactions.
- * 
- * @see OptimisticTxMap
- * @see PessimisticTxMap
- */
-public class TxMap<K, V> extends
-        AbstractTransactionalResourceManager<TxMap.MapTxContext> implements 
Map<K, V>,
-        TransactionalResourceManager {
-
-    protected Map<K, V> wrapped = new ConcurrentHashMap<K, V>();
-
-    //
-    // Map methods
-    // 
-
-    /**
-     * @see Map#clear()
-     */
-    public void clear() {
-        MapTxContext txContext = getActiveTx();
-        if (txContext != null) {
-            txContext.clear();
-        } else {
-            wrapped.clear();
-        }
-    }
-
-    /**
-     * @see Map#size()
-     */
-    public int size() {
-        MapTxContext txContext = getActiveTx();
-        if (txContext != null) {
-            return txContext.size();
-        } else {
-            return wrapped.size();
-        }
-    }
-
-    /**
-     * @see Map#isEmpty()
-     */
-    public boolean isEmpty() {
-        MapTxContext txContext = getActiveTx();
-        if (txContext == null) {
-            return wrapped.isEmpty();
-        } else {
-            return txContext.isEmpty();
-        }
-    }
-
-    /**
-     * @see Map#containsKey(java.lang.Object)
-     */
-    public boolean containsKey(Object key) {
-        return keySet().contains(key);
-    }
-
-    /**
-     * @see Map#containsValue(java.lang.Object)
-     */
-    public boolean containsValue(Object value) {
-        MapTxContext txContext = getActiveTx();
-
-        if (txContext == null) {
-            return wrapped.containsValue(value);
-        } else {
-            return values().contains(value);
-        }
-    }
-
-    /**
-     * @see Map#values()
-     */
-    public Collection values() {
-
-        MapTxContext txContext = getActiveTx();
-
-        if (txContext == null) {
-            return wrapped.values();
-        } else {
-            // XXX expensive :(
-            Collection values = new ArrayList();
-            for (Iterator it = keySet().iterator(); it.hasNext();) {
-                Object key = it.next();
-                Object value = get(key);
-                // XXX we have no isolation, so get entry might have been
-                // deleted in the meantime
-                if (value != null) {
-                    values.add(value);
-                }
-            }
-            return values;
-        }
-    }
-
-    /**
-     * @see Map#putAll(java.util.Map)
-     */
-    public void putAll(Map map) {
-        MapTxContext txContext = getActiveTx();
-
-        if (txContext == null) {
-            wrapped.putAll(map);
-        } else {
-            for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
-                Map.Entry<K, V> entry = (Map.Entry) it.next();
-                txContext.put(entry.getKey(), entry.getValue());
-            }
-        }
-    }
-
-    /**
-     * @see Map#entrySet()
-     */
-    public Set entrySet() {
-        MapTxContext txContext = getActiveTx();
-        if (txContext == null) {
-            return wrapped.entrySet();
-        } else {
-            Set entrySet = new HashSet();
-            // XXX expensive :(
-            for (Iterator it = keySet().iterator(); it.hasNext();) {
-                Object key = it.next();
-                Object value = get(key);
-                // XXX we have no isolation, so get entry might have been
-                // deleted in the meantime
-                if (value != null) {
-                    entrySet.add(new HashEntry(key, value));
-                }
-            }
-            return entrySet;
-        }
-    }
-
-    /**
-     * @see Map#keySet()
-     */
-    public Set keySet() {
-        MapTxContext txContext = getActiveTx();
-
-        if (txContext == null) {
-            return wrapped.keySet();
-        } else {
-            return txContext.keys();
-        }
-    }
-
-    /**
-     * @see Map#get(java.lang.Object)
-     */
-    public V get(Object key) {
-        MapTxContext txContext = getActiveTx();
-
-        if (txContext != null) {
-            return txContext.get(key);
-        } else {
-            return wrapped.get(key);
-        }
-    }
-
-    /**
-     * @see Map#remove(java.lang.Object)
-     */
-    public V remove(Object key) {
-        MapTxContext txContext = getActiveTx();
-
-        if (txContext == null) {
-            return wrapped.remove(key);
-        } else {
-            V oldValue = get(key);
-            txContext.remove(key);
-            return oldValue;
-        }
-    }
-
-    /**
-     * @see Map#put(java.lang.Object, java.lang.Object)
-     */
-    public V put(K key, V value) {
-        MapTxContext txContext = getActiveTx();
-
-        if (txContext == null) {
-            return wrapped.put(key, value);
-        } else {
-            V oldValue = get(key);
-            txContext.put(key, value);
-            return oldValue;
-        }
-
-    }
-
-    @Override
-    protected MapTxContext createContext() {
-        return new MapTxContext();
-    }
-
-    @Override
-    protected MapTxContext getActiveTx() {
-        return activeTx.get();
-    }
-
-    // mostly copied from org.apache.commons.collections.map.AbstractHashedMap
-    protected static class HashEntry implements Map.Entry {
-        /** The key */
-        protected Object key;
-
-        /** The value */
-        protected Object value;
-
-        protected HashEntry(Object key, Object value) {
-            this.key = key;
-            this.value = value;
-        }
-
-        public Object getKey() {
-            return key;
-        }
-
-        public Object getValue() {
-            return value;
-        }
-
-        public Object setValue(Object value) {
-            Object old = this.value;
-            this.value = value;
-            return old;
-        }
-
-        public boolean equals(Object obj) {
-            if (obj == this) {
-                return true;
-            }
-            if (!(obj instanceof Map.Entry)) {
-                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()));
-        }
-
-        public int hashCode() {
-            return (getKey() == null ? 0 : getKey().hashCode())
-                    ^ (getValue() == null ? 0 : getValue().hashCode());
-        }
-
-        public String toString() {
-            return new 
StringBuffer().append(getKey()).append('=').append(getValue()).toString();
-        }
-    }
-
-    public class MapTxContext extends AbstractTxContext {
-        protected Set deletes;
-
-        protected Map<K, V> changes;
-
-        protected Map<K, V> adds;
-
-        protected boolean cleared;
-
-        protected MapTxContext() {
-            deletes = new HashSet();
-            changes = new HashMap<K, V>();
-            adds = new HashMap<K, V>();
-            cleared = false;
-        }
-
-        protected Set keys() {
-            Set keySet = new HashSet();
-            if (!cleared) {
-                keySet.addAll(wrapped.keySet());
-                keySet.removeAll(deletes);
-            }
-            keySet.addAll(adds.keySet());
-            return keySet;
-        }
-
-        protected V get(Object key) {
-
-            if (deletes.contains(key)) {
-                // reflects that entry has been deleted in this tx
-                return null;
-            }
-
-            if (changes.containsKey(key)) {
-                return changes.get(key);
-            }
-
-            if (adds.containsKey(key)) {
-                return adds.get(key);
-            }
-
-            if (cleared) {
-                return null;
-            } else {
-                // not modified in this tx
-                return wrapped.get(key);
-            }
-        }
-
-        protected void put(K key, V value) {
-            try {
-                setReadOnly(false);
-                deletes.remove(key);
-                if (wrapped.containsKey(key)) {
-                    changes.put(key, value);
-                } else {
-                    adds.put(key, value);
-                }
-            } catch (RuntimeException e) {
-                markForRollback();
-                throw e;
-            } catch (Error e) {
-                markForRollback();
-                throw e;
-            }
-        }
-
-        protected void remove(Object key) {
-
-            try {
-                setReadOnly(false);
-                changes.remove(key);
-                adds.remove(key);
-                if (wrapped.containsKey(key) && !cleared) {
-                    deletes.add(key);
-                }
-            } catch (RuntimeException e) {
-                markForRollback();
-                throw e;
-            } catch (Error e) {
-                markForRollback();
-                throw e;
-            }
-        }
-
-        protected int size() {
-            int size = (cleared ? 0 : wrapped.size());
-
-            size -= deletes.size();
-            size += adds.size();
-
-            return size;
-        }
-
-        protected void clear() {
-            setReadOnly(false);
-            cleared = true;
-            deletes.clear();
-            changes.clear();
-            adds.clear();
-        }
-
-        protected boolean isEmpty() {
-            return (size() == 0);
-        }
-
-        public void commit() {
-            if (!isReadOnly()) {
-
-                if (cleared) {
-                    wrapped.clear();
-                }
-
-                wrapped.putAll(changes);
-                wrapped.putAll(adds);
-
-                for (Iterator it = deletes.iterator(); it.hasNext();) {
-                    Object key = it.next();
-                    wrapped.remove(key);
-                }
-            }
-        }
-
-    }
+import org.apache.commons.transaction.ManageableResourceManager;
 
+public interface TxMap<K, V> extends Map<K, V>, ManageableResourceManager {
 }

Added: 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/test/org/apache/commons/transaction/TransactionImplTest.java
URL: 
http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/test/org/apache/commons/transaction/TransactionImplTest.java?view=auto&rev=558494
==============================================================================
--- 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/test/org/apache/commons/transaction/TransactionImplTest.java
 (added)
+++ 
jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/test/org/apache/commons/transaction/TransactionImplTest.java
 Sun Jul 22 08:16:04 2007
@@ -0,0 +1,41 @@
+package org.apache.commons.transaction;
+
+import java.util.concurrent.TimeUnit;
+
+import junit.framework.JUnit4TestAdapter;
+
+import org.apache.commons.transaction.locking.LockManager;
+import org.apache.commons.transaction.locking.RWLockManager;
+import org.apache.commons.transaction.memory.PessimisticTxMap;
+import org.apache.commons.transaction.memory.TxMap;
+import org.junit.Test;
+
+public class TransactionImplTest {
+    public static junit.framework.Test suite() {
+        return new JUnit4TestAdapter(TransactionImplTest.class);
+    }
+
+    @Test
+    public void basic() {
+        LockManager lm = new RWLockManager<String, String>();
+        Transaction t = new TransactionImpl(lm);
+        TxMap<String, Object> txMap1 = new PessimisticTxMap<String, 
Object>("TxMap1");
+        t.enlistResourceManager(txMap1);
+        TxMap<String, Object> txMap2 = new PessimisticTxMap<String, 
Object>("TxMap2");
+        t.enlistResourceManager(txMap2);
+
+        try {
+            t.start(60, TimeUnit.SECONDS);
+            txMap1.put("Olli", "Huhu");
+            txMap2.put("Olli", "Haha");
+            t.commit();
+        } catch (Throwable throwable) {
+            t.rollback();
+        }
+
+    }
+    
+    public static void main(String[] args) {
+        new TransactionImplTest().basic();
+    }
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to