Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2d92c36f authored by Lee Shombert's avatar Lee Shombert
Browse files

Allow DEFERRED transactions to run in parallel

Bug: 279042342

A DEFERRED SQLite transaction is now read-only.  It will prefer the
"secondary" connections rather than the single, primary database
connection.  This allows multiple DEFERRED transactions to run in
parallel.

Because the DEFERRED transaction mode is used for read-only
transactions, the public APIs are renamed.

Test: atest
 * SQLiteDatabaseTest

Change-Id: Ida25a58d36767ebd23b20ba0d9ab8a1d4c0dfdc3
parent d3e8774d
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -14254,11 +14254,11 @@ package android.database.sqlite {
  public final class SQLiteDatabase extends android.database.sqlite.SQLiteClosable {
    method public void beginTransaction();
    method public void beginTransactionDeferred();
    method public void beginTransactionNonExclusive();
    method public void beginTransactionReadOnly();
    method public void beginTransactionWithListener(@Nullable android.database.sqlite.SQLiteTransactionListener);
    method public void beginTransactionWithListenerDeferred(@Nullable android.database.sqlite.SQLiteTransactionListener);
    method public void beginTransactionWithListenerNonExclusive(@Nullable android.database.sqlite.SQLiteTransactionListener);
    method public void beginTransactionWithListenerReadOnly(@Nullable android.database.sqlite.SQLiteTransactionListener);
    method public android.database.sqlite.SQLiteStatement compileStatement(String) throws android.database.SQLException;
    method @NonNull public static android.database.sqlite.SQLiteDatabase create(@Nullable android.database.sqlite.SQLiteDatabase.CursorFactory);
    method @NonNull public static android.database.sqlite.SQLiteDatabase createInMemory(@NonNull android.database.sqlite.SQLiteDatabase.OpenParams);
+30 −23
Original line number Diff line number Diff line
@@ -675,27 +675,31 @@ public final class SQLiteDatabase extends SQLiteClosable {
    }

    /**
     * Begins a transaction in DEFERRED mode.
     * Begins a transaction in DEFERRED mode, with the android-specific constraint that the
     * transaction is read-only. The database may not be modified inside a read-only transaction.
     * <p>
     * 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.
     * Read-only transactions may run concurrently with other read-only transactions, and if they
     * database is in WAL mode, they may also run concurrently with IMMEDIATE or EXCLUSIVE
     * transactions.
     * <p>
     * Here is the standard idiom for transactions:
     * Transactions can be nested.  However, the behavior of the transaction is not altered by
     * nested transactions.  A nested transaction may be any of the three transaction types but if
     * the outermost type is read-only then nested transactions remain read-only, regardless of how
     * they are started.
     * <p>
     * Here is the standard idiom for read-only transactions:
     *
     * <pre>
     *   db.beginTransactionDeferred();
     *   db.beginTransactionReadOnly();
     *   try {
     *     ...
     *     db.setTransactionSuccessful();
     *   } finally {
     *     db.endTransaction();
     *   }
     * </pre>
     */
    public void beginTransactionDeferred() {
        beginTransactionWithListenerDeferred(null);
    public void beginTransactionReadOnly() {
        beginTransactionWithListenerReadOnly(null);
    }

    /**
@@ -758,26 +762,26 @@ public final class SQLiteDatabase extends SQLiteClosable {
    }

    /**
     * Begins a transaction in DEFERRED mode.
     * Begins a transaction in read-only mode with a {@link SQLiteTransactionListener} listener.
     * The database may not be updated inside a read-only transaction.
     * <p>
     * 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.
     * Transactions can be nested.  However, the behavior of the transaction is not altered by
     * nested transactions.  A nested transaction may be any of the three transaction types but if
     * the outermost type is read-only then nested transactions remain read-only, regardless of how
     * they are started.
     * <p>
     * Here is the standard idiom for transactions:
     * Here is the standard idiom for read-only transactions:
     *
     * <pre>
     *   db.beginTransactionDeferred();
     *   db.beginTransactionWightListenerReadOnly(listener);
     *   try {
     *     ...
     *     db.setTransactionSuccessful();
     *   } finally {
     *     db.endTransaction();
     *   }
     * </pre>
     */
    public void beginTransactionWithListenerDeferred(
    public void beginTransactionWithListenerReadOnly(
            @Nullable SQLiteTransactionListener transactionListener) {
        beginTransaction(transactionListener, SQLiteSession.TRANSACTION_MODE_DEFERRED);
    }
@@ -792,15 +796,18 @@ public final class SQLiteDatabase extends SQLiteClosable {

    /**
     * Begin a transaction with the specified mode.  Valid modes are
     * {@link SquLiteSession.TRANSACTION_MODE_DEFERRED},
     * {@link SquLiteSession.TRANSACTION_MODE_IMMEDIATE}, and
     * {@link SquLiteSession.TRANSACTION_MODE_EXCLUSIVE}.
     * {@link SQLiteSession.TRANSACTION_MODE_DEFERRED},
     * {@link SQLiteSession.TRANSACTION_MODE_IMMEDIATE}, and
     * {@link SQLiteSession.TRANSACTION_MODE_EXCLUSIVE}.
     */
    private void beginTransaction(@Nullable SQLiteTransactionListener listener, int mode) {
        acquireReference();
        try {
            // DEFERRED transactions are read-only to allows concurrent read-only transactions.
            // Others are read/write.
            boolean readOnly = (mode == SQLiteSession.TRANSACTION_MODE_DEFERRED);
            getThreadSession().beginTransaction(mode, listener,
                    getThreadDefaultConnectionFlags(false /*readOnly*/), null);
                    getThreadDefaultConnectionFlags(readOnly), null);
        } finally {
            releaseReference();
        }