|
|
|
@ -30,7 +30,9 @@ import org.json.JSONException;
|
|
|
|
|
import org.json.JSONObject;
|
|
|
|
|
|
|
|
|
|
import java.io.File;
|
|
|
|
|
import java.io.FileOutputStream;
|
|
|
|
|
import java.lang.reflect.Field;
|
|
|
|
|
import java.nio.channels.FileLock;
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.Arrays;
|
|
|
|
|
import java.util.Collections;
|
|
|
|
@ -123,6 +125,7 @@ public abstract class DB extends RoomDatabase {
|
|
|
|
|
static final String DB_NAME = "fairemail";
|
|
|
|
|
static final int DEFAULT_QUERY_THREADS = 4; // AndroidX default thread count: 4
|
|
|
|
|
static final int DEFAULT_CACHE_SIZE = 20; // percentage of memory class
|
|
|
|
|
private static final long DB_LOCK_TIMEOUT = 60 * 1000L;
|
|
|
|
|
private static final int DB_JOURNAL_SIZE_LIMIT = 1048576; // requery/sqlite-android default
|
|
|
|
|
private static final int DB_CHECKPOINT = 1000; // requery/sqlite-android default
|
|
|
|
|
|
|
|
|
@ -425,6 +428,40 @@ public abstract class DB extends RoomDatabase {
|
|
|
|
|
Log.d("ROOM invalidated=" + TextUtils.join(",", tables));
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Ref: https://android-review.googlesource.com/c/platform/frameworks/support/+/1797472
|
|
|
|
|
Log.i("DB critical section start");
|
|
|
|
|
File dbDir = context.getDatabasePath(DB_NAME).getParentFile();
|
|
|
|
|
dbDir.mkdirs();
|
|
|
|
|
File lockFile = new File(dbDir, DB_NAME + ".lock");
|
|
|
|
|
try (FileOutputStream fos = new FileOutputStream(lockFile)) {
|
|
|
|
|
ObjectHolder<FileLock> lock = new ObjectHolder<>(null);
|
|
|
|
|
try {
|
|
|
|
|
Thread thread = new Thread(new Runnable() {
|
|
|
|
|
@Override
|
|
|
|
|
public void run() {
|
|
|
|
|
try {
|
|
|
|
|
lock.value = fos.getChannel().lock();
|
|
|
|
|
} catch (Throwable ex) {
|
|
|
|
|
Log.e(ex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
thread.start();
|
|
|
|
|
thread.join(DB_LOCK_TIMEOUT);
|
|
|
|
|
if (thread.isAlive())
|
|
|
|
|
throw new IllegalArgumentException("DB critical section failed");
|
|
|
|
|
|
|
|
|
|
// Force migration
|
|
|
|
|
sInstance.getOpenHelper().getWritableDatabase();
|
|
|
|
|
} finally {
|
|
|
|
|
if (lock.value != null)
|
|
|
|
|
lock.value.release();
|
|
|
|
|
}
|
|
|
|
|
} catch (Throwable ex) {
|
|
|
|
|
Log.e(ex);
|
|
|
|
|
}
|
|
|
|
|
Log.i("DB critical section end");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return sInstance;
|
|
|
|
|