From 657ae584182f6f12e7b424dd2a5d5a3cbb5274ca Mon Sep 17 00:00:00 2001 From: Henrik Tunedal Date: Mon, 14 Feb 2011 01:32:13 +0100 Subject: [PATCH] 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). --- src/org/fdroid/fdroid/DB.java | 12 ++++++++++++ src/org/fdroid/fdroid/RepoXMLHandler.java | 11 +++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/org/fdroid/fdroid/DB.java b/src/org/fdroid/fdroid/DB.java index 96fedc77c..32ca3b443 100644 --- a/src/org/fdroid/fdroid/DB.java +++ b/src/org/fdroid/fdroid/DB.java @@ -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. diff --git a/src/org/fdroid/fdroid/RepoXMLHandler.java b/src/org/fdroid/fdroid/RepoXMLHandler.java index 89d138c53..eba7107b0 100644 --- a/src/org/fdroid/fdroid/RepoXMLHandler.java +++ b/src/org/fdroid/fdroid/RepoXMLHandler.java @@ -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 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(); } }