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

Commit 0aa4713e authored by Jeff Brown's avatar Jeff Brown Committed by Android (Google) Code Review
Browse files

Merge "Support enabling WAL using a flag when DB is opened."

parents cbe55a1c 47847f3f
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -5204,6 +5204,7 @@ package android.content {
    field public static final java.lang.String LAYOUT_INFLATER_SERVICE = "layout_inflater";
    field public static final java.lang.String LAYOUT_INFLATER_SERVICE = "layout_inflater";
    field public static final java.lang.String LOCATION_SERVICE = "location";
    field public static final java.lang.String LOCATION_SERVICE = "location";
    field public static final int MODE_APPEND = 32768; // 0x8000
    field public static final int MODE_APPEND = 32768; // 0x8000
    field public static final int MODE_ENABLE_WRITE_AHEAD_LOGGING = 8; // 0x8
    field public static final int MODE_MULTI_PROCESS = 4; // 0x4
    field public static final int MODE_MULTI_PROCESS = 4; // 0x4
    field public static final int MODE_PRIVATE = 0; // 0x0
    field public static final int MODE_PRIVATE = 0; // 0x0
    field public static final int MODE_WORLD_READABLE = 1; // 0x1
    field public static final int MODE_WORLD_READABLE = 1; // 0x1
@@ -7334,6 +7335,7 @@ package android.database.sqlite {
    method public deprecated boolean isDbLockedByOtherThreads();
    method public deprecated boolean isDbLockedByOtherThreads();
    method public boolean isOpen();
    method public boolean isOpen();
    method public boolean isReadOnly();
    method public boolean isReadOnly();
    method public boolean isWriteAheadLoggingEnabled();
    method public deprecated void markTableSyncable(java.lang.String, java.lang.String);
    method public deprecated void markTableSyncable(java.lang.String, java.lang.String);
    method public deprecated void markTableSyncable(java.lang.String, java.lang.String, java.lang.String);
    method public deprecated void markTableSyncable(java.lang.String, java.lang.String, java.lang.String);
    method public boolean needUpgrade(int);
    method public boolean needUpgrade(int);
@@ -7375,6 +7377,7 @@ package android.database.sqlite {
    field public static final int CONFLICT_REPLACE = 5; // 0x5
    field public static final int CONFLICT_REPLACE = 5; // 0x5
    field public static final int CONFLICT_ROLLBACK = 1; // 0x1
    field public static final int CONFLICT_ROLLBACK = 1; // 0x1
    field public static final int CREATE_IF_NECESSARY = 268435456; // 0x10000000
    field public static final int CREATE_IF_NECESSARY = 268435456; // 0x10000000
    field public static final int ENABLE_WRITE_AHEAD_LOGGING = 536870912; // 0x20000000
    field public static final int MAX_SQL_CACHE_SIZE = 100; // 0x64
    field public static final int MAX_SQL_CACHE_SIZE = 100; // 0x64
    field public static final int NO_LOCALIZED_COLLATORS = 16; // 0x10
    field public static final int NO_LOCALIZED_COLLATORS = 16; // 0x10
    field public static final int OPEN_READONLY = 1; // 0x1
    field public static final int OPEN_READONLY = 1; // 0x1
@@ -7438,6 +7441,7 @@ package android.database.sqlite {
    method public void onDowngrade(android.database.sqlite.SQLiteDatabase, int, int);
    method public void onDowngrade(android.database.sqlite.SQLiteDatabase, int, int);
    method public void onOpen(android.database.sqlite.SQLiteDatabase);
    method public void onOpen(android.database.sqlite.SQLiteDatabase);
    method public abstract void onUpgrade(android.database.sqlite.SQLiteDatabase, int, int);
    method public abstract void onUpgrade(android.database.sqlite.SQLiteDatabase, int, int);
    method public void setWriteAheadLoggingEnabled(boolean);
  }
  }
  public class SQLiteOutOfMemoryException extends android.database.sqlite.SQLiteException {
  public class SQLiteOutOfMemoryException extends android.database.sqlite.SQLiteException {
+6 −5
Original line number Original line Diff line number Diff line
@@ -766,17 +766,18 @@ class ContextImpl extends Context {


    @Override
    @Override
    public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) {
    public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) {
        File f = validateFilePath(name, true);
        return openOrCreateDatabase(name, mode, factory, null);
        SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(f, factory);
        setFilePermissionsFromMode(f.getPath(), mode, 0);
        return db;
    }
    }


    @Override
    @Override
    public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory,
    public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory,
            DatabaseErrorHandler errorHandler) {
            DatabaseErrorHandler errorHandler) {
        File f = validateFilePath(name, true);
        File f = validateFilePath(name, true);
        SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(f.getPath(), factory, errorHandler);
        int flags = SQLiteDatabase.CREATE_IF_NECESSARY;
        if ((mode & MODE_ENABLE_WRITE_AHEAD_LOGGING) != 0) {
            flags |= SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING;
        }
        SQLiteDatabase db = SQLiteDatabase.openDatabase(f.getPath(), factory, flags, errorHandler);
        setFilePermissionsFromMode(f.getPath(), mode, 0);
        setFilePermissionsFromMode(f.getPath(), mode, 0);
        return db;
        return db;
    }
    }
+14 −0
Original line number Original line Diff line number Diff line
@@ -98,6 +98,16 @@ public abstract class Context {
     */
     */
    public static final int MODE_MULTI_PROCESS = 0x0004;
    public static final int MODE_MULTI_PROCESS = 0x0004;


    /**
     * Database open flag: when set, the database is opened with write-ahead
     * logging enabled by default.
     *
     * @see #openOrCreateDatabase(String, int, CursorFactory)
     * @see #openOrCreateDatabase(String, int, CursorFactory, DatabaseErrorHandler)
     * @see SQLiteDatabase#enableWriteAheadLogging
     */
    public static final int MODE_ENABLE_WRITE_AHEAD_LOGGING = 0x0008;

    /**
    /**
     * Flag for {@link #bindService}: automatically create the service as long
     * Flag for {@link #bindService}: automatically create the service as long
     * as the binding exists.  Note that while this will create the service,
     * as the binding exists.  Note that while this will create the service,
@@ -691,6 +701,7 @@ public abstract class Context {
     * @param mode Operating mode.  Use 0 or {@link #MODE_PRIVATE} for the
     * @param mode Operating mode.  Use 0 or {@link #MODE_PRIVATE} for the
     *     default operation, {@link #MODE_WORLD_READABLE}
     *     default operation, {@link #MODE_WORLD_READABLE}
     *     and {@link #MODE_WORLD_WRITEABLE} to control permissions.
     *     and {@link #MODE_WORLD_WRITEABLE} to control permissions.
     *     Use {@link #MODE_ENABLE_WRITE_AHEAD_LOGGING} to enable write-ahead logging by default.
     * @param factory An optional factory class that is called to instantiate a
     * @param factory An optional factory class that is called to instantiate a
     *     cursor when query is called.
     *     cursor when query is called.
     *
     *
@@ -700,6 +711,7 @@ public abstract class Context {
     * @see #MODE_PRIVATE
     * @see #MODE_PRIVATE
     * @see #MODE_WORLD_READABLE
     * @see #MODE_WORLD_READABLE
     * @see #MODE_WORLD_WRITEABLE
     * @see #MODE_WORLD_WRITEABLE
     * @see #MODE_ENABLE_WRITE_AHEAD_LOGGING
     * @see #deleteDatabase
     * @see #deleteDatabase
     */
     */
    public abstract SQLiteDatabase openOrCreateDatabase(String name,
    public abstract SQLiteDatabase openOrCreateDatabase(String name,
@@ -716,6 +728,7 @@ public abstract class Context {
     * @param mode Operating mode.  Use 0 or {@link #MODE_PRIVATE} for the
     * @param mode Operating mode.  Use 0 or {@link #MODE_PRIVATE} for the
     *     default operation, {@link #MODE_WORLD_READABLE}
     *     default operation, {@link #MODE_WORLD_READABLE}
     *     and {@link #MODE_WORLD_WRITEABLE} to control permissions.
     *     and {@link #MODE_WORLD_WRITEABLE} to control permissions.
     *     Use {@link #MODE_ENABLE_WRITE_AHEAD_LOGGING} to enable write-ahead logging by default.
     * @param factory An optional factory class that is called to instantiate a
     * @param factory An optional factory class that is called to instantiate a
     *     cursor when query is called.
     *     cursor when query is called.
     * @param errorHandler the {@link DatabaseErrorHandler} to be used when sqlite reports database
     * @param errorHandler the {@link DatabaseErrorHandler} to be used when sqlite reports database
@@ -726,6 +739,7 @@ public abstract class Context {
     * @see #MODE_PRIVATE
     * @see #MODE_PRIVATE
     * @see #MODE_WORLD_READABLE
     * @see #MODE_WORLD_READABLE
     * @see #MODE_WORLD_WRITEABLE
     * @see #MODE_WORLD_WRITEABLE
     * @see #MODE_ENABLE_WRITE_AHEAD_LOGGING
     * @see #deleteDatabase
     * @see #deleteDatabase
     */
     */
    public abstract SQLiteDatabase openOrCreateDatabase(String name,
    public abstract SQLiteDatabase openOrCreateDatabase(String name,
+3 −2
Original line number Original line Diff line number Diff line
@@ -269,7 +269,7 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen


    private void setWalModeFromConfiguration() {
    private void setWalModeFromConfiguration() {
        if (!mConfiguration.isInMemoryDb() && !mIsReadOnlyConnection) {
        if (!mConfiguration.isInMemoryDb() && !mIsReadOnlyConnection) {
            if (mConfiguration.walEnabled) {
            if ((mConfiguration.openFlags & SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0) {
                setJournalMode("WAL");
                setJournalMode("WAL");
                setSyncMode(SQLiteGlobal.getWALSyncMode());
                setSyncMode(SQLiteGlobal.getWALSyncMode());
            } else {
            } else {
@@ -389,7 +389,8 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
        }
        }


        // Remember what changed.
        // Remember what changed.
        boolean walModeChanged = configuration.walEnabled != mConfiguration.walEnabled;
        boolean walModeChanged = ((configuration.openFlags ^ mConfiguration.openFlags)
                & SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0;
        boolean localeChanged = !configuration.locale.equals(mConfiguration.locale);
        boolean localeChanged = !configuration.locale.equals(mConfiguration.locale);


        // Update configuration parameters.
        // Update configuration parameters.
+24 −10
Original line number Original line Diff line number Diff line
@@ -81,6 +81,7 @@ public final class SQLiteConnectionPool implements Closeable {
    private final Object mLock = new Object();
    private final Object mLock = new Object();
    private final AtomicBoolean mConnectionLeaked = new AtomicBoolean();
    private final AtomicBoolean mConnectionLeaked = new AtomicBoolean();
    private final SQLiteDatabaseConfiguration mConfiguration;
    private final SQLiteDatabaseConfiguration mConfiguration;
    private int mMaxConnectionPoolSize;
    private boolean mIsOpen;
    private boolean mIsOpen;
    private int mNextConnectionId;
    private int mNextConnectionId;


@@ -146,6 +147,7 @@ public final class SQLiteConnectionPool implements Closeable {


    private SQLiteConnectionPool(SQLiteDatabaseConfiguration configuration) {
    private SQLiteConnectionPool(SQLiteDatabaseConfiguration configuration) {
        mConfiguration = new SQLiteDatabaseConfiguration(configuration);
        mConfiguration = new SQLiteDatabaseConfiguration(configuration);
        setMaxConnectionPoolSizeLocked();
    }
    }


    @Override
    @Override
@@ -257,8 +259,9 @@ public final class SQLiteConnectionPool implements Closeable {
        synchronized (mLock) {
        synchronized (mLock) {
            throwIfClosedLocked();
            throwIfClosedLocked();


            boolean restrictToOneConnection = false;
            boolean walModeChanged = ((configuration.openFlags ^ mConfiguration.openFlags)
            if (mConfiguration.walEnabled != configuration.walEnabled) {
                    & SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0;
            if (walModeChanged) {
                // WAL mode can only be changed if there are no acquired connections
                // WAL mode can only be changed if there are no acquired connections
                // because we need to close all but the primary connection first.
                // because we need to close all but the primary connection first.
                if (!mAcquiredConnections.isEmpty()) {
                if (!mAcquiredConnections.isEmpty()) {
@@ -272,15 +275,13 @@ public final class SQLiteConnectionPool implements Closeable {
                // because none of them are in use.
                // because none of them are in use.
                closeAvailableNonPrimaryConnectionsAndLogExceptionsLocked();
                closeAvailableNonPrimaryConnectionsAndLogExceptionsLocked();
                assert mAvailableNonPrimaryConnections.isEmpty();
                assert mAvailableNonPrimaryConnections.isEmpty();

                restrictToOneConnection = true;
            }
            }


            if (mConfiguration.openFlags != configuration.openFlags) {
            if (mConfiguration.openFlags != configuration.openFlags) {
                // If we are changing open flags and WAL mode at the same time, then
                // If we are changing open flags and WAL mode at the same time, then
                // we have no choice but to close the primary connection beforehand
                // we have no choice but to close the primary connection beforehand
                // because there can only be one connection open when we change WAL mode.
                // because there can only be one connection open when we change WAL mode.
                if (restrictToOneConnection) {
                if (walModeChanged) {
                    closeAvailableConnectionsAndLogExceptionsLocked();
                    closeAvailableConnectionsAndLogExceptionsLocked();
                }
                }


@@ -296,9 +297,11 @@ public final class SQLiteConnectionPool implements Closeable {


                mAvailablePrimaryConnection = newPrimaryConnection;
                mAvailablePrimaryConnection = newPrimaryConnection;
                mConfiguration.updateParametersFrom(configuration);
                mConfiguration.updateParametersFrom(configuration);
                setMaxConnectionPoolSizeLocked();
            } else {
            } else {
                // Reconfigure the database connections in place.
                // Reconfigure the database connections in place.
                mConfiguration.updateParametersFrom(configuration);
                mConfiguration.updateParametersFrom(configuration);
                setMaxConnectionPoolSizeLocked();


                closeExcessConnectionsAndLogExceptionsLocked();
                closeExcessConnectionsAndLogExceptionsLocked();
                reconfigureAllConnectionsLocked();
                reconfigureAllConnectionsLocked();
@@ -360,8 +363,7 @@ public final class SQLiteConnectionPool implements Closeable {
                    mAvailablePrimaryConnection = connection;
                    mAvailablePrimaryConnection = connection;
                }
                }
                wakeConnectionWaitersLocked();
                wakeConnectionWaitersLocked();
            } else if (mAvailableNonPrimaryConnections.size() >=
            } else if (mAvailableNonPrimaryConnections.size() >= mMaxConnectionPoolSize - 1) {
                    mConfiguration.maxConnectionPoolSize - 1) {
                closeConnectionAndLogExceptionsLocked(connection);
                closeConnectionAndLogExceptionsLocked(connection);
            } else {
            } else {
                if (recycleConnectionLocked(connection, status)) {
                if (recycleConnectionLocked(connection, status)) {
@@ -499,7 +501,7 @@ public final class SQLiteConnectionPool implements Closeable {
    // Can't throw.
    // Can't throw.
    private void closeExcessConnectionsAndLogExceptionsLocked() {
    private void closeExcessConnectionsAndLogExceptionsLocked() {
        int availableCount = mAvailableNonPrimaryConnections.size();
        int availableCount = mAvailableNonPrimaryConnections.size();
        while (availableCount-- > mConfiguration.maxConnectionPoolSize - 1) {
        while (availableCount-- > mMaxConnectionPoolSize - 1) {
            SQLiteConnection connection =
            SQLiteConnection connection =
                    mAvailableNonPrimaryConnections.remove(availableCount);
                    mAvailableNonPrimaryConnections.remove(availableCount);
            closeConnectionAndLogExceptionsLocked(connection);
            closeConnectionAndLogExceptionsLocked(connection);
@@ -874,7 +876,7 @@ public final class SQLiteConnectionPool implements Closeable {
        if (mAvailablePrimaryConnection != null) {
        if (mAvailablePrimaryConnection != null) {
            openConnections += 1;
            openConnections += 1;
        }
        }
        if (openConnections >= mConfiguration.maxConnectionPoolSize) {
        if (openConnections >= mMaxConnectionPoolSize) {
            return null;
            return null;
        }
        }
        connection = openConnectionLocked(mConfiguration,
        connection = openConnectionLocked(mConfiguration,
@@ -926,6 +928,18 @@ public final class SQLiteConnectionPool implements Closeable {
        return (connectionFlags & CONNECTION_FLAG_INTERACTIVE) != 0 ? 1 : 0;
        return (connectionFlags & CONNECTION_FLAG_INTERACTIVE) != 0 ? 1 : 0;
    }
    }


    private void setMaxConnectionPoolSizeLocked() {
        if ((mConfiguration.openFlags & SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0) {
            mMaxConnectionPoolSize = SQLiteGlobal.getWALConnectionPoolSize();
        } else {
            // TODO: We don't actually need to restrict the connection pool size to 1
            // for non-WAL databases.  There might be reasons to use connection pooling
            // with other journal modes.  For now, enabling connection pooling and
            // using WAL are the same thing in the API.
            mMaxConnectionPoolSize = 1;
        }
    }

    private void throwIfClosedLocked() {
    private void throwIfClosedLocked() {
        if (!mIsOpen) {
        if (!mIsOpen) {
            throw new IllegalStateException("Cannot perform this operation "
            throw new IllegalStateException("Cannot perform this operation "
@@ -972,7 +986,7 @@ public final class SQLiteConnectionPool implements Closeable {
        synchronized (mLock) {
        synchronized (mLock) {
            printer.println("Connection pool for " + mConfiguration.path + ":");
            printer.println("Connection pool for " + mConfiguration.path + ":");
            printer.println("  Open: " + mIsOpen);
            printer.println("  Open: " + mIsOpen);
            printer.println("  Max connections: " + mConfiguration.maxConnectionPoolSize);
            printer.println("  Max connections: " + mMaxConnectionPoolSize);


            printer.println("  Available primary connection:");
            printer.println("  Available primary connection:");
            if (mAvailablePrimaryConnection != null) {
            if (mAvailablePrimaryConnection != null) {
Loading