From 3e44cc0515fc222fb4f43a3b624795863ba4429b Mon Sep 17 00:00:00 2001 From: "Brian S. O'Neill" Date: Sun, 20 Jan 2008 21:42:57 +0000 Subject: Split TransactionManager and created TransactionScope class. --- .../com/amazon/carbonado/repo/jdbc/JDBCBlob.java | 4 +- .../com/amazon/carbonado/repo/jdbc/JDBCClob.java | 4 +- .../amazon/carbonado/repo/jdbc/JDBCRepository.java | 23 +++--- .../amazon/carbonado/repo/jdbc/JDBCStorage.java | 10 +-- .../repo/jdbc/JDBCTransactionManager.java | 13 ++-- .../amazon/carbonado/repo/sleepycat/BDBCursor.java | 18 ++--- .../carbonado/repo/sleepycat/BDBRepository.java | 19 +++-- .../carbonado/repo/sleepycat/BDBStorage.java | 82 +++++++++++----------- .../repo/sleepycat/BDBTransactionManager.java | 8 ++- 9 files changed, 88 insertions(+), 93 deletions(-) (limited to 'src/main/java/com/amazon/carbonado/repo') diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCBlob.java b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCBlob.java index ba5cdcf..69a8f3d 100644 --- a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCBlob.java +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCBlob.java @@ -126,7 +126,7 @@ class JDBCBlob extends AbstractBlob implements JDBCLob { throw new FetchException("Blob value is null"); } try { - JDBCTransaction txn = mRepo.localTxnManager().getTxn(); + JDBCTransaction txn = mRepo.localTxnScope().getTxn(); if (txn != null) { txn.register(this); } @@ -143,7 +143,7 @@ class JDBCBlob extends AbstractBlob implements JDBCLob { if ((mBlob = mLoader.load(mRepo)) == null) { throw new PersistException("Blob value is null"); } - JDBCTransaction txn = mRepo.localTxnManager().getTxn(); + JDBCTransaction txn = mRepo.localTxnScope().getTxn(); if (txn != null) { txn.register(this); } diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCClob.java b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCClob.java index c4e74f1..eedaf80 100644 --- a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCClob.java +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCClob.java @@ -126,7 +126,7 @@ class JDBCClob extends AbstractClob implements JDBCLob { throw new FetchException("Clob value is null"); } try { - JDBCTransaction txn = mRepo.localTxnManager().getTxn(); + JDBCTransaction txn = mRepo.localTxnScope().getTxn(); if (txn != null) { txn.register(this); } @@ -143,7 +143,7 @@ class JDBCClob extends AbstractClob implements JDBCLob { if ((mClob = mLoader.load(mRepo)) == null) { throw new PersistException("Clob value is null"); } - JDBCTransaction txn = mRepo.localTxnManager().getTxn(); + JDBCTransaction txn = mRepo.localTxnScope().getTxn(); if (txn != null) { txn.register(this); } diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCRepository.java b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCRepository.java index 0d93570..dd4e1ad 100644 --- a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCRepository.java +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCRepository.java @@ -55,7 +55,7 @@ import com.amazon.carbonado.info.StorableProperty; import com.amazon.carbonado.sequence.SequenceCapability; import com.amazon.carbonado.sequence.SequenceValueProducer; import com.amazon.carbonado.spi.AbstractRepository; -import com.amazon.carbonado.spi.TransactionManager; +import com.amazon.carbonado.spi.TransactionScope; import com.amazon.carbonado.util.ThrowUnchecked; /** @@ -324,7 +324,7 @@ public class JDBCRepository extends AbstractRepository */ // Is called by auto-generated code and must be public. public boolean isTransactionForUpdate() { - return localTransactionManager().isForUpdate(); + return localTransactionScope().isForUpdate(); } /** @@ -419,7 +419,7 @@ public class JDBCRepository extends AbstractRepository throw new FetchException("Repository is closed"); } - JDBCTransaction txn = localTransactionManager().getTxn(); + JDBCTransaction txn = localTransactionScope().getTxn(); if (txn != null) { // Return the connection used by the current transaction. return txn.getConnection(); @@ -656,10 +656,6 @@ public class JDBCRepository extends AbstractRepository return mLog; } - protected TransactionManager createTransactionManager() { - return new JDBCTransactionManager(this); - } - protected Storage createStorage(Class type) throws RepositoryException { @@ -701,11 +697,12 @@ public class JDBCRepository extends AbstractRepository return mSupportStrategy.createSequenceValueProducer(name); } - /** - * Returns the thread-local JDBCTransactionManager, creating it if needed. - */ - // Provides access to transaction manager from other classes. - TransactionManager localTxnManager() { - return localTransactionManager(); + protected JDBCTransactionManager createTransactionManager() { + return new JDBCTransactionManager(this); + } + + // Provides access to transaction scope from other classes. + final TransactionScope localTxnScope() { + return localTransactionScope(); } } diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorage.java b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorage.java index 3fbd302..e6fe277 100644 --- a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorage.java +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorage.java @@ -213,7 +213,7 @@ class JDBCStorage extends StandardQueryFactory if (jblob != null) { try { - JDBCTransaction txn = mRepository.localTxnManager().getTxn(); + JDBCTransaction txn = mRepository.localTxnScope().getTxn(); if (txn != null) { txn.register(jblob); } @@ -235,7 +235,7 @@ class JDBCStorage extends StandardQueryFactory if (jclob != null) { try { - JDBCTransaction txn = mRepository.localTxnManager().getTxn(); + JDBCTransaction txn = mRepository.localTxnScope().getTxn(); if (txn != null) { txn.register(jclob); } @@ -606,7 +606,7 @@ class JDBCStorage extends StandardQueryFactory } public Cursor fetch(FilterValues values) throws FetchException { - boolean forUpdate = mRepository.localTxnManager().isForUpdate(); + boolean forUpdate = mRepository.localTxnScope().isForUpdate(); Connection con = mRepository.getConnection(); try { PreparedStatement ps = con.prepareStatement(prepareSelect(values, forUpdate)); @@ -674,7 +674,7 @@ class JDBCStorage extends StandardQueryFactory throws IOException { indent(app, indentLevel); - boolean forUpdate = mRepository.localTxnManager().isForUpdate(); + boolean forUpdate = mRepository.localTxnScope().isForUpdate(); app.append(prepareSelect(values, forUpdate)); app.append('\n'); return true; @@ -684,7 +684,7 @@ class JDBCStorage extends StandardQueryFactory throws IOException { try { - boolean forUpdate = mRepository.localTxnManager().isForUpdate(); + boolean forUpdate = mRepository.localTxnScope().isForUpdate(); String statement = prepareSelect(values, forUpdate); return mRepository.getSupportStrategy().printPlan(app, indentLevel, statement); } catch (FetchException e) { diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCTransactionManager.java b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCTransactionManager.java index a70e4c3..ca63331 100644 --- a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCTransactionManager.java +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCTransactionManager.java @@ -29,8 +29,7 @@ import com.amazon.carbonado.Transaction; import com.amazon.carbonado.spi.TransactionManager; /** - * Manages transactions for JDBCRepository. Only one instance is allocated per - * thread. + * Manages transactions for JDBCRepository. * * @author Brian S O'Neill */ @@ -46,11 +45,6 @@ class JDBCTransactionManager extends TransactionManager { mRepositoryRef = new WeakReference(repository); } - @Override - public boolean isForUpdate() { - return super.isForUpdate() && mRepositoryRef.get().supportsSelectForUpdate(); - } - protected IsolationLevel selectIsolationLevel(Transaction parent, IsolationLevel level) { JDBCRepository repo = mRepositoryRef.get(); if (repo == null) { @@ -59,6 +53,11 @@ class JDBCTransactionManager extends TransactionManager { return repo.selectIsolationLevel(parent, level); } + protected boolean supportsForUpdate() { + JDBCRepository repo = mRepositoryRef.get(); + return repo != null && repo.supportsSelectForUpdate(); + } + protected JDBCTransaction createTxn(JDBCTransaction parent, IsolationLevel level) throws SQLException, FetchException { diff --git a/src/main/java/com/amazon/carbonado/repo/sleepycat/BDBCursor.java b/src/main/java/com/amazon/carbonado/repo/sleepycat/BDBCursor.java index f16d2f7..b2a1f32 100644 --- a/src/main/java/com/amazon/carbonado/repo/sleepycat/BDBCursor.java +++ b/src/main/java/com/amazon/carbonado/repo/sleepycat/BDBCursor.java @@ -25,7 +25,7 @@ import com.amazon.carbonado.Storable; import com.amazon.carbonado.raw.RawCursor; import com.amazon.carbonado.raw.RawUtil; -import com.amazon.carbonado.spi.TransactionManager; +import com.amazon.carbonado.spi.TransactionScope; /** * @@ -35,10 +35,10 @@ import com.amazon.carbonado.spi.TransactionManager; abstract class BDBCursor extends RawCursor { private static final byte[] NO_DATA = new byte[0]; - private final TransactionManager mTxnMgr; + private final TransactionScope mScope; private final BDBStorage mStorage; /** - * @param txnMgr + * @param scope * @param startBound specify the starting key for the cursor, or null if first * @param inclusiveStart true if start bound is inclusive * @param endBound specify the ending key for the cursor, or null if last @@ -50,7 +50,7 @@ abstract class BDBCursor extends RawCursor { * @throws ClassCastException if lock is not an object passed by * {@link BDBStorage#openCursor BDBStorage.openCursor} */ - protected BDBCursor(TransactionManager txnMgr, + protected BDBCursor(TransactionScope scope, byte[] startBound, boolean inclusiveStart, byte[] endBound, boolean inclusiveEnd, int maxPrefix, @@ -58,19 +58,19 @@ abstract class BDBCursor extends RawCursor { BDBStorage storage) throws FetchException { - super(txnMgr.getLock(), + super(scope.getLock(), startBound, inclusiveStart, endBound, inclusiveEnd, maxPrefix, reverse); - mTxnMgr = txnMgr; + mScope = scope; mStorage = storage; - txnMgr.register(storage.getStorableType(), this); + scope.register(storage.getStorableType(), this); } void open() throws FetchException { try { - cursor_open(mTxnMgr.getTxn(), mTxnMgr.getIsolationLevel()); + cursor_open(mScope.getTxn(), mScope.getIsolationLevel()); } catch (Exception e) { throw mStorage.toFetchException(e); } @@ -80,7 +80,7 @@ abstract class BDBCursor extends RawCursor { try { super.close(); } finally { - mTxnMgr.unregister(mStorage.getStorableType(), this); + mScope.unregister(mStorage.getStorableType(), this); } } diff --git a/src/main/java/com/amazon/carbonado/repo/sleepycat/BDBRepository.java b/src/main/java/com/amazon/carbonado/repo/sleepycat/BDBRepository.java index 45fe85c..a0c549b 100644 --- a/src/main/java/com/amazon/carbonado/repo/sleepycat/BDBRepository.java +++ b/src/main/java/com/amazon/carbonado/repo/sleepycat/BDBRepository.java @@ -63,7 +63,7 @@ import com.amazon.carbonado.sequence.SequenceValueProducer; import com.amazon.carbonado.spi.AbstractRepository; import com.amazon.carbonado.spi.ExceptionTransformer; import com.amazon.carbonado.spi.LobEngine; -import com.amazon.carbonado.spi.TransactionManager; +import com.amazon.carbonado.spi.TransactionScope; /** * Repository implementation backed by a Berkeley DB. Data is encoded in the @@ -326,10 +326,6 @@ abstract class BDBRepository extends AbstractRepository return mLog; } - protected TransactionManager createTransactionManager() { - return new BDBTransactionManager(mExTransformer, this); - } - protected Storage createStorage(Class type) throws RepositoryException { @@ -346,6 +342,10 @@ abstract class BDBRepository extends AbstractRepository return new SequenceValueGenerator(BDBRepository.this, name); } + protected BDBTransactionManager createTransactionManager() { + return new BDBTransactionManager(mExTransformer, this); + } + /** * @see com.amazon.carbonado.spi.RepositoryBuilder#isMaster */ @@ -489,12 +489,9 @@ abstract class BDBRepository extends AbstractRepository return mExTransformer.toRepositoryException(e); } - /** - * Returns the thread-local BDBTransactionManager, creating it if needed. - */ - // Provides access to transaction manager from other classes. - TransactionManager localTxnManager() { - return localTransactionManager(); + // Provides access to transaction scope from other classes. + final TransactionScope localTxnScope() { + return localTransactionScope(); } /** diff --git a/src/main/java/com/amazon/carbonado/repo/sleepycat/BDBStorage.java b/src/main/java/com/amazon/carbonado/repo/sleepycat/BDBStorage.java index 0b9f53c..77ea7d7 100644 --- a/src/main/java/com/amazon/carbonado/repo/sleepycat/BDBStorage.java +++ b/src/main/java/com/amazon/carbonado/repo/sleepycat/BDBStorage.java @@ -78,7 +78,7 @@ import com.amazon.carbonado.sequence.SequenceValueProducer; import com.amazon.carbonado.spi.IndexInfoImpl; import com.amazon.carbonado.spi.LobEngine; import com.amazon.carbonado.spi.StorableIndexSet; -import com.amazon.carbonado.spi.TransactionManager; +import com.amazon.carbonado.spi.TransactionScope; import com.amazon.carbonado.spi.TriggerManager; /** @@ -203,18 +203,18 @@ abstract class BDBStorage implements Storage, Storag } } - TransactionManager txnMgr = localTxnManager(); + TransactionScope scope = localTxnScope(); // Lock out shutdown task. - txnMgr.getLock().lock(); + scope.getLock().lock(); try { try { - db_truncate(txnMgr.getTxn()); + db_truncate(scope.getTxn()); } catch (Exception e) { throw toPersistException(e); } } finally { - txnMgr.getLock().unlock(); + scope.getLock().unlock(); } } @@ -317,7 +317,7 @@ abstract class BDBStorage implements Storage, Storag boolean reverseOrder) throws FetchException { - TransactionManager txnMgr = localTxnManager(); + TransactionScope scope = localTxnScope(); if (reverseRange) { { @@ -334,7 +334,7 @@ abstract class BDBStorage implements Storage, Storag } // Lock out shutdown task. - txnMgr.getLock().lock(); + scope.getLock().lock(); try { StorableCodec codec = mStorableCodec; @@ -381,7 +381,7 @@ abstract class BDBStorage implements Storage, Storag try { BDBCursor cursor = openCursor - (txnMgr, + (scope, startBound, inclusiveStart, endBound, inclusiveEnd, mStorableCodec.getPrimaryKeyPrefixLength(), @@ -394,7 +394,7 @@ abstract class BDBStorage implements Storage, Storag throw toFetchException(e); } } finally { - txnMgr.getLock().unlock(); + scope.getLock().unlock(); } } @@ -447,15 +447,15 @@ abstract class BDBStorage implements Storage, Storag boolean isPrimaryEmpty; try { - TransactionManager txnMgr = mRepository.localTxnManager(); + TransactionScope scope = mRepository.localTxnScope(); // Lock out shutdown task. - txnMgr.getLock().lock(); + scope.getLock().lock(); try { primaryDatabase = env_openPrimaryDatabase(openTxn, databaseName); primaryInfo = registerPrimaryDatabase(readOnly, layout); - isPrimaryEmpty = db_isEmpty(null, primaryDatabase, txnMgr.isForUpdate()); + isPrimaryEmpty = db_isEmpty(null, primaryDatabase, scope.isForUpdate()); } finally { - txnMgr.getLock().unlock(); + scope.getLock().unlock(); } } catch (Exception e) { throw toRepositoryException(e); @@ -572,7 +572,7 @@ abstract class BDBStorage implements Storage, Storag } try { - Txn txn = mRepository.localTxnManager().getTxn(); + Txn txn = mRepository.localTxnScope().getTxn(); return db_compact(txn, mPrimaryDatabase, start, end); } catch (Exception e) { throw mRepository.toRepositoryException(e); @@ -637,7 +637,7 @@ abstract class BDBStorage implements Storage, Storag /** * @param txn optional transaction to commit when cursor is closed - * @param txnMgr + * @param scope * @param startBound specify the starting key for the cursor, or null if first * @param inclusiveStart true if start bound is inclusive * @param endBound specify the ending key for the cursor, or null if last @@ -647,7 +647,7 @@ abstract class BDBStorage implements Storage, Storag * @param database database to use */ protected abstract BDBCursor openCursor - (TransactionManager txnMgr, + (TransactionScope scope, byte[] startBound, boolean inclusiveStart, byte[] endBound, boolean inclusiveEnd, int maxPrefix, @@ -667,8 +667,8 @@ abstract class BDBStorage implements Storage, Storag return mRepository.toRepositoryException(e); } - TransactionManager localTxnManager() { - return mRepository.localTxnManager(); + TransactionScope localTxnScope() { + return mRepository.localTxnScope(); } /** @@ -726,15 +726,15 @@ abstract class BDBStorage implements Storage, Storag * prevent threads from starting work that will likely fail along the way. */ void checkClosed() throws FetchException { - TransactionManager txnMgr = localTxnManager(); + TransactionScope scope = localTxnScope(); // Lock out shutdown task. - txnMgr.getLock().lock(); + scope.getLock().lock(); try { if (mPrimaryDatabase == null) { // If shuting down, this will force us to block forever. try { - txnMgr.getTxn(); + scope.getTxn(); } catch (Exception e) { // Don't care. } @@ -742,20 +742,20 @@ abstract class BDBStorage implements Storage, Storag throw new FetchException("Repository closed"); } } finally { - txnMgr.getLock().unlock(); + scope.getLock().unlock(); } } void close() throws Exception { - TransactionManager txnMgr = mRepository.localTxnManager(); - txnMgr.getLock().lock(); + TransactionScope scope = mRepository.localTxnScope(); + scope.getLock().lock(); try { if (mPrimaryDatabase != null) { db_close(mPrimaryDatabase); mPrimaryDatabase = null; } } finally { - txnMgr.getLock().unlock(); + scope.getLock().unlock(); } } @@ -998,18 +998,18 @@ abstract class BDBStorage implements Storage, Storag } public byte[] tryLoad(byte[] key) throws FetchException { - TransactionManager txnMgr = mStorage.localTxnManager(); + TransactionScope scope = mStorage.localTxnScope(); byte[] result; // Lock out shutdown task. - txnMgr.getLock().lock(); + scope.getLock().lock(); try { try { - result = mStorage.db_get(txnMgr.getTxn(), key, txnMgr.isForUpdate()); + result = mStorage.db_get(scope.getTxn(), key, scope.isForUpdate()); } catch (Throwable e) { throw mStorage.toFetchException(e); } } finally { - txnMgr.getLock().unlock(); + scope.getLock().unlock(); } if (result == NOT_FOUND) { return null; @@ -1021,18 +1021,18 @@ abstract class BDBStorage implements Storage, Storag } public boolean tryInsert(S storable, byte[] key, byte[] value) throws PersistException { - TransactionManager txnMgr = mStorage.localTxnManager(); + TransactionScope scope = mStorage.localTxnScope(); Object result; // Lock out shutdown task. - txnMgr.getLock().lock(); + scope.getLock().lock(); try { try { - result = mStorage.db_putNoOverwrite(txnMgr.getTxn(), key, value); + result = mStorage.db_putNoOverwrite(scope.getTxn(), key, value); } catch (Throwable e) { throw mStorage.toPersistException(e); } } finally { - txnMgr.getLock().unlock(); + scope.getLock().unlock(); } if (result == KEY_EXIST) { return false; @@ -1044,34 +1044,34 @@ abstract class BDBStorage implements Storage, Storag } public void store(S storable, byte[] key, byte[] value) throws PersistException { - TransactionManager txnMgr = mStorage.localTxnManager(); + TransactionScope scope = mStorage.localTxnScope(); // Lock out shutdown task. - txnMgr.getLock().lock(); + scope.getLock().lock(); try { try { - if (!mStorage.db_put(txnMgr.getTxn(), key, value)) { + if (!mStorage.db_put(scope.getTxn(), key, value)) { throw new PersistException("Failed"); } } catch (Throwable e) { throw mStorage.toPersistException(e); } } finally { - txnMgr.getLock().unlock(); + scope.getLock().unlock(); } } public boolean tryDelete(byte[] key) throws PersistException { - TransactionManager txnMgr = mStorage.localTxnManager(); + TransactionScope scope = mStorage.localTxnScope(); // Lock out shutdown task. - txnMgr.getLock().lock(); + scope.getLock().lock(); try { try { - return mStorage.db_delete(txnMgr.getTxn(), key); + return mStorage.db_delete(scope.getTxn(), key); } catch (Throwable e) { throw mStorage.toPersistException(e); } } finally { - txnMgr.getLock().unlock(); + scope.getLock().unlock(); } } diff --git a/src/main/java/com/amazon/carbonado/repo/sleepycat/BDBTransactionManager.java b/src/main/java/com/amazon/carbonado/repo/sleepycat/BDBTransactionManager.java index f9b0c6c..5e0af3b 100644 --- a/src/main/java/com/amazon/carbonado/repo/sleepycat/BDBTransactionManager.java +++ b/src/main/java/com/amazon/carbonado/repo/sleepycat/BDBTransactionManager.java @@ -29,9 +29,7 @@ import com.amazon.carbonado.spi.ExceptionTransformer; import com.amazon.carbonado.spi.TransactionManager; /** - * This class is used for tracking transactions and open cursors. Each - * thread that uses the BDBRepository instance is assigned at most one - * BDBTransactionManager instance. + * This class is used for tracking transactions and open cursors. * * @author Brian S O'Neill */ @@ -51,6 +49,10 @@ class BDBTransactionManager extends TransactionManager { return repository().selectIsolationLevel(parent, level); } + protected boolean supportsForUpdate() { + return true; + } + protected Txn createTxn(Txn parent, IsolationLevel level) throws Exception { if (level == IsolationLevel.NONE) { return null; -- cgit v1.2.3