diff options
author | Fred Quintana <fredq@google.com> | 2009-09-03 12:14:06 -0700 |
---|---|---|
committer | Fred Quintana <fredq@google.com> | 2009-09-08 17:25:09 -0700 |
commit | c4516a7b62de525e3d6d5e76851bdfaf12c11f05 (patch) | |
tree | c6808a36cddaced64341a1f11a66d3f471d49d22 /core/java/android/database | |
parent | b80f698362e84b83e1c44c92fb76b0fdf1a5ef6d (diff) | |
download | frameworks_base-c4516a7b62de525e3d6d5e76851bdfaf12c11f05.zip frameworks_base-c4516a7b62de525e3d6d5e76851bdfaf12c11f05.tar.gz frameworks_base-c4516a7b62de525e3d6d5e76851bdfaf12c11f05.tar.bz2 |
add a transaction monitor
Diffstat (limited to 'core/java/android/database')
3 files changed, 88 insertions, 5 deletions
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java index 57bf3f7..4f31ef0 100644 --- a/core/java/android/database/sqlite/SQLiteDatabase.java +++ b/core/java/android/database/sqlite/SQLiteDatabase.java @@ -175,6 +175,11 @@ public class SQLiteDatabase extends SQLiteClosable { */ private boolean mTransactionIsSuccessful; + /** + * Valid during the life of a transaction. + */ + private SQLiteTransactionListener mTransactionListener; + /** Synchronize on this when accessing the database */ private final ReentrantLock mLock = new ReentrantLock(true); @@ -394,6 +399,31 @@ public class SQLiteDatabase extends SQLiteClosable { * </pre> */ public void beginTransaction() { + beginTransactionWithListener(null /* transactionStatusCallback */); + } + + /** + * Begins a transaction. Transactions can be nested. When the outer transaction is ended all of + * the work done in that transaction and all of the nested transactions will be committed or + * rolled back. The changes will be rolled back if any transaction is ended without being + * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed. + * + * <p>Here is the standard idiom for transactions: + * + * <pre> + * db.beginTransactionWithListener(listener); + * try { + * ... + * db.setTransactionSuccessful(); + * } finally { + * db.endTransaction(); + * } + * </pre> + * @param transactionListener listener that should be notified when the transaction begins, + * commits, or is rolled back, either explicitly or by a call to + * {@link #yieldIfContendedSafely}. + */ + public void beginTransactionWithListener(SQLiteTransactionListener transactionListener) { lockForced(); boolean ok = false; try { @@ -413,8 +443,17 @@ public class SQLiteDatabase extends SQLiteClosable { // This thread didn't already have the lock, so begin a database // transaction now. execSQL("BEGIN EXCLUSIVE;"); + mTransactionListener = transactionListener; mTransactionIsSuccessful = true; mInnerTransactionIsSuccessful = false; + if (transactionListener != null) { + try { + transactionListener.onBegin(); + } catch (RuntimeException e) { + execSQL("ROLLBACK;"); + throw e; + } + } ok = true; } finally { if (!ok) { @@ -442,11 +481,27 @@ public class SQLiteDatabase extends SQLiteClosable { if (mLock.getHoldCount() != 1) { return; } + RuntimeException savedException = null; + if (mTransactionListener != null) { + try { + if (mTransactionIsSuccessful) { + mTransactionListener.onCommit(); + } else { + mTransactionListener.onRollback(); + } + } catch (RuntimeException e) { + savedException = e; + mTransactionIsSuccessful = false; + } + } if (mTransactionIsSuccessful) { execSQL("COMMIT;"); } else { try { execSQL("ROLLBACK;"); + if (savedException != null) { + throw savedException; + } } catch (SQLException e) { if (Config.LOGD) { Log.d(TAG, "exception during rollback, maybe the DB previously " @@ -455,6 +510,7 @@ public class SQLiteDatabase extends SQLiteClosable { } } } finally { + mTransactionListener = null; unlockForced(); if (Config.LOGV) { Log.v(TAG, "unlocked " + Thread.currentThread() @@ -561,6 +617,7 @@ public class SQLiteDatabase extends SQLiteClosable { return false; } setTransactionSuccessful(); + SQLiteTransactionListener transactionListener = mTransactionListener; endTransaction(); if (checkFullyYielded) { if (this.isDbLockedByCurrentThread()) { @@ -586,7 +643,7 @@ public class SQLiteDatabase extends SQLiteClosable { } } } - beginTransaction(); + beginTransactionWithListener(transactionListener); return true; } diff --git a/core/java/android/database/sqlite/SQLiteDebug.java b/core/java/android/database/sqlite/SQLiteDebug.java index d04afb0..84d8879 100644 --- a/core/java/android/database/sqlite/SQLiteDebug.java +++ b/core/java/android/database/sqlite/SQLiteDebug.java @@ -17,6 +17,7 @@ package android.database.sqlite; import android.util.Config; +import android.util.Log; /** * Provides debugging info about all SQLite databases running in the current process. @@ -27,23 +28,27 @@ public final class SQLiteDebug { /** * Controls the printing of SQL statements as they are executed. */ - public static final boolean DEBUG_SQL_STATEMENTS = Config.LOGV; + public static final boolean DEBUG_SQL_STATEMENTS = + Log.isLoggable("SQLiteStatements", Log.VERBOSE); /** * Controls the stack trace reporting of active cursors being * finalized. */ - public static final boolean DEBUG_ACTIVE_CURSOR_FINALIZATION = Config.LOGV; + public static final boolean DEBUG_ACTIVE_CURSOR_FINALIZATION = + Log.isLoggable("SQLiteCursorClosing", Log.VERBOSE); /** * Controls the tracking of time spent holding the database lock. */ - public static final boolean DEBUG_LOCK_TIME_TRACKING = false; + public static final boolean DEBUG_LOCK_TIME_TRACKING = + Log.isLoggable("SQLiteLockTime", Log.VERBOSE); /** * Controls the printing of stack traces when tracking the time spent holding the database lock. */ - public static final boolean DEBUG_LOCK_TIME_TRACKING_STACK_TRACE = false; + public static final boolean DEBUG_LOCK_TIME_TRACKING_STACK_TRACE = + Log.isLoggable("SQLiteLockStackTrace", Log.VERBOSE); /** * Contains statistics about the active pagers in the current process. diff --git a/core/java/android/database/sqlite/SQLiteTransactionListener.java b/core/java/android/database/sqlite/SQLiteTransactionListener.java new file mode 100644 index 0000000..e97ece8 --- /dev/null +++ b/core/java/android/database/sqlite/SQLiteTransactionListener.java @@ -0,0 +1,21 @@ +package android.database.sqlite; + +/** + * A listener for transaction events. + */ +public interface SQLiteTransactionListener { + /** + * Called immediately after the transaction begins. + */ + void onBegin(); + + /** + * Called immediately before commiting the transaction. + */ + void onCommit(); + + /** + * Called if the transaction is about to be rolled back. + */ + void onRollback(); +} |