diff options
author | Brian S. O'Neill <bronee@gmail.com> | 2011-08-10 17:39:53 +0000 |
---|---|---|
committer | Brian S. O'Neill <bronee@gmail.com> | 2011-08-10 17:39:53 +0000 |
commit | 312018c6ef5a3231c260e4ecdcd4c83588b56479 (patch) | |
tree | d10da20e9c35ad2b154f3a4f98ba4bf5a09b0e71 /src | |
parent | 83d83766e4a82051c440996738f4249a355ca0b6 (diff) |
Fix thread-local memory leaks.
Diffstat (limited to 'src')
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();
}
}
|