summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/java/com/amazon/carbonado/repo/map/MapRepository.java5
-rw-r--r--src/main/java/com/amazon/carbonado/txn/TransactionManager.java31
-rw-r--r--src/main/java/com/amazon/carbonado/txn/TransactionScope.java14
3 files changed, 48 insertions, 2 deletions
diff --git a/src/main/java/com/amazon/carbonado/repo/map/MapRepository.java b/src/main/java/com/amazon/carbonado/repo/map/MapRepository.java
index 7fbe16a..ac847f1 100644
--- a/src/main/java/com/amazon/carbonado/repo/map/MapRepository.java
+++ b/src/main/java/com/amazon/carbonado/repo/map/MapRepository.java
@@ -90,6 +90,11 @@ class MapRepository extends AbstractRepository<MapTransaction>
}
@Override
+ protected void finalize() {
+ close();
+ }
+
+ @Override
protected Log getLog() {
return null;
}
diff --git a/src/main/java/com/amazon/carbonado/txn/TransactionManager.java b/src/main/java/com/amazon/carbonado/txn/TransactionManager.java
index 19aec4d..6ae3b2e 100644
--- a/src/main/java/com/amazon/carbonado/txn/TransactionManager.java
+++ b/src/main/java/com/amazon/carbonado/txn/TransactionManager.java
@@ -157,6 +157,9 @@ public abstract class TransactionManager<Txn> {
for (TransactionScope<?> scope : mAllScopes.keySet()) {
scope.close();
}
+
+ mAllScopes.clear();
+ mLocalScope.remove();
}
public synchronized boolean isClosed() {
@@ -270,4 +273,32 @@ public abstract class TransactionManager<Txn> {
* Aborts and closes the given internal transaction.
*/
protected abstract void abortTxn(Txn txn) throws PersistException;
+
+ static class Closed extends TransactionManager<Object> {
+ static final Closed THE = new Closed();
+
+ @Override
+ protected IsolationLevel selectIsolationLevel(Transaction parent, IsolationLevel level) {
+ return IsolationLevel.SERIALIZABLE;
+ }
+
+ @Override
+ protected boolean supportsForUpdate() {
+ return true;
+ }
+
+ @Override
+ protected Object createTxn(Object parent, IsolationLevel level) throws Exception {
+ throw new IllegalStateException("Transaction manager is closed");
+ }
+
+ @Override
+ protected boolean commitTxn(Object txn) throws PersistException {
+ return false;
+ }
+
+ @Override
+ protected void abortTxn(Object txn) throws PersistException {
+ }
+ }
}
diff --git a/src/main/java/com/amazon/carbonado/txn/TransactionScope.java b/src/main/java/com/amazon/carbonado/txn/TransactionScope.java
index 2110ff6..7ff5997 100644
--- a/src/main/java/com/amazon/carbonado/txn/TransactionScope.java
+++ b/src/main/java/com/amazon/carbonado/txn/TransactionScope.java
@@ -43,9 +43,16 @@ import com.amazon.carbonado.spi.ExceptionTransformer;
* @see TransactionManager
*/
public class TransactionScope<Txn> {
- final TransactionManager<Txn> mTxnMgr;
final Lock mLock;
+ // Note: Cannot be final because it needs to be replaced by close
+ // method. Access doesn't need to be synchronized, because only one thread
+ // ever accesses scope instances. The close method might be called by a
+ // separate thread, in which case the closed transaction manager reference
+ // might not be immediately visible by the thread which needs it. This is
+ // not harmful.
+ TransactionManager<Txn> mTxnMgr;
+
TransactionImpl<Txn> mActive;
// Tracks all registered cursors by storage type.
@@ -55,8 +62,8 @@ public class TransactionScope<Txn> {
private boolean mDetached;
TransactionScope(TransactionManager<Txn> txnMgr, boolean closed) {
- mTxnMgr = txnMgr;
mLock = new ReentrantLock(true);
+ mTxnMgr = txnMgr;
if (closed) {
mLock.lock();
try {
@@ -332,6 +339,9 @@ public class TransactionScope<Txn> {
}
} finally {
mClosed = true;
+ // Swap TransactionManager out with a dummy one, to allow the
+ // original one to get freed.
+ mTxnMgr = (TransactionManager<Txn>) TransactionManager.Closed.THE;
mLock.unlock();
}
}