commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ozeigerm...@apache.org
Subject svn commit: r555807 [1/2] - in /jakarta/commons/proper/transaction/branches/TRANSACTION_2/src: java/org/apache/commons/transaction/ java/org/apache/commons/transaction/file/ java/org/apache/commons/transaction/locking/ java/org/apache/commons/transacti...
Date Thu, 12 Jul 2007 22:57:45 GMT
Author: ozeigermann
Date: Thu Jul 12 15:57:44 2007
New Revision: 555807

URL: http://svn.apache.org/viewvc?view=rev&rev=555807
Log:
Completition of all features 2.0 should have. This still is work in progress and subject to change. Might not even compile right now.

Added:
    jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/AbstractTransactionManager.java
    jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/Status.java
    jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/TransactionManager.java
    jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/TxContext.java
    jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/BlockingLockPolicy.java
    jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/FileResourceManager.java
    jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/LockPolicy.java
    jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/ResourceIdToPathMapper.java
    jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/TxBookKeepingLockManager.java
    jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/TxFileResourceManager.java
    jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/URLEncodeIdMapper.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/memory/
    jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/OptimisticMapWrapper.java
    jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/PessimisticMapWrapper.java
    jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/TransactionalMapWrapper.java
    jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/util/ComboInputStreamMulticaster.java
      - copied, changed from r555614, jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/ComboInputStreamMulticaster.java
    jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/util/InputStreamMulticaster.java
      - copied, changed from r555614, jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/InputStreamMulticaster.java
Removed:
    jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/ComboInputStreamMulticaster.java
    jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/InputStreamMulticaster.java
Modified:
    jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/GenericBookKeepingLockManager.java
    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/LockManager.java
    jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/MultiLevelLock.java
    jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/MultiLevelLockImpl.java
    jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/MultiLevelLockManager.java
    jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/NativeLockManager.java
    jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/NoOpMultiLevelLock.java
    jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/util/FileHelper.java
    jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/test/org/apache/commons/transaction/file/ComboInputStreamMulticasterTest.java

Added: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/AbstractTransactionManager.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/AbstractTransactionManager.java?view=auto&rev=555807
==============================================================================
--- jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/AbstractTransactionManager.java (added)
+++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/AbstractTransactionManager.java Thu Jul 12 15:57:44 2007
@@ -0,0 +1,214 @@
+/*
+ * 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.HashSet;
+import java.util.Set;
+
+/**
+ * Not thread-safe. FIXME: Should it be?
+ * 
+ * @author olli
+ *
+ * @param <T>
+ */
+public abstract class AbstractTransactionManager<T extends TxContext> implements TransactionManager {
+    protected ThreadLocal<T> activeTx = new ThreadLocal<T>();
+
+    protected Set<T> activeTransactions = new HashSet<T>();
+
+    protected Set<T> suspendedTransactions = new HashSet<T>();
+
+    protected abstract T createContext();
+
+    @Override
+    public boolean isReadOnly() {
+        TxContext txContext = getActiveTx();
+
+        if (txContext == null) {
+            throw new IllegalStateException("Active thread " + Thread.currentThread()
+                    + " not associated with a transaction!");
+        }
+
+        return txContext.isReadOnly();
+    }
+
+    @Override
+    public boolean isTransactionMarkedForRollback() {
+        TxContext txContext = getActiveTx();
+
+        if (txContext == null) {
+            throw new IllegalStateException("Active thread " + Thread.currentThread()
+                    + " not associated with a transaction!");
+        }
+
+        return (txContext.getStatus() == Status.MARKED_ROLLBACK);
+    }
+
+    @Override
+    public void markTransactionForRollback() {
+        TxContext txContext = getActiveTx();
+
+        if (txContext == null) {
+            throw new IllegalStateException("Active thread " + Thread.currentThread()
+                    + " not associated with a transaction!");
+        }
+
+        txContext.setStatus(Status.MARKED_ROLLBACK);
+    }
+
+    /**
+     * Suspends the transaction associated to the current thread. I.e. the
+     * associated between the current thread and the transaction is deleted.
+     * This is useful when you want to continue the transaction in another
+     * thread later. Call {@link #resumeTransaction(TxContext)} - possibly in
+     * another thread than the current - to resume work on the transaction. <br>
+     * <br>
+     * <em>Caution:</em> When calling this method the returned identifier for
+     * the transaction is the only remaining reference to the transaction, so be
+     * sure to remember it or the transaction will be eventually deleted (and
+     * thereby rolled back) as garbage.
+     * 
+     * @return an identifier for the suspended transaction, will be needed to
+     *         later resume the transaction by
+     *         {@link #resumeTransaction(TxContext)}
+     * 
+     * @see #resumeTransaction(TxContext)
+     */
+    public TxContext suspendTransaction() {
+        T txContext = getActiveTx();
+
+        if (txContext == null) {
+            throw new IllegalStateException("Active thread " + Thread.currentThread()
+                    + " not associated with a transaction!");
+        }
+
+        suspendedTransactions.add(txContext);
+        setActiveTx(null);
+        return txContext;
+    }
+
+    /**
+     * Resumes a transaction in the current thread that has previously been
+     * suspened by {@link #suspendTransaction()}.
+     * 
+     * @param suspendedTx
+     *            the identifier for the transaction to be resumed, delivered by
+     *            {@link #suspendTransaction()}
+     * 
+     * @see #suspendTransaction()
+     */
+    public void resumeTransaction(T suspendedTx) {
+        T txContext = getActiveTx();
+
+        if (txContext != null) {
+            throw new IllegalStateException("Active thread " + Thread.currentThread()
+                    + " already associated with a transaction!");
+        }
+
+        if (suspendedTx == null) {
+            throw new IllegalStateException("No transaction to resume!");
+        }
+
+        if (!suspendedTransactions.contains(suspendedTx)) {
+            throw new IllegalStateException("Transaction to resume needs to be suspended!");
+        }
+
+        suspendedTransactions.remove(txContext);
+        setActiveTx(suspendedTx);
+    }
+
+    @Override
+    public Status getTransactionState() {
+        TxContext txContext = getActiveTx();
+
+        if (txContext == null) {
+            return Status.NO_TRANSACTION;
+        }
+        return txContext.getStatus();
+    }
+
+    @Override
+    public void startTransaction() {
+        if (getActiveTx() != null) {
+            throw new IllegalStateException("Active thread " + Thread.currentThread()
+                    + " already associated with a transaction!");
+        }
+        T txContent = createContext();
+        setActiveTx(txContent);
+        activeTransactions.add(txContent);
+
+    }
+
+    @Override
+    public void rollbackTransaction() {
+        TxContext txContext = getActiveTx();
+
+        if (txContext == null) {
+            throw new IllegalStateException("Active thread " + Thread.currentThread()
+                    + " not associated with a transaction!");
+        }
+
+        txContext.dispose();
+        setActiveTx(null);
+        activeTransactions.remove(txContext);
+    }
+
+    @Override
+    public void commitTransaction() {
+        TxContext txContext = getActiveTx();
+
+        if (txContext == null) {
+            throw new IllegalStateException("Active thread " + Thread.currentThread()
+                    + " not associated with a transaction!");
+        }
+
+        if (txContext.getStatus() == Status.MARKED_ROLLBACK) {
+            throw new IllegalStateException("Active thread " + Thread.currentThread()
+                    + " is marked for rollback!");
+        }
+
+        txContext.commit();
+        txContext.dispose();
+        setActiveTx(null);
+    }
+
+    @Override
+    public boolean prepareTransaction() {
+        TxContext 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) {
+        // not needed
+    }
+
+    protected T getActiveTx() {
+        return activeTx.get();
+    }
+
+    protected void setActiveTx(T txContext) {
+        activeTx.set(txContext);
+    }
+
+}

Added: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/Status.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/Status.java?view=auto&rev=555807
==============================================================================
--- jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/Status.java (added)
+++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/Status.java Thu Jul 12 15:57:44 2007
@@ -0,0 +1,5 @@
+package org.apache.commons.transaction;
+
+public enum Status {
+    ACTIVE, COMMITTED, COMMITTING, MARKED_ROLLBACK, NO_TRANSACTION, PREPARED, PREPARING, ROLLEDBACK, ROLLING_BACK, UNKNOWN
+}

Added: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/TransactionManager.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/TransactionManager.java?view=auto&rev=555807
==============================================================================
--- jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/TransactionManager.java (added)
+++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/TransactionManager.java Thu Jul 12 15:57:44 2007
@@ -0,0 +1,106 @@
+/*
+ * 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;
+
+public interface TransactionManager {
+    /**
+     * TODO
+     * 
+     * @param mSecs
+     */
+    public void setTransactionTimeout(long mSecs);
+
+    /**
+     * TODO
+     * 
+     * @return
+     */
+    public boolean prepareTransaction();
+
+    /**
+     * 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 {@link #commitTransaction()} is called. Use
+     * {@link #rollbackTransaction()} to discard your changes. After calling
+     * either method there will be no transaction associated to the current
+     * thread any longer. <br>
+     * <br>
+     * <em>Caution:</em> Be careful to finally call one of those methods, as
+     * otherwise the transaction will lurk around for ever.
+     * 
+     * @see #commitTransaction()
+     * @see #rollbackTransaction()
+     */
+    public void startTransaction();
+
+    /**
+     * Checks whether this transaction has been marked to allow a rollback as
+     * the only valid outcome. This can be set my method
+     * {@link #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();
+
+    /**
+     * Marks the current transaction to allow only a rollback as valid outcome.
+     * 
+     * @see #isTransactionMarkedForRollback()
+     */
+    public void markTransactionForRollback();
+
+    /**
+     * Discards all changes made in the current transaction and deletes the
+     * association between the current thread and the transaction.
+     * 
+     * @see #startTransaction()
+     * @see #commitTransaction()
+     */
+    public void rollbackTransaction();
+
+    /**
+     * Commits all changes made in the current transaction and deletes the
+     * association between the current thread and the transaction.
+     * 
+     * @see #startTransaction()
+     * @see #rollbackTransaction()
+     */
+    public void commitTransaction();
+
+    /**
+     * Returns the state of the current transaction.
+     * 
+     * @return state of the current transaction as decribed in the
+     *         {@link Status} interface.
+     */
+    public Status getTransactionState();
+
+    /**
+     * Checks if any write operations have been performed inside this
+     * transaction.
+     * 
+     * @return <code>true</code> if no write opertation has been performed
+     *         inside the current transaction, <code>false</code> otherwise
+     */
+    public boolean isReadOnly();
+
+}

Added: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/TxContext.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/TxContext.java?view=auto&rev=555807
==============================================================================
--- jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/TxContext.java (added)
+++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/TxContext.java Thu Jul 12 15:57:44 2007
@@ -0,0 +1,31 @@
+/*
+ * 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;
+
+public interface TxContext {
+    Status getStatus();
+
+    void setStatus(Status status);
+
+    void commit();
+
+    boolean prepare();
+
+    void dispose();
+
+    boolean isReadOnly();
+}

Added: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/BlockingLockPolicy.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/BlockingLockPolicy.java?view=auto&rev=555807
==============================================================================
--- jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/BlockingLockPolicy.java (added)
+++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/BlockingLockPolicy.java Thu Jul 12 15:57:44 2007
@@ -0,0 +1,48 @@
+/*
+ * 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.file;
+
+import java.util.concurrent.locks.ReadWriteLock;
+
+import org.apache.commons.transaction.locking.BookKeepingLockManager;
+
+public class BlockingLockPolicy implements LockPolicy {
+    protected BookKeepingLockManager<String, ReadWriteLock> lm;
+
+    public BookKeepingLockManager<String, ReadWriteLock> getLm() {
+        return lm;
+    }
+
+    public void setLm(BookKeepingLockManager<String, ReadWriteLock> lm) {
+        this.lm = lm;
+    }
+
+    protected ReadWriteLock initLock(String id) {
+        return getLm().putIfAbsent(id, getLm().create());
+    }
+
+    public boolean readLock(String id) throws InterruptedException {
+        initLock(id).readLock().lock();
+        return true;
+    }
+
+    public boolean writeLock(String id) throws InterruptedException {
+        initLock(id).writeLock().lock();
+        return true;
+
+    }
+}

Added: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/FileResourceManager.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/FileResourceManager.java?view=auto&rev=555807
==============================================================================
--- jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/FileResourceManager.java (added)
+++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/FileResourceManager.java Thu Jul 12 15:57:44 2007
@@ -0,0 +1,40 @@
+/*
+ * 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.file;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public interface FileResourceManager {
+    public InputStream read(String id) throws IOException;
+
+    public OutputStream write(String id) throws IOException;
+
+    public boolean remove(String id) throws IOException;
+
+    public boolean create(String id) throws IOException;
+
+    public boolean move(String sourceId, String destinationId) throws IOException;
+
+    public boolean copy(String sourceId, String destinationId) throws IOException;
+
+    public boolean createDir(String id) throws IOException;
+
+    public boolean removeDir(String id) throws IOException;
+
+}

Added: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/LockPolicy.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/LockPolicy.java?view=auto&rev=555807
==============================================================================
--- jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/LockPolicy.java (added)
+++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/LockPolicy.java Thu Jul 12 15:57:44 2007
@@ -0,0 +1,23 @@
+/*
+ * 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.file;
+
+public interface LockPolicy {
+
+    boolean readLock(String id) throws InterruptedException;
+    boolean writeLock(String id) throws InterruptedException;
+}

Added: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/ResourceIdToPathMapper.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/ResourceIdToPathMapper.java?view=auto&rev=555807
==============================================================================
--- jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/ResourceIdToPathMapper.java (added)
+++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/ResourceIdToPathMapper.java Thu Jul 12 15:57:44 2007
@@ -0,0 +1,31 @@
+/*
+ * 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.file;
+
+/**
+ * Mapper from a resourceId to a path string.
+ *
+ * @version $Id: ResourceIdToPathMapper.java 493628 2007-01-07 01:42:48Z joerg $
+ * @since 1.1
+ */
+public interface ResourceIdToPathMapper {
+    
+    public String getPathForWrite(String path);
+    public String getPathForRead(String resourceId);
+    public String getDeletePath(String path);
+
+}

Added: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/TxBookKeepingLockManager.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/TxBookKeepingLockManager.java?view=auto&rev=555807
==============================================================================
--- jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/TxBookKeepingLockManager.java (added)
+++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/TxBookKeepingLockManager.java Thu Jul 12 15:57:44 2007
@@ -0,0 +1,20 @@
+package org.apache.commons.transaction.file;
+
+import java.util.Set;
+import java.util.concurrent.locks.ReadWriteLock;
+
+import org.apache.commons.transaction.locking.BookKeepingLockManager;
+import org.apache.commons.transaction.locking.GenericLockManager;
+
+public class TxBookKeepingLockManager extends GenericLockManager<String, ReadWriteLock> implements BookKeepingLockManager<String, ReadWriteLock>{
+    
+    public Set<ReadWriteLock> getAllLocksForCurrentThread() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public ReadWriteLock create() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+}

Added: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/TxFileResourceManager.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/TxFileResourceManager.java?view=auto&rev=555807
==============================================================================
--- jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/TxFileResourceManager.java (added)
+++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/TxFileResourceManager.java Thu Jul 12 15:57:44 2007
@@ -0,0 +1,173 @@
+/*
+ * 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.file;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.transaction.Status;
+import org.apache.commons.transaction.TransactionManager;
+
+public class TxFileResourceManager implements FileResourceManager, TransactionManager {
+
+    private Log logger = LogFactory.getLog(getClass());
+
+    protected String contextFile = "transaction.log";
+
+    protected ResourceIdToPathMapper idMapper;
+
+    protected LockPolicy lockPolicy;
+
+    public String getContextFile() {
+        return contextFile;
+    }
+
+    public void setContextFile(String contextFile) {
+        this.contextFile = contextFile;
+    }
+
+    public InputStream read(String id) throws IOException {
+        try {
+            getLockPolicy().readLock(id);
+        } catch (InterruptedException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        String path = getIdMapper().getPathForRead(id);
+        return new FileInputStream(new File(path));
+    }
+
+    public OutputStream write(String id) throws IOException {
+        try {
+            getLockPolicy().writeLock(id);
+        } catch (InterruptedException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        String path = getIdMapper().getPathForRead(id);
+        return new FileOutputStream(new File(path));
+    }
+
+    public boolean remove(String id) throws IOException {
+        try {
+            getLockPolicy().writeLock(id);
+        } catch (InterruptedException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        String path = getIdMapper().getDeletePath(id);
+        return new File(path).delete();
+    }
+
+    public boolean create(String id) throws IOException {
+        try {
+            getLockPolicy().writeLock(id);
+        } catch (InterruptedException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        String path = getIdMapper().getDeletePath(id);
+        return new File(path).createNewFile();
+    }
+
+    public ResourceIdToPathMapper getIdMapper() {
+        return idMapper;
+    }
+
+    public void setIdMapper(ResourceIdToPathMapper idMapper) {
+        this.idMapper = idMapper;
+    }
+
+    public LockPolicy getLockPolicy() {
+        return lockPolicy;
+    }
+
+    public void setLockPolicy(LockPolicy lockPolicy) {
+        this.lockPolicy = lockPolicy;
+    }
+
+    public boolean copy(String sourceId, String destinationId) throws IOException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public boolean createDir(String id) throws IOException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public boolean move(String sourceId, String destinationId) throws IOException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public boolean removeDir(String id) throws IOException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public void commitTransaction() {
+        // TODO Auto-generated method stub
+        
+    }
+
+    public Status getTransactionState() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public boolean isReadOnly() {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public boolean isTransactionMarkedForRollback() {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public void markTransactionForRollback() {
+        // TODO Auto-generated method stub
+        
+    }
+
+    public boolean prepareTransaction() {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public void rollbackTransaction() {
+        // TODO Auto-generated method stub
+        
+    }
+
+    public void setTransactionTimeout(long mSecs) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    public void startTransaction() {
+        // TODO Auto-generated method stub
+        
+    }
+}

Added: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/URLEncodeIdMapper.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/URLEncodeIdMapper.java?view=auto&rev=555807
==============================================================================
--- jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/URLEncodeIdMapper.java (added)
+++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/URLEncodeIdMapper.java Thu Jul 12 15:57:44 2007
@@ -0,0 +1,186 @@
+/*
+ * 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.file;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.transaction.util.FileHelper;
+
+public class URLEncodeIdMapper implements ResourceIdToPathMapper {
+    
+    private Log logger = LogFactory.getLog(getClass());
+
+    protected String workChangeDir = "change";
+
+    protected String workDeleteDir = "delete";
+
+    protected String workDir;
+
+    protected String storeDir;
+
+
+    
+    public String getStoreDir() {
+        return storeDir;
+    }
+
+    public void setStoreDir(String storeDir) {
+        this.storeDir = storeDir;
+    }
+
+    public String getWorkDir() {
+        return workDir;
+    }
+
+    public void setWorkDir(String workDir) {
+        this.workDir = workDir;
+    }
+
+    public String getWorkChangeDir() {
+        return workChangeDir;
+    }
+
+    public void setWorkChangeDir(String workChangeDir) {
+        this.workChangeDir = workChangeDir;
+    }
+
+    public String getWorkDeleteDir() {
+        return workDeleteDir;
+    }
+
+    public void setWorkDeleteDir(String workDeleteDir) {
+        this.workDeleteDir = workDeleteDir;
+    }
+
+    public String getPathForId(String resourceId) {
+        String path = resourceId.toString();
+        try {
+            path = URLEncoder.encode(path, "UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            // we know this will not happen
+        }
+        return path;
+    }
+    
+    public String assureLeadingSlash(String pathObject) {
+        String path = "";
+        if (pathObject != null) {
+                path = getPathForId(pathObject);
+            if (path.length() > 0 && path.charAt(0) != '/' && path.charAt(0) != '\\') {
+                path = "/" + path;
+            }
+        }
+        return path;
+    }
+
+    public String getMainPath(String path) {
+        StringBuffer buf = new StringBuffer(storeDir.length() + path.toString().length() + 5);
+        buf.append(storeDir).append(assureLeadingSlash(path));
+        return buf.toString();
+    }
+
+    public String getCurrentTxId() {
+        return Thread.currentThread().toString();
+    }
+
+    public String getTransactionBaseDir() {
+        return workDir + '/' + getCurrentTxId();
+    }
+
+    public String getChangePath(String path) {
+        String txBaseDir = getTransactionBaseDir();
+        StringBuffer buf = new StringBuffer(txBaseDir.length() + path.toString().length()
+                + getWorkChangeDir().length() + 5);
+        buf.append(txBaseDir).append('/').append(getWorkChangeDir()).append(
+                assureLeadingSlash(path));
+        return buf.toString();
+    }
+
+    public String getDeletePath(String path) {
+        String txBaseDir = getTransactionBaseDir();
+        StringBuffer buf = new StringBuffer(txBaseDir.length() + path.toString().length()
+                + getWorkDeleteDir() + 5);
+        buf.append(txBaseDir).append('/').append(getWorkDeleteDir()).append(
+                assureLeadingSlash(path));
+        return buf.toString();
+    }
+
+    public String getPathForWrite(String path) {
+        try {
+            // when we want to write, be sure to write to a local copy
+            String txChangePath = getChangePath(path);
+            if (!FileHelper.fileExists(txChangePath)) {
+                FileHelper.createFile(txChangePath);
+            }
+            return txChangePath;
+        } catch (IOException e) {
+            throw new Error("Can not write to resource at '" + path);
+                    
+        }
+    }
+
+    public String getPathForRead(String resourceId) {
+
+        String mainPath = getMainPath(resourceId);
+        String txChangePath = getChangePath(resourceId);
+        String txDeletePath = getDeletePath(resourceId);
+
+        // now, this gets a bit complicated:
+
+        boolean changeExists = FileHelper.fileExists(txChangePath);
+        boolean deleteExists = FileHelper.fileExists(txDeletePath);
+        boolean mainExists = FileHelper.fileExists(mainPath);
+        boolean resourceIsDir = ((mainExists && new File(mainPath).isDirectory()) || (changeExists && new File(
+                txChangePath).isDirectory()));
+        if (resourceIsDir) {
+            logger.warn("Resource at '" + resourceId + "' maps to directory");
+        }
+
+        // first do some sane checks
+
+        // this may never be, two cases are possible, both disallowing to have a
+        // delete together with a change
+        // 1. first there was a change, than a delete -> at least delete file
+        // exists (when there is a file in main store)
+        // 2. first there was a delete, than a change -> only change file exists
+        if (!resourceIsDir && changeExists && deleteExists) {
+            throw new Error("Inconsistent delete and change combination for resource at '"
+                    + resourceId + "'");
+        }
+
+        // you should not have been allowed to delete a file that does not exist
+        // at all
+        if (deleteExists && !mainExists) {
+            throw new Error("Inconsistent delete for resource at '" + resourceId + "'");
+        }
+
+        if (changeExists) {
+            return txChangePath;
+        } else if (mainExists && !deleteExists) {
+            return mainPath;
+        } else {
+            return null;
+        }
+    }
+
+
+}
\ No newline at end of file

Modified: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/GenericBookKeepingLockManager.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/GenericBookKeepingLockManager.java?view=diff&rev=555807&r1=555806&r2=555807
==============================================================================
--- jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/GenericBookKeepingLockManager.java (original)
+++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/GenericBookKeepingLockManager.java Thu Jul 12 15:57:44 2007
@@ -3,7 +3,7 @@
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
-public class GenericBookKeepingLockManager<K, L> extends GenericLockManager<K, L> implements BookKeepingLockManager<K, L>{
+public abstract class GenericBookKeepingLockManager<K, L> extends GenericLockManager<K, L> implements BookKeepingLockManager<K, L>{
     
     protected final ConcurrentHashMap<K, L> globalOwners = new ConcurrentHashMap<K, L>();
 

Modified: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/GenericLockManager.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/GenericLockManager.java?view=diff&rev=555807&r1=555806&r2=555807
==============================================================================
--- jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/GenericLockManager.java (original)
+++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/GenericLockManager.java Thu Jul 12 15:57:44 2007
@@ -2,18 +2,18 @@
 
 import java.util.concurrent.ConcurrentHashMap;
 
-public class GenericLockManager<K, L> implements LockManager<K, L> {
+public abstract class GenericLockManager<K, L> implements LockManager<K, L> {
     
     protected final ConcurrentHashMap<K, L> globalLocks = new ConcurrentHashMap<K, L>();
 
     @Override
-    public L getLock(K key) {
+    public L get(K key) {
         return globalLocks.get(key);
     }
     
     @Override
-    public L createLockIfAbsent(K key, L lock) {
-        L existingLock = getLock(key);
+    public L putIfAbsent(K key, L lock) {
+        L existingLock = get(key);
         if (existingLock == null) {
             L concurrentlyInsertedLock = globalLocks.putIfAbsent(key, lock);
             if (concurrentlyInsertedLock != null)
@@ -24,7 +24,7 @@
     }
     
     @Override
-    public L removeLock(K key) {
+    public L remove(K key) {
         return globalLocks.remove(key);
     }
 

Added: 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=auto&rev=555807
==============================================================================
--- jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/LockException.java (added)
+++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/LockException.java Thu Jul 12 15:57:44 2007
@@ -0,0 +1,81 @@
+/*
+ * 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.locking;
+
+/**
+ * Exception displaying a lock problem.
+ * 
+ * @version $Id: LockException.java 493628 2007-01-07 01:42:48Z joerg $
+ * @since 1.1
+ */
+public class LockException extends RuntimeException {
+
+    /**
+     * Thread has been interrupted while waiting for lock.
+     */
+    public static final int CODE_INTERRUPTED = 1;
+
+    /**
+     * Maximum wait time for a lock has been exceeded.
+     */
+    public static final int CODE_TIMED_OUT = 2;
+
+    /**
+     * Locking request canceled because of deadlock.
+     */
+    public static final int CODE_DEADLOCK_VICTIM = 3;
+
+    protected Object resourceId;
+
+    protected String reason;
+
+    protected int code;
+
+    public LockException(String reason, int code, Object resourceId) {
+        this.reason = reason;
+        this.code = code;
+        this.resourceId = resourceId;
+    }
+
+    /**
+     * Returns the formal reason for the exception.
+     * 
+     * @return one of {@link #CODE_INTERRUPTED},{@link #CODE_TIMED_OUT}or
+     *         {@link #CODE_DEADLOCK_VICTIM}.
+     */
+    public int getCode() {
+        return code;
+    }
+
+    /**
+     * Returns the resource the lock was tried on.
+     * 
+     * @return the resource or <code>null</code> if not applicable
+     */
+    public Object getResourceId() {
+        return resourceId;
+    }
+
+    /**
+     * Returns the verbose for the exception.
+     * 
+     * @return the reason message
+     */
+    public String getReason() {
+        return reason;
+    }
+}
\ No newline at end of file

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=555807&r1=555806&r2=555807
==============================================================================
--- 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 Thu Jul 12 15:57:44 2007
@@ -2,9 +2,11 @@
 
 
 public interface LockManager<K, L> {
-    public L getLock(K key);
+    public L get(K key);
 
-    public L createLockIfAbsent(K key, L lock);
+    public L putIfAbsent(K key, L lock);
 
-    public L removeLock(K key);
+    public L remove(K key);
+    
+    public L create();
 }

Modified: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/MultiLevelLock.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/MultiLevelLock.java?view=diff&rev=555807&r1=555806&r2=555807
==============================================================================
--- jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/MultiLevelLock.java (original)
+++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/MultiLevelLock.java Thu Jul 12 15:57:44 2007
@@ -1,7 +1,8 @@
 package org.apache.commons.transaction.locking;
 
 import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
 
-public interface MultiLevelLock {
+public interface MultiLevelLock extends ReadWriteLock {
     Lock getLock(int level);
 }

Modified: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/MultiLevelLockImpl.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/MultiLevelLockImpl.java?view=diff&rev=555807&r1=555806&r2=555807
==============================================================================
--- jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/MultiLevelLockImpl.java (original)
+++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/MultiLevelLockImpl.java Thu Jul 12 15:57:44 2007
@@ -28,7 +28,8 @@
         if (level > maxLevel)
             throw new IllegalArgumentException("The requested lock level (" + level
                     + ") is higher than the maximum lock level (" + maxLevel + ")");
-
+        // FIXME
+        return null;
     }
 
     private class InternalMLLock implements Lock {
@@ -58,7 +59,7 @@
         }
 
         public void unlock() {
-            LockSupport.unpark(thread)();
+//            LockSupport.unpark(thread)();
         }
     }
 
@@ -68,6 +69,16 @@
 
     public void setMaxLevel(int maxLevel) {
         this.maxLevel = maxLevel;
+    }
+
+    public Lock readLock() {
+        // FIXME
+        return getLock(1);
+    }
+
+    public Lock writeLock() {
+        // FIXME
+        return getLock(2);
     }
 
 }

Modified: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/MultiLevelLockManager.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/MultiLevelLockManager.java?view=diff&rev=555807&r1=555806&r2=555807
==============================================================================
--- jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/MultiLevelLockManager.java (original)
+++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/MultiLevelLockManager.java Thu Jul 12 15:57:44 2007
@@ -2,4 +2,9 @@
 
 
 public class MultiLevelLockManager extends GenericLockManager<Object, MultiLevelLock> implements LockManager<Object, MultiLevelLock> {
+
+    public MultiLevelLock create() {
+        // FIXME: Needs maximum level
+        return new MultiLevelLockImpl();
+    }
 }

Modified: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/NativeLockManager.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/NativeLockManager.java?view=diff&rev=555807&r1=555806&r2=555807
==============================================================================
--- jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/NativeLockManager.java (original)
+++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/NativeLockManager.java Thu Jul 12 15:57:44 2007
@@ -2,4 +2,8 @@
 
 
 public class NativeLockManager extends GenericLockManager<Object, Object> implements LockManager<Object, Object> {
+
+    public Object create() {
+        return new Object();
+    }
 }

Modified: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/NoOpMultiLevelLock.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/NoOpMultiLevelLock.java?view=diff&rev=555807&r1=555806&r2=555807
==============================================================================
--- jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/NoOpMultiLevelLock.java (original)
+++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/NoOpMultiLevelLock.java Thu Jul 12 15:57:44 2007
@@ -10,4 +10,14 @@
         return internalLock;
     }
 
+
+    public Lock readLock() {
+        return internalLock;
+    }
+
+
+    public Lock writeLock() {
+        return internalLock;
+    }
+
 }

Added: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/OptimisticMapWrapper.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/OptimisticMapWrapper.java?view=auto&rev=555807
==============================================================================
--- jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/OptimisticMapWrapper.java (added)
+++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/OptimisticMapWrapper.java Thu Jul 12 15:57:44 2007
@@ -0,0 +1,339 @@
+/*
+ * 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.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
+ * may also fail to commit. 
+ *  
+ * <br>
+ * Start a transaction by calling {@link #startTransaction()}. Then perform the normal actions on the map and
+ * finally either call {@link #commitTransaction()} to make your changes permanent or {@link #rollbackTransaction()} to
+ * undo them.
+ * <br>
+ * <em>Caution:</em> Do not modify values retrieved by {@link #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 {@link #put(Object, Object)}.
+ * <br>
+ * <em>Note:</em> This wrapper guarantees isolation level <code>SERIALIZABLE</code>.
+ * <br>
+ * <em>Caution:</em> This implementation might be slow when large amounts of data is changed in a transaction as much references will need to be copied around.
+ * 
+ * @version $Id: OptimisticMapWrapper.java 493628 2007-01-07 01:42:48Z joerg $
+ * @see TransactionalMapWrapper
+ * @see PessimisticMapWrapper
+ */
+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 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}. 
+     * 
+     * @param wrapped map to be wrapped
+     */
+    public OptimisticMapWrapper(Map wrapped) {
+        super(wrapped);
+        commitLock = new ReadWriteLock("COMMIT", logger);
+    }
+
+    public void rollbackTransaction() {
+        TxContext txContext = getActiveTx();
+        super.rollbackTransaction();
+        activeTransactions.remove(txContext);
+    }
+
+    public void commitTransaction() throws ConflictException {
+        commitTransaction(false);
+    }
+
+    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!");
+        }
+
+        if (txContext.status == STATUS_MARKED_ROLLBACK) {
+            throw new IllegalStateException("Active thread " + Thread.currentThread() + " is marked for rollback!");
+        }
+        
+        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);
+                }
+            }
+    
+            activeTransactions.remove(txContext);
+            copyChangesToConcurrentTransactions();
+            super.commitTransaction();
+            
+        } catch (InterruptedException e) {
+            // XXX a bit dirty ;)
+            throw new ConflictException(e);
+        } finally {
+            commitLock.release(txContext);
+        }
+    }
+
+    // TODO: Shouldn't we return a collection rather than a single key here?
+    public Object checkForConflicts() {
+        CopyingTxContext txContext = (CopyingTxContext) getActiveTx();
+
+        Set keys = txContext.changedKeys();
+        Set externalKeys = txContext.externalChangedKeys();
+
+        for (Iterator it2 = keys.iterator(); it2.hasNext();) {
+            Object key = it2.next();
+            if (externalKeys.contains(key)) {
+                return key;
+            }
+        }
+        return null;
+    }
+
+    protected void copyChangesToConcurrentTransactions() {
+        CopyingTxContext thisTxContext = (CopyingTxContext) getActiveTx();
+
+        synchronized (activeTransactions) {
+            for (Iterator it = activeTransactions.iterator(); it.hasNext();) {
+                CopyingTxContext otherTxContext = (CopyingTxContext) it.next();
+
+                // no need to copy data if the other transaction does not access global map anyway
+                if (otherTxContext.cleared)
+                    continue;
+
+                if (thisTxContext.cleared) {
+                    // we will clear everything, so we have to copy everything before
+                    otherTxContext.externalChanges.putAll(wrapped);
+                } else // no need to check if we have already copied everthing
+                {
+                    for (Iterator it2 = thisTxContext.changes.entrySet().iterator(); it2.hasNext();) {
+                        Map.Entry entry = (Map.Entry) it2.next();
+                        Object value = wrapped.get(entry.getKey());
+                        if (value != null) {
+                            // undo change
+                            otherTxContext.externalChanges.put(entry.getKey(), value);
+                        } else {
+                            // undo add
+                            otherTxContext.externalDeletes.add(entry.getKey());
+                        }
+                    }
+
+                    for (Iterator it2 = thisTxContext.deletes.iterator(); it2.hasNext();) {
+                        // undo delete
+                        Object key = it2.next();
+                        Object value = wrapped.get(key);
+                        otherTxContext.externalChanges.put(key, value);
+                    }
+                }
+            }
+        }
+    }
+
+    public class CopyingTxContext extends TxContext {
+        protected Map externalChanges;
+        protected Map externalAdds;
+        protected Set externalDeletes;
+
+        protected CopyingTxContext() {
+            super();
+            externalChanges = mapFactory.createMap();
+            externalDeletes = setFactory.createSet();
+            externalAdds = mapFactory.createMap();
+        }
+
+        protected Set externalChangedKeys() {
+            Set keySet = new HashSet();
+            keySet.addAll(externalDeletes);
+            keySet.addAll(externalChanges.keySet());
+            keySet.addAll(externalAdds.keySet());
+            return keySet;
+        }
+
+        protected Set changedKeys() {
+            Set keySet = new HashSet();
+            keySet.addAll(deletes);
+            keySet.addAll(changes.keySet());
+            keySet.addAll(adds.keySet());
+            return keySet;
+        }
+
+        protected Set keys() {
+            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);
+            }
+        }
+
+        protected Object get(Object key) {
+            try {
+                commitLock.acquireRead(this, ACCESS_TIMEOUT);
+
+                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 {
+                    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);
+            }
+        }
+
+        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() {
+            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() {
+            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() {
+            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 {
+            activeTransactions.remove(this);
+            super.finalize();
+        }
+    }
+}

Added: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/PessimisticMapWrapper.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/PessimisticMapWrapper.java?view=auto&rev=555807
==============================================================================
--- jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/PessimisticMapWrapper.java (added)
+++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/PessimisticMapWrapper.java Thu Jul 12 15:57:44 2007
@@ -0,0 +1,164 @@
+/*
+ * 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.memory;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.transaction.locking.ReadWriteLockManager;
+import org.apache.commons.transaction.util.LoggerFacade;
+
+/**
+ * Wrapper that adds transactional control to all kinds of maps that implement the {@link Map} interface. By using
+ * pessimistic transaction control (blocking locks) this wrapper has better isolation than {@link TransactionalMapWrapper}, but
+ * also has less possible concurrency and may even deadlock. A commit, however, will never fail.
+ * <br>
+ * Start a transaction by calling {@link #startTransaction()}. Then perform the normal actions on the map and
+ * finally either call {@link #commitTransaction()} to make your changes permanent or {@link #rollbackTransaction()} to
+ * undo them.
+ * <br>
+ * <em>Caution:</em> Do not modify values retrieved by {@link #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 {@link #put(Object, Object)}.
+ * <br>
+ * <em>Note:</em> This wrapper guarantees isolation level <code>SERIALIZABLE</code>.
+ * 
+ * @version $Id: PessimisticMapWrapper.java 493628 2007-01-07 01:42:48Z joerg $
+ * @see TransactionalMapWrapper
+ * @see OptimisticMapWrapper
+ */
+public class PessimisticMapWrapper<LockingTxContext> extends TransactionalMapWrapper {
+
+    protected static final int READ = 1;
+    protected static final int WRITE = 2;
+
+    protected static final Object GLOBAL_LOCK = "GLOBAL";
+
+    protected ReadWriteLockManager lockManager;
+//    protected MultiLevelLock globalLock;
+    protected long readTimeOut = 60000; /* FIXME: pass in ctor */
+
+    /**
+     * Creates a new pessimistic transactional map wrapper. Temporary maps and sets to store transactional
+     * data will be instances of {@link java.util.HashMap} and {@link java.util.HashSet}. 
+     * 
+     * @param wrapped map to be wrapped
+     */
+    public PessimisticMapWrapper(Map wrapped) {
+        super(wrapped);
+        lockManager = new ReadWriteLockManager(logger, readTimeOut);
+//        globalLock = new GenericLock(GLOBAL_LOCK_NAME, WRITE, logger);
+    }
+
+    public Collection values() {
+        assureGlobalReadLock();
+        return super.values();
+    }
+
+    public Set entrySet() {
+        assureGlobalReadLock();
+        return super.entrySet();
+    }
+
+    public Set keySet() {
+        assureGlobalReadLock();
+        return super.keySet();
+    }
+
+    public Object remove(Object key) {
+        // assure we get a write lock before super can get a read lock to avoid lots
+        // of deadlocks
+        assureWriteLock(key);
+        return super.remove(key);
+    }
+
+    public Object put(Object key, Object value) {
+        // assure we get a write lock before super can get a read lock to avoid lots
+        // of deadlocks
+        assureWriteLock(key);
+        return super.put(key, value);
+    }
+
+    protected void assureWriteLock(Object key) {
+        LockingTxContext txContext = (LockingTxContext) getActiveTx();
+        if (txContext != null) {
+            lockManager.writeLock(txContext, key);
+            // XXX fake intention lock (prohibits global WRITE)
+            lockManager.readLock(txContext, GLOBAL_LOCK); 
+        }
+    }
+    
+    protected void assureGlobalReadLock() {
+        LockingTxContext txContext = (LockingTxContext) getActiveTx();
+        if (txContext != null) {
+            // XXX fake intention lock (prohibits global WRITE)
+            lockManager.readLock(txContext, GLOBAL_LOCK); 
+        }
+    }
+    
+    public class LockingTxContext extends MapTxContext {
+
+        protected Set keys() {
+            lockManager.readLock(this, GLOBAL_LOCK); 
+            return super.keys();
+        }
+
+        protected Object get(Object key) {
+            lockManager.readLock(this, key);
+            // XXX fake intention lock (prohibits global WRITE)
+            lockManager.readLock(this, GLOBAL_LOCK);
+            return super.get(key);
+        }
+
+        protected void put(Object key, Object value) {
+            lockManager.writeLock(this, key);
+            // XXX fake intention lock (prohibits global WRITE)
+            lockManager.readLock(this, GLOBAL_LOCK);
+            super.put(key, value);
+        }
+
+        protected void remove(Object key) {
+            lockManager.writeLock(this, key);
+            // XXX fake intention lock (prohibits global WRITE)
+            lockManager.readLock(this, GLOBAL_LOCK);
+            super.remove(key);
+        }
+
+        protected int size() {
+            // XXX this is bad luck, we need a global read lock just for the size :( :( :(
+            lockManager.readLock(this, GLOBAL_LOCK);
+            return super.size();
+        }
+
+        protected void clear() {
+            lockManager.writeLock(this, GLOBAL_LOCK);
+            super.clear();
+        }
+
+        protected void dispose() {
+            super.dispose();
+            lockManager.releaseAll(this);
+        }
+
+        protected void finalize() throws Throwable {
+            dispose();
+            super.finalize();
+        }
+    }
+
+}



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