Merge change 23474 into eclair
* changes: Breaking sleep after yield into small quanta.
This commit is contained in:
@@ -62,53 +62,53 @@ public class SQLiteDatabase extends SQLiteClosable {
|
|||||||
*/
|
*/
|
||||||
public enum ConflictAlgorithm {
|
public enum ConflictAlgorithm {
|
||||||
/**
|
/**
|
||||||
* When a constraint violation occurs, an immediate ROLLBACK occurs,
|
* When a constraint violation occurs, an immediate ROLLBACK occurs,
|
||||||
* thus ending the current transaction, and the command aborts with a
|
* thus ending the current transaction, and the command aborts with a
|
||||||
* return code of SQLITE_CONSTRAINT. If no transaction is active
|
* return code of SQLITE_CONSTRAINT. If no transaction is active
|
||||||
* (other than the implied transaction that is created on every command)
|
* (other than the implied transaction that is created on every command)
|
||||||
* then this algorithm works the same as ABORT.
|
* then this algorithm works the same as ABORT.
|
||||||
*/
|
*/
|
||||||
ROLLBACK("ROLLBACK"),
|
ROLLBACK("ROLLBACK"),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When a constraint violation occurs,no ROLLBACK is executed
|
* When a constraint violation occurs,no ROLLBACK is executed
|
||||||
* so changes from prior commands within the same transaction
|
* so changes from prior commands within the same transaction
|
||||||
* are preserved. This is the default behavior.
|
* are preserved. This is the default behavior.
|
||||||
*/
|
*/
|
||||||
ABORT("ABORT"),
|
ABORT("ABORT"),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When a constraint violation occurs, the command aborts with a return
|
* When a constraint violation occurs, the command aborts with a return
|
||||||
* code SQLITE_CONSTRAINT. But any changes to the database that
|
* code SQLITE_CONSTRAINT. But any changes to the database that
|
||||||
* the command made prior to encountering the constraint violation
|
* the command made prior to encountering the constraint violation
|
||||||
* are preserved and are not backed out.
|
* are preserved and are not backed out.
|
||||||
*/
|
*/
|
||||||
FAIL("FAIL"),
|
FAIL("FAIL"),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When a constraint violation occurs, the one row that contains
|
* When a constraint violation occurs, the one row that contains
|
||||||
* the constraint violation is not inserted or changed.
|
* the constraint violation is not inserted or changed.
|
||||||
* But the command continues executing normally. Other rows before and
|
* But the command continues executing normally. Other rows before and
|
||||||
* after the row that contained the constraint violation continue to be
|
* after the row that contained the constraint violation continue to be
|
||||||
* inserted or updated normally. No error is returned.
|
* inserted or updated normally. No error is returned.
|
||||||
*/
|
*/
|
||||||
IGNORE("IGNORE"),
|
IGNORE("IGNORE"),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When a UNIQUE constraint violation occurs, the pre-existing rows that
|
* When a UNIQUE constraint violation occurs, the pre-existing rows that
|
||||||
* are causing the constraint violation are removed prior to inserting
|
* are causing the constraint violation are removed prior to inserting
|
||||||
* or updating the current row. Thus the insert or update always occurs.
|
* or updating the current row. Thus the insert or update always occurs.
|
||||||
* The command continues executing normally. No error is returned.
|
* The command continues executing normally. No error is returned.
|
||||||
* If a NOT NULL constraint violation occurs, the NULL value is replaced
|
* If a NOT NULL constraint violation occurs, the NULL value is replaced
|
||||||
* by the default value for that column. If the column has no default
|
* by the default value for that column. If the column has no default
|
||||||
* value, then the ABORT algorithm is used. If a CHECK constraint
|
* value, then the ABORT algorithm is used. If a CHECK constraint
|
||||||
* violation occurs then the IGNORE algorithm is used. When this conflict
|
* violation occurs then the IGNORE algorithm is used. When this conflict
|
||||||
* resolution strategy deletes rows in order to satisfy a constraint,
|
* resolution strategy deletes rows in order to satisfy a constraint,
|
||||||
* it does not invoke delete triggers on those rows.
|
* it does not invoke delete triggers on those rows.
|
||||||
* This behavior might change in a future release.
|
* This behavior might change in a future release.
|
||||||
*/
|
*/
|
||||||
REPLACE("REPLACE");
|
REPLACE("REPLACE");
|
||||||
|
|
||||||
private final String mValue;
|
private final String mValue;
|
||||||
ConflictAlgorithm(String value) {
|
ConflictAlgorithm(String value) {
|
||||||
mValue = value;
|
mValue = value;
|
||||||
@@ -117,7 +117,7 @@ public class SQLiteDatabase extends SQLiteClosable {
|
|||||||
return mValue;
|
return mValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maximum Length Of A LIKE Or GLOB Pattern
|
* Maximum Length Of A LIKE Or GLOB Pattern
|
||||||
* The pattern matching algorithm used in the default LIKE and GLOB implementation
|
* The pattern matching algorithm used in the default LIKE and GLOB implementation
|
||||||
@@ -180,17 +180,19 @@ public class SQLiteDatabase extends SQLiteClosable {
|
|||||||
|
|
||||||
private long mLockAcquiredWallTime = 0L;
|
private long mLockAcquiredWallTime = 0L;
|
||||||
private long mLockAcquiredThreadTime = 0L;
|
private long mLockAcquiredThreadTime = 0L;
|
||||||
|
|
||||||
// limit the frequency of complaints about each database to one within 20 sec
|
// limit the frequency of complaints about each database to one within 20 sec
|
||||||
// unless run command adb shell setprop log.tag.Database VERBOSE
|
// unless run command adb shell setprop log.tag.Database VERBOSE
|
||||||
private static final int LOCK_WARNING_WINDOW_IN_MS = 20000;
|
private static final int LOCK_WARNING_WINDOW_IN_MS = 20000;
|
||||||
/** If the lock is held this long then a warning will be printed when it is released. */
|
/** If the lock is held this long then a warning will be printed when it is released. */
|
||||||
private static final int LOCK_ACQUIRED_WARNING_TIME_IN_MS = 300;
|
private static final int LOCK_ACQUIRED_WARNING_TIME_IN_MS = 300;
|
||||||
private static final int LOCK_ACQUIRED_WARNING_THREAD_TIME_IN_MS = 100;
|
private static final int LOCK_ACQUIRED_WARNING_THREAD_TIME_IN_MS = 100;
|
||||||
private static final int LOCK_ACQUIRED_WARNING_TIME_IN_MS_ALWAYS_PRINT = 2000;
|
private static final int LOCK_ACQUIRED_WARNING_TIME_IN_MS_ALWAYS_PRINT = 2000;
|
||||||
|
|
||||||
|
private static final int SLEEP_AFTER_YIELD_QUANTUM = 500;
|
||||||
|
|
||||||
private long mLastLockMessageTime = 0L;
|
private long mLastLockMessageTime = 0L;
|
||||||
|
|
||||||
/** Used by native code, do not rename */
|
/** Used by native code, do not rename */
|
||||||
/* package */ int mNativeHandle = 0;
|
/* package */ int mNativeHandle = 0;
|
||||||
|
|
||||||
@@ -205,15 +207,15 @@ public class SQLiteDatabase extends SQLiteClosable {
|
|||||||
|
|
||||||
/** The optional factory to use when creating new Cursors */
|
/** The optional factory to use when creating new Cursors */
|
||||||
private CursorFactory mFactory;
|
private CursorFactory mFactory;
|
||||||
|
|
||||||
private WeakHashMap<SQLiteClosable, Object> mPrograms;
|
private WeakHashMap<SQLiteClosable, Object> mPrograms;
|
||||||
|
|
||||||
private final RuntimeException mLeakedException;
|
private final RuntimeException mLeakedException;
|
||||||
|
|
||||||
// package visible, since callers will access directly to minimize overhead in the case
|
// package visible, since callers will access directly to minimize overhead in the case
|
||||||
// that logging is not enabled.
|
// that logging is not enabled.
|
||||||
/* package */ final boolean mLogStats;
|
/* package */ final boolean mLogStats;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param closable
|
* @param closable
|
||||||
*/
|
*/
|
||||||
@@ -225,7 +227,7 @@ public class SQLiteDatabase extends SQLiteClosable {
|
|||||||
unlock();
|
unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeSQLiteClosable(SQLiteClosable closable) {
|
void removeSQLiteClosable(SQLiteClosable closable) {
|
||||||
lock();
|
lock();
|
||||||
try {
|
try {
|
||||||
@@ -233,8 +235,8 @@ public class SQLiteDatabase extends SQLiteClosable {
|
|||||||
} finally {
|
} finally {
|
||||||
unlock();
|
unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onAllReferencesReleased() {
|
protected void onAllReferencesReleased() {
|
||||||
if (isOpen()) {
|
if (isOpen()) {
|
||||||
@@ -245,10 +247,10 @@ public class SQLiteDatabase extends SQLiteClosable {
|
|||||||
/**
|
/**
|
||||||
* Attempts to release memory that SQLite holds but does not require to
|
* Attempts to release memory that SQLite holds but does not require to
|
||||||
* operate properly. Typically this memory will come from the page cache.
|
* operate properly. Typically this memory will come from the page cache.
|
||||||
*
|
*
|
||||||
* @return the number of bytes actually released
|
* @return the number of bytes actually released
|
||||||
*/
|
*/
|
||||||
static public native int releaseMemory();
|
static public native int releaseMemory();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Control whether or not the SQLiteDatabase is made thread-safe by using locks
|
* Control whether or not the SQLiteDatabase is made thread-safe by using locks
|
||||||
@@ -284,7 +286,7 @@ public class SQLiteDatabase extends SQLiteClosable {
|
|||||||
* touch the native sqlite3* object since it is single threaded and uses
|
* touch the native sqlite3* object since it is single threaded and uses
|
||||||
* a polling lock contention algorithm. The lock is recursive, and may be acquired
|
* a polling lock contention algorithm. The lock is recursive, and may be acquired
|
||||||
* multiple times by the same thread. This is a no-op if mLockingEnabled is false.
|
* multiple times by the same thread. This is a no-op if mLockingEnabled is false.
|
||||||
*
|
*
|
||||||
* @see #unlock()
|
* @see #unlock()
|
||||||
*/
|
*/
|
||||||
/* package */ void lock() {
|
/* package */ void lock() {
|
||||||
@@ -320,7 +322,7 @@ public class SQLiteDatabase extends SQLiteClosable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Releases the database lock. This is a no-op if mLockingEnabled is false.
|
* Releases the database lock. This is a no-op if mLockingEnabled is false.
|
||||||
*
|
*
|
||||||
* @see #unlock()
|
* @see #unlock()
|
||||||
*/
|
*/
|
||||||
/* package */ void unlock() {
|
/* package */ void unlock() {
|
||||||
@@ -350,7 +352,7 @@ public class SQLiteDatabase extends SQLiteClosable {
|
|||||||
private void checkLockHoldTime() {
|
private void checkLockHoldTime() {
|
||||||
// Use elapsed real-time since the CPU may sleep when waiting for IO
|
// Use elapsed real-time since the CPU may sleep when waiting for IO
|
||||||
long elapsedTime = SystemClock.elapsedRealtime();
|
long elapsedTime = SystemClock.elapsedRealtime();
|
||||||
long lockedTime = elapsedTime - mLockAcquiredWallTime;
|
long lockedTime = elapsedTime - mLockAcquiredWallTime;
|
||||||
if (lockedTime < LOCK_ACQUIRED_WARNING_TIME_IN_MS_ALWAYS_PRINT &&
|
if (lockedTime < LOCK_ACQUIRED_WARNING_TIME_IN_MS_ALWAYS_PRINT &&
|
||||||
!Log.isLoggable(TAG, Log.VERBOSE) &&
|
!Log.isLoggable(TAG, Log.VERBOSE) &&
|
||||||
(elapsedTime - mLastLockMessageTime) < LOCK_WARNING_WINDOW_IN_MS) {
|
(elapsedTime - mLastLockMessageTime) < LOCK_WARNING_WINDOW_IN_MS) {
|
||||||
@@ -567,10 +569,21 @@ public class SQLiteDatabase extends SQLiteClosable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sleepAfterYieldDelay > 0) {
|
if (sleepAfterYieldDelay > 0) {
|
||||||
try {
|
// Sleep for up to sleepAfterYieldDelay milliseconds, waking up periodically to
|
||||||
Thread.sleep(sleepAfterYieldDelay);
|
// check if anyone is using the database. If the database is not contended,
|
||||||
} catch (InterruptedException e) {
|
// retake the lock and return.
|
||||||
Thread.interrupted();
|
long remainingDelay = sleepAfterYieldDelay;
|
||||||
|
while (remainingDelay > 0) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(remainingDelay < SLEEP_AFTER_YIELD_QUANTUM ?
|
||||||
|
remainingDelay : SLEEP_AFTER_YIELD_QUANTUM);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.interrupted();
|
||||||
|
}
|
||||||
|
remainingDelay -= SLEEP_AFTER_YIELD_QUANTUM;
|
||||||
|
if (mLock.getQueueLength() == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
beginTransaction();
|
beginTransaction();
|
||||||
@@ -720,9 +733,9 @@ public class SQLiteDatabase extends SQLiteClosable {
|
|||||||
if (program != null) {
|
if (program != null) {
|
||||||
program.onAllReferencesReleasedFromContainer();
|
program.onAllReferencesReleasedFromContainer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Native call to close the database.
|
* Native call to close the database.
|
||||||
*/
|
*/
|
||||||
@@ -1157,8 +1170,8 @@ public class SQLiteDatabase extends SQLiteClosable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs the provided SQL and returns a cursor over the result set.
|
* Runs the provided SQL and returns a cursor over the result set.
|
||||||
* The cursor will read an initial set of rows and the return to the caller.
|
* The cursor will read an initial set of rows and the return to the caller.
|
||||||
* It will continue to read in batches and send data changed notifications
|
* It will continue to read in batches and send data changed notifications
|
||||||
* when the later batches are ready.
|
* when the later batches are ready.
|
||||||
* @param sql the SQL query. The SQL string must not be ; terminated
|
* @param sql the SQL query. The SQL string must not be ; terminated
|
||||||
* @param selectionArgs You may include ?s in where clause in the query,
|
* @param selectionArgs You may include ?s in where clause in the query,
|
||||||
@@ -1167,19 +1180,19 @@ public class SQLiteDatabase extends SQLiteClosable {
|
|||||||
* @param initialRead set the initial count of items to read from the cursor
|
* @param initialRead set the initial count of items to read from the cursor
|
||||||
* @param maxRead set the count of items to read on each iteration after the first
|
* @param maxRead set the count of items to read on each iteration after the first
|
||||||
* @return A {@link Cursor} object, which is positioned before the first entry
|
* @return A {@link Cursor} object, which is positioned before the first entry
|
||||||
*
|
*
|
||||||
* This work is incomplete and not fully tested or reviewed, so currently
|
* This work is incomplete and not fully tested or reviewed, so currently
|
||||||
* hidden.
|
* hidden.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public Cursor rawQuery(String sql, String[] selectionArgs,
|
public Cursor rawQuery(String sql, String[] selectionArgs,
|
||||||
int initialRead, int maxRead) {
|
int initialRead, int maxRead) {
|
||||||
SQLiteCursor c = (SQLiteCursor)rawQueryWithFactory(
|
SQLiteCursor c = (SQLiteCursor)rawQueryWithFactory(
|
||||||
null, sql, selectionArgs, null);
|
null, sql, selectionArgs, null);
|
||||||
c.setLoadStyle(initialRead, maxRead);
|
c.setLoadStyle(initialRead, maxRead);
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience method for inserting a row into the database.
|
* Convenience method for inserting a row into the database.
|
||||||
*
|
*
|
||||||
@@ -1232,7 +1245,7 @@ public class SQLiteDatabase extends SQLiteClosable {
|
|||||||
*/
|
*/
|
||||||
public long replace(String table, String nullColumnHack, ContentValues initialValues) {
|
public long replace(String table, String nullColumnHack, ContentValues initialValues) {
|
||||||
try {
|
try {
|
||||||
return insertWithOnConflict(table, nullColumnHack, initialValues,
|
return insertWithOnConflict(table, nullColumnHack, initialValues,
|
||||||
ConflictAlgorithm.REPLACE);
|
ConflictAlgorithm.REPLACE);
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
Log.e(TAG, "Error inserting " + initialValues, e);
|
Log.e(TAG, "Error inserting " + initialValues, e);
|
||||||
@@ -1254,7 +1267,7 @@ public class SQLiteDatabase extends SQLiteClosable {
|
|||||||
*/
|
*/
|
||||||
public long replaceOrThrow(String table, String nullColumnHack,
|
public long replaceOrThrow(String table, String nullColumnHack,
|
||||||
ContentValues initialValues) throws SQLException {
|
ContentValues initialValues) throws SQLException {
|
||||||
return insertWithOnConflict(table, nullColumnHack, initialValues,
|
return insertWithOnConflict(table, nullColumnHack, initialValues,
|
||||||
ConflictAlgorithm.REPLACE);
|
ConflictAlgorithm.REPLACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1410,7 +1423,7 @@ public class SQLiteDatabase extends SQLiteClosable {
|
|||||||
public int update(String table, ContentValues values, String whereClause, String[] whereArgs) {
|
public int update(String table, ContentValues values, String whereClause, String[] whereArgs) {
|
||||||
return updateWithOnConflict(table, values, whereClause, whereArgs, null);
|
return updateWithOnConflict(table, values, whereClause, whereArgs, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience method for updating rows in the database.
|
* Convenience method for updating rows in the database.
|
||||||
*
|
*
|
||||||
@@ -1423,7 +1436,7 @@ public class SQLiteDatabase extends SQLiteClosable {
|
|||||||
* @return the number of rows affected
|
* @return the number of rows affected
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public int updateWithOnConflict(String table, ContentValues values,
|
public int updateWithOnConflict(String table, ContentValues values,
|
||||||
String whereClause, String[] whereArgs, ConflictAlgorithm algorithm) {
|
String whereClause, String[] whereArgs, ConflictAlgorithm algorithm) {
|
||||||
if (!isOpen()) {
|
if (!isOpen()) {
|
||||||
throw new IllegalStateException("database not open");
|
throw new IllegalStateException("database not open");
|
||||||
@@ -1440,7 +1453,7 @@ public class SQLiteDatabase extends SQLiteClosable {
|
|||||||
sql.append(algorithm.value());
|
sql.append(algorithm.value());
|
||||||
sql.append(" ");
|
sql.append(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
sql.append(table);
|
sql.append(table);
|
||||||
sql.append(" SET ");
|
sql.append(" SET ");
|
||||||
|
|
||||||
@@ -1601,7 +1614,7 @@ public class SQLiteDatabase extends SQLiteClosable {
|
|||||||
mFlags = flags;
|
mFlags = flags;
|
||||||
mPath = path;
|
mPath = path;
|
||||||
mLogStats = "1".equals(android.os.SystemProperties.get("db.logstats"));
|
mLogStats = "1".equals(android.os.SystemProperties.get("db.logstats"));
|
||||||
|
|
||||||
mLeakedException = new IllegalStateException(path +
|
mLeakedException = new IllegalStateException(path +
|
||||||
" SQLiteDatabase created and never closed");
|
" SQLiteDatabase created and never closed");
|
||||||
mFactory = factory;
|
mFactory = factory;
|
||||||
|
|||||||
Reference in New Issue
Block a user