summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/amazon/carbonado/IsolationLevel.java6
-rw-r--r--src/main/java/com/amazon/carbonado/repo/indexed/ManagedIndex.java16
-rw-r--r--src/main/java/com/amazon/carbonado/repo/jdbc/JDBCRepository.java21
-rw-r--r--src/main/java/com/amazon/carbonado/repo/jdbc/JDBCTransaction.java27
-rw-r--r--src/main/java/com/amazon/carbonado/repo/sleepycat/BDBTransactionManager.java6
-rw-r--r--src/main/java/com/amazon/carbonado/spi/TransactionManager.java4
6 files changed, 56 insertions, 24 deletions
diff --git a/src/main/java/com/amazon/carbonado/IsolationLevel.java b/src/main/java/com/amazon/carbonado/IsolationLevel.java
index 7571205..fc8c747 100644
--- a/src/main/java/com/amazon/carbonado/IsolationLevel.java
+++ b/src/main/java/com/amazon/carbonado/IsolationLevel.java
@@ -48,6 +48,12 @@ package com.amazon.carbonado;
public enum IsolationLevel {
/**
+ * Indicates that no actual transaction is in progress. If this level is
+ * specified when entering a transaction, it uses auto-commit mode.
+ */
+ NONE,
+
+ /**
* Indicates that dirty reads, non-repeatable reads and phantom reads can
* occur. This level allows modifications by one transaction to be read by
* another transaction before any changes have been committed (a "dirty
diff --git a/src/main/java/com/amazon/carbonado/repo/indexed/ManagedIndex.java b/src/main/java/com/amazon/carbonado/repo/indexed/ManagedIndex.java
index 80ad172..bb17067 100644
--- a/src/main/java/com/amazon/carbonado/repo/indexed/ManagedIndex.java
+++ b/src/main/java/com/amazon/carbonado/repo/indexed/ManagedIndex.java
@@ -296,14 +296,10 @@ class ManagedIndex<S extends Storable> implements IndexEntryAccessor<S> {
void populateIndex(Repository repo, Storage<S> masterStorage) throws RepositoryException {
MergeSortBuffer buffer;
Comparator c;
- Transaction txn;
-
- if (repo.getTransactionIsolationLevel() == null) {
- txn = null;
- } else {
- txn = repo.enterTopTransaction(IsolationLevel.READ_COMMITTED);
- }
+ // Enter top transaction with isolation level of none to make sure
+ // preload operation does not run in a long nested transaction.
+ Transaction txn = repo.enterTopTransaction(IsolationLevel.NONE);
try {
Cursor<S> cursor = masterStorage.query().fetch();
if (!cursor.hasNext()) {
@@ -335,10 +331,10 @@ class ManagedIndex<S extends Storable> implements IndexEntryAccessor<S> {
while (cursor.hasNext()) {
buffer.add(makeIndexEntry(cursor.next()));
}
+
+ // No need to commit transaction because no changes should have been made.
} finally {
- if (txn != null) {
- txn.exit();
- }
+ txn.exit();
}
buffer.sort();
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 3a6ec68..f9c6d25 100644
--- a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCRepository.java
+++ b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCRepository.java
@@ -79,7 +79,9 @@ public class JDBCRepository
static IsolationLevel mapIsolationLevelFromJdbc(int jdbcLevel) {
switch (jdbcLevel) {
- case Connection.TRANSACTION_READ_UNCOMMITTED: default:
+ case Connection.TRANSACTION_NONE: default:
+ return IsolationLevel.NONE;
+ case Connection.TRANSACTION_READ_UNCOMMITTED:
return IsolationLevel.READ_UNCOMMITTED;
case Connection.TRANSACTION_READ_COMMITTED:
return IsolationLevel.READ_COMMITTED;
@@ -92,7 +94,9 @@ public class JDBCRepository
static int mapIsolationLevelToJdbc(IsolationLevel level) {
switch (level) {
- case READ_UNCOMMITTED: default:
+ case NONE: default:
+ return Connection.TRANSACTION_NONE;
+ case READ_UNCOMMITTED:
return Connection.TRANSACTION_READ_UNCOMMITTED;
case READ_COMMITTED:
return Connection.TRANSACTION_READ_COMMITTED;
@@ -513,9 +517,14 @@ public class JDBCRepository
// Get connection outside synchronized section since it may block.
Connection con = mDataSource.getConnection();
- con.setAutoCommit(false);
- if (level != mDefaultIsolationLevel) {
- con.setTransactionIsolation(mapIsolationLevelToJdbc(level));
+
+ if (level == IsolationLevel.NONE) {
+ con.setAutoCommit(true);
+ } else {
+ con.setAutoCommit(false);
+ if (level != mDefaultIsolationLevel) {
+ con.setTransactionIsolation(mapIsolationLevelToJdbc(level));
+ }
}
synchronized (mAllTxnMgrs) {
@@ -609,6 +618,8 @@ public class JDBCRepository
}
switch (desiredLevel) {
+ case NONE:
+ return IsolationLevel.NONE;
case READ_UNCOMMITTED:
return mReadUncommittedLevel;
case READ_COMMITTED:
diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCTransaction.java b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCTransaction.java
index d92228d..832745b 100644
--- a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCTransaction.java
+++ b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCTransaction.java
@@ -34,10 +34,12 @@ import com.amazon.carbonado.IsolationLevel;
* @author Brian S O'Neill
*/
class JDBCTransaction {
+ // Use this magic value to indicate that the isolation level need not be
+ // changed when the transaction ends. This is a little optimization to
+ // avoid a round trip call to the remote database.
+ private static final int LEVEL_NOT_CHANGED = -1;
+
private final Connection mConnection;
- // Use TRANSACTION_NONE as a magic value to indicate that the isolation
- // level need not be changed when the transaction ends. This is a little
- // optimization to avoid a round trip call to the remote database.
private final int mOriginalLevel;
private Savepoint mSavepoint;
@@ -46,7 +48,7 @@ class JDBCTransaction {
JDBCTransaction(Connection con) {
mConnection = con;
// Don't change level upon abort.
- mOriginalLevel = Connection.TRANSACTION_NONE;
+ mOriginalLevel = LEVEL_NOT_CHANGED;
}
/**
@@ -57,16 +59,19 @@ class JDBCTransaction {
if (level == null) {
// Don't change level upon abort.
- mOriginalLevel = Connection.TRANSACTION_NONE;
+ mOriginalLevel = LEVEL_NOT_CHANGED;
} else {
int newLevel = JDBCRepository.mapIsolationLevelToJdbc(level);
int originalLevel = mConnection.getTransactionIsolation();
if (newLevel == originalLevel) {
// Don't change level upon abort.
- mOriginalLevel = Connection.TRANSACTION_NONE;
+ mOriginalLevel = LEVEL_NOT_CHANGED;
} else {
- // Don't change level upon abort.
+ // Do change level upon abort.
mOriginalLevel = originalLevel;
+ if (originalLevel == Connection.TRANSACTION_NONE) {
+ mConnection.setAutoCommit(false);
+ }
mConnection.setTransactionIsolation(newLevel);
}
}
@@ -105,8 +110,12 @@ class JDBCTransaction {
return mConnection;
} else {
mConnection.rollback(mSavepoint);
- if (mOriginalLevel != Connection.TRANSACTION_NONE) {
- mConnection.setTransactionIsolation(mOriginalLevel);
+ if (mOriginalLevel != LEVEL_NOT_CHANGED) {
+ if (mOriginalLevel == Connection.TRANSACTION_NONE) {
+ mConnection.setAutoCommit(true);
+ } else {
+ mConnection.setTransactionIsolation(mOriginalLevel);
+ }
}
mSavepoint = null;
return null;
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 4c6105f..53ca5e4 100644
--- a/src/main/java/com/amazon/carbonado/repo/sleepycat/BDBTransactionManager.java
+++ b/src/main/java/com/amazon/carbonado/repo/sleepycat/BDBTransactionManager.java
@@ -49,6 +49,9 @@ class BDBTransactionManager<Txn> extends TransactionManager<Txn> {
}
protected Txn createTxn(Txn parent, IsolationLevel level) throws Exception {
+ if (level == IsolationLevel.NONE) {
+ return null;
+ }
return repository().txn_begin(parent, level);
}
@@ -56,6 +59,9 @@ class BDBTransactionManager<Txn> extends TransactionManager<Txn> {
protected Txn createTxn(Txn parent, IsolationLevel level, int timeout, TimeUnit unit)
throws Exception
{
+ if (level == IsolationLevel.NONE) {
+ return null;
+ }
if (timeout == 0) {
return repository().txn_begin_nowait(parent, level);
} else {
diff --git a/src/main/java/com/amazon/carbonado/spi/TransactionManager.java b/src/main/java/com/amazon/carbonado/spi/TransactionManager.java
index 144b411..e8cc637 100644
--- a/src/main/java/com/amazon/carbonado/spi/TransactionManager.java
+++ b/src/main/java/com/amazon/carbonado/spi/TransactionManager.java
@@ -304,6 +304,8 @@ public abstract class TransactionManager<Txn> {
*
* @param parent optional parent transaction
* @param level required isolation level
+ * @return new transaction, parent transaction, or possibly null if required
+ * isolation level is none
*/
protected abstract Txn createTxn(Txn parent, IsolationLevel level) throws Exception;
@@ -320,6 +322,8 @@ public abstract class TransactionManager<Txn> {
* @param level required isolation level
* @param timeout desired timeout for lock acquisition, never negative
* @param unit timeout unit, never null
+ * @return new transaction, parent transaction, or possibly null if required
+ * isolation level is none
*/
protected Txn createTxn(Txn parent, IsolationLevel level,
int timeout, TimeUnit unit)