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]