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