Wrap database update in an explicit transaction

All changes to the database in SQLite must be done within a
transaction, so if there isn't one in progress one will be started
implicitly, i.e. each change will be done in a separate transaction.

Since committing a transaction is a fairly expensive operation - on
some filesystems ridiculously expensive - it should be done as
sparingly as possible.

In tests on my Galaxy S, this change makes the update between 2500%
and 4500% faster (for slightly over 100 applications).
This commit is contained in:
Henrik Tunedal 2011-02-14 01:32:13 +01:00
parent 0d1be2d967
commit 657ae58418
2 changed files with 19 additions and 4 deletions

View File

@ -491,6 +491,10 @@ public class DB {
updateApps = getApps(null, null, true);
Log.d("FDroid", "AppUpdate: " + updateApps.size()
+ " apps before starting.");
// Wrap the whole update in a transaction. Make sure to call
// either endUpdate or cancelUpdate to commit or discard it,
// respectively.
db.beginTransaction();
}
// Called when a repo update ends. Any applications that have not been
@ -521,12 +525,20 @@ public class DB {
}
}
}
// Commit updates to the database.
db.setTransactionSuccessful();
db.endTransaction();
Log.d("FDroid", "AppUpdate: " + updateApps.size()
+ " apps on completion.");
updateApps = null;
return;
}
// Called instead of endUpdate if the update failed.
public void cancelUpdate() {
db.endTransaction();
}
// Called during update to supply new details for an application (or
// details of a completely new one). Calls to this must be wrapped by
// a call to beginUpdate and a call to endUpdate.

View File

@ -223,6 +223,7 @@ public class RepoXMLHandler extends DefaultHandler {
public static boolean doUpdates(Context ctx, DB db) {
long startTime = System.currentTimeMillis();
boolean success = true;
db.beginUpdate();
Vector<DB.Repo> repos = db.getRepos();
for (DB.Repo repo : repos) {
@ -262,12 +263,12 @@ public class RepoXMLHandler extends DefaultHandler {
jar.close();
if (certs == null) {
Log.d("FDroid", "No signature found in index");
return false;
return success = false;
}
if (certs.length != 1) {
Log.d("FDroid", "Expected one signature - found "
+ certs.length);
return false;
return success = false;
}
byte[] sig = certs[0].getEncoded();
@ -285,7 +286,7 @@ public class RepoXMLHandler extends DefaultHandler {
if (!ssig.equals(repo.pubkey)) {
Log.d("FDroid", "Index signature mismatch");
return false;
return success = false;
}
} else {
@ -324,10 +325,12 @@ public class RepoXMLHandler extends DefaultHandler {
} catch (Exception e) {
Log.e("FDroid", "Exception updating from " + repo.address
+ ":\n" + Log.getStackTraceString(e));
return false;
return success = false;
} finally {
ctx.deleteFile("tempindex.xml");
ctx.deleteFile("tempindex.jar");
if (!success)
db.cancelUpdate();
}
}