Skip to content

Commit

Permalink
Android DBRunner class (constructor) now accepts db options as JSON o…
Browse files Browse the repository at this point in the history
…bject

(preparation for workaround for Android db locking/closing issue [see #193])

Replace tabs with spaces
  • Loading branch information
Chris Brody committed Mar 9, 2015
1 parent af04b67 commit 60a4380
Showing 1 changed file with 58 additions and 46 deletions.
104 changes: 58 additions & 46 deletions src/android/org/pgsqlite/SQLitePlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ private boolean executeAndPossiblyThrow(Action action, JSONArray args, CallbackC
o = args.getJSONObject(0);
dbname = o.getString("name");
// open database and start reading its queue
this.startDatabase(dbname, o.has("createFromResource"), cbc);
this.startDatabase(dbname, o, cbc);
break;

case close:
Expand Down Expand Up @@ -158,14 +158,14 @@ private boolean executeAndPossiblyThrow(Action action, JSONArray args, CallbackC
DBQuery q = new DBQuery(queries, queryIDs, jsonparams, cbc);
DBRunner r = dbrmap.get(dbname);
if (r != null) {
try {
r.q.put(q);
} catch(Exception e) {
Log.e(SQLitePlugin.class.getSimpleName(), "couldn't add to queue", e);
cbc.error("couldn't add to queue");
}
try {
r.q.put(q);
} catch(Exception e) {
Log.e(SQLitePlugin.class.getSimpleName(), "couldn't add to queue", e);
cbc.error("couldn't add to queue");
}
} else {
cbc.error("database not open");
cbc.error("database not open");
}
break;
}
Expand Down Expand Up @@ -198,19 +198,19 @@ public void onDestroy() {
// LOCAL METHODS
// --------------------------------------------------------------------------

private void startDatabase(String dbname, boolean createFromAssets, CallbackContext cbc) {
private void startDatabase(String dbname, JSONObject options, CallbackContext cbc) {
// TODO: is it an issue that we can orphan an existing thread? What should we do here?
// If we re-use the existing DBRunner it might be in the process of closing...
DBRunner r = dbrmap.get(dbname);

// Brody TODO: It may be better to terminate the existing db thread here & start a new one, instead.
if (r != null) {
// don't orphan the existing thread; just re-open the existing database.
// In the worst case it might be in the process of closing, but even that's less serious
// than orphaning the old DBRunner.
// don't orphan the existing thread; just re-open the existing database.
// In the worst case it might be in the process of closing, but even that's less serious
// than orphaning the old DBRunner.
cbc.success();
} else {
r = new DBRunner(dbname, createFromAssets, cbc);
r = new DBRunner(dbname, options, cbc);
dbrmap.put(dbname, r);
this.cordova.getThreadPool().execute(r);
}
Expand All @@ -224,7 +224,7 @@ private SQLiteDatabase openDatabase(String dbname, boolean createFromAssets, Cal
try {
if (this.getDatabase(dbname) != null) {
// this should not happen - should be blocked at the execute("open") level
cbc.error("database already open");
if (cbc != null) cbc.error("database already open");
throw new Exception("database already open");
}

Expand All @@ -240,11 +240,13 @@ private SQLiteDatabase openDatabase(String dbname, boolean createFromAssets, Cal

SQLiteDatabase mydb = SQLiteDatabase.openOrCreateDatabase(dbfile, null);

cbc.success();
//if (cbc != null) // needed for Android locking/closing workaround
cbc.success();

return mydb;
} catch (SQLiteException e) {
cbc.error("can't open database " + e);
//if (cbc != null) // needed for Android locking/closing workaround
cbc.error("can't open database " + e);
throw e;
}
}
Expand Down Expand Up @@ -308,15 +310,15 @@ private void closeDatabase(String dbName, CallbackContext cbc) {
try {
r.q.put(new DBQuery(false, cbc));
} catch(Exception e) {
if (cbc != null) {
cbc.error("couldn't close database" + e);
}
if (cbc != null) {
cbc.error("couldn't close database" + e);
}
Log.e(SQLitePlugin.class.getSimpleName(), "couldn't close database", e);
}
} else {
if (cbc != null) {
cbc.success();
}
if (cbc != null) {
cbc.success();
}
}
}

Expand All @@ -339,9 +341,9 @@ private void deleteDatabase(String dbname, CallbackContext cbc) {
try {
r.q.put(new DBQuery(true, cbc));
} catch(Exception e) {
if (cbc != null) {
cbc.error("couldn't close database" + e);
}
if (cbc != null) {
cbc.error("couldn't close database" + e);
}
Log.e(SQLitePlugin.class.getSimpleName(), "couldn't close database", e);
}
} else {
Expand All @@ -367,14 +369,14 @@ private boolean deleteDatabaseNow(String dbname) {
if (android.os.Build.VERSION.SDK_INT >= 11) {
// Use try & catch just in case android.os.Build.VERSION.SDK_INT >= 16 was lying:
try {
return SQLiteDatabase.deleteDatabase(dbfile);
return SQLiteDatabase.deleteDatabase(dbfile);
} catch (Exception e) {
Log.e(SQLitePlugin.class.getSimpleName(), "couldn't delete because old SDK_INT", e);
return deleteDatabasePreHoneycomb(dbfile);
}
} else {
// use old API
return deleteDatabasePreHoneycomb(dbfile);
return deleteDatabasePreHoneycomb(dbfile);
}
}

Expand Down Expand Up @@ -413,9 +415,9 @@ private void executeSqlBatch(String dbname, String[] queryarr, JSONArray[] jsonp
SQLiteDatabase mydb = getDatabase(dbname);

if (mydb == null) {
// not allowed - can only happen if someone has closed (and possibly deleted) a database and then re-used the database
cbc.error("database has been closed");
return;
// not allowed - can only happen if someone has closed (and possibly deleted) a database and then re-used the database
cbc.error("database has been closed");
return;
}


Expand Down Expand Up @@ -818,15 +820,17 @@ private void bindPreHoneycomb(JSONObject row, String key, Cursor cursor, int i)

private class DBRunner implements Runnable {
final String dbname;
final boolean createFromAssets;
private boolean createFromAssets;
//private boolean androidLockWorkaround;
final BlockingQueue<DBQuery> q;
final CallbackContext openCbc;

SQLiteDatabase mydb;

DBRunner(final String dbname, boolean createFromAssets, CallbackContext cbc) {
DBRunner(final String dbname, JSONObject options, CallbackContext cbc) {
this.dbname = dbname;
this.createFromAssets = createFromAssets;
this.createFromAssets = options.has("createFromResource");
//this.androidLockWorkaround = options.has("androidLockWorkaround");
this.q = new LinkedBlockingQueue<DBQuery>();
this.openCbc = cbc;
}
Expand All @@ -848,6 +852,14 @@ public void run() {
while (!dbq.stop) {
executeSqlBatch(dbname, dbq.queries, dbq.jsonparams, dbq.queryIDs, dbq.cbc);

// XXX workaround for Android locking/closing issue:
//if (androidLockWorkaround && dbq.queries.length == 1 && dbq.queries[0] == "COMMIT") {
// Log.v(SQLitePlugin.class.getSimpleName(), "close and reopen db");
// closeDatabaseNow(dbname);
// this.mydb = openDatabase(dbname, false, null);
// Log.v(SQLitePlugin.class.getSimpleName(), "close and reopen db finished");
//}

dbq = q.take();
}
} catch (Exception e) {
Expand All @@ -861,24 +873,24 @@ public void run() {
dbrmap.remove(dbname); // (should) remove ourself

if (!dbq.delete) {
dbq.cbc.success();
dbq.cbc.success();
} else {
try {
boolean deleteResult = deleteDatabaseNow(dbname);
if (deleteResult) {
dbq.cbc.success();
} else {
dbq.cbc.error("couldn't delete database");
}
} catch (Exception e) {
Log.e(SQLitePlugin.class.getSimpleName(), "couldn't delete database", e);
dbq.cbc.error("couldn't delete database: " + e);
}
try {
boolean deleteResult = deleteDatabaseNow(dbname);
if (deleteResult) {
dbq.cbc.success();
} else {
dbq.cbc.error("couldn't delete database");
}
} catch (Exception e) {
Log.e(SQLitePlugin.class.getSimpleName(), "couldn't delete database", e);
dbq.cbc.error("couldn't delete database: " + e);
}
}
} catch (Exception e) {
Log.e(SQLitePlugin.class.getSimpleName(), "couldn't close database", e);
if (dbq.cbc != null) {
dbq.cbc.error("couldn't close database: " + e);
dbq.cbc.error("couldn't close database: " + e);
}
}
}
Expand Down

0 comments on commit 60a4380

Please sign in to comment.