Merge "sometimes database lock is not held before compiling a statement"

This commit is contained in:
Vasu Nori
2010-05-03 13:05:06 -07:00
committed by Android (Google) Code Review
3 changed files with 32 additions and 25 deletions

View File

@@ -78,20 +78,13 @@ import android.util.Log;
* existing compiled SQL program already around
*/
private void compile(String sql, boolean forceCompilation) {
if (!mDatabase.isOpen()) {
throw new IllegalStateException("database " + mDatabase.getPath() + " already closed");
}
mDatabase.verifyLockOwner();
// Only compile if we don't have a valid statement already or the caller has
// explicitly requested a recompile.
if (forceCompilation) {
mDatabase.lock();
try {
// Note that the native_compile() takes care of destroying any previously
// existing programs before it compiles.
native_compile(sql);
} finally {
mDatabase.unlock();
}
// Note that the native_compile() takes care of destroying any previously
// existing programs before it compiles.
native_compile(sql);
}
}

View File

@@ -275,20 +275,22 @@ public class SQLiteDatabase extends SQLiteClosable {
// if it needs to be removed to accommodate a new entry,
// close {@link SQLiteCompiledSql} represented by this entry, if not in use
// and then let it be removed from the Map.
synchronized(mCompiledQueries) { // probably not necessary, but can't hurt
if (this.size() <= mMaxSqlCacheSize) {
// cache is not full. nothing needs to be removed
return false;
}
// cache is full. eldest will be removed.
SQLiteCompiledSql entry = eldest.getValue();
if (!entry.isInUse()) {
// this {@link SQLiteCompiledSql} is not in use. release it.
entry.releaseSqlStatement();
}
// return true, so that this entry is removed automatically by the caller.
return true;
// when this is called, the caller must be trying to add a just-compiled stmt
// to cache; i.e., caller should already have acquired database lock AND
// the lock on mCompiledQueries. do as assert of these two 2 facts.
verifyLockOwner();
if (this.size() <= mMaxSqlCacheSize) {
// cache is not full. nothing needs to be removed
return false;
}
// cache is full. eldest will be removed.
SQLiteCompiledSql entry = eldest.getValue();
if (!entry.isInUse()) {
// this {@link SQLiteCompiledSql} is not in use. release it.
entry.releaseSqlStatement();
}
// return true, so that this entry is removed automatically by the caller.
return true;
}
};
/**
@@ -1979,6 +1981,15 @@ public class SQLiteDatabase extends SQLiteClosable {
}
}
/* package */ void verifyLockOwner() {
if (!isOpen()) {
throw new IllegalStateException("database " + getPath() + " already closed");
}
if (!isDbLockedByCurrentThread() && mLockingEnabled) {
throw new IllegalStateException("Don't have database lock!");
}
}
/*
* ============================================================================
*

View File

@@ -39,9 +39,11 @@ public class SQLiteDirectCursorDriver implements SQLiteCursorDriver {
public Cursor query(CursorFactory factory, String[] selectionArgs) {
// Compile the query
SQLiteQuery query = new SQLiteQuery(mDatabase, mSql, 0, selectionArgs);
SQLiteQuery query = null;
try {
mDatabase.lock();
query = new SQLiteQuery(mDatabase, mSql, 0, selectionArgs);
// Arg binding
int numArgs = selectionArgs == null ? 0 : selectionArgs.length;
for (int i = 0; i < numArgs; i++) {
@@ -61,6 +63,7 @@ public class SQLiteDirectCursorDriver implements SQLiteCursorDriver {
} finally {
// Make sure this object is cleaned up if something happens
if (query != null) query.close();
mDatabase.unlock();
}
}