Small optimization to UpdateRepos

This commit is contained in:
topjohnwu 2018-07-04 20:13:12 +08:00
parent c78896a335
commit 153d0f5505
5 changed files with 89 additions and 117 deletions

View File

@ -90,7 +90,6 @@ public class ProcessRepoZip extends ParallelTask<Void, Object, Boolean> {
HttpURLConnection conn; HttpURLConnection conn;
do { do {
conn = WebService.request(mLink, null); conn = WebService.request(mLink, null);
if (conn == null) return null;
total = conn.getContentLength(); total = conn.getContentLength();
if (total < 0) if (total < 0)
conn.disconnect(); conn.disconnect();

View File

@ -1,6 +1,8 @@
package com.topjohnwu.magisk.asyncs; package com.topjohnwu.magisk.asyncs;
import android.database.Cursor;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.text.TextUtils;
import com.topjohnwu.magisk.MagiskManager; import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.ReposFragment; import com.topjohnwu.magisk.ReposFragment;
@ -11,20 +13,22 @@ import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.WebService; import com.topjohnwu.magisk.utils.WebService;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import java.io.File;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
public class UpdateRepos extends ParallelTask<Void, Void, Void> { public class UpdateRepos extends ParallelTask<Void, Void, Void> {
@ -35,7 +39,8 @@ public class UpdateRepos extends ParallelTask<Void, Void, Void> {
private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
private MagiskManager mm; private MagiskManager mm;
private List<String> cached, etags, newEtags = new LinkedList<>(); private List<String> etags, newEtags = new LinkedList<>();
private Set<String> cached;
private boolean forceUpdate; private boolean forceUpdate;
private AtomicInteger taskCount = new AtomicInteger(0); private AtomicInteger taskCount = new AtomicInteger(0);
final private Object allDone = new Object(); final private Object allDone = new Object();
@ -43,13 +48,6 @@ public class UpdateRepos extends ParallelTask<Void, Void, Void> {
public UpdateRepos(boolean force) { public UpdateRepos(boolean force) {
mm = MagiskManager.get(); mm = MagiskManager.get();
mm.repoLoadDone.reset(); mm.repoLoadDone.reset();
// Legacy data cleanup
File old = new File(mm.getApplicationInfo().dataDir + "/shared_prefs", "RepoMap.xml");
if (old.exists() || mm.prefs.getString("repomap", null) != null) {
old.delete();
mm.prefs.edit().remove("version").remove("repomap").remove(Const.Key.ETAG_KEY).apply();
mm.repoDB.clearRepo();
}
forceUpdate = force; forceUpdate = force;
} }
@ -82,75 +80,61 @@ public class UpdateRepos extends ParallelTask<Void, Void, Void> {
} }
} }
private void loadJSON(String jsonString) throws Exception { private boolean loadJSON(String jsonString) throws JSONException, ParseException {
JSONArray jsonArray = new JSONArray(jsonString); JSONArray jsonArray = new JSONArray(jsonString);
// Empty page, throw error // Empty page, halt
if (jsonArray.length() == 0) if (jsonArray.length() == 0)
throw new Exception(); return false;
for (int i = 0; i < jsonArray.length(); i++) { for (int i = 0; i < jsonArray.length(); i++) {
JSONObject rawRepo = jsonArray.getJSONObject(i); JSONObject rawRepo = jsonArray.getJSONObject(i);
String id = rawRepo.getString("description"); String id = rawRepo.getString("description");
String name = rawRepo.getString("name"); String name = rawRepo.getString("name");
Date date = dateFormat.parse(rawRepo.getString("pushed_at")); Date date = dateFormat.parse(rawRepo.getString("pushed_at"));
final List<String> c = cached; Set<String> set = Collections.synchronizedSet(cached);
queueTask(() -> { queueTask(() -> {
Repo repo = mm.repoDB.getRepo(id); Repo repo = mm.repoDB.getRepo(id);
Boolean updated;
try { try {
if (repo == null) { if (repo == null)
repo = new Repo(name, date); repo = new Repo(name);
updated = true; else
} else { set.remove(id);
// Popout from cached repo.update(date);
synchronized (c) {
c.remove(id);
}
if (forceUpdate) {
repo.update();
updated = true;
} else {
updated = repo.update(date);
}
}
if (updated) {
mm.repoDB.addRepo(repo); mm.repoDB.addRepo(repo);
publishProgress(); publishProgress();
}
} catch (Repo.IllegalRepoException e) { } catch (Repo.IllegalRepoException e) {
Logger.debug(e.getMessage()); Logger.debug(e.getMessage());
mm.repoDB.removeRepo(id); mm.repoDB.removeRepo(id);
} }
}); });
} }
return true;
} }
private boolean loadPage(int page, int mode) { private boolean loadPage(int page, int mode) {
Map<String, String> header = new HashMap<>(); Map<String, String> header = new HashMap<>();
String etag = (mode == CHECK_ETAG && page < etags.size()) ? etags.get(page) : ""; if (mode == CHECK_ETAG && page < etags.size())
header.put(Const.Key.IF_NONE_MATCH, etag); header.put(Const.Key.IF_NONE_MATCH, etags.get(page));
String url = Utils.fmt(Const.Url.REPO_URL, page + 1); String url = Utils.fmt(Const.Url.REPO_URL, page + 1);
HttpURLConnection conn = WebService.request(url, header);
try { try {
if (conn == null) HttpURLConnection conn = WebService.request(url, header);
throw new Exception();
if (conn.getResponseCode() == HttpURLConnection.HTTP_NOT_MODIFIED) { if (conn.getResponseCode() == HttpURLConnection.HTTP_NOT_MODIFIED) {
// Current page is not updated, check the next page // Current page is not updated, check the next page
return page + 1 < etags.size() && loadPage(page + 1, CHECK_ETAG); return loadPage(page + 1, CHECK_ETAG);
} }
loadJSON(WebService.getString(conn)); if (!loadJSON(WebService.getString(conn)))
return mode != CHECK_ETAG;
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
// Don't continue return false;
return true;
} }
/* If one page is updated, we force update all pages */ /* If one page is updated, we force update all pages */
// Update ETAG // Update ETAG
etag = header.get(Const.Key.ETAG_KEY); String etag = header.get(Const.Key.ETAG_KEY);
etag = etag.substring(etag.indexOf('\"'), etag.lastIndexOf('\"') + 1); etag = etag.substring(etag.indexOf('\"'), etag.lastIndexOf('\"') + 1);
if (mode == LOAD_PREV) { if (mode == LOAD_PREV) {
// We are loading a previous page, push the new tag to the front // We are loading a previous page, push the new tag to the front
@ -188,16 +172,22 @@ public class UpdateRepos extends ParallelTask<Void, Void, Void> {
@Override @Override
protected Void doInBackground(Void... voids) { protected Void doInBackground(Void... voids) {
etags = new ArrayList<>(Arrays.asList(mm.prefs.getString(Const.Key.ETAG_KEY, "").split(","))); etags = Arrays.asList(mm.prefs.getString(Const.Key.ETAG_KEY, "").split(","));
cached = mm.repoDB.getRepoIDList(); cached = mm.repoDB.getRepoIDSet();
if (!loadPage(0, CHECK_ETAG)) { if (loadPage(0, CHECK_ETAG)) {
// Nothing changed online waitTasks();
if (forceUpdate) {
for (String id : cached) { // The leftover cached means they are removed from online repo
if (id == null) continue; mm.repoDB.removeRepo(cached);
// Update ETag
mm.prefs.edit().putString(Const.Key.ETAG_KEY, TextUtils.join(",", newEtags)).apply();
} else if (forceUpdate) {
Cursor c = mm.repoDB.getRawCursor();
while (c.moveToNext()) {
Repo repo = new Repo(c);
queueTask(() -> { queueTask(() -> {
Repo repo = mm.repoDB.getRepo(id);
try { try {
repo.update(); repo.update();
mm.repoDB.addRepo(repo); mm.repoDB.addRepo(repo);
@ -207,21 +197,7 @@ public class UpdateRepos extends ParallelTask<Void, Void, Void> {
} }
}); });
} }
}
waitTasks(); waitTasks();
} else {
waitTasks();
// The leftover cached means they are removed from online repo
mm.repoDB.removeRepo(cached);
// Update ETag
StringBuilder etagBuilder = new StringBuilder();
for (int i = 0; i < newEtags.size(); ++i) {
if (i != 0) etagBuilder.append(",");
etagBuilder.append(newEtags.get(i));
}
mm.prefs.edit().putString(Const.Key.ETAG_KEY, etagBuilder.toString()).apply();
} }
return null; return null;
} }

View File

@ -17,10 +17,8 @@ public class Repo extends BaseModule {
private String repoName; private String repoName;
private Date mLastUpdate; private Date mLastUpdate;
public Repo(String name, Date lastUpdate) throws IllegalRepoException { public Repo(String name) {
mLastUpdate = lastUpdate;
repoName = name; repoName = name;
update();
} }
public Repo(Cursor c) { public Repo(Cursor c) {
@ -48,13 +46,9 @@ public class Repo extends BaseModule {
} }
} }
public boolean update(Date lastUpdate) throws IllegalRepoException { public void update(Date lastUpdate) throws IllegalRepoException {
if (lastUpdate.after(mLastUpdate)) {
mLastUpdate = lastUpdate; mLastUpdate = lastUpdate;
update(); update();
return true;
}
return false;
} }
@Override @Override

View File

@ -10,8 +10,8 @@ import com.topjohnwu.magisk.container.Repo;
import com.topjohnwu.magisk.utils.Const; import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.Utils; import com.topjohnwu.magisk.utils.Utils;
import java.util.LinkedList; import java.util.HashSet;
import java.util.List; import java.util.Set;
public class RepoDatabaseHelper extends SQLiteOpenHelper { public class RepoDatabaseHelper extends SQLiteOpenHelper {
@ -74,7 +74,7 @@ public class RepoDatabaseHelper extends SQLiteOpenHelper {
mDb.delete(TABLE_NAME, "repo_name=?", new String[] { repo.getRepoName() }); mDb.delete(TABLE_NAME, "repo_name=?", new String[] { repo.getRepoName() });
} }
public void removeRepo(List<String> list) { public void removeRepo(Iterable<String> list) {
for (String id : list) { for (String id : list) {
if (id == null) continue; if (id == null) continue;
mDb.delete(TABLE_NAME, "id=?", new String[] { id }); mDb.delete(TABLE_NAME, "id=?", new String[] { id });
@ -94,6 +94,10 @@ public class RepoDatabaseHelper extends SQLiteOpenHelper {
return null; return null;
} }
public Cursor getRawCursor() {
return mDb.query(TABLE_NAME, null, null, null, null, null, null);
}
public Cursor getRepoCursor() { public Cursor getRepoCursor() {
String orderBy = null; String orderBy = null;
switch (mm.repoOrder) { switch (mm.repoOrder) {
@ -108,13 +112,13 @@ public class RepoDatabaseHelper extends SQLiteOpenHelper {
null, null, orderBy); null, null, orderBy);
} }
public List<String> getRepoIDList() { public Set<String> getRepoIDSet() {
LinkedList<String> ret = new LinkedList<>(); HashSet<String> set = new HashSet<>(300);
try (Cursor c = mDb.query(TABLE_NAME, null, null, null, null, null, null)) { try (Cursor c = mDb.query(TABLE_NAME, null, null, null, null, null, null)) {
while (c.moveToNext()) { while (c.moveToNext()) {
ret.add(c.getString(c.getColumnIndex("id"))); set.add(c.getString(c.getColumnIndex("id")));
} }
} }
return ret; return set;
} }
} }

View File

@ -15,9 +15,13 @@ public class WebService {
} }
public static String getString(String url, Map<String, String> header) { public static String getString(String url, Map<String, String> header) {
try {
HttpURLConnection conn = request(url, header); HttpURLConnection conn = request(url, header);
if (conn == null) return "";
return getString(conn); return getString(conn);
} catch (IOException e) {
e.printStackTrace();
return "";
}
} }
public static String getString(HttpURLConnection conn) { public static String getString(HttpURLConnection conn) {
@ -40,8 +44,7 @@ public class WebService {
} }
} }
public static HttpURLConnection request(String address, Map<String, String> header) { public static HttpURLConnection request(String address, Map<String, String> header) throws IOException {
try {
URL url = new URL(address); URL url = new URL(address);
HttpURLConnection conn = (HttpURLConnection) url.openConnection(); HttpURLConnection conn = (HttpURLConnection) url.openConnection();
@ -65,9 +68,5 @@ public class WebService {
} }
return conn; return conn;
} catch (Exception e) {
e.printStackTrace();
return null;
}
} }
} }