Simplify FTS management

pull/172/head
M66B 5 years ago
parent 97d25a9cb4
commit e39e8baa13

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

@ -85,6 +85,10 @@ public class FtsDbHelper extends SQLiteOpenHelper {
db.insert("message", SQLiteDatabase.CONFLICT_FAIL, cv); db.insert("message", SQLiteDatabase.CONFLICT_FAIL, cv);
} }
static void delete(SQLiteDatabase db) {
db.delete("message", null, null);
}
static void delete(SQLiteDatabase db, long id) { static void delete(SQLiteDatabase db, long id) {
db.delete("message", "rowid = ?", new Object[]{id}); db.delete("message", "rowid = ?", new Object[]{id});
} }
@ -120,4 +124,13 @@ public class FtsDbHelper extends SQLiteOpenHelper {
null, null, null, null,
null, null, "time"); 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')");
}
} }

@ -19,7 +19,18 @@ package eu.faircode.email;
Copyright 2018-2020 by Marcel Bokhorst (M66B) Copyright 2018-2020 by Marcel Bokhorst (M66B)
*/ */
import androidx.annotation.Nullable;
public class TupleFtsStats { public class TupleFtsStats {
public long fts; public long fts;
public long total; 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;
}
} }

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

@ -47,29 +47,18 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/swFts" /> 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 <TextView
android:id="@+id/tvFtsIndexed" android:id="@+id/tvFtsIndexed"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:layout_marginEnd="48dp" android:layout_marginEnd="48dp"
android:text="@string/title_advanced_fts_indexed" android:text="@string/title_advanced_fts_indexed"
android:textAppearance="@style/TextAppearance.AppCompat.Small" android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textStyle="italic" android:textStyle="italic"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btnFtsReset" /> app:layout_constraintTop_toBottomOf="@id/tvFtsHint" />
<androidx.appcompat.widget.SwitchCompat <androidx.appcompat.widget.SwitchCompat
android:id="@+id/swEnglish" android:id="@+id/swEnglish"

@ -383,7 +383,7 @@
<string name="title_advanced_external_search">Allow other apps to search in messages</string> <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">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_english">Force English language</string>
<string name="title_advanced_watchdog">Periodically check if FairEmail is still active</string> <string name="title_advanced_watchdog">Periodically check if FairEmail is still active</string>
<string name="title_advanced_updates">Check for updates</string> <string name="title_advanced_updates">Check for updates</string>

Loading…
Cancel
Save