diff options
author | Jeff Brown <jeffbrown@google.com> | 2012-03-06 13:48:56 -0800 |
---|---|---|
committer | Jeff Brown <jeffbrown@google.com> | 2012-03-06 16:42:56 -0800 |
commit | 03bd302aebbb77f4f95789a269c8a5463ac5a840 (patch) | |
tree | abd49f5d5e379f75c9cab050b7426e492884e542 /core/java/android | |
parent | b4827c089fc0aec49a73cc32cd18d2ce4d627c5a (diff) | |
download | frameworks_base-03bd302aebbb77f4f95789a269c8a5463ac5a840.zip frameworks_base-03bd302aebbb77f4f95789a269c8a5463ac5a840.tar.gz frameworks_base-03bd302aebbb77f4f95789a269c8a5463ac5a840.tar.bz2 |
Don't close the database until all references released.
SQLiteDatabase.close() should call releaseReference() rather than
closing the database immediately. SQLiteDatabase should also hold
a reference to itself while performing certain operations to
ensure that they complete normally even if another thread closes
the database at the same time.
Fixed a couple of missing or redundant uses of acquireReference()
related to CursorWindows.
To be honest, the reference counting performed by SQLiteClosable should
not be needed, but we're stuck with it in the API.
Bug: 6104842
Change-Id: I3444a697409905d4a36b56418dc7766f5ba76b59
Diffstat (limited to 'core/java/android')
-rw-r--r-- | core/java/android/database/Cursor.java | 4 | ||||
-rw-r--r-- | core/java/android/database/CursorWindow.java | 17 | ||||
-rw-r--r-- | core/java/android/database/DatabaseUtils.java | 97 | ||||
-rw-r--r-- | core/java/android/database/sqlite/SQLiteClosable.java | 55 | ||||
-rw-r--r-- | core/java/android/database/sqlite/SQLiteConnection.java | 65 | ||||
-rw-r--r-- | core/java/android/database/sqlite/SQLiteDatabase.java | 354 | ||||
-rw-r--r-- | core/java/android/database/sqlite/SQLiteProgram.java | 7 |
7 files changed, 350 insertions, 249 deletions
diff --git a/core/java/android/database/Cursor.java b/core/java/android/database/Cursor.java index 59ec89d..907833d 100644 --- a/core/java/android/database/Cursor.java +++ b/core/java/android/database/Cursor.java @@ -20,6 +20,8 @@ import android.content.ContentResolver; import android.net.Uri; import android.os.Bundle; +import java.io.Closeable; + /** * This interface provides random read-write access to the result set returned * by a database query. @@ -27,7 +29,7 @@ import android.os.Bundle; * Cursor implementations are not required to be synchronized so code using a Cursor from multiple * threads should perform its own synchronization when using the Cursor. */ -public interface Cursor { +public interface Cursor extends Closeable { /* * Values returned by {@link #getType(int)}. * These should be consistent with the corresponding types defined in CursorWindow.h diff --git a/core/java/android/database/CursorWindow.java b/core/java/android/database/CursorWindow.java index 85f570c..f1f3017 100644 --- a/core/java/android/database/CursorWindow.java +++ b/core/java/android/database/CursorWindow.java @@ -169,14 +169,6 @@ public class CursorWindow extends SQLiteClosable implements Parcelable { } /** - * Closes the cursor window and frees its underlying resources when all other - * remaining references have been released. - */ - public void close() { - releaseReference(); - } - - /** * Clears out the existing contents of the window, making it safe to reuse * for new data. * <p> @@ -703,8 +695,13 @@ public class CursorWindow extends SQLiteClosable implements Parcelable { } public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(mStartPos); - nativeWriteToParcel(mWindowPtr, dest); + acquireReference(); + try { + dest.writeInt(mStartPos); + nativeWriteToParcel(mWindowPtr, dest); + } finally { + releaseReference(); + } if ((flags & Parcelable.PARCELABLE_WRITE_RETURN_VALUE) != 0) { releaseReference(); diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java index 0022118..99d260e 100644 --- a/core/java/android/database/DatabaseUtils.java +++ b/core/java/android/database/DatabaseUtils.java @@ -269,63 +269,56 @@ public class DatabaseUtils { if (position < 0 || position >= cursor.getCount()) { return; } - window.acquireReference(); - try { - final int oldPos = cursor.getPosition(); - final int numColumns = cursor.getColumnCount(); - window.clear(); - window.setStartPosition(position); - window.setNumColumns(numColumns); - if (cursor.moveToPosition(position)) { - do { - if (!window.allocRow()) { - break; - } - for (int i = 0; i < numColumns; i++) { - final int type = cursor.getType(i); - final boolean success; - switch (type) { - case Cursor.FIELD_TYPE_NULL: - success = window.putNull(position, i); - break; - - case Cursor.FIELD_TYPE_INTEGER: - success = window.putLong(cursor.getLong(i), position, i); - break; - - case Cursor.FIELD_TYPE_FLOAT: - success = window.putDouble(cursor.getDouble(i), position, i); - break; - - case Cursor.FIELD_TYPE_BLOB: { - final byte[] value = cursor.getBlob(i); - success = value != null ? window.putBlob(value, position, i) - : window.putNull(position, i); - break; - } - - default: // assume value is convertible to String - case Cursor.FIELD_TYPE_STRING: { - final String value = cursor.getString(i); - success = value != null ? window.putString(value, position, i) - : window.putNull(position, i); - break; - } + final int oldPos = cursor.getPosition(); + final int numColumns = cursor.getColumnCount(); + window.clear(); + window.setStartPosition(position); + window.setNumColumns(numColumns); + if (cursor.moveToPosition(position)) { + do { + if (!window.allocRow()) { + break; + } + for (int i = 0; i < numColumns; i++) { + final int type = cursor.getType(i); + final boolean success; + switch (type) { + case Cursor.FIELD_TYPE_NULL: + success = window.putNull(position, i); + break; + + case Cursor.FIELD_TYPE_INTEGER: + success = window.putLong(cursor.getLong(i), position, i); + break; + + case Cursor.FIELD_TYPE_FLOAT: + success = window.putDouble(cursor.getDouble(i), position, i); + break; + + case Cursor.FIELD_TYPE_BLOB: { + final byte[] value = cursor.getBlob(i); + success = value != null ? window.putBlob(value, position, i) + : window.putNull(position, i); + break; } - if (!success) { - window.freeLastRow(); + + default: // assume value is convertible to String + case Cursor.FIELD_TYPE_STRING: { + final String value = cursor.getString(i); + success = value != null ? window.putString(value, position, i) + : window.putNull(position, i); break; } } - position += 1; - } while (cursor.moveToNext()); - } - cursor.moveToPosition(oldPos); - } catch (IllegalStateException e){ - // simply ignore it - } finally { - window.releaseReference(); + if (!success) { + window.freeLastRow(); + break; + } + } + position += 1; + } while (cursor.moveToNext()); } + cursor.moveToPosition(oldPos); } /** diff --git a/core/java/android/database/sqlite/SQLiteClosable.java b/core/java/android/database/sqlite/SQLiteClosable.java index 7e91a7b..adfbc6e 100644 --- a/core/java/android/database/sqlite/SQLiteClosable.java +++ b/core/java/android/database/sqlite/SQLiteClosable.java @@ -16,15 +16,39 @@ package android.database.sqlite; +import java.io.Closeable; + /** * An object created from a SQLiteDatabase that can be closed. + * + * This class implements a primitive reference counting scheme for database objects. */ -public abstract class SQLiteClosable { +public abstract class SQLiteClosable implements Closeable { private int mReferenceCount = 1; + /** + * Called when the last reference to the object was released by + * a call to {@link #releaseReference()} or {@link #close()}. + */ protected abstract void onAllReferencesReleased(); - protected void onAllReferencesReleasedFromContainer() {} + /** + * Called when the last reference to the object was released by + * a call to {@link #releaseReferenceFromContainer()}. + * + * @deprecated Do not use. + */ + @Deprecated + protected void onAllReferencesReleasedFromContainer() { + onAllReferencesReleased(); + } + + /** + * Acquires a reference to the object. + * + * @throws IllegalStateException if the last reference to the object has already + * been released. + */ public void acquireReference() { synchronized(this) { if (mReferenceCount <= 0) { @@ -35,6 +59,12 @@ public abstract class SQLiteClosable { } } + /** + * Releases a reference to the object, closing the object if the last reference + * was released. + * + * @see #onAllReferencesReleased() + */ public void releaseReference() { boolean refCountIsZero = false; synchronized(this) { @@ -45,6 +75,14 @@ public abstract class SQLiteClosable { } } + /** + * Releases a reference to the object that was owned by the container of the object, + * closing the object if the last reference was released. + * + * @see #onAllReferencesReleasedFromContainer() + * @deprecated Do not use. + */ + @Deprecated public void releaseReferenceFromContainer() { boolean refCountIsZero = false; synchronized(this) { @@ -54,4 +92,17 @@ public abstract class SQLiteClosable { onAllReferencesReleasedFromContainer(); } } + + /** + * Releases a reference to the object, closing the object if the last reference + * was released. + * + * Calling this method is equivalent to calling {@link #releaseReference}. + * + * @see #releaseReference() + * @see #onAllReferencesReleased() + */ + public void close() { + releaseReference(); + } } diff --git a/core/java/android/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java index d16f29f..0db3e4f 100644 --- a/core/java/android/database/sqlite/SQLiteConnection.java +++ b/core/java/android/database/sqlite/SQLiteConnection.java @@ -704,44 +704,49 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen throw new IllegalArgumentException("window must not be null."); } - int actualPos = -1; - int countedRows = -1; - int filledRows = -1; - final int cookie = mRecentOperations.beginOperation("executeForCursorWindow", - sql, bindArgs); + window.acquireReference(); try { - final PreparedStatement statement = acquirePreparedStatement(sql); + int actualPos = -1; + int countedRows = -1; + int filledRows = -1; + final int cookie = mRecentOperations.beginOperation("executeForCursorWindow", + sql, bindArgs); try { - throwIfStatementForbidden(statement); - bindArguments(statement, bindArgs); - applyBlockGuardPolicy(statement); - attachCancellationSignal(cancellationSignal); + final PreparedStatement statement = acquirePreparedStatement(sql); try { - final long result = nativeExecuteForCursorWindow( - mConnectionPtr, statement.mStatementPtr, window.mWindowPtr, - startPos, requiredPos, countAllRows); - actualPos = (int)(result >> 32); - countedRows = (int)result; - filledRows = window.getNumRows(); - window.setStartPosition(actualPos); - return countedRows; + throwIfStatementForbidden(statement); + bindArguments(statement, bindArgs); + applyBlockGuardPolicy(statement); + attachCancellationSignal(cancellationSignal); + try { + final long result = nativeExecuteForCursorWindow( + mConnectionPtr, statement.mStatementPtr, window.mWindowPtr, + startPos, requiredPos, countAllRows); + actualPos = (int)(result >> 32); + countedRows = (int)result; + filledRows = window.getNumRows(); + window.setStartPosition(actualPos); + return countedRows; + } finally { + detachCancellationSignal(cancellationSignal); + } } finally { - detachCancellationSignal(cancellationSignal); + releasePreparedStatement(statement); } + } catch (RuntimeException ex) { + mRecentOperations.failOperation(cookie, ex); + throw ex; } finally { - releasePreparedStatement(statement); + if (mRecentOperations.endOperationDeferLog(cookie)) { + mRecentOperations.logOperation(cookie, "window='" + window + + "', startPos=" + startPos + + ", actualPos=" + actualPos + + ", filledRows=" + filledRows + + ", countedRows=" + countedRows); + } } - } catch (RuntimeException ex) { - mRecentOperations.failOperation(cookie, ex); - throw ex; } finally { - if (mRecentOperations.endOperationDeferLog(cookie)) { - mRecentOperations.logOperation(cookie, "window='" + window - + "', startPos=" + startPos - + ", actualPos=" + actualPos - + ", filledRows=" + filledRows - + ", countedRows=" + countedRows); - } + window.releaseReference(); } } diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java index 604247e..d41b484 100644 --- a/core/java/android/database/sqlite/SQLiteDatabase.java +++ b/core/java/android/database/sqlite/SQLiteDatabase.java @@ -492,9 +492,16 @@ public final class SQLiteDatabase extends SQLiteClosable { private void beginTransaction(SQLiteTransactionListener transactionListener, boolean exclusive) { - getThreadSession().beginTransaction(exclusive ? SQLiteSession.TRANSACTION_MODE_EXCLUSIVE : - SQLiteSession.TRANSACTION_MODE_IMMEDIATE, transactionListener, - getThreadDefaultConnectionFlags(false /*readOnly*/), null); + acquireReference(); + try { + getThreadSession().beginTransaction( + exclusive ? SQLiteSession.TRANSACTION_MODE_EXCLUSIVE : + SQLiteSession.TRANSACTION_MODE_IMMEDIATE, + transactionListener, + getThreadDefaultConnectionFlags(false /*readOnly*/), null); + } finally { + releaseReference(); + } } /** @@ -502,7 +509,12 @@ public final class SQLiteDatabase extends SQLiteClosable { * are committed and rolled back. */ public void endTransaction() { - getThreadSession().endTransaction(null); + acquireReference(); + try { + getThreadSession().endTransaction(null); + } finally { + releaseReference(); + } } /** @@ -515,7 +527,12 @@ public final class SQLiteDatabase extends SQLiteClosable { * transaction is already marked as successful. */ public void setTransactionSuccessful() { - getThreadSession().setTransactionSuccessful(); + acquireReference(); + try { + getThreadSession().setTransactionSuccessful(); + } finally { + releaseReference(); + } } /** @@ -524,7 +541,12 @@ public final class SQLiteDatabase extends SQLiteClosable { * @return True if the current thread is in a transaction. */ public boolean inTransaction() { - return getThreadSession().hasTransaction(); + acquireReference(); + try { + return getThreadSession().hasTransaction(); + } finally { + releaseReference(); + } } /** @@ -540,7 +562,12 @@ public final class SQLiteDatabase extends SQLiteClosable { * @return True if the current thread is holding an active connection to the database. */ public boolean isDbLockedByCurrentThread() { - return getThreadSession().hasConnection(); + acquireReference(); + try { + return getThreadSession().hasConnection(); + } finally { + releaseReference(); + } } /** @@ -599,7 +626,12 @@ public final class SQLiteDatabase extends SQLiteClosable { } private boolean yieldIfContendedHelper(boolean throwIfUnsafe, long sleepAfterYieldDelay) { - return getThreadSession().yieldTransaction(sleepAfterYieldDelay, throwIfUnsafe, null); + acquireReference(); + try { + return getThreadSession().yieldTransaction(sleepAfterYieldDelay, throwIfUnsafe, null); + } finally { + releaseReference(); + } } /** @@ -788,13 +820,6 @@ public final class SQLiteDatabase extends SQLiteClosable { } /** - * Close the database. - */ - public void close() { - dispose(false); - } - - /** * Registers a CustomFunction callback as a function that can be called from * SQLite database triggers. * @@ -948,8 +973,12 @@ public final class SQLiteDatabase extends SQLiteClosable { * {@link SQLiteStatement}s are not synchronized, see the documentation for more details. */ public SQLiteStatement compileStatement(String sql) throws SQLException { - throwIfNotOpen(); // fail fast - return new SQLiteStatement(this, sql, null); + acquireReference(); + try { + return new SQLiteStatement(this, sql, null); + } finally { + releaseReference(); + } } /** @@ -1110,12 +1139,16 @@ public final class SQLiteDatabase extends SQLiteClosable { boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit, CancellationSignal cancellationSignal) { - throwIfNotOpen(); // fail fast - String sql = SQLiteQueryBuilder.buildQueryString( - distinct, table, columns, selection, groupBy, having, orderBy, limit); + acquireReference(); + try { + String sql = SQLiteQueryBuilder.buildQueryString( + distinct, table, columns, selection, groupBy, having, orderBy, limit); - return rawQueryWithFactory(cursorFactory, sql, selectionArgs, - findEditTable(table), cancellationSignal); + return rawQueryWithFactory(cursorFactory, sql, selectionArgs, + findEditTable(table), cancellationSignal); + } finally { + releaseReference(); + } } /** @@ -1260,12 +1293,15 @@ public final class SQLiteDatabase extends SQLiteClosable { public Cursor rawQueryWithFactory( CursorFactory cursorFactory, String sql, String[] selectionArgs, String editTable, CancellationSignal cancellationSignal) { - throwIfNotOpen(); // fail fast - - SQLiteCursorDriver driver = new SQLiteDirectCursorDriver(this, sql, editTable, - cancellationSignal); - return driver.query(cursorFactory != null ? cursorFactory : mCursorFactory, - selectionArgs); + acquireReference(); + try { + SQLiteCursorDriver driver = new SQLiteDirectCursorDriver(this, sql, editTable, + cancellationSignal); + return driver.query(cursorFactory != null ? cursorFactory : mCursorFactory, + selectionArgs); + } finally { + releaseReference(); + } } /** @@ -1384,38 +1420,44 @@ public final class SQLiteDatabase extends SQLiteClosable { */ public long insertWithOnConflict(String table, String nullColumnHack, ContentValues initialValues, int conflictAlgorithm) { - StringBuilder sql = new StringBuilder(); - sql.append("INSERT"); - sql.append(CONFLICT_VALUES[conflictAlgorithm]); - sql.append(" INTO "); - sql.append(table); - sql.append('('); - - Object[] bindArgs = null; - int size = (initialValues != null && initialValues.size() > 0) ? initialValues.size() : 0; - if (size > 0) { - bindArgs = new Object[size]; - int i = 0; - for (String colName : initialValues.keySet()) { - sql.append((i > 0) ? "," : ""); - sql.append(colName); - bindArgs[i++] = initialValues.get(colName); + acquireReference(); + try { + StringBuilder sql = new StringBuilder(); + sql.append("INSERT"); + sql.append(CONFLICT_VALUES[conflictAlgorithm]); + sql.append(" INTO "); + sql.append(table); + sql.append('('); + + Object[] bindArgs = null; + int size = (initialValues != null && initialValues.size() > 0) + ? initialValues.size() : 0; + if (size > 0) { + bindArgs = new Object[size]; + int i = 0; + for (String colName : initialValues.keySet()) { + sql.append((i > 0) ? "," : ""); + sql.append(colName); + bindArgs[i++] = initialValues.get(colName); + } + sql.append(')'); + sql.append(" VALUES ("); + for (i = 0; i < size; i++) { + sql.append((i > 0) ? ",?" : "?"); + } + } else { + sql.append(nullColumnHack + ") VALUES (NULL"); } sql.append(')'); - sql.append(" VALUES ("); - for (i = 0; i < size; i++) { - sql.append((i > 0) ? ",?" : "?"); - } - } else { - sql.append(nullColumnHack + ") VALUES (NULL"); - } - sql.append(')'); - SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs); - try { - return statement.executeInsert(); + SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs); + try { + return statement.executeInsert(); + } finally { + statement.close(); + } } finally { - statement.close(); + releaseReference(); } } @@ -1430,12 +1472,17 @@ public final class SQLiteDatabase extends SQLiteClosable { * whereClause. */ public int delete(String table, String whereClause, String[] whereArgs) { - SQLiteStatement statement = new SQLiteStatement(this, "DELETE FROM " + table + - (!TextUtils.isEmpty(whereClause) ? " WHERE " + whereClause : ""), whereArgs); + acquireReference(); try { - return statement.executeUpdateDelete(); + SQLiteStatement statement = new SQLiteStatement(this, "DELETE FROM " + table + + (!TextUtils.isEmpty(whereClause) ? " WHERE " + whereClause : ""), whereArgs); + try { + return statement.executeUpdateDelete(); + } finally { + statement.close(); + } } finally { - statement.close(); + releaseReference(); } } @@ -1470,38 +1517,43 @@ public final class SQLiteDatabase extends SQLiteClosable { throw new IllegalArgumentException("Empty values"); } - StringBuilder sql = new StringBuilder(120); - sql.append("UPDATE "); - sql.append(CONFLICT_VALUES[conflictAlgorithm]); - sql.append(table); - sql.append(" SET "); - - // move all bind args to one array - int setValuesSize = values.size(); - int bindArgsSize = (whereArgs == null) ? setValuesSize : (setValuesSize + whereArgs.length); - Object[] bindArgs = new Object[bindArgsSize]; - int i = 0; - for (String colName : values.keySet()) { - sql.append((i > 0) ? "," : ""); - sql.append(colName); - bindArgs[i++] = values.get(colName); - sql.append("=?"); - } - if (whereArgs != null) { - for (i = setValuesSize; i < bindArgsSize; i++) { - bindArgs[i] = whereArgs[i - setValuesSize]; + acquireReference(); + try { + StringBuilder sql = new StringBuilder(120); + sql.append("UPDATE "); + sql.append(CONFLICT_VALUES[conflictAlgorithm]); + sql.append(table); + sql.append(" SET "); + + // move all bind args to one array + int setValuesSize = values.size(); + int bindArgsSize = (whereArgs == null) ? setValuesSize : (setValuesSize + whereArgs.length); + Object[] bindArgs = new Object[bindArgsSize]; + int i = 0; + for (String colName : values.keySet()) { + sql.append((i > 0) ? "," : ""); + sql.append(colName); + bindArgs[i++] = values.get(colName); + sql.append("=?"); + } + if (whereArgs != null) { + for (i = setValuesSize; i < bindArgsSize; i++) { + bindArgs[i] = whereArgs[i - setValuesSize]; + } + } + if (!TextUtils.isEmpty(whereClause)) { + sql.append(" WHERE "); + sql.append(whereClause); } - } - if (!TextUtils.isEmpty(whereClause)) { - sql.append(" WHERE "); - sql.append(whereClause); - } - SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs); - try { - return statement.executeUpdateDelete(); + SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs); + try { + return statement.executeUpdateDelete(); + } finally { + statement.close(); + } } finally { - statement.close(); + releaseReference(); } } @@ -1579,24 +1631,29 @@ public final class SQLiteDatabase extends SQLiteClosable { } private int executeSql(String sql, Object[] bindArgs) throws SQLException { - if (DatabaseUtils.getSqlStatementType(sql) == DatabaseUtils.STATEMENT_ATTACH) { - boolean disableWal = false; - synchronized (mLock) { - if (!mHasAttachedDbsLocked) { - mHasAttachedDbsLocked = true; - disableWal = true; + acquireReference(); + try { + if (DatabaseUtils.getSqlStatementType(sql) == DatabaseUtils.STATEMENT_ATTACH) { + boolean disableWal = false; + synchronized (mLock) { + if (!mHasAttachedDbsLocked) { + mHasAttachedDbsLocked = true; + disableWal = true; + } + } + if (disableWal) { + disableWriteAheadLogging(); } } - if (disableWal) { - disableWriteAheadLogging(); - } - } - SQLiteStatement statement = new SQLiteStatement(this, sql, bindArgs); - try { - return statement.executeUpdateDelete(); + SQLiteStatement statement = new SQLiteStatement(this, sql, bindArgs); + try { + return statement.executeUpdateDelete(); + } finally { + statement.close(); + } } finally { - statement.close(); + releaseReference(); } } @@ -1881,26 +1938,32 @@ public final class SQLiteDatabase extends SQLiteClosable { attachedDbs.add(new Pair<String, String>("main", mConfigurationLocked.path)); return attachedDbs; } + + acquireReference(); } - // has attached databases. query sqlite to get the list of attached databases. - Cursor c = null; try { - c = rawQuery("pragma database_list;", null); - while (c.moveToNext()) { - // sqlite returns a row for each database in the returned list of databases. - // in each row, - // 1st column is the database name such as main, or the database - // name specified on the "ATTACH" command - // 2nd column is the database file path. - attachedDbs.add(new Pair<String, String>(c.getString(1), c.getString(2))); + // has attached databases. query sqlite to get the list of attached databases. + Cursor c = null; + try { + c = rawQuery("pragma database_list;", null); + while (c.moveToNext()) { + // sqlite returns a row for each database in the returned list of databases. + // in each row, + // 1st column is the database name such as main, or the database + // name specified on the "ATTACH" command + // 2nd column is the database file path. + attachedDbs.add(new Pair<String, String>(c.getString(1), c.getString(2))); + } + } finally { + if (c != null) { + c.close(); + } } + return attachedDbs; } finally { - if (c != null) { - c.close(); - } + releaseReference(); } - return attachedDbs; } /** @@ -1917,35 +1980,38 @@ public final class SQLiteDatabase extends SQLiteClosable { * false otherwise. */ public boolean isDatabaseIntegrityOk() { - throwIfNotOpen(); // fail fast - - List<Pair<String, String>> attachedDbs = null; + acquireReference(); try { - attachedDbs = getAttachedDbs(); - if (attachedDbs == null) { - throw new IllegalStateException("databaselist for: " + getPath() + " couldn't " + - "be retrieved. probably because the database is closed"); + List<Pair<String, String>> attachedDbs = null; + try { + attachedDbs = getAttachedDbs(); + if (attachedDbs == null) { + throw new IllegalStateException("databaselist for: " + getPath() + " couldn't " + + "be retrieved. probably because the database is closed"); + } + } catch (SQLiteException e) { + // can't get attachedDb list. do integrity check on the main database + attachedDbs = new ArrayList<Pair<String, String>>(); + attachedDbs.add(new Pair<String, String>("main", getPath())); } - } catch (SQLiteException e) { - // can't get attachedDb list. do integrity check on the main database - attachedDbs = new ArrayList<Pair<String, String>>(); - attachedDbs.add(new Pair<String, String>("main", getPath())); - } - for (int i = 0; i < attachedDbs.size(); i++) { - Pair<String, String> p = attachedDbs.get(i); - SQLiteStatement prog = null; - try { - prog = compileStatement("PRAGMA " + p.first + ".integrity_check(1);"); - String rslt = prog.simpleQueryForString(); - if (!rslt.equalsIgnoreCase("ok")) { - // integrity_checker failed on main or attached databases - Log.e(TAG, "PRAGMA integrity_check on " + p.second + " returned: " + rslt); - return false; + for (int i = 0; i < attachedDbs.size(); i++) { + Pair<String, String> p = attachedDbs.get(i); + SQLiteStatement prog = null; + try { + prog = compileStatement("PRAGMA " + p.first + ".integrity_check(1);"); + String rslt = prog.simpleQueryForString(); + if (!rslt.equalsIgnoreCase("ok")) { + // integrity_checker failed on main or attached databases + Log.e(TAG, "PRAGMA integrity_check on " + p.second + " returned: " + rslt); + return false; + } + } finally { + if (prog != null) prog.close(); } - } finally { - if (prog != null) prog.close(); } + } finally { + releaseReference(); } return true; } @@ -1955,12 +2021,6 @@ public final class SQLiteDatabase extends SQLiteClosable { return "SQLiteDatabase: " + getPath(); } - private void throwIfNotOpen() { - synchronized (mConnectionPoolLocked) { - throwIfNotOpenLocked(); - } - } - private void throwIfNotOpenLocked() { if (mConnectionPoolLocked == null) { throw new IllegalStateException("The database '" + mConfigurationLocked.label diff --git a/core/java/android/database/sqlite/SQLiteProgram.java b/core/java/android/database/sqlite/SQLiteProgram.java index 9f0edfb..94a23cb 100644 --- a/core/java/android/database/sqlite/SQLiteProgram.java +++ b/core/java/android/database/sqlite/SQLiteProgram.java @@ -190,13 +190,6 @@ public abstract class SQLiteProgram extends SQLiteClosable { } /** - * Release this program's resources, making it invalid. - */ - public void close() { - releaseReference(); - } - - /** * Given an array of String bindArgs, this method binds all of them in one single call. * * @param bindArgs the String array of bind args, none of which must be null. |