vendredi 29 janvier 2016

SQLiteReadOnlyDatabaseException: attempt to write a readonly database (code 1032)

So in some rare instances, I'm seeing the "attempt to write a readonly database" message, and I can't figure out where the problem lies. I'll start with the stacktrace in my logcat... as you can see from the timestamp I'm checking db.isReadOnly() only 1ms before I attempt the write. (isOpen=true, readOnly=false)

01-29 12:30:04.289: D/AWT(7802): #410.Got writable database (230537815): isOpen: (true) isReadOnly: (false) inTransaction: (false)
01-29 12:30:04.289: E/SQLiteLog(7802): (1032) statement aborts at 15: [INSERT INTO Events(col1,col2,col3,col4) VALUES (?,?,?,?)] 
01-29 12:30:04.290: E/SQLiteDatabase(7802): Error inserting data="scrubbed" data2="scrubbed"
01-29 12:30:04.290: E/SQLiteDatabase(7802): android.database.sqlite.SQLiteReadOnlyDatabaseException: attempt to write a readonly database (code 1032)
01-29 12:30:04.290: E/SQLiteDatabase(7802):     at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
01-29 12:30:04.290: E/SQLiteDatabase(7802):     at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:780)
01-29 12:30:04.290: E/SQLiteDatabase(7802):     at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:788)
01-29 12:30:04.290: E/SQLiteDatabase(7802):     at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:86)
01-29 12:30:04.290: E/SQLiteDatabase(7802):     at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1471)
01-29 12:30:04.290: E/SQLiteDatabase(7802):     at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1341)
01-29 12:30:04.290: E/SQLiteDatabase(7802):     at com.company.DbHelper.insertBatch(DbHelper.java:171)

From my source:

public void insertBatch(LinkedList<WriteQueue.DatabaseRecord> writeQueue) throws Exception {
    Log.d("AWT", "DbHelper->insertBatch()");

    if (writeQueue == null) {
        return;
    }

    Iterator<DatabaseRecord> it = writeQueue.iterator();
    SQLiteDatabase db = this.getWritableDatabase();

    Log.d("AWT", String.format("Got writable database (%s): isOpen: (%s) isReadOnly: (%s) inTransaction: (%s)",
            db.hashCode(), db.isOpen(), db.isReadOnly(), db.inTransaction()));

    try {
        db.beginTransaction();

        while (it.hasNext()) {
            DatabaseRecord record = it.next();

            ContentValues initialValues = new ContentValues();
            initialValues.put(col1, val1);
            initialValues.put(col2, val2);
            initialValues.put(col3, val3);
            initialValues.put(col4, val4);

            db.insert(DBTBL, null, initialValues);
        }
        db.setTransactionSuccessful();
    } catch (Exception e) {
        Log.e(TAG, "Error inserting batch record into database.", e);
    } finally {
        try {
            db.endTransaction();
        } catch (Exception e) {
            Log.e(TAG, Global.DB_ERROR, e);
        }
    }
}

So I think that maybe one of two things is happening.

  1. The DB really is being closed/set to "readonly" in that 1ms between the check and the attempted batch insert.
  2. isReadOnly is lying to me and not accurately reporting the state of the database.

Out of ideas at this point though but I'm willing to try anything suggested.

Aucun commentaire:

Enregistrer un commentaire