Use temporary, in memory database for update process.
This increases the speed of the complex queries required at the end of the update process to: * calculate suggested version codes * figure out icon urls * etc, by two orders of magnitude.
This commit is contained in:
parent
ab248525e0
commit
721dcb00c1
@ -91,9 +91,8 @@ public class RepoPersister {
|
||||
// end of the process. This is due to the fact that we can't verify the cert
|
||||
// the index was signed with until we've finished reading it - and we don't
|
||||
// want to put stuff in the real database until we are sure it is from a
|
||||
// trusted source.
|
||||
// trusted source. It also helps performance as it is done via an in-memory database.
|
||||
TempAppProvider.Helper.init(context);
|
||||
TempApkProvider.Helper.init(context);
|
||||
hasBeenInitialized = true;
|
||||
}
|
||||
|
||||
|
@ -68,12 +68,16 @@ public class TempApkProvider extends ApkProvider {
|
||||
/**
|
||||
* Deletes the old temporary table (if it exists). Then creates a new temporary apk provider
|
||||
* table and populates it with all the data from the real apk provider table.
|
||||
*
|
||||
* This is package local because it must be invoked after
|
||||
* {@link org.fdroid.fdroid.data.TempAppProvider.Helper#init(Context)}. Due to this
|
||||
* dependence, that method invokes this one itself, rather than leaving it to the
|
||||
* {@link RepoPersister}.
|
||||
*/
|
||||
public static void init(Context context) {
|
||||
static void init(Context context) {
|
||||
Uri uri = Uri.withAppendedPath(getContentUri(), PATH_INIT);
|
||||
context.getContentResolver().insert(uri, new ContentValues());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -123,11 +127,11 @@ public class TempApkProvider extends ApkProvider {
|
||||
|
||||
private void initTable() {
|
||||
final SQLiteDatabase db = db();
|
||||
db.execSQL("DROP TABLE IF EXISTS " + getTableName());
|
||||
db.execSQL("CREATE TABLE " + getTableName() + " AS SELECT * FROM " + DBHelper.TABLE_APK);
|
||||
db.execSQL("CREATE INDEX IF NOT EXISTS apk_vercode on " + getTableName() + " (vercode);");
|
||||
db.execSQL("CREATE INDEX IF NOT EXISTS apk_id on " + getTableName() + " (id);");
|
||||
db.execSQL("CREATE INDEX IF NOT EXISTS apk_compatible ON " + getTableName() + " (compatible);");
|
||||
final String memoryDbName = TempAppProvider.DB;
|
||||
db.execSQL("CREATE TABLE " + memoryDbName + "." + getTableName() + " AS SELECT * FROM main." + DBHelper.TABLE_APK);
|
||||
db.execSQL("CREATE INDEX IF NOT EXISTS " + memoryDbName + ".apk_vercode on " + getTableName() + " (vercode);");
|
||||
db.execSQL("CREATE INDEX IF NOT EXISTS " + memoryDbName + ".apk_id on " + getTableName() + " (id);");
|
||||
db.execSQL("CREATE INDEX IF NOT EXISTS " + memoryDbName + ".apk_compatible ON " + getTableName() + " (compatible);");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,8 +3,10 @@ package org.fdroid.fdroid.data;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.UriMatcher;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import org.fdroid.fdroid.Utils;
|
||||
@ -16,6 +18,11 @@ public class TempAppProvider extends AppProvider {
|
||||
|
||||
private static final String TAG = "TempAppProvider";
|
||||
|
||||
/**
|
||||
* The name of the in memory database used for updating.
|
||||
*/
|
||||
static final String DB = "temp_update_db";
|
||||
|
||||
private static final String PROVIDER_NAME = "TempAppProvider";
|
||||
|
||||
private static final String TABLE_TEMP_APP = "temp_" + DBHelper.TABLE_APP;
|
||||
@ -60,6 +67,7 @@ public class TempAppProvider extends AppProvider {
|
||||
public static void init(Context context) {
|
||||
Uri uri = Uri.withAppendedPath(getContentUri(), PATH_INIT);
|
||||
context.getContentResolver().insert(uri, new ContentValues());
|
||||
TempApkProvider.Helper.init(context);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -111,13 +119,30 @@ public class TempAppProvider extends AppProvider {
|
||||
return count;
|
||||
}
|
||||
|
||||
private void ensureTempTableDetached(SQLiteDatabase db) {
|
||||
Cursor cursor = db.rawQuery("PRAGMA database_list", null);
|
||||
try {
|
||||
cursor.moveToFirst();
|
||||
while (!cursor.isAfterLast()) {
|
||||
String name = cursor.getString(cursor.getColumnIndex("name"));
|
||||
if (TextUtils.equals(name, DB)) {
|
||||
db.execSQL("DETACH DATABASE " + DB);
|
||||
}
|
||||
cursor.moveToNext();
|
||||
}
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void initTable() {
|
||||
final SQLiteDatabase db = db();
|
||||
db.execSQL("DROP TABLE IF EXISTS " + getTableName());
|
||||
db.execSQL("CREATE TABLE " + getTableName() + " AS SELECT * FROM " + DBHelper.TABLE_APP);
|
||||
db.execSQL("CREATE INDEX IF NOT EXISTS app_id ON " + getTableName() + " (id);");
|
||||
db.execSQL("CREATE INDEX IF NOT EXISTS app_upstreamVercode ON " + getTableName() + " (upstreamVercode);");
|
||||
db.execSQL("CREATE INDEX IF NOT EXISTS app_compatible ON " + getTableName() + " (compatible);");
|
||||
ensureTempTableDetached(db);
|
||||
db.execSQL("ATTACH DATABASE ':memory:' AS " + DB);
|
||||
db.execSQL("CREATE TABLE " + DB + "." + getTableName() + " AS SELECT * FROM main." + DBHelper.TABLE_APP);
|
||||
db.execSQL("CREATE INDEX IF NOT EXISTS " + DB + ".app_id ON " + getTableName() + " (id);");
|
||||
db.execSQL("CREATE INDEX IF NOT EXISTS " + DB + ".app_upstreamVercode ON " + getTableName() + " (upstreamVercode);");
|
||||
db.execSQL("CREATE INDEX IF NOT EXISTS " + DB + ".app_compatible ON " + getTableName() + " (compatible);");
|
||||
}
|
||||
|
||||
private void commitTable() {
|
||||
@ -125,21 +150,22 @@ public class TempAppProvider extends AppProvider {
|
||||
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);
|
||||
final String tempApp = DB + "." + TempAppProvider.TABLE_TEMP_APP;
|
||||
final String tempApk = DB + "." + TempApkProvider.TABLE_TEMP_APK;
|
||||
|
||||
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);
|
||||
db.execSQL("DELETE FROM " + DBHelper.TABLE_APP + " WHERE 1");
|
||||
db.execSQL("INSERT INTO " + DBHelper.TABLE_APP + " SELECT * FROM " + tempApp);
|
||||
|
||||
db.execSQL("DELETE FROM " + DBHelper.TABLE_APK + " WHERE 1");
|
||||
db.execSQL("INSERT INTO " + DBHelper.TABLE_APK + " SELECT * FROM " + tempApk);
|
||||
|
||||
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();
|
||||
db.execSQL("DETACH DATABASE " + DB); // Can't be done in a transaction.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user