From 9727dc505c4c6854b4e27656f31456b994f1d123 Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Sun, 13 Dec 2015 09:14:40 +1100 Subject: [PATCH 1/3] Rename temp tables rather than `DELETE` + `INSERT SELECT`. This requires renaming the old app/apk tables to be deleted and the temp ones to be renamed. This is done in a transaction to ensure we always have at least `fdroid_app` and `fdroid_apk`. Well, two transactions, one for renaming the `fdroid_app` table and one for `fdroid_apk`. --- .../src/org/fdroid/fdroid/UpdateService.java | 1 - .../org/fdroid/fdroid/data/RepoPersister.java | 3 +- .../fdroid/fdroid/data/TempApkProvider.java | 25 ++------------- .../fdroid/fdroid/data/TempAppProvider.java | 32 +++++++++++++++---- 4 files changed, 28 insertions(+), 33 deletions(-) diff --git a/F-Droid/src/org/fdroid/fdroid/UpdateService.java b/F-Droid/src/org/fdroid/fdroid/UpdateService.java index b8f00f4b5..1b9543a12 100644 --- a/F-Droid/src/org/fdroid/fdroid/UpdateService.java +++ b/F-Droid/src/org/fdroid/fdroid/UpdateService.java @@ -391,7 +391,6 @@ public class UpdateService extends IntentService implements ProgressListener { if (!changes) { Utils.debugLog(TAG, "Not checking app details or compatibility, because all repos were up to date."); } else { - sendStatus(this, STATUS_INFO, getString(R.string.status_checking_compatibility)); notifyContentProviders(); if (prefs.getBoolean(Preferences.PREF_UPD_NOTIFY, true)) { diff --git a/F-Droid/src/org/fdroid/fdroid/data/RepoPersister.java b/F-Droid/src/org/fdroid/fdroid/data/RepoPersister.java index d50f4fa5d..1164e77c8 100644 --- a/F-Droid/src/org/fdroid/fdroid/data/RepoPersister.java +++ b/F-Droid/src/org/fdroid/fdroid/data/RepoPersister.java @@ -78,8 +78,7 @@ public class RepoPersister { public void commit(ContentValues repoDetailsToSave) throws RepoUpdater.UpdateException { flushBufferToDb(); - TempAppProvider.Helper.commit(context); - TempApkProvider.Helper.commit(context); + TempAppProvider.Helper.commitAppsAndApks(context); RepoProvider.Helper.update(context, repo, repoDetailsToSave); } diff --git a/F-Droid/src/org/fdroid/fdroid/data/TempApkProvider.java b/F-Droid/src/org/fdroid/fdroid/data/TempApkProvider.java index 995a6f025..bf4cd7340 100644 --- a/F-Droid/src/org/fdroid/fdroid/data/TempApkProvider.java +++ b/F-Droid/src/org/fdroid/fdroid/data/TempApkProvider.java @@ -17,26 +17,23 @@ public class TempApkProvider extends ApkProvider { private static final String PROVIDER_NAME = "TempApkProvider"; - static final String TABLE_TEMP_APK = "temp_fdroid_apk"; + static final String TABLE_TEMP_APK = "temp_" + DBHelper.TABLE_APK; private static final String PATH_INIT = "init"; - private static final String PATH_COMMIT = "commit"; private static final int CODE_INIT = 10000; - private static final int CODE_COMMIT = CODE_INIT + 1; private static final UriMatcher matcher = new UriMatcher(-1); static { matcher.addURI(getAuthority(), PATH_INIT, CODE_INIT); - matcher.addURI(getAuthority(), PATH_COMMIT, CODE_COMMIT); matcher.addURI(getAuthority(), PATH_APK + "/#/*", CODE_SINGLE); matcher.addURI(getAuthority(), PATH_REPO_APK + "/#/*", CODE_REPO_APK); } @Override protected String getTableName() { - return "temp_" + super.getTableName(); + return TABLE_TEMP_APK; } public static String getAuthority() { @@ -76,15 +73,6 @@ public class TempApkProvider extends ApkProvider { context.getContentResolver().insert(uri, new ContentValues()); } - /** - * Saves data from the temp table to the apk table, by removing _EVERYTHING_ from the real - * apk table and inserting all of the records from here. The temporary table is then removed. - */ - public static void commit(Context context) { - Uri uri = Uri.withAppendedPath(getContentUri(), PATH_COMMIT); - context.getContentResolver().insert(uri, new ContentValues()); - } - } @Override @@ -93,9 +81,6 @@ public class TempApkProvider extends ApkProvider { case CODE_INIT: initTable(); return null; - case CODE_COMMIT: - commitTable(); - return null; default: return super.insert(uri, values); } @@ -140,10 +125,4 @@ public class TempApkProvider extends ApkProvider { write().execSQL("CREATE TABLE " + getTableName() + " AS SELECT * FROM " + DBHelper.TABLE_APK); } - private void commitTable() { - Log.i(TAG, "Deleting all apks from " + DBHelper.TABLE_APK + " so they can be copied from " + getTableName()); - write().execSQL("DELETE FROM " + DBHelper.TABLE_APK); - write().execSQL("INSERT INTO " + DBHelper.TABLE_APK + " SELECT * FROM " + getTableName()); - getContext().getContentResolver().notifyChange(ApkProvider.getContentUri(), null); - } } diff --git a/F-Droid/src/org/fdroid/fdroid/data/TempAppProvider.java b/F-Droid/src/org/fdroid/fdroid/data/TempAppProvider.java index 391265d01..5949c97e9 100644 --- a/F-Droid/src/org/fdroid/fdroid/data/TempAppProvider.java +++ b/F-Droid/src/org/fdroid/fdroid/data/TempAppProvider.java @@ -3,9 +3,12 @@ package org.fdroid.fdroid.data; import android.content.ContentValues; import android.content.Context; import android.content.UriMatcher; +import android.database.sqlite.SQLiteDatabase; import android.net.Uri; import android.util.Log; +import org.fdroid.fdroid.Utils; + /** * This class does all of its operations in a temporary sqlite table. */ @@ -15,7 +18,7 @@ public class TempAppProvider extends AppProvider { private static final String PROVIDER_NAME = "TempAppProvider"; - private static final String TABLE_TEMP_APP = "temp_fdroid_app"; + private static final String TABLE_TEMP_APP = "temp_" + DBHelper.TABLE_APP; private static final String PATH_INIT = "init"; private static final String PATH_COMMIT = "commit"; @@ -63,11 +66,10 @@ public class TempAppProvider extends AppProvider { * Saves data from the temp table to the apk table, by removing _EVERYTHING_ from the real * apk table and inserting all of the records from here. The temporary table is then removed. */ - public static void commit(Context context) { + public static void commitAppsAndApks(Context context) { Uri uri = Uri.withAppendedPath(getContentUri(), PATH_COMMIT); context.getContentResolver().insert(uri, new ContentValues()); } - } @Override @@ -115,9 +117,25 @@ public class TempAppProvider extends AppProvider { } private void commitTable() { - Log.i(TAG, "Deleting all apks from " + DBHelper.TABLE_APP + " so they can be copied from " + getTableName()); - write().execSQL("DELETE FROM " + DBHelper.TABLE_APP); - write().execSQL("INSERT INTO " + DBHelper.TABLE_APP + " SELECT * FROM " + getTableName()); - getContext().getContentResolver().notifyChange(AppProvider.getContentUri(), null); + final SQLiteDatabase db = write(); + try { + db.beginTransaction(); + + Log.i(TAG, "Renaming " + TABLE_TEMP_APP + " to " + DBHelper.TABLE_APP); + db.execSQL("DROP TABLE " + DBHelper.TABLE_APP); + db.execSQL("ALTER TABLE " + TABLE_TEMP_APP + " RENAME TO " + DBHelper.TABLE_APP); + + Log.i(TAG, "Renaming " + TempApkProvider.TABLE_TEMP_APK + " to " + DBHelper.TABLE_APK); + db.execSQL("DROP TABLE " + DBHelper.TABLE_APK); + db.execSQL("ALTER TABLE " + TempApkProvider.TABLE_TEMP_APK + " RENAME TO " + DBHelper.TABLE_APK); + + Utils.debugLog(TAG, "Successfully renamed both tables, will commit transaction"); + db.setTransactionSuccessful(); + + getContext().getContentResolver().notifyChange(AppProvider.getContentUri(), null); + getContext().getContentResolver().notifyChange(ApkProvider.getContentUri(), null); + } finally { + db.endTransaction(); + } } } From c24cd89028e0708ef640b7e6b48e54dd8c750c95 Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Sun, 13 Dec 2015 10:28:03 +1100 Subject: [PATCH 2/3] Only create compatibility checker once per repo. Looks like a non-trivial amount of work is done in the constructor interrogating the features of the current device. This only needs to be done once. --- F-Droid/src/org/fdroid/fdroid/data/RepoPersister.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/F-Droid/src/org/fdroid/fdroid/data/RepoPersister.java b/F-Droid/src/org/fdroid/fdroid/data/RepoPersister.java index 1164e77c8..2302ddd23 100644 --- a/F-Droid/src/org/fdroid/fdroid/data/RepoPersister.java +++ b/F-Droid/src/org/fdroid/fdroid/data/RepoPersister.java @@ -62,9 +62,13 @@ public class RepoPersister { @NonNull private final Map> apksToSave = new HashMap<>(); + @NonNull + private final CompatibilityChecker checker; + public RepoPersister(@NonNull Context context, @NonNull Repo repo) { this.repo = repo; this.context = context; + checker = new CompatibilityChecker(context); } public void saveToDb(App app, List packages) throws RepoUpdater.UpdateException { @@ -281,7 +285,6 @@ public class RepoPersister { * in order to see if, and why an apk is not compatible. */ private void calcApkCompatibilityFlags(List apks) { - final CompatibilityChecker checker = new CompatibilityChecker(context); for (final Apk apk : apks) { final List reasons = checker.getIncompatibleReasons(apk); if (reasons.size() > 0) { From 1ae1ae73685f955493ca165520117b1d6b441ddf Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Sun, 13 Dec 2015 18:04:02 +1100 Subject: [PATCH 3/3] Add indexes to temp tables when updating. The idnexes which are added are for those columns which are used to calculate information such as latest upstream version. These queries use subqueries which seemed to be adversely impacted by the lack of indexes. In total, reduced update time on test device from just over 100 seconds to just over 60 seconds. --- F-Droid/src/org/fdroid/fdroid/data/TempApkProvider.java | 3 +++ F-Droid/src/org/fdroid/fdroid/data/TempAppProvider.java | 3 +++ 2 files changed, 6 insertions(+) diff --git a/F-Droid/src/org/fdroid/fdroid/data/TempApkProvider.java b/F-Droid/src/org/fdroid/fdroid/data/TempApkProvider.java index bf4cd7340..269437122 100644 --- a/F-Droid/src/org/fdroid/fdroid/data/TempApkProvider.java +++ b/F-Droid/src/org/fdroid/fdroid/data/TempApkProvider.java @@ -123,6 +123,9 @@ public class TempApkProvider extends ApkProvider { private void initTable() { write().execSQL("DROP TABLE IF EXISTS " + getTableName()); write().execSQL("CREATE TABLE " + getTableName() + " AS SELECT * FROM " + DBHelper.TABLE_APK); + write().execSQL("CREATE INDEX IF NOT EXISTS apk_vercode on " + getTableName() + " (vercode);"); + write().execSQL("CREATE INDEX IF NOT EXISTS apk_id on " + getTableName() + " (id);"); + write().execSQL("CREATE INDEX IF NOT EXISTS apk_compatible ON " + getTableName() + " (compatible);"); } } diff --git a/F-Droid/src/org/fdroid/fdroid/data/TempAppProvider.java b/F-Droid/src/org/fdroid/fdroid/data/TempAppProvider.java index 5949c97e9..e60a8271e 100644 --- a/F-Droid/src/org/fdroid/fdroid/data/TempAppProvider.java +++ b/F-Droid/src/org/fdroid/fdroid/data/TempAppProvider.java @@ -114,6 +114,9 @@ public class TempAppProvider extends AppProvider { private void initTable() { write().execSQL("DROP TABLE IF EXISTS " + getTableName()); write().execSQL("CREATE TABLE " + getTableName() + " AS SELECT * FROM " + DBHelper.TABLE_APP); + write().execSQL("CREATE INDEX IF NOT EXISTS app_id ON " + getTableName() + " (id);"); + write().execSQL("CREATE INDEX IF NOT EXISTS app_upstreamVercode ON " + getTableName() + " (upstreamVercode);"); + write().execSQL("CREATE INDEX IF NOT EXISTS app_compatible ON " + getTableName() + " (compatible);"); } private void commitTable() {