From a5c1b86d141fce913e5439677730007ee3f23e95 Mon Sep 17 00:00:00 2001 From: "Brian S. O'Neill" Date: Mon, 21 Jan 2008 02:08:27 +0000 Subject: Minor method name changes and added (commented out) detach/attach logic. --- .../amazon/carbonado/spi/AbstractRepository.java | 10 ++-- .../amazon/carbonado/spi/TransactionManager.java | 51 ++++++++++++++---- .../com/amazon/carbonado/spi/TransactionScope.java | 62 ++++++++++++++++++---- 3 files changed, 99 insertions(+), 24 deletions(-) (limited to 'src/main/java') diff --git a/src/main/java/com/amazon/carbonado/spi/AbstractRepository.java b/src/main/java/com/amazon/carbonado/spi/AbstractRepository.java index 7150f56..c9bc0b5 100644 --- a/src/main/java/com/amazon/carbonado/spi/AbstractRepository.java +++ b/src/main/java/com/amazon/carbonado/spi/AbstractRepository.java @@ -112,19 +112,19 @@ public abstract class AbstractRepository } public Transaction enterTransaction() { - return mTxnMgr.localTransactionScope().enter(null); + return mTxnMgr.localScope().enter(null); } public Transaction enterTransaction(IsolationLevel level) { - return mTxnMgr.localTransactionScope().enter(level); + return mTxnMgr.localScope().enter(level); } public Transaction enterTopTransaction(IsolationLevel level) { - return mTxnMgr.localTransactionScope().enterTop(level); + return mTxnMgr.localScope().enterTop(level); } public IsolationLevel getTransactionIsolationLevel() { - return mTxnMgr.localTransactionScope().getIsolationLevel(); + return mTxnMgr.localScope().getIsolationLevel(); } /** @@ -217,7 +217,7 @@ public abstract class AbstractRepository * Returns the thread-local TransactionScope, creating it if needed. */ protected TransactionScope localTransactionScope() { - return mTxnMgr.localTransactionScope(); + return mTxnMgr.localScope(); } /** diff --git a/src/main/java/com/amazon/carbonado/spi/TransactionManager.java b/src/main/java/com/amazon/carbonado/spi/TransactionManager.java index 9afddd8..4a28d24 100644 --- a/src/main/java/com/amazon/carbonado/spi/TransactionManager.java +++ b/src/main/java/com/amazon/carbonado/spi/TransactionManager.java @@ -35,12 +35,12 @@ import com.amazon.carbonado.Transaction; * @author Brian S O'Neill */ public abstract class TransactionManager { - private static final int NOT_CLOSED = 0, CLOSED = 1, SUSPENDED = 2; + private static final int OPEN = 0, CLOSED = 1, SUSPENDED = 2; private final ThreadLocal> mLocalScope; private final Map, ?> mAllScopes; - private int mClosedState; + private int mState; public TransactionManager() { mLocalScope = new ThreadLocal>(); @@ -50,17 +50,17 @@ public abstract class TransactionManager { /** * Returns the thread-local TransactionScope, creating it if needed. */ - public TransactionScope localTransactionScope() { + public TransactionScope localScope() { TransactionScope scope = mLocalScope.get(); if (scope == null) { - int closedState; + int state; synchronized (this) { - closedState = mClosedState; - scope = new TransactionScope(this, closedState != NOT_CLOSED); + state = mState; + scope = new TransactionScope(this, state != OPEN); mAllScopes.put(scope, null); } mLocalScope.set(scope); - if (closedState == SUSPENDED) { + if (state == SUSPENDED) { // Immediately suspend new scope. scope.getLock().lock(); } @@ -68,6 +68,39 @@ public abstract class TransactionManager { return scope; } + /** + * Detaches the thread-local TransactionScope from the current thread. It + * can be {@link TransactionScope#attach attached} later, and to any thread + * which does not currently have a TransactionScope. + * + * @return detached thread-local TransactionScope or null if none + */ + /* + public TransactionScope detachLocalScope() { + TransactionScope scope = mLocalScope.get(); + if (scope != null) { + if (!scope.detach()) { + scope = null; + } else { + mLocalScope.remove(); + } + } + return scope; + } + */ + + // Called by TransactionScope. + /* + void attach(TransactionScope scope) { + TransactionScope existing = mLocalScope.get(); + if (existing == null || existing == scope) { + mLocalScope.set(scope); + } else { + throw new IllegalStateException("Current thread already has a transaction scope"); + } + } + */ + /** * Closes all transaction scopes. Should be called only when repository is * closed. @@ -76,7 +109,7 @@ public abstract class TransactionManager { * with transactions */ public synchronized void close(boolean suspend) throws RepositoryException { - if (mClosedState == SUSPENDED) { + if (mState == SUSPENDED) { // If suspended, attempting to close again will likely deadlock. return; } @@ -90,7 +123,7 @@ public abstract class TransactionManager { } } - mClosedState = suspend ? SUSPENDED : CLOSED; + mState = suspend ? SUSPENDED : CLOSED; for (TransactionScope scope : mAllScopes.keySet()) { scope.close(); diff --git a/src/main/java/com/amazon/carbonado/spi/TransactionScope.java b/src/main/java/com/amazon/carbonado/spi/TransactionScope.java index 28d8260..0ac2cee 100644 --- a/src/main/java/com/amazon/carbonado/spi/TransactionScope.java +++ b/src/main/java/com/amazon/carbonado/spi/TransactionScope.java @@ -41,6 +41,8 @@ import com.amazon.carbonado.Transaction; * @see TransactionManager */ public class TransactionScope { + private static final int OPEN = 0, DETACHED = 1, CLOSED = 2; + final TransactionManager mTxnMgr; final Lock mLock; @@ -49,12 +51,12 @@ public class TransactionScope { // Tracks all registered cursors by storage type. private Map, CursorList>> mCursors; - private boolean mClosed; + private int mState; TransactionScope(TransactionManager txnMgr, boolean closed) { mTxnMgr = txnMgr; mLock = new ReentrantLock(true); - mClosed = closed; + mState = closed ? CLOSED : OPEN; } /** @@ -118,7 +120,7 @@ public class TransactionScope { public void register(Class type, Cursor cursor) { mLock.lock(); try { - checkState(); + checkClosed(); if (mCursors == null) { mCursors = new IdentityHashMap, CursorList>>(); } @@ -177,7 +179,7 @@ public class TransactionScope { public Txn getTxn() throws Exception { mLock.lock(); try { - checkState(); + checkClosed(); return mActive == null ? null : mActive.getTxn(); } finally { mLock.unlock(); @@ -190,7 +192,7 @@ public class TransactionScope { public boolean isForUpdate() { mLock.lock(); try { - return (mClosed || mActive == null) ? false : mActive.isForUpdate(); + return (mState == CLOSED || mActive == null) ? false : mActive.isForUpdate(); } finally { mLock.unlock(); } @@ -203,11 +205,51 @@ public class TransactionScope { public IsolationLevel getIsolationLevel() { mLock.lock(); try { - return (mClosed || mActive == null) ? null : mActive.getIsolationLevel(); + return (mState == CLOSED || mActive == null) ? null : mActive.getIsolationLevel(); + } finally { + mLock.unlock(); + } + } + + /** + * Attach this scope to the current thread, if it has been {@link + * TransactionManager#detachLocalScope detached}. + * + * @throws IllegalStateException if scope is not detached or if current + * thread already has a transaction scope + */ + /* + public void attach() { + mLock.lock(); + try { + if (mState != DETACHED) { + throw new IllegalStateException("Transaction scope is not detached"); + } + mState = OPEN; + } finally { + mLock.unlock(); + } + mTxnMgr.attach(this); + } + */ + + /** + * @return false if closed + */ + /* + boolean detach() { + mLock.lock(); + try { + if (mState == CLOSED) { + return false; + } + mState = DETACHED; + return true; } finally { mLock.unlock(); } } + */ /** * Exits all transactions and closes all cursors. Should be called only @@ -216,7 +258,7 @@ public class TransactionScope { void close() throws RepositoryException { mLock.lock(); try { - if (!mClosed) { + if (mState != CLOSED) { while (mActive != null) { mActive.exit(); } @@ -227,7 +269,7 @@ public class TransactionScope { } } } finally { - mClosed = true; + mState = CLOSED; mLock.unlock(); } } @@ -235,8 +277,8 @@ public class TransactionScope { /** * Caller must hold mLock. */ - private void checkState() { - if (mClosed) { + private void checkClosed() { + if (mState == CLOSED) { throw new IllegalStateException("Repository is closed"); } } -- cgit v1.2.3