1e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown/* 2e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Copyright (C) 2011 The Android Open Source Project 3e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 4e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 5e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * you may not use this file except in compliance with the License. 6e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * You may obtain a copy of the License at 7e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 8e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * http://www.apache.org/licenses/LICENSE-2.0 9e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 10e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Unless required by applicable law or agreed to in writing, software 11e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 12e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * See the License for the specific language governing permissions and 14e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * limitations under the License. 15e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 16e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 17e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownpackage android.database.sqlite; 18e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 19e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownimport dalvik.system.CloseGuard; 20e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 21e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownimport android.database.sqlite.SQLiteDebug.DbStats; 22a7771df3696954f0e279407e8894a916a7cb26ccJeff Brownimport android.os.CancellationSignal; 23a7771df3696954f0e279407e8894a916a7cb26ccJeff Brownimport android.os.OperationCanceledException; 24e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownimport android.os.SystemClock; 25e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownimport android.util.Log; 26e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownimport android.util.PrefixPrinter; 27e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownimport android.util.Printer; 28e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 29e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownimport java.io.Closeable; 30e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownimport java.util.ArrayList; 31e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownimport java.util.Map; 32e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownimport java.util.WeakHashMap; 33e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownimport java.util.concurrent.atomic.AtomicBoolean; 34e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownimport java.util.concurrent.locks.LockSupport; 35e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 36e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown/** 37e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Maintains a pool of active SQLite database connections. 38e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <p> 39e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * At any given time, a connection is either owned by the pool, or it has been 40e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * acquired by a {@link SQLiteSession}. When the {@link SQLiteSession} is 41e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * finished with the connection it is using, it must return the connection 42e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * back to the pool. 43e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p><p> 44e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * The pool holds strong references to the connections it owns. However, 45e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * it only holds <em>weak references</em> to the connections that sessions 46e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * have acquired from it. Using weak references in the latter case ensures 47e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * that the connection pool can detect when connections have been improperly 48e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * abandoned so that it can create new connections to replace them if needed. 49e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p><p> 50e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * The connection pool is thread-safe (but the connections themselves are not). 51e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p> 52e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 53e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <h2>Exception safety</h2> 54e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <p> 55e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * This code attempts to maintain the invariant that opened connections are 56e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * always owned. Unfortunately that means it needs to handle exceptions 57e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * all over to ensure that broken connections get cleaned up. Most 58e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * operations invokving SQLite can throw {@link SQLiteException} or other 59e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * runtime exceptions. This is a bit of a pain to deal with because the compiler 60e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * cannot help us catch missing exception handling code. 61e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p><p> 62e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * The general rule for this file: If we are making calls out to 63e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * {@link SQLiteConnection} then we must be prepared to handle any 64e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * runtime exceptions it might throw at us. Note that out-of-memory 65e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * is an {@link Error}, not a {@link RuntimeException}. We don't trouble ourselves 66e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * handling out of memory because it is hard to do anything at all sensible then 67e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * and most likely the VM is about to crash. 68e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p> 69e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 70e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @hide 71e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 72e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownpublic final class SQLiteConnectionPool implements Closeable { 73e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private static final String TAG = "SQLiteConnectionPool"; 74e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 75e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Amount of time to wait in milliseconds before unblocking acquireConnection 76e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // and logging a message about the connection pool being busy. 77e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private static final long CONNECTION_POOL_BUSY_MILLIS = 30 * 1000; // 30 seconds 78e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 79e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private final CloseGuard mCloseGuard = CloseGuard.get(); 80e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 81e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private final Object mLock = new Object(); 82e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private final AtomicBoolean mConnectionLeaked = new AtomicBoolean(); 83e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private final SQLiteDatabaseConfiguration mConfiguration; 8447847f3f4dcf2a0dbea0bc0e4f02528e21d37a88Jeff Brown private int mMaxConnectionPoolSize; 85e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private boolean mIsOpen; 86e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private int mNextConnectionId; 87e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 88e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private ConnectionWaiter mConnectionWaiterPool; 89e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private ConnectionWaiter mConnectionWaiterQueue; 90e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 91e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Strong references to all available connections. 92e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private final ArrayList<SQLiteConnection> mAvailableNonPrimaryConnections = 93e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown new ArrayList<SQLiteConnection>(); 94e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private SQLiteConnection mAvailablePrimaryConnection; 95e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 96559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown // Describes what should happen to an acquired connection when it is returned to the pool. 97559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown enum AcquiredConnectionStatus { 98559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown // The connection should be returned to the pool as usual. 99559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown NORMAL, 100559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown 101559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown // The connection must be reconfigured before being returned. 102559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown RECONFIGURE, 103559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown 104559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown // The connection must be closed and discarded. 105559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown DISCARD, 106559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown } 107559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown 108e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Weak references to all acquired connections. The associated value 109559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown // indicates whether the connection must be reconfigured before being 110559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown // returned to the available connection list or discarded. 111e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // For example, the prepared statement cache size may have changed and 112559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown // need to be updated in preparation for the next client. 113559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown private final WeakHashMap<SQLiteConnection, AcquiredConnectionStatus> mAcquiredConnections = 114559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown new WeakHashMap<SQLiteConnection, AcquiredConnectionStatus>(); 115e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 116e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** 117e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Connection flag: Read-only. 118e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <p> 119e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * This flag indicates that the connection will only be used to 120e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * perform read-only operations. 121e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p> 122e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 123e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public static final int CONNECTION_FLAG_READ_ONLY = 1 << 0; 124e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 125e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** 126e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Connection flag: Primary connection affinity. 127e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <p> 128e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * This flag indicates that the primary connection is required. 129e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * This flag helps support legacy applications that expect most data modifying 130e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * operations to be serialized by locking the primary database connection. 131e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Setting this flag essentially implements the old "db lock" concept by preventing 132e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * an operation from being performed until it can obtain exclusive access to 133e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * the primary connection. 134e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p> 135e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 136e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public static final int CONNECTION_FLAG_PRIMARY_CONNECTION_AFFINITY = 1 << 1; 137e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 138e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** 139e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Connection flag: Connection is being used interactively. 140e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <p> 141e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * This flag indicates that the connection is needed by the UI thread. 142e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * The connection pool can use this flag to elevate the priority 143e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * of the database connection request. 144e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p> 145e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 146e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public static final int CONNECTION_FLAG_INTERACTIVE = 1 << 2; 147e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 148e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private SQLiteConnectionPool(SQLiteDatabaseConfiguration configuration) { 149e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mConfiguration = new SQLiteDatabaseConfiguration(configuration); 15047847f3f4dcf2a0dbea0bc0e4f02528e21d37a88Jeff Brown setMaxConnectionPoolSizeLocked(); 151e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 152e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 153e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown @Override 154e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown protected void finalize() throws Throwable { 155e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown try { 156e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown dispose(true); 157e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } finally { 158e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown super.finalize(); 159e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 160e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 161e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 162e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** 163e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Opens a connection pool for the specified database. 164e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 165e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param configuration The database configuration. 166e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @return The connection pool. 167e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 168e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @throws SQLiteException if a database error occurs. 169e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 170e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public static SQLiteConnectionPool open(SQLiteDatabaseConfiguration configuration) { 171e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (configuration == null) { 172e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw new IllegalArgumentException("configuration must not be null."); 173e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 174e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 175e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Create the pool. 176e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteConnectionPool pool = new SQLiteConnectionPool(configuration); 177e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown pool.open(); // might throw 178e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return pool; 179e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 180e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 181e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Might throw 182e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private void open() { 183e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Open the primary connection. 184e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // This might throw if the database is corrupt. 185559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown mAvailablePrimaryConnection = openConnectionLocked(mConfiguration, 186e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown true /*primaryConnection*/); // might throw 187e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 188e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Mark the pool as being open for business. 189e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mIsOpen = true; 190e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mCloseGuard.open("close"); 191e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 192e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 193e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** 194e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Closes the connection pool. 195e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <p> 196e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * When the connection pool is closed, it will refuse all further requests 197e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * to acquire connections. All connections that are currently available in 198e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * the pool are closed immediately. Any connections that are still in use 199e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * will be closed as soon as they are returned to the pool. 200e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p> 201e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 202e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @throws IllegalStateException if the pool has been closed. 203e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 204e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public void close() { 205e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown dispose(false); 206e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 207e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 208e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private void dispose(boolean finalized) { 209e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (mCloseGuard != null) { 210e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (finalized) { 211e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mCloseGuard.warnIfOpen(); 212e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 213e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mCloseGuard.close(); 214e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 215e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 216e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (!finalized) { 217e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Close all connections. We don't need (or want) to do this 218e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // when finalized because we don't know what state the connections 219e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // themselves will be in. The finalizer is really just here for CloseGuard. 220e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // The connections will take care of themselves when their own finalizers run. 221e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown synchronized (mLock) { 222e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throwIfClosedLocked(); 223e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 224e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mIsOpen = false; 225e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 226559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown closeAvailableConnectionsAndLogExceptionsLocked(); 227e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 228e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown final int pendingCount = mAcquiredConnections.size(); 229e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (pendingCount != 0) { 230e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown Log.i(TAG, "The connection pool for " + mConfiguration.label 231e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown + " has been closed but there are still " 232e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown + pendingCount + " connections in use. They will be closed " 233e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown + "as they are released back to the pool."); 234e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 235e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 236e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown wakeConnectionWaitersLocked(); 237e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 238e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 239e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 240e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 241e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** 242e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Reconfigures the database configuration of the connection pool and all of its 243e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * connections. 244e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <p> 245e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Configuration changes are propagated down to connections immediately if 246e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * they are available or as soon as they are released. This includes changes 247e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * that affect the size of the pool. 248e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p> 249e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 250e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param configuration The new configuration. 251e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 252e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @throws IllegalStateException if the pool has been closed. 253e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 254e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public void reconfigure(SQLiteDatabaseConfiguration configuration) { 255e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (configuration == null) { 256e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw new IllegalArgumentException("configuration must not be null."); 257e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 258e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 259e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown synchronized (mLock) { 260e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throwIfClosedLocked(); 261e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 26247847f3f4dcf2a0dbea0bc0e4f02528e21d37a88Jeff Brown boolean walModeChanged = ((configuration.openFlags ^ mConfiguration.openFlags) 26347847f3f4dcf2a0dbea0bc0e4f02528e21d37a88Jeff Brown & SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0; 26447847f3f4dcf2a0dbea0bc0e4f02528e21d37a88Jeff Brown if (walModeChanged) { 265e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fcJeff Brown // WAL mode can only be changed if there are no acquired connections 266e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fcJeff Brown // because we need to close all but the primary connection first. 267e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fcJeff Brown if (!mAcquiredConnections.isEmpty()) { 268e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fcJeff Brown throw new IllegalStateException("Write Ahead Logging (WAL) mode cannot " 269e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fcJeff Brown + "be enabled or disabled while there are transactions in " 270e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fcJeff Brown + "progress. Finish all transactions and release all active " 271e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fcJeff Brown + "database connections first."); 272e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fcJeff Brown } 273e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fcJeff Brown 274e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fcJeff Brown // Close all non-primary connections. This should happen immediately 275e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fcJeff Brown // because none of them are in use. 276e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fcJeff Brown closeAvailableNonPrimaryConnectionsAndLogExceptionsLocked(); 277e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fcJeff Brown assert mAvailableNonPrimaryConnections.isEmpty(); 278e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fcJeff Brown } 279e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fcJeff Brown 28096496adb611ced49ed1c2c778c616d1f8a5d0e6bJeff Brown boolean foreignKeyModeChanged = configuration.foreignKeyConstraintsEnabled 28196496adb611ced49ed1c2c778c616d1f8a5d0e6bJeff Brown != mConfiguration.foreignKeyConstraintsEnabled; 28296496adb611ced49ed1c2c778c616d1f8a5d0e6bJeff Brown if (foreignKeyModeChanged) { 28396496adb611ced49ed1c2c778c616d1f8a5d0e6bJeff Brown // Foreign key constraints can only be changed if there are no transactions 28496496adb611ced49ed1c2c778c616d1f8a5d0e6bJeff Brown // in progress. To make this clear, we throw an exception if there are 28596496adb611ced49ed1c2c778c616d1f8a5d0e6bJeff Brown // any acquired connections. 28696496adb611ced49ed1c2c778c616d1f8a5d0e6bJeff Brown if (!mAcquiredConnections.isEmpty()) { 28796496adb611ced49ed1c2c778c616d1f8a5d0e6bJeff Brown throw new IllegalStateException("Foreign Key Constraints cannot " 28896496adb611ced49ed1c2c778c616d1f8a5d0e6bJeff Brown + "be enabled or disabled while there are transactions in " 28996496adb611ced49ed1c2c778c616d1f8a5d0e6bJeff Brown + "progress. Finish all transactions and release all active " 29096496adb611ced49ed1c2c778c616d1f8a5d0e6bJeff Brown + "database connections first."); 29196496adb611ced49ed1c2c778c616d1f8a5d0e6bJeff Brown } 29296496adb611ced49ed1c2c778c616d1f8a5d0e6bJeff Brown } 29396496adb611ced49ed1c2c778c616d1f8a5d0e6bJeff Brown 294559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown if (mConfiguration.openFlags != configuration.openFlags) { 295e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fcJeff Brown // If we are changing open flags and WAL mode at the same time, then 296e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fcJeff Brown // we have no choice but to close the primary connection beforehand 297e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fcJeff Brown // because there can only be one connection open when we change WAL mode. 29847847f3f4dcf2a0dbea0bc0e4f02528e21d37a88Jeff Brown if (walModeChanged) { 299e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fcJeff Brown closeAvailableConnectionsAndLogExceptionsLocked(); 300e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fcJeff Brown } 301e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fcJeff Brown 302559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown // Try to reopen the primary connection using the new open flags then 303559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown // close and discard all existing connections. 304559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown // This might throw if the database is corrupt or cannot be opened in 305559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown // the new mode in which case existing connections will remain untouched. 306559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown SQLiteConnection newPrimaryConnection = openConnectionLocked(configuration, 307559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown true /*primaryConnection*/); // might throw 308e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 309559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown closeAvailableConnectionsAndLogExceptionsLocked(); 310559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown discardAcquiredConnectionsLocked(); 311e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 312559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown mAvailablePrimaryConnection = newPrimaryConnection; 313559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown mConfiguration.updateParametersFrom(configuration); 31447847f3f4dcf2a0dbea0bc0e4f02528e21d37a88Jeff Brown setMaxConnectionPoolSizeLocked(); 315559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown } else { 316559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown // Reconfigure the database connections in place. 317559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown mConfiguration.updateParametersFrom(configuration); 31847847f3f4dcf2a0dbea0bc0e4f02528e21d37a88Jeff Brown setMaxConnectionPoolSizeLocked(); 319559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown 320559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown closeExcessConnectionsAndLogExceptionsLocked(); 321559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown reconfigureAllConnectionsLocked(); 322559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown } 323e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 324e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown wakeConnectionWaitersLocked(); 325e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 326e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 327e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 328e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** 329e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Acquires a connection from the pool. 330e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <p> 331e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * The caller must call {@link #releaseConnection} to release the connection 332e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * back to the pool when it is finished. Failure to do so will result 333e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * in much unpleasantness. 334e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p> 335e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 336e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param sql If not null, try to find a connection that already has 337e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * the specified SQL statement in its prepared statement cache. 338e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param connectionFlags The connection request flags. 3394c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * @param cancellationSignal A signal to cancel the operation in progress, or null if none. 340e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @return The connection that was acquired, never null. 341e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 342e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @throws IllegalStateException if the pool has been closed. 343e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @throws SQLiteException if a database error occurs. 34475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * @throws OperationCanceledException if the operation was canceled. 345e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 34675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown public SQLiteConnection acquireConnection(String sql, int connectionFlags, 3474c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown CancellationSignal cancellationSignal) { 3484c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown return waitForConnection(sql, connectionFlags, cancellationSignal); 349e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 350e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 351e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** 352e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Releases a connection back to the pool. 353e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <p> 354e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * It is ok to call this method after the pool has closed, to release 355e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * connections that were still in use at the time of closure. 356e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p> 357e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 358e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param connection The connection to release. Must not be null. 359e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 360e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @throws IllegalStateException if the connection was not acquired 361e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * from this pool or if it has already been released. 362e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 363e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public void releaseConnection(SQLiteConnection connection) { 364e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown synchronized (mLock) { 365559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown AcquiredConnectionStatus status = mAcquiredConnections.remove(connection); 366559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown if (status == null) { 367e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw new IllegalStateException("Cannot perform this operation " 368e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown + "because the specified connection was not acquired " 369e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown + "from this pool or has already been released."); 370e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 371e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 372e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (!mIsOpen) { 373e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown closeConnectionAndLogExceptionsLocked(connection); 374e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else if (connection.isPrimaryConnection()) { 375559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown if (recycleConnectionLocked(connection, status)) { 376559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown assert mAvailablePrimaryConnection == null; 377e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mAvailablePrimaryConnection = connection; 378e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 379e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown wakeConnectionWaitersLocked(); 38047847f3f4dcf2a0dbea0bc0e4f02528e21d37a88Jeff Brown } else if (mAvailableNonPrimaryConnections.size() >= mMaxConnectionPoolSize - 1) { 381e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown closeConnectionAndLogExceptionsLocked(connection); 382e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else { 383559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown if (recycleConnectionLocked(connection, status)) { 384e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mAvailableNonPrimaryConnections.add(connection); 385e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 386e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown wakeConnectionWaitersLocked(); 387e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 388e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 389e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 390e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 391559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown // Can't throw. 392559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown private boolean recycleConnectionLocked(SQLiteConnection connection, 393559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown AcquiredConnectionStatus status) { 394559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown if (status == AcquiredConnectionStatus.RECONFIGURE) { 395559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown try { 396559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown connection.reconfigure(mConfiguration); // might throw 397559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown } catch (RuntimeException ex) { 398559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown Log.e(TAG, "Failed to reconfigure released connection, closing it: " 399559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown + connection, ex); 400559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown status = AcquiredConnectionStatus.DISCARD; 401559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown } 402559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown } 403559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown if (status == AcquiredConnectionStatus.DISCARD) { 404559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown closeConnectionAndLogExceptionsLocked(connection); 405559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown return false; 406559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown } 407559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown return true; 408559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown } 409559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown 410e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** 411e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Returns true if the session should yield the connection due to 412e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * contention over available database connections. 413e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 414e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param connection The connection owned by the session. 415e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param connectionFlags The connection request flags. 416e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @return True if the session should yield its connection. 417e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 418e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @throws IllegalStateException if the connection was not acquired 419e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * from this pool or if it has already been released. 420e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 421e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public boolean shouldYieldConnection(SQLiteConnection connection, int connectionFlags) { 422e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown synchronized (mLock) { 423e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (!mAcquiredConnections.containsKey(connection)) { 424e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw new IllegalStateException("Cannot perform this operation " 425e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown + "because the specified connection was not acquired " 426e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown + "from this pool or has already been released."); 427e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 428e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 429e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (!mIsOpen) { 430e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return false; 431e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 432e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 433e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return isSessionBlockingImportantConnectionWaitersLocked( 434e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown connection.isPrimaryConnection(), connectionFlags); 435e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 436e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 437e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 438e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** 439e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Collects statistics about database connection memory usage. 440e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 441e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param dbStatsList The list to populate. 442e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 443e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public void collectDbStats(ArrayList<DbStats> dbStatsList) { 444e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown synchronized (mLock) { 445e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (mAvailablePrimaryConnection != null) { 446e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mAvailablePrimaryConnection.collectDbStats(dbStatsList); 447e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 448e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 449e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown for (SQLiteConnection connection : mAvailableNonPrimaryConnections) { 450e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown connection.collectDbStats(dbStatsList); 451e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 452e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 453e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown for (SQLiteConnection connection : mAcquiredConnections.keySet()) { 454e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown connection.collectDbStatsUnsafe(dbStatsList); 455e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 456e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 457e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 458e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 459e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Might throw. 460559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown private SQLiteConnection openConnectionLocked(SQLiteDatabaseConfiguration configuration, 461559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown boolean primaryConnection) { 462e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown final int connectionId = mNextConnectionId++; 463559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown return SQLiteConnection.open(this, configuration, 464e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown connectionId, primaryConnection); // might throw 465e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 466e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 467e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown void onConnectionLeaked() { 468e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // This code is running inside of the SQLiteConnection finalizer. 469e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // 470e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // We don't know whether it is just the connection that has been finalized (and leaked) 471e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // or whether the connection pool has also been or is about to be finalized. 472e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Consequently, it would be a bad idea to try to grab any locks or to 473e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // do any significant work here. So we do the simplest possible thing and 474e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // set a flag. waitForConnection() periodically checks this flag (when it 475e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // times out) so that it can recover from leaked connections and wake 476e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // itself or other threads up if necessary. 477e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // 478e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // You might still wonder why we don't try to do more to wake up the waiters 479e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // immediately. First, as explained above, it would be hard to do safely 480e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // unless we started an extra Thread to function as a reference queue. Second, 481e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // this is never supposed to happen in normal operation. Third, there is no 482e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // guarantee that the GC will actually detect the leak in a timely manner so 483e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // it's not all that important that we recover from the leak in a timely manner 484e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // either. Fourth, if a badly behaved application finds itself hung waiting for 485e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // several seconds while waiting for a leaked connection to be detected and recreated, 486e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // then perhaps its authors will have added incentive to fix the problem! 487e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 488e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown Log.w(TAG, "A SQLiteConnection object for database '" 489e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown + mConfiguration.label + "' was leaked! Please fix your application " 490e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown + "to end transactions in progress properly and to close the database " 491e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown + "when it is no longer needed."); 492e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 493e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mConnectionLeaked.set(true); 494e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 495e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 496e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Can't throw. 497559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown private void closeAvailableConnectionsAndLogExceptionsLocked() { 498e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fcJeff Brown closeAvailableNonPrimaryConnectionsAndLogExceptionsLocked(); 499559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown 500559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown if (mAvailablePrimaryConnection != null) { 501559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown closeConnectionAndLogExceptionsLocked(mAvailablePrimaryConnection); 502559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown mAvailablePrimaryConnection = null; 503559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown } 504559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown } 505559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown 506559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown // Can't throw. 507e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fcJeff Brown private void closeAvailableNonPrimaryConnectionsAndLogExceptionsLocked() { 508e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fcJeff Brown final int count = mAvailableNonPrimaryConnections.size(); 509e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fcJeff Brown for (int i = 0; i < count; i++) { 510e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fcJeff Brown closeConnectionAndLogExceptionsLocked(mAvailableNonPrimaryConnections.get(i)); 511e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fcJeff Brown } 512e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fcJeff Brown mAvailableNonPrimaryConnections.clear(); 513e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fcJeff Brown } 514e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fcJeff Brown 515e67ca420e4eb6ddf8ceefeb0d9dcc47d9ca189fcJeff Brown // Can't throw. 516559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown private void closeExcessConnectionsAndLogExceptionsLocked() { 517559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown int availableCount = mAvailableNonPrimaryConnections.size(); 51847847f3f4dcf2a0dbea0bc0e4f02528e21d37a88Jeff Brown while (availableCount-- > mMaxConnectionPoolSize - 1) { 519559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown SQLiteConnection connection = 520559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown mAvailableNonPrimaryConnections.remove(availableCount); 521559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown closeConnectionAndLogExceptionsLocked(connection); 522559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown } 523559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown } 524559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown 525559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown // Can't throw. 526e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private void closeConnectionAndLogExceptionsLocked(SQLiteConnection connection) { 527e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown try { 528e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown connection.close(); // might throw 529e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } catch (RuntimeException ex) { 530e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown Log.e(TAG, "Failed to close connection, its fate is now in the hands " 531e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown + "of the merciful GC: " + connection, ex); 532e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 533e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 534e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 535e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Can't throw. 536559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown private void discardAcquiredConnectionsLocked() { 537559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown markAcquiredConnectionsLocked(AcquiredConnectionStatus.DISCARD); 538559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown } 539559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown 540559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown // Can't throw. 541e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private void reconfigureAllConnectionsLocked() { 542e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (mAvailablePrimaryConnection != null) { 543e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown try { 544e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mAvailablePrimaryConnection.reconfigure(mConfiguration); // might throw 545e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } catch (RuntimeException ex) { 546e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown Log.e(TAG, "Failed to reconfigure available primary connection, closing it: " 547e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown + mAvailablePrimaryConnection, ex); 548e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown closeConnectionAndLogExceptionsLocked(mAvailablePrimaryConnection); 549e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mAvailablePrimaryConnection = null; 550e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 551e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 552e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 553e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int count = mAvailableNonPrimaryConnections.size(); 554e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown for (int i = 0; i < count; i++) { 555e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown final SQLiteConnection connection = mAvailableNonPrimaryConnections.get(i); 556e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown try { 557e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown connection.reconfigure(mConfiguration); // might throw 558e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } catch (RuntimeException ex) { 559e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown Log.e(TAG, "Failed to reconfigure available non-primary connection, closing it: " 560e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown + connection, ex); 561e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown closeConnectionAndLogExceptionsLocked(connection); 562e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mAvailableNonPrimaryConnections.remove(i--); 563e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown count -= 1; 564e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 565e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 566e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 567559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown markAcquiredConnectionsLocked(AcquiredConnectionStatus.RECONFIGURE); 568559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown } 569559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown 570559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown // Can't throw. 571559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown private void markAcquiredConnectionsLocked(AcquiredConnectionStatus status) { 572e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (!mAcquiredConnections.isEmpty()) { 573e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown ArrayList<SQLiteConnection> keysToUpdate = new ArrayList<SQLiteConnection>( 574e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mAcquiredConnections.size()); 575559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown for (Map.Entry<SQLiteConnection, AcquiredConnectionStatus> entry 576559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown : mAcquiredConnections.entrySet()) { 577559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown AcquiredConnectionStatus oldStatus = entry.getValue(); 578559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown if (status != oldStatus 579559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown && oldStatus != AcquiredConnectionStatus.DISCARD) { 580e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown keysToUpdate.add(entry.getKey()); 581e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 582e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 583e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown final int updateCount = keysToUpdate.size(); 584e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown for (int i = 0; i < updateCount; i++) { 585559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown mAcquiredConnections.put(keysToUpdate.get(i), status); 586e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 587e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 588e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 589e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 590e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Might throw. 59175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown private SQLiteConnection waitForConnection(String sql, int connectionFlags, 5924c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown CancellationSignal cancellationSignal) { 593e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown final boolean wantPrimaryConnection = 594e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown (connectionFlags & CONNECTION_FLAG_PRIMARY_CONNECTION_AFFINITY) != 0; 595e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 596e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown final ConnectionWaiter waiter; 597aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown final int nonce; 598e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown synchronized (mLock) { 599e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throwIfClosedLocked(); 600e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 60175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown // Abort if canceled. 6024c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown if (cancellationSignal != null) { 6034c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown cancellationSignal.throwIfCanceled(); 60475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 60575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 606e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Try to acquire a connection. 607e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteConnection connection = null; 608e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (!wantPrimaryConnection) { 609e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown connection = tryAcquireNonPrimaryConnectionLocked( 610e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sql, connectionFlags); // might throw 611e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 612e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (connection == null) { 613e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown connection = tryAcquirePrimaryConnectionLocked(connectionFlags); // might throw 614e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 615e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (connection != null) { 616e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return connection; 617e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 618e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 619e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // No connections available. Enqueue a waiter in priority order. 620e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown final int priority = getPriority(connectionFlags); 621e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown final long startTime = SystemClock.uptimeMillis(); 622e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown waiter = obtainConnectionWaiterLocked(Thread.currentThread(), startTime, 623e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown priority, wantPrimaryConnection, sql, connectionFlags); 624e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown ConnectionWaiter predecessor = null; 625e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown ConnectionWaiter successor = mConnectionWaiterQueue; 626e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown while (successor != null) { 627e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (priority > successor.mPriority) { 628e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown waiter.mNext = successor; 629e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown break; 630e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 631e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown predecessor = successor; 632e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown successor = successor.mNext; 633e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 634e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (predecessor != null) { 635e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown predecessor.mNext = waiter; 636e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else { 637e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mConnectionWaiterQueue = waiter; 638e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 63975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 640aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown nonce = waiter.mNonce; 641aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } 642aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown 643aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown // Set up the cancellation listener. 644aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown if (cancellationSignal != null) { 645aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown cancellationSignal.setOnCancelListener(new CancellationSignal.OnCancelListener() { 646aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown @Override 647aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown public void onCancel() { 648aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown synchronized (mLock) { 649aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown if (waiter.mNonce == nonce) { 650aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown cancelConnectionWaiterLocked(waiter); 65175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 65275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 653aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } 654aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown }); 655e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 656aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown try { 657aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown // Park the thread until a connection is assigned or the pool is closed. 658aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown // Rethrow an exception from the wait, if we got one. 659aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown long busyTimeoutMillis = CONNECTION_POOL_BUSY_MILLIS; 660aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown long nextBusyTimeoutTime = waiter.mStartTime + busyTimeoutMillis; 661aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown for (;;) { 662aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown // Detect and recover from connection leaks. 663aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown if (mConnectionLeaked.compareAndSet(true, false)) { 664aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown synchronized (mLock) { 665aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown wakeConnectionWaitersLocked(); 666aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } 66775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 668e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 669aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown // Wait to be unparked (may already have happened), a timeout, or interruption. 670aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown LockSupport.parkNanos(this, busyTimeoutMillis * 1000000L); 671e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 672aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown // Clear the interrupted flag, just in case. 673aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown Thread.interrupted(); 674e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 675aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown // Check whether we are done waiting yet. 676aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown synchronized (mLock) { 677aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown throwIfClosedLocked(); 678aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown 679aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown final SQLiteConnection connection = waiter.mAssignedConnection; 680aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown final RuntimeException ex = waiter.mException; 681aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown if (connection != null || ex != null) { 682aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown recycleConnectionWaiterLocked(waiter); 683aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown if (connection != null) { 684aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown return connection; 685aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } 686aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown throw ex; // rethrow! 68775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 688e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 689aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown final long now = SystemClock.uptimeMillis(); 690aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown if (now < nextBusyTimeoutTime) { 691aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown busyTimeoutMillis = now - nextBusyTimeoutTime; 692aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } else { 693aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown logConnectionPoolBusyLocked(now - waiter.mStartTime, connectionFlags); 694aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown busyTimeoutMillis = CONNECTION_POOL_BUSY_MILLIS; 695aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown nextBusyTimeoutTime = now + busyTimeoutMillis; 696aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } 697e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 698e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 699aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } finally { 700aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown // Remove the cancellation listener. 701aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown if (cancellationSignal != null) { 702aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown cancellationSignal.setOnCancelListener(null); 703aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown } 704e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 705e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 706e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 707e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Can't throw. 708aeee2f5d7564614da7b5e1aedb8816fc6559b2e9Jeff Brown private void cancelConnectionWaiterLocked(ConnectionWaiter waiter) { 70975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown if (waiter.mAssignedConnection != null || waiter.mException != null) { 71075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown // Waiter is done waiting but has not woken up yet. 71175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown return; 71275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 71375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 71475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown // Waiter must still be waiting. Dequeue it. 71575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown ConnectionWaiter predecessor = null; 71675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown ConnectionWaiter current = mConnectionWaiterQueue; 71775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown while (current != waiter) { 71875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown assert current != null; 71975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown predecessor = current; 72075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown current = current.mNext; 72175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 72275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown if (predecessor != null) { 72375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown predecessor.mNext = waiter.mNext; 72475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } else { 72575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown mConnectionWaiterQueue = waiter.mNext; 72675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 72775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 72875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown // Send the waiter an exception and unpark it. 72975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown waiter.mException = new OperationCanceledException(); 73075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown LockSupport.unpark(waiter.mThread); 73175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 73275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown // Check whether removing this waiter will enable other waiters to make progress. 73375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown wakeConnectionWaitersLocked(); 73475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 73575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 73675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown // Can't throw. 737e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private void logConnectionPoolBusyLocked(long waitMillis, int connectionFlags) { 738e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown final Thread thread = Thread.currentThread(); 739e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown StringBuilder msg = new StringBuilder(); 740e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown msg.append("The connection pool for database '").append(mConfiguration.label); 741e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown msg.append("' has been unable to grant a connection to thread "); 742e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown msg.append(thread.getId()).append(" (").append(thread.getName()).append(") "); 743e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown msg.append("with flags 0x").append(Integer.toHexString(connectionFlags)); 744e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown msg.append(" for ").append(waitMillis * 0.001f).append(" seconds.\n"); 745e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 746e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown ArrayList<String> requests = new ArrayList<String>(); 747e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int activeConnections = 0; 748e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int idleConnections = 0; 749e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (!mAcquiredConnections.isEmpty()) { 750559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown for (SQLiteConnection connection : mAcquiredConnections.keySet()) { 751e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown String description = connection.describeCurrentOperationUnsafe(); 752e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (description != null) { 753e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown requests.add(description); 754e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown activeConnections += 1; 755e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else { 756e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown idleConnections += 1; 757e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 758e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 759e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 760e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int availableConnections = mAvailableNonPrimaryConnections.size(); 761e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (mAvailablePrimaryConnection != null) { 762e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown availableConnections += 1; 763e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 764e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 765e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown msg.append("Connections: ").append(activeConnections).append(" active, "); 766e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown msg.append(idleConnections).append(" idle, "); 767e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown msg.append(availableConnections).append(" available.\n"); 768e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 769e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (!requests.isEmpty()) { 770e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown msg.append("\nRequests in progress:\n"); 771e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown for (String request : requests) { 772e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown msg.append(" ").append(request).append("\n"); 773e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 774e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 775e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 776e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown Log.w(TAG, msg.toString()); 777e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 778e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 779e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Can't throw. 780e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private void wakeConnectionWaitersLocked() { 781e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Unpark all waiters that have requests that we can fulfill. 782e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // This method is designed to not throw runtime exceptions, although we might send 783e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // a waiter an exception for it to rethrow. 784e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown ConnectionWaiter predecessor = null; 785e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown ConnectionWaiter waiter = mConnectionWaiterQueue; 786e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown boolean primaryConnectionNotAvailable = false; 787e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown boolean nonPrimaryConnectionNotAvailable = false; 788e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown while (waiter != null) { 789e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown boolean unpark = false; 790e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (!mIsOpen) { 791e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown unpark = true; 792e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else { 793e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown try { 794e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteConnection connection = null; 795e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (!waiter.mWantPrimaryConnection && !nonPrimaryConnectionNotAvailable) { 796e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown connection = tryAcquireNonPrimaryConnectionLocked( 797e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown waiter.mSql, waiter.mConnectionFlags); // might throw 798e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (connection == null) { 799e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown nonPrimaryConnectionNotAvailable = true; 800e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 801e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 802e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (connection == null && !primaryConnectionNotAvailable) { 803e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown connection = tryAcquirePrimaryConnectionLocked( 804e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown waiter.mConnectionFlags); // might throw 805e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (connection == null) { 806e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown primaryConnectionNotAvailable = true; 807e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 808e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 809e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (connection != null) { 810e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown waiter.mAssignedConnection = connection; 811e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown unpark = true; 812e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else if (nonPrimaryConnectionNotAvailable && primaryConnectionNotAvailable) { 813e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // There are no connections available and the pool is still open. 814e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // We cannot fulfill any more connection requests, so stop here. 815e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown break; 816e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 817e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } catch (RuntimeException ex) { 818e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Let the waiter handle the exception from acquiring a connection. 819e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown waiter.mException = ex; 820e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown unpark = true; 821e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 822e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 823e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 824e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown final ConnectionWaiter successor = waiter.mNext; 825e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (unpark) { 826e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (predecessor != null) { 827e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown predecessor.mNext = successor; 828e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else { 829e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mConnectionWaiterQueue = successor; 830e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 831e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown waiter.mNext = null; 832e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 833e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown LockSupport.unpark(waiter.mThread); 834e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else { 835e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown predecessor = waiter; 836e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 837e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown waiter = successor; 838e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 839e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 840e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 841e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Might throw. 842e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private SQLiteConnection tryAcquirePrimaryConnectionLocked(int connectionFlags) { 843e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // If the primary connection is available, acquire it now. 844e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteConnection connection = mAvailablePrimaryConnection; 845e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (connection != null) { 846e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mAvailablePrimaryConnection = null; 847e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown finishAcquireConnectionLocked(connection, connectionFlags); // might throw 848e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return connection; 849e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 850e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 851e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Make sure that the primary connection actually exists and has just been acquired. 852e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown for (SQLiteConnection acquiredConnection : mAcquiredConnections.keySet()) { 853e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (acquiredConnection.isPrimaryConnection()) { 854e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return null; 855e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 856e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 857e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 858e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Uhoh. No primary connection! Either this is the first time we asked 859e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // for it, or maybe it leaked? 860559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown connection = openConnectionLocked(mConfiguration, 861559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown true /*primaryConnection*/); // might throw 862e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown finishAcquireConnectionLocked(connection, connectionFlags); // might throw 863e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return connection; 864e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 865e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 866e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Might throw. 867e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private SQLiteConnection tryAcquireNonPrimaryConnectionLocked( 868e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown String sql, int connectionFlags) { 869e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Try to acquire the next connection in the queue. 870e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteConnection connection; 871e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown final int availableCount = mAvailableNonPrimaryConnections.size(); 872e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (availableCount > 1 && sql != null) { 873e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // If we have a choice, then prefer a connection that has the 874e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // prepared statement in its cache. 875e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown for (int i = 0; i < availableCount; i++) { 876e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown connection = mAvailableNonPrimaryConnections.get(i); 877e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (connection.isPreparedStatementInCache(sql)) { 878e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mAvailableNonPrimaryConnections.remove(i); 879e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown finishAcquireConnectionLocked(connection, connectionFlags); // might throw 880e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return connection; 881e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 882e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 883e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 884e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (availableCount > 0) { 885e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Otherwise, just grab the next one. 886e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown connection = mAvailableNonPrimaryConnections.remove(availableCount - 1); 887e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown finishAcquireConnectionLocked(connection, connectionFlags); // might throw 888e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return connection; 889e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 890e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 891e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Expand the pool if needed. 892e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int openConnections = mAcquiredConnections.size(); 893e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (mAvailablePrimaryConnection != null) { 894e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown openConnections += 1; 895e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 89647847f3f4dcf2a0dbea0bc0e4f02528e21d37a88Jeff Brown if (openConnections >= mMaxConnectionPoolSize) { 897e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return null; 898e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 899559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown connection = openConnectionLocked(mConfiguration, 900559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown false /*primaryConnection*/); // might throw 901e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown finishAcquireConnectionLocked(connection, connectionFlags); // might throw 902e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return connection; 903e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 904e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 905e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Might throw. 906e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private void finishAcquireConnectionLocked(SQLiteConnection connection, int connectionFlags) { 907e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown try { 908e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown final boolean readOnly = (connectionFlags & CONNECTION_FLAG_READ_ONLY) != 0; 909e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown connection.setOnlyAllowReadOnlyOperations(readOnly); 910e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 911559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown mAcquiredConnections.put(connection, AcquiredConnectionStatus.NORMAL); 912e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } catch (RuntimeException ex) { 913e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown Log.e(TAG, "Failed to prepare acquired connection for session, closing it: " 914e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown + connection +", connectionFlags=" + connectionFlags); 915e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown closeConnectionAndLogExceptionsLocked(connection); 916e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw ex; // rethrow! 917e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 918e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 919e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 920e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private boolean isSessionBlockingImportantConnectionWaitersLocked( 921e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown boolean holdingPrimaryConnection, int connectionFlags) { 922e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown ConnectionWaiter waiter = mConnectionWaiterQueue; 923e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (waiter != null) { 924e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown final int priority = getPriority(connectionFlags); 925e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown do { 926e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Only worry about blocked connections that have same or lower priority. 927e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (priority > waiter.mPriority) { 928e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown break; 929e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 930e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 931e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // If we are holding the primary connection then we are blocking the waiter. 932e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Likewise, if we are holding a non-primary connection and the waiter 933e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // would accept a non-primary connection, then we are blocking the waier. 934e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (holdingPrimaryConnection || !waiter.mWantPrimaryConnection) { 935e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return true; 936e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 937e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 938e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown waiter = waiter.mNext; 939e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } while (waiter != null); 940e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 941e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return false; 942e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 943e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 944e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private static int getPriority(int connectionFlags) { 945e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return (connectionFlags & CONNECTION_FLAG_INTERACTIVE) != 0 ? 1 : 0; 946e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 947e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 94847847f3f4dcf2a0dbea0bc0e4f02528e21d37a88Jeff Brown private void setMaxConnectionPoolSizeLocked() { 94947847f3f4dcf2a0dbea0bc0e4f02528e21d37a88Jeff Brown if ((mConfiguration.openFlags & SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0) { 95047847f3f4dcf2a0dbea0bc0e4f02528e21d37a88Jeff Brown mMaxConnectionPoolSize = SQLiteGlobal.getWALConnectionPoolSize(); 95147847f3f4dcf2a0dbea0bc0e4f02528e21d37a88Jeff Brown } else { 95247847f3f4dcf2a0dbea0bc0e4f02528e21d37a88Jeff Brown // TODO: We don't actually need to restrict the connection pool size to 1 95347847f3f4dcf2a0dbea0bc0e4f02528e21d37a88Jeff Brown // for non-WAL databases. There might be reasons to use connection pooling 95447847f3f4dcf2a0dbea0bc0e4f02528e21d37a88Jeff Brown // with other journal modes. For now, enabling connection pooling and 95547847f3f4dcf2a0dbea0bc0e4f02528e21d37a88Jeff Brown // using WAL are the same thing in the API. 95647847f3f4dcf2a0dbea0bc0e4f02528e21d37a88Jeff Brown mMaxConnectionPoolSize = 1; 95747847f3f4dcf2a0dbea0bc0e4f02528e21d37a88Jeff Brown } 95847847f3f4dcf2a0dbea0bc0e4f02528e21d37a88Jeff Brown } 95947847f3f4dcf2a0dbea0bc0e4f02528e21d37a88Jeff Brown 960e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private void throwIfClosedLocked() { 961e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (!mIsOpen) { 962e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw new IllegalStateException("Cannot perform this operation " 963559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown + "because the connection pool has been closed."); 964e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 965e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 966e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 967e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private ConnectionWaiter obtainConnectionWaiterLocked(Thread thread, long startTime, 968e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int priority, boolean wantPrimaryConnection, String sql, int connectionFlags) { 969e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown ConnectionWaiter waiter = mConnectionWaiterPool; 970e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (waiter != null) { 971e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mConnectionWaiterPool = waiter.mNext; 972e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown waiter.mNext = null; 973e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else { 974e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown waiter = new ConnectionWaiter(); 975e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 976e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown waiter.mThread = thread; 977e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown waiter.mStartTime = startTime; 978e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown waiter.mPriority = priority; 979e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown waiter.mWantPrimaryConnection = wantPrimaryConnection; 980e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown waiter.mSql = sql; 981e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown waiter.mConnectionFlags = connectionFlags; 982e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return waiter; 983e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 984e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 985e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private void recycleConnectionWaiterLocked(ConnectionWaiter waiter) { 986e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown waiter.mNext = mConnectionWaiterPool; 987e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown waiter.mThread = null; 988e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown waiter.mSql = null; 989e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown waiter.mAssignedConnection = null; 990e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown waiter.mException = null; 99175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown waiter.mNonce += 1; 992e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mConnectionWaiterPool = waiter; 993e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 994e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 995e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** 996e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Dumps debugging information about this connection pool. 997e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 998e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param printer The printer to receive the dump, not null. 999a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown * @param verbose True to dump more verbose information. 1000e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 1001a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown public void dump(Printer printer, boolean verbose) { 1002e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown Printer indentedPrinter = PrefixPrinter.create(printer, " "); 1003e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown synchronized (mLock) { 1004e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown printer.println("Connection pool for " + mConfiguration.path + ":"); 1005e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown printer.println(" Open: " + mIsOpen); 100647847f3f4dcf2a0dbea0bc0e4f02528e21d37a88Jeff Brown printer.println(" Max connections: " + mMaxConnectionPoolSize); 1007e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 1008e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown printer.println(" Available primary connection:"); 1009e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (mAvailablePrimaryConnection != null) { 1010a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown mAvailablePrimaryConnection.dump(indentedPrinter, verbose); 1011e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else { 1012e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown indentedPrinter.println("<none>"); 1013e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 1014e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 1015e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown printer.println(" Available non-primary connections:"); 1016e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (!mAvailableNonPrimaryConnections.isEmpty()) { 1017e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown final int count = mAvailableNonPrimaryConnections.size(); 1018e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown for (int i = 0; i < count; i++) { 1019a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown mAvailableNonPrimaryConnections.get(i).dump(indentedPrinter, verbose); 1020e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 1021e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else { 1022e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown indentedPrinter.println("<none>"); 1023e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 1024e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 1025e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown printer.println(" Acquired connections:"); 1026e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (!mAcquiredConnections.isEmpty()) { 1027559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown for (Map.Entry<SQLiteConnection, AcquiredConnectionStatus> entry : 1028e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mAcquiredConnections.entrySet()) { 1029e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown final SQLiteConnection connection = entry.getKey(); 1030a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown connection.dumpUnsafe(indentedPrinter, verbose); 1031559d0645ac8f80491671fa5d3c63e8f296f2909eJeff Brown indentedPrinter.println(" Status: " + entry.getValue()); 1032e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 1033e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else { 1034e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown indentedPrinter.println("<none>"); 1035e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 1036e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 1037e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown printer.println(" Connection waiters:"); 1038e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (mConnectionWaiterQueue != null) { 1039e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int i = 0; 1040e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown final long now = SystemClock.uptimeMillis(); 1041e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown for (ConnectionWaiter waiter = mConnectionWaiterQueue; waiter != null; 1042e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown waiter = waiter.mNext, i++) { 1043e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown indentedPrinter.println(i + ": waited for " 1044e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown + ((now - waiter.mStartTime) * 0.001f) 1045e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown + " ms - thread=" + waiter.mThread 1046e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown + ", priority=" + waiter.mPriority 1047e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown + ", sql='" + waiter.mSql + "'"); 1048e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 1049e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else { 1050e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown indentedPrinter.println("<none>"); 1051e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 1052e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 1053e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 1054e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 1055e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown @Override 1056e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public String toString() { 1057e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return "SQLiteConnectionPool: " + mConfiguration.path; 1058e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 1059e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 1060e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private static final class ConnectionWaiter { 1061e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public ConnectionWaiter mNext; 1062e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public Thread mThread; 1063e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public long mStartTime; 1064e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public int mPriority; 1065e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public boolean mWantPrimaryConnection; 1066e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public String mSql; 1067e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public int mConnectionFlags; 1068e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public SQLiteConnection mAssignedConnection; 1069e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public RuntimeException mException; 107075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown public int mNonce; 1071e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 1072e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 1073