Simplify FTS management

This commit is contained in:
M66B 2020-01-16 09:44:54 +01:00
parent 97d25a9cb4
commit e39e8baa13
6 changed files with 75 additions and 54 deletions

View File

@ -46,10 +46,11 @@ import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.Observer;
import androidx.preference.PreferenceManager;
import io.requery.android.database.sqlite.SQLiteDatabase;
public class FragmentOptionsMisc extends FragmentBase implements SharedPreferences.OnSharedPreferenceChangeListener {
private SwitchCompat swExternalSearch;
private SwitchCompat swFts;
private Button btnFtsReset;
private TextView tvFtsIndexed;
private SwitchCompat swEnglish;
private SwitchCompat swWatchdog;
@ -93,7 +94,6 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc
swExternalSearch = view.findViewById(R.id.swExternalSearch);
swFts = view.findViewById(R.id.swFts);
btnFtsReset = view.findViewById(R.id.btnFtsReset);
tvFtsIndexed = view.findViewById(R.id.tvFtsIndexed);
swEnglish = view.findViewById(R.id.swEnglish);
swWatchdog = view.findViewById(R.id.swWatchdog);
@ -137,33 +137,31 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
prefs.edit().putBoolean("fts", checked).apply();
WorkerFts.init(getContext(), true);
}
});
btnFtsReset.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Bundle args = new Bundle();
if (!checked) {
Bundle args = new Bundle();
new SimpleTask<Void>() {
@Override
protected Void onExecute(Context context, Bundle args) throws Throwable {
DB db = DB.getInstance(context);
db.message().resetFts();
return null;
}
new SimpleTask<Void>() {
@Override
protected Void onExecute(Context context, Bundle args) {
SQLiteDatabase sdb = FtsDbHelper.getInstance(context);
FtsDbHelper.delete(sdb);
FtsDbHelper.optimize(sdb);
@Override
protected void onExecuted(Bundle args, Void data) {
WorkerFts.init(getContext(), true);
}
DB db = DB.getInstance(context);
db.message().resetFts();
@Override
protected void onException(Bundle args, Throwable ex) {
Log.unexpectedError(getParentFragmentManager(), ex);
}
}.execute(FragmentOptionsMisc.this, args, "fts:reset");
return null;
}
@Override
protected void onException(Bundle args, Throwable ex) {
Log.unexpectedError(getParentFragmentManager(), ex);
}
}.execute(FragmentOptionsMisc.this, args, "fts:reset");
}
}
});
@ -246,12 +244,18 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc
DB db = DB.getInstance(getContext());
db.message().liveFts().observe(getViewLifecycleOwner(), new Observer<TupleFtsStats>() {
private TupleFtsStats last = null;
@Override
public void onChanged(TupleFtsStats stats) {
if (stats == null)
tvFtsIndexed.setText(null);
else
tvFtsIndexed.setText(getString(R.string.title_advanced_fts_indexed, stats.fts, stats.total));
else if (last == null || !last.equals(stats))
tvFtsIndexed.setText(getString(R.string.title_advanced_fts_indexed,
stats.fts,
stats.total,
Helper.humanReadableByteCount(FtsDbHelper.size(getContext()), true)));
last = stats;
}
});

View File

@ -85,6 +85,10 @@ public class FtsDbHelper extends SQLiteOpenHelper {
db.insert("message", SQLiteDatabase.CONFLICT_FAIL, cv);
}
static void delete(SQLiteDatabase db) {
db.delete("message", null, null);
}
static void delete(SQLiteDatabase db, long id) {
db.delete("message", "rowid = ?", new Object[]{id});
}
@ -120,4 +124,13 @@ public class FtsDbHelper extends SQLiteOpenHelper {
null, null,
null, null, "time");
}
static long size(Context context) {
return context.getDatabasePath(DATABASE_NAME).length();
}
static void optimize(SQLiteDatabase db) {
Log.i("FTS optimize");
db.execSQL("INSERT INTO message (message) VALUES ('optimize')");
}
}

View File

@ -19,7 +19,18 @@ package eu.faircode.email;
Copyright 2018-2020 by Marcel Bokhorst (M66B)
*/
import androidx.annotation.Nullable;
public class TupleFtsStats {
public long fts;
public long total;
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof TupleFtsStats) {
TupleFtsStats other = (TupleFtsStats) obj;
return (this.fts == other.fts && this.total == other.total);
} else
return false;
}
}

View File

@ -68,6 +68,7 @@ public class WorkerCleanup extends Worker {
static void cleanup(Context context, boolean manual) {
DB db = DB.getInstance(context);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
try {
Log.i("Start cleanup manual=" + manual);
@ -111,7 +112,6 @@ public class WorkerCleanup extends Worker {
ServiceSynchronize.reschedule(context);
// Clear last search
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
prefs.edit().remove("last_search").apply();
}
@ -193,21 +193,26 @@ public class WorkerCleanup extends Worker {
}
}
Log.i("Cleanup FTS");
int fts = 0;
SQLiteDatabase sdb = FtsDbHelper.getInstance(context);
try (Cursor cursor = FtsDbHelper.getIds(sdb)) {
while (cursor.moveToNext()) {
long rowid = cursor.getLong(0);
EntityMessage message = db.message().getMessage(rowid);
if (message == null) {
Log.i("Deleting rowid" + rowid);
FtsDbHelper.delete(sdb, rowid);
fts++;
boolean fts = prefs.getBoolean("fts", true);
Log.i("Cleanup FTS=" + fts);
if (fts) {
int deleted = 0;
SQLiteDatabase sdb = FtsDbHelper.getInstance(context);
try (Cursor cursor = FtsDbHelper.getIds(sdb)) {
while (cursor.moveToNext()) {
long rowid = cursor.getLong(0);
EntityMessage message = db.message().getMessage(rowid);
if (message == null || !message.fts) {
Log.i("Deleting FTS rowid=" + rowid);
FtsDbHelper.delete(sdb, rowid);
deleted++;
}
}
}
Log.i("Cleanup FTS=" + deleted);
if (manual)
FtsDbHelper.optimize(sdb);
}
Log.i("Cleanup FTS=" + fts);
Log.i("Cleanup contacts");
int contacts = db.contact().deleteContacts(now - KEEP_CONTACTS_DURATION);
@ -221,7 +226,6 @@ public class WorkerCleanup extends Worker {
} finally {
Log.i("End cleanup");
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
prefs.edit()
.remove("crash_report_count")
.putLong("last_cleanup", new Date().getTime())

View File

@ -47,29 +47,18 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/swFts" />
<Button
android:id="@+id/btnFtsReset"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:minWidth="0dp"
android:minHeight="0dp"
android:text="@string/title_reset"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvFtsHint" />
<TextView
android:id="@+id/tvFtsIndexed"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:layout_marginEnd="48dp"
android:text="@string/title_advanced_fts_indexed"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textStyle="italic"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btnFtsReset" />
app:layout_constraintTop_toBottomOf="@id/tvFtsHint" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/swEnglish"

View File

@ -383,7 +383,7 @@
<string name="title_advanced_external_search">Allow other apps to search in messages</string>
<string name="title_advanced_fts">Build search index</string>
<string name="title_advanced_fts_indexed">%1$d/%2$d indexed</string>
<string name="title_advanced_fts_indexed">%1$d / %2$d messages indexed (%3$s)</string>
<string name="title_advanced_english">Force English language</string>
<string name="title_advanced_watchdog">Periodically check if FairEmail is still active</string>
<string name="title_advanced_updates">Check for updates</string>