Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android SQLite Database: SQLiteDiskIOException: disk I/O error (code 1802)

I have an app that makes use of the SQLite database.

I created the database when the application starts, calling the constructor of RSSDatabase, which works fine. After a button is clicked, I fetch data from RSS feeds and insert data in an AsyncTask, but that causes an error when I called db.insert("posts", "", values), here is the error message for logcat:

02-04 21:43:22.050  19154-19357/com.example.aolreader E/SQLiteLog﹕ (1802) os_unix.c:30026: (2) stat(/data/data/com.example.aolreader/databases/rss_db) -
02-04 21:43:22.050  19154-19357/com.example.aolreader E/SQLiteLog﹕ (1802) statement aborts at 13: [INSERT INTO posts(author,title,date,description,link) VALUES (?,?,?,?,?)]
02-04 21:43:22.050  19154-19357/com.example.aolreader E/SQLiteDatabase﹕ Error inserting author=AP title=UK admits ‘limited’ role in Operation Blue Star  date=Tue, 4 Feb 2014 19:03:27 +0530 description=
    The British government had recently ordered an urgent investigation into possible U.K. involvement in the raid.
    link=http://www.thehindu.com/news/international/world/uk-admits-limited-role-in-operation-blue-star/article5653316.ece
    android.database.sqlite.SQLiteDiskIOException: disk I/O error (code 1802)
            at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
            at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:782)
            at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:788)
            at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:86)
            at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1469)
            at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1339)
            at com.example.aolreader.RSSDatabase.insertPost(RSSDatabase.java:44)
            at com.example.aolreader.XMLRSSActivity.parseNews(XMLRSSActivity.java:386)
            at com.example.aolreader.XMLRSSActivity.access$000(XMLRSSActivity.java:33)
            at com.example.aolreader.XMLRSSActivity$ParseTask.doInBackground(XMLRSSActivity.java:171)
            at com.example.aolreader.XMLRSSActivity$ParseTask.doInBackground(XMLRSSActivity.java:134)
            at android.os.AsyncTask$2.call(AsyncTask.java:288)
            at java.util.concurrent.FutureTask.run(FutureTask.java:237)
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
            at java.lang.Thread.run(Thread.java:841)

I googled this error and found that it is probably caused by different thread accessing the database at the same time, but I looked into my code and found no condition where multiple threads have race conditions.

Here is my database helper class:

class RSSDatabaseHelper extends SQLiteOpenHelper {

    private static final String createPostTableSql = "create table posts (" +
            "_id integer primary key autoincrement," +
            "title varchar," +
            "author varchar," +
            "link varchar," +
            "description varchar," +
            "date varchar)";

    private Context context;

    public RSSDatabaseHelper(Context c, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(c, name, factory, version);
        context = c;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(createPostTableSql);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("drop table if exists posts");
        onCreate(db);
    }
}

And my database class:

public class RSSDatabase {
    private static RSSDatabase instance;

    private SQLiteDatabase db;
    private RSSDatabaseHelper dbHelper;

    private RSSDatabase(Context c) {
        dbHelper = new RSSDatabaseHelper(c, "rss_db", null, 1);
        db = dbHelper.getWritableDatabase();
    }

    public static synchronized RSSDatabase getDatabaseInstance(Context c) {
        if (instance == null) {
            instance = new RSSDatabase(c);
        }
        return instance;
    }

    public void insertPost(Post post) {
        ContentValues values = new ContentValues();
        values.put("title", post.title);
        values.put("author", post.author);
        values.put("link", post.link);
        values.put("description", post.description);
        values.put("date", post.date);
        db.insert("posts", "", values);
    }
}

Could anyone shed some light on this issue?

Thanks in advance!

like image 468
Guanlun Avatar asked Feb 04 '14 13:02

Guanlun


1 Answers

When the application starts, calling the constructor of RSSDatabase, UI Thread is locking your database

db = dbHelper.getWritableDatabase(); // In the constructor

Now from Async task( different thread), You are trying to insert data in the database which is locked by UI thread. This will throw an exception because the first write has a lock on the db.

like image 76
Zohra Khan Avatar answered Oct 28 '22 05:10

Zohra Khan