Reorganise database access to prevent locking issues
This commit is contained in:
parent
568b615ecf
commit
0623801474
@ -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);
|
||||
app = db.getApps(appid, null, true, false).get(0);
|
||||
DB.Apk curver = app.getCurrentVersion(compatChecker);
|
||||
DB.Apk curver;
|
||||
try {
|
||||
DB db = DB.getDB();
|
||||
compatChecker = db.getCompatibilityChecker();
|
||||
app = db.getApps(appid, null, true, false).get(0);
|
||||
curver = app.getCurrentVersion(compatChecker);
|
||||
} finally {
|
||||
DB.releaseDB();
|
||||
}
|
||||
app_currentvercode = curver == null ? 0 : curver.vercode;
|
||||
|
||||
// Get the signature of the installed package...
|
||||
|
@ -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) {
|
||||
|
@ -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,23 +324,34 @@ public class FDroid extends TabActivity implements OnItemClickListener,
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
// 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);
|
||||
categories.add(cat_all);
|
||||
for (String s : db.getCategories()) {
|
||||
Log.d("FDroid", "s: " + s);
|
||||
categories.add(s);
|
||||
}
|
||||
categories.add(cat_whatsnew);
|
||||
categories.add(cat_recentlyupdated);
|
||||
if (currentCategory == null)
|
||||
currentCategory = cat_all;
|
||||
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"...
|
||||
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);
|
||||
categories.add(s);
|
||||
}
|
||||
categories.add(cat_whatsnew);
|
||||
categories.add(cat_recentlyupdated);
|
||||
if (currentCategory == null)
|
||||
currentCategory = cat_all;
|
||||
|
||||
apps = db.getApps(null, null, update, true);
|
||||
} finally {
|
||||
DB.releaseDB();
|
||||
}
|
||||
|
||||
Vector<DB.App> apps = db.getApps(null, null, update, true);
|
||||
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
|
||||
|
@ -22,5 +22,13 @@ import android.app.Application;
|
||||
|
||||
public class FDroidApp extends Application {
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
DB.initDB(getApplicationContext());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -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() {
|
||||
repos = db.getRepos();
|
||||
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,22 +92,22 @@ 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]);
|
||||
fingerprint[i]);
|
||||
}
|
||||
server_line.put("fingerprint", formatter.toString());
|
||||
} catch (Exception e) {
|
||||
Log.w("FDroid", "Unable to get certificate fingerprint.\n"
|
||||
+ Log.getStackTraceString(e));
|
||||
+ Log.getStackTraceString(e));
|
||||
}
|
||||
}
|
||||
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);
|
||||
db.changeServerStatus(repos.get(position).address);
|
||||
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();
|
||||
db.addServer(uri_str, 10, null);
|
||||
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) {
|
||||
db.removeServers(rem_lst);
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user