mirror of
https://github.com/M66B/FairEmail.git
synced 2026-04-27 11:16:51 +02:00
Updated ROOM
This commit is contained in:
@@ -20,6 +20,7 @@ import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteException;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@@ -89,6 +90,9 @@ public class InvalidationTracker {
|
||||
@NonNull
|
||||
private Map<String, Set<String>> mViewTables;
|
||||
|
||||
@Nullable
|
||||
AutoCloser mAutoCloser = null;
|
||||
|
||||
@SuppressWarnings("WeakerAccess") /* synthetic access */
|
||||
final RoomDatabase mDatabase;
|
||||
|
||||
@@ -159,6 +163,23 @@ public class InvalidationTracker {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the auto closer for this invalidation tracker so that the invalidation tracker can
|
||||
* ensure that the database is not closed if there are pending invalidations that haven't yet
|
||||
* been flushed.
|
||||
*
|
||||
* This also adds a callback to the autocloser to ensure that the InvalidationTracker is in
|
||||
* an ok state once the table is invalidated.
|
||||
*
|
||||
* This must be called before the database is used.
|
||||
*
|
||||
* @param autoCloser the autocloser associated with the db
|
||||
*/
|
||||
void setAutoCloser(AutoCloser autoCloser) {
|
||||
this.mAutoCloser = autoCloser;
|
||||
mAutoCloser.setAutoCloseCallback(this::onAutoCloseCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal method to initialize table tracking.
|
||||
* <p>
|
||||
@@ -182,6 +203,13 @@ public class InvalidationTracker {
|
||||
}
|
||||
}
|
||||
|
||||
void onAutoCloseCallback() {
|
||||
synchronized (this) {
|
||||
mInitialized = false;
|
||||
mObservedTableTracker.resetTriggerState();
|
||||
}
|
||||
}
|
||||
|
||||
void startMultiInstanceInvalidation(Context context, String name) {
|
||||
mMultiInstanceInvalidationClient = new MultiInstanceInvalidationClient(context, name, this,
|
||||
mDatabase.getQueryExecutor());
|
||||
@@ -249,6 +277,9 @@ public class InvalidationTracker {
|
||||
* <p>
|
||||
* If one of the tables in the Observer does not exist in the database, this method throws an
|
||||
* {@link IllegalArgumentException}.
|
||||
* <p>
|
||||
* This method should be called on a background/worker thread as it performs database
|
||||
* operations.
|
||||
*
|
||||
* @param observer The observer which listens the database for changes.
|
||||
*/
|
||||
@@ -305,6 +336,15 @@ public class InvalidationTracker {
|
||||
return tables.toArray(new String[tables.size()]);
|
||||
}
|
||||
|
||||
private static void beginTransactionInternal(SupportSQLiteDatabase database) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
|
||||
&& database.isWriteAheadLoggingEnabled()) {
|
||||
database.beginTransactionNonExclusive();
|
||||
} else {
|
||||
database.beginTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an observer but keeps a weak reference back to it.
|
||||
* <p>
|
||||
@@ -322,6 +362,9 @@ public class InvalidationTracker {
|
||||
|
||||
/**
|
||||
* Removes the observer from the observers list.
|
||||
* <p>
|
||||
* This method should be called on a background/worker thread as it performs database
|
||||
* operations.
|
||||
*
|
||||
* @param observer The observer to remove.
|
||||
*/
|
||||
@@ -360,8 +403,8 @@ public class InvalidationTracker {
|
||||
public void run() {
|
||||
final Lock closeLock = mDatabase.getCloseLock();
|
||||
Set<Integer> invalidatedTableIds = null;
|
||||
closeLock.lock();
|
||||
try {
|
||||
closeLock.lock();
|
||||
|
||||
if (!ensureInitialization()) {
|
||||
return;
|
||||
@@ -383,7 +426,7 @@ public class InvalidationTracker {
|
||||
// This transaction has to be on the underlying DB rather than the RoomDatabase
|
||||
// in order to avoid a recursive loop after endTransaction.
|
||||
SupportSQLiteDatabase db = mDatabase.getOpenHelper().getWritableDatabase();
|
||||
db.beginTransaction();
|
||||
db.beginTransactionNonExclusive();
|
||||
try {
|
||||
invalidatedTableIds = checkUpdatedTable();
|
||||
db.setTransactionSuccessful();
|
||||
@@ -399,6 +442,10 @@ public class InvalidationTracker {
|
||||
exception);
|
||||
} finally {
|
||||
closeLock.unlock();
|
||||
|
||||
if (mAutoCloser != null) {
|
||||
mAutoCloser.decrementCountAndScheduleClose();
|
||||
}
|
||||
}
|
||||
if (invalidatedTableIds != null && !invalidatedTableIds.isEmpty()) {
|
||||
synchronized (mObserverMap) {
|
||||
@@ -439,6 +486,13 @@ public class InvalidationTracker {
|
||||
public void refreshVersionsAsync() {
|
||||
// TODO we should consider doing this sync instead of async.
|
||||
if (mPendingRefresh.compareAndSet(false, true)) {
|
||||
if (mAutoCloser != null) {
|
||||
// refreshVersionsAsync is called with the ref count incremented from
|
||||
// RoomDatabase, so the db can't be closed here, but we need to be sure that our
|
||||
// db isn't closed until refresh is completed. This increment call must be
|
||||
// matched with a corresponding call in mRefreshRunnable.
|
||||
mAutoCloser.incrementCountAndEnsureDbIsOpen();
|
||||
}
|
||||
mDatabase.getQueryExecutor().execute(mRefreshRunnable);
|
||||
}
|
||||
}
|
||||
@@ -451,6 +505,10 @@ public class InvalidationTracker {
|
||||
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
|
||||
@WorkerThread
|
||||
public void refreshVersionsSync() {
|
||||
if (mAutoCloser != null) {
|
||||
// This increment call must be matched with a corresponding call in mRefreshRunnable.
|
||||
mAutoCloser.incrementCountAndEnsureDbIsOpen();
|
||||
}
|
||||
syncTriggers();
|
||||
mRefreshRunnable.run();
|
||||
}
|
||||
@@ -495,7 +553,7 @@ public class InvalidationTracker {
|
||||
return;
|
||||
}
|
||||
final int limit = tablesToSync.length;
|
||||
database.beginTransaction();
|
||||
beginTransactionInternal(database);
|
||||
try {
|
||||
for (int tableId = 0; tableId < limit; tableId++) {
|
||||
switch (tablesToSync[tableId]) {
|
||||
@@ -785,6 +843,17 @@ public class InvalidationTracker {
|
||||
return needTriggerSync;
|
||||
}
|
||||
|
||||
/**
|
||||
* If we are re-opening the db we'll need to add all the triggers that we need so change
|
||||
* the current state to false for all.
|
||||
*/
|
||||
void resetTriggerState() {
|
||||
synchronized (this) {
|
||||
Arrays.fill(mTriggerStates, false);
|
||||
mNeedsSync = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If this returns non-null, you must call onSyncCompleted.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user