Reorganise database access to prevent locking issues

This commit is contained in:
Ciaran Gultnieks 2012-09-10 21:01:39 +01:00
parent 568b615ecf
commit 0623801474
7 changed files with 135 additions and 65 deletions

View File

@ -23,6 +23,8 @@ import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import org.fdroid.fdroid.DB.Apk.CompatibilityChecker;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.app.ProgressDialog;
@ -157,13 +159,12 @@ public class AppDetails extends ListActivity {
private static final int MARKET = Menu.FIRST + 5;
private static final int DONATE = Menu.FIRST + 6;
private DB db;
private DB.App app;
private int app_currentvercode;
private DB.Apk curapk;
private String appid;
private CompatibilityChecker compatChecker;
private PackageManager mPm;
private DB.Apk.CompatibilityChecker compatChecker;
private DownloadHandler downloadHandler;
private boolean stateRetained;
@ -197,8 +198,6 @@ public class AppDetails extends ListActivity {
@Override
protected void onStart() {
super.onStart();
db = new DB(this);
compatChecker = db.getCompatibilityChecker();
mPm = getPackageManager();
// Get the preferences we're going to use in this Activity...
SharedPreferences prefs = PreferenceManager
@ -235,8 +234,6 @@ public class AppDetails extends ListActivity {
@Override
protected void onStop() {
db.close();
db = null;
super.onStop();
}
@ -275,8 +272,15 @@ public class AppDetails extends ListActivity {
// also when something has been installed/uninstalled.
private void reset() {
Log.d("FDroid", "Getting application details for " + appid);
DB.Apk curver;
try {
DB db = DB.getDB();
compatChecker = db.getCompatibilityChecker();
app = db.getApps(appid, null, true, false).get(0);
DB.Apk curver = app.getCurrentVersion(compatChecker);
curver = app.getCurrentVersion(compatChecker);
} finally {
DB.releaseDB();
}
app_currentvercode = curver == null ? 0 : curver.vercode;
// Get the signature of the installed package...

View File

@ -27,6 +27,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.concurrent.Semaphore;
import android.content.ContentValues;
import android.content.Context;
@ -44,6 +45,31 @@ import android.util.Log;
public class DB {
private static Semaphore dbSync = new Semaphore(1, true);
static DB dbInstance = null;
// Initialise the database. Called once when the application starts up.
static void initDB(Context ctx) {
dbInstance = new DB(ctx);
}
// Get access to the database. Must be called before any database activity,
// and releaseDB must be called subsequently. Returns null in the event of
// failure.
static DB getDB() {
try {
dbSync.acquire();
return dbInstance;
} catch (InterruptedException e) {
return null;
}
}
// Release database access lock acquired via getDB().
static void releaseDB() {
dbSync.release();
}
private static final String DATABASE_NAME = "fdroid";
// Possible values of the SQLite flag "synchronous"
@ -131,7 +157,7 @@ public class DB {
// To skip compatibility checks, pass null as the checker.
public Apk getCurrentVersion(DB.Apk.CompatibilityChecker checker) {
// Try and return the version that's in Google's market first...
// Try and return the real current version first...
if (marketVersion != null && marketVercode > 0) {
for (Apk apk : apks) {
if (apk.vercode == marketVercode
@ -140,7 +166,7 @@ public class DB {
}
}
// If we don't know the market version, or we don't have it, we
// If we don't know the current version, or we don't have it, we
// return the most recent compatible version we have...
int latestcode = -1;
Apk latestapk = null;
@ -396,7 +422,7 @@ public class DB {
// database.
private SimpleDateFormat mDateFormat = new SimpleDateFormat("yyyy-MM-dd");
public DB(Context ctx) {
private DB(Context ctx) {
mContext = ctx;
DBHelper h = new DBHelper(ctx);
@ -568,12 +594,13 @@ public class DB {
app.marketVercode = c.getInt(c
.getColumnIndex("marketVercode"));
String sAdded = c.getString(c.getColumnIndex("added"));
app.added = (sAdded == null || sAdded.length() == 0) ? null : mDateFormat
.parse(sAdded);
app.added = (sAdded == null || sAdded.length() == 0) ? null
: mDateFormat.parse(sAdded);
String sLastUpdated = c.getString(c
.getColumnIndex("lastUpdated"));
app.lastUpdated = (sLastUpdated == null || sLastUpdated.length() == 0) ? null
: mDateFormat.parse(sLastUpdated);
app.lastUpdated = (sLastUpdated == null || sLastUpdated
.length() == 0) ? null : mDateFormat
.parse(sLastUpdated);
app.hasUpdates = false;
c2 = db.rawQuery("select * from " + TABLE_APK
@ -873,8 +900,12 @@ public class DB {
values.put("trackerURL", upapp.trackerURL);
values.put("sourceURL", upapp.sourceURL);
values.put("donateURL", upapp.donateURL);
values.put("added", upapp.added == null ? "" : mDateFormat.format(upapp.added));
values.put("lastUpdated", upapp.added == null ? "" : mDateFormat.format(upapp.lastUpdated));
values.put("added",
upapp.added == null ? "" : mDateFormat.format(upapp.added));
values.put(
"lastUpdated",
upapp.added == null ? "" : mDateFormat
.format(upapp.lastUpdated));
values.put("marketVersion", upapp.marketVersion);
values.put("marketVercode", upapp.marketVercode);
values.put("antiFeatures", CommaSeparatedList.str(upapp.antiFeatures));
@ -907,7 +938,8 @@ public class DB {
values.put("apkName", upapk.apkName);
values.put("apkSource", upapk.apkSource);
values.put("minSdkVersion", upapk.minSdkVersion);
values.put("added", upapk.added == null ? "" : mDateFormat.format(upapk.added));
values.put("added",
upapk.added == null ? "" : mDateFormat.format(upapk.added));
values.put("permissions", CommaSeparatedList.str(upapk.permissions));
values.put("features", CommaSeparatedList.str(upapk.features));
if (oldapk != null) {

View File

@ -70,8 +70,6 @@ public class FDroid extends TabActivity implements OnItemClickListener,
private static final int ABOUT = Menu.FIRST + 3;
private static final int SEARCH = Menu.FIRST + 4;
private DB db = null;
// Apps that are available to be installed
private AppListAdapter apps_av = new AppListAdapter(this);
@ -135,14 +133,12 @@ public class FDroid extends TabActivity implements OnItemClickListener,
@Override
protected void onStart() {
super.onStart();
db = new DB(this);
triedEmptyUpdate = false;
populateLists(true);
}
@Override
protected void onStop() {
db.close();
super.onStop();
}
@ -328,12 +324,19 @@ public class FDroid extends TabActivity implements OnItemClickListener,
long startTime = System.currentTimeMillis();
// Populate the category list with the real categories, and the locally
DB db;
Vector<DB.App> apps;
String cat_all, cat_whatsnew, cat_recentlyupdated;
try {
db = DB.getDB();
// Populate the category list with the real categories, and the
// locally
// generated meta-categories for "All", "What's New" and "Recently
// Updated"...
String cat_all = getString(R.string.category_all);
String cat_whatsnew = getString(R.string.category_whatsnew);
String cat_recentlyupdated = getString(R.string.category_recentlyupdated);
cat_all = getString(R.string.category_all);
cat_whatsnew = getString(R.string.category_whatsnew);
cat_recentlyupdated = getString(R.string.category_recentlyupdated);
categories.add(cat_all);
for (String s : db.getCategories()) {
Log.d("FDroid", "s: " + s);
@ -344,7 +347,11 @@ public class FDroid extends TabActivity implements OnItemClickListener,
if (currentCategory == null)
currentCategory = cat_all;
Vector<DB.App> apps = db.getApps(null, null, update, true);
apps = db.getApps(null, null, update, true);
} finally {
DB.releaseDB();
}
if (apps.isEmpty()) {
// Don't attempt this more than once - we may have invalid
// repositories.
@ -419,8 +426,9 @@ public class FDroid extends TabActivity implements OnItemClickListener,
public UpdateReceiver(Handler handler) {
super(handler);
}
@Override
protected void onReceiveResult (int resultCode, Bundle resultData) {
protected void onReceiveResult(int resultCode, Bundle resultData) {
if (resultCode == 1) {
Toast.makeText(FDroid.this,
getString(R.string.connection_error_msg),
@ -432,6 +440,7 @@ public class FDroid extends TabActivity implements OnItemClickListener,
pd.dismiss();
}
}
private UpdateReceiver mUpdateReceiver;
// Force a repo update now. A progress dialog is shown and the UpdateService

View File

@ -22,5 +22,13 @@ import android.app.Application;
public class FDroidApp extends Application {
@Override
public void onCreate() {
super.onCreate();
DB.initDB(getApplicationContext());
}
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2010-12 Ciaran Gultnieks, ciaran@ciarang.com
* Copyright (C) 2009 Roberto Jacinto, roberto.jacinto@caixamagica.pt
* Copyright (C) 2010 Ciaran Gultnieks, ciaran@ciarang.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -44,8 +44,6 @@ import android.widget.SimpleAdapter;
public class ManageRepo extends ListActivity {
private DB db = null;
private final int ADD_REPO = 1;
private final int REM_REPO = 2;
@ -59,8 +57,6 @@ public class ManageRepo extends ListActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.repolist);
db = new DB(this);
}
@Override
@ -71,7 +67,12 @@ public class ManageRepo extends ListActivity {
}
private void redraw() {
try {
DB db = DB.getDB();
repos = db.getRepos();
} finally {
DB.releaseDB();
}
List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
Map<String, Object> server_line;
@ -91,7 +92,7 @@ public class ManageRepo extends ListActivity {
byte[] fingerprint = digest.digest();
Formatter formatter = new Formatter(new StringBuilder());
formatter.format("%02X", fingerprint[0]);
for (int i=1; i < fingerprint.length; i++) {
for (int i = 1; i < fingerprint.length; i++) {
formatter.format(i % 5 == 0 ? " %02X" : ":%02X",
fingerprint[i]);
}
@ -104,9 +105,9 @@ public class ManageRepo extends ListActivity {
result.add(server_line);
}
SimpleAdapter show_out = new SimpleAdapter(this, result,
R.layout.repolisticons,
new String[] { "address", "inuse", "fingerprint" },
new int[] { R.id.uri, R.id.img, R.id.fingerprint });
R.layout.repolisticons, new String[] { "address", "inuse",
"fingerprint" }, new int[] { R.id.uri, R.id.img,
R.id.fingerprint });
setListAdapter(show_out);
}
@ -115,7 +116,12 @@ public class ManageRepo extends ListActivity {
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
try {
DB db = DB.getDB();
db.changeServerStatus(repos.get(position).address);
} finally {
DB.releaseDB();
}
changed = true;
redraw();
}
@ -150,7 +156,12 @@ public class ManageRepo extends ListActivity {
EditText uri = (EditText) alrt
.findViewById(R.id.edit_uri);
String uri_str = uri.getText().toString();
try {
DB db = DB.getDB();
db.addServer(uri_str, 10, null);
} finally {
DB.releaseDB();
}
changed = true;
redraw();
}
@ -180,11 +191,9 @@ public class ManageRepo extends ListActivity {
public void onClick(DialogInterface dialog,
int whichButton, boolean isChecked) {
if (isChecked) {
rem_lst
.addElement(repos.get(whichButton).address);
rem_lst.addElement(repos.get(whichButton).address);
} else {
rem_lst
.removeElement(repos.get(whichButton).address);
rem_lst.removeElement(repos.get(whichButton).address);
}
}
});
@ -192,7 +201,12 @@ public class ManageRepo extends ListActivity {
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
try {
DB db = DB.getDB();
db.removeServers(rem_lst);
} finally {
DB.releaseDB();
}
changed = true;
redraw();
}
@ -217,7 +231,6 @@ public class ManageRepo extends ListActivity {
if (changed)
ret.putExtra("update", true);
this.setResult(RESULT_OK, ret);
db.close();
super.finish();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2011 Ciaran Gultnieks, ciaran@ciarang.com
* Copyright (C) 2011-12 Ciaran Gultnieks, ciaran@ciarang.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -67,8 +67,13 @@ public class SearchResults extends ListActivity {
}
private void updateView() {
DB db = new DB(this);
Vector<DB.App> apps = db.getApps(null, mQuery, false, true);
Vector<DB.App> apps;
try {
DB db = DB.getDB();
apps = db.getApps(null, mQuery, false, true);
} finally {
DB.releaseDB();
}
TextView tv = (TextView) findViewById(R.id.description);
String headertext;
if(apps.size()==0)
@ -86,7 +91,6 @@ public class SearchResults extends ListActivity {
}
applist.notifyDataSetChanged();
setListAdapter(applist);
db.close();
}

View File

@ -89,7 +89,7 @@ public class UpdateService extends IntentService {
// Do the update...
DB db = null;
try {
db = new DB(getBaseContext());
db = DB.getDB();
boolean notify = prefs.getBoolean("updateNotify", false);
// Get the number of updates available before we
@ -141,7 +141,7 @@ public class UpdateService extends IntentService {
}
} finally {
if (db != null)
db.close();
DB.releaseDB();
}
}