618 lines
24 KiB
Java
618 lines
24 KiB
Java
package androidx.room;
|
|
|
|
import android.annotation.SuppressLint;
|
|
import android.content.Context;
|
|
import android.database.Cursor;
|
|
import android.database.sqlite.SQLiteException;
|
|
import android.util.Log;
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.Nullable;
|
|
import androidx.annotation.RestrictTo;
|
|
import androidx.annotation.VisibleForTesting;
|
|
import androidx.annotation.WorkerThread;
|
|
import androidx.arch.core.internal.SafeIterableMap;
|
|
import androidx.lifecycle.LiveData;
|
|
import androidx.sqlite.db.SimpleSQLiteQuery;
|
|
import androidx.sqlite.db.SupportSQLiteDatabase;
|
|
import androidx.sqlite.db.SupportSQLiteStatement;
|
|
import c.d.b.a.a;
|
|
import java.lang.ref.WeakReference;
|
|
import java.util.Arrays;
|
|
import java.util.Collections;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.Iterator;
|
|
import java.util.Locale;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
import java.util.concurrent.Callable;
|
|
import java.util.concurrent.atomic.AtomicBoolean;
|
|
import java.util.concurrent.locks.Lock;
|
|
public class InvalidationTracker {
|
|
private static final String CREATE_TRACKING_TABLE_SQL = "CREATE TEMP TABLE room_table_modification_log(table_id INTEGER PRIMARY KEY, invalidated INTEGER NOT NULL DEFAULT 0)";
|
|
private static final String INVALIDATED_COLUMN_NAME = "invalidated";
|
|
@VisibleForTesting
|
|
public static final String RESET_UPDATED_TABLES_SQL = "UPDATE room_table_modification_log SET invalidated = 0 WHERE invalidated = 1 ";
|
|
@VisibleForTesting
|
|
public static final String SELECT_UPDATED_TABLES_SQL = "SELECT * FROM room_table_modification_log WHERE invalidated = 1;";
|
|
private static final String TABLE_ID_COLUMN_NAME = "table_id";
|
|
private static final String[] TRIGGERS = {"UPDATE", "DELETE", "INSERT"};
|
|
private static final String UPDATE_TABLE_NAME = "room_table_modification_log";
|
|
public volatile SupportSQLiteStatement mCleanupStatement;
|
|
public final RoomDatabase mDatabase;
|
|
private volatile boolean mInitialized;
|
|
private final InvalidationLiveDataContainer mInvalidationLiveDataContainer;
|
|
private MultiInstanceInvalidationClient mMultiInstanceInvalidationClient;
|
|
private ObservedTableTracker mObservedTableTracker;
|
|
@SuppressLint({"RestrictedApi"})
|
|
@VisibleForTesting
|
|
public final SafeIterableMap<Observer, ObserverWrapper> mObserverMap;
|
|
public AtomicBoolean mPendingRefresh;
|
|
@VisibleForTesting
|
|
public Runnable mRefreshRunnable;
|
|
@NonNull
|
|
public final HashMap<String, Integer> mTableIdLookup;
|
|
public final String[] mTableNames;
|
|
@NonNull
|
|
private Map<String, Set<String>> mViewTables;
|
|
|
|
/* renamed from: androidx.room.InvalidationTracker$1 reason: invalid class name */
|
|
public class AnonymousClass1 implements Runnable {
|
|
public AnonymousClass1() {
|
|
}
|
|
|
|
/* JADX INFO: finally extract failed */
|
|
private Set<Integer> checkUpdatedTable() {
|
|
HashSet hashSet = new HashSet();
|
|
Cursor query = InvalidationTracker.this.mDatabase.query(new SimpleSQLiteQuery("SELECT * FROM room_table_modification_log WHERE invalidated = 1;"));
|
|
while (query.moveToNext()) {
|
|
try {
|
|
hashSet.add(Integer.valueOf(query.getInt(0)));
|
|
} catch (Throwable th) {
|
|
query.close();
|
|
throw th;
|
|
}
|
|
}
|
|
query.close();
|
|
if (!hashSet.isEmpty()) {
|
|
InvalidationTracker.this.mCleanupStatement.executeUpdateDelete();
|
|
}
|
|
return hashSet;
|
|
}
|
|
|
|
@Override // java.lang.Runnable
|
|
public void run() {
|
|
Lock closeLock = InvalidationTracker.this.mDatabase.getCloseLock();
|
|
Set<Integer> set = null;
|
|
try {
|
|
closeLock.lock();
|
|
if (!InvalidationTracker.this.ensureInitialization()) {
|
|
closeLock.unlock();
|
|
} else if (!InvalidationTracker.this.mPendingRefresh.compareAndSet(true, false)) {
|
|
closeLock.unlock();
|
|
} else if (InvalidationTracker.this.mDatabase.inTransaction()) {
|
|
closeLock.unlock();
|
|
} else {
|
|
RoomDatabase roomDatabase = InvalidationTracker.this.mDatabase;
|
|
if (roomDatabase.mWriteAheadLoggingEnabled) {
|
|
SupportSQLiteDatabase writableDatabase = roomDatabase.getOpenHelper().getWritableDatabase();
|
|
writableDatabase.beginTransaction();
|
|
try {
|
|
set = checkUpdatedTable();
|
|
writableDatabase.setTransactionSuccessful();
|
|
} finally {
|
|
writableDatabase.endTransaction();
|
|
}
|
|
} else {
|
|
set = checkUpdatedTable();
|
|
}
|
|
closeLock.unlock();
|
|
if (set != null && !set.isEmpty()) {
|
|
synchronized (InvalidationTracker.this.mObserverMap) {
|
|
Iterator<Map.Entry<Observer, ObserverWrapper>> it = InvalidationTracker.this.mObserverMap.iterator();
|
|
while (it.hasNext()) {
|
|
it.next().getValue().notifyByTableInvalidStatus(set);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} catch (SQLiteException | IllegalStateException e) {
|
|
Log.e("ROOM", "Cannot run invalidation tracker. Is the db closed?", e);
|
|
} catch (Throwable th) {
|
|
closeLock.unlock();
|
|
throw th;
|
|
}
|
|
}
|
|
}
|
|
|
|
public static class ObservedTableTracker {
|
|
public static final int ADD = 1;
|
|
public static final int NO_OP = 0;
|
|
public static final int REMOVE = 2;
|
|
public boolean mNeedsSync;
|
|
public boolean mPendingSync;
|
|
public final long[] mTableObservers;
|
|
public final int[] mTriggerStateChanges;
|
|
public final boolean[] mTriggerStates;
|
|
|
|
public ObservedTableTracker(int i) {
|
|
long[] jArr = new long[i];
|
|
this.mTableObservers = jArr;
|
|
boolean[] zArr = new boolean[i];
|
|
this.mTriggerStates = zArr;
|
|
this.mTriggerStateChanges = new int[i];
|
|
Arrays.fill(jArr, 0L);
|
|
Arrays.fill(zArr, false);
|
|
}
|
|
|
|
@Nullable
|
|
public int[] getTablesToSync() {
|
|
synchronized (this) {
|
|
if (this.mNeedsSync) {
|
|
if (!this.mPendingSync) {
|
|
int length = this.mTableObservers.length;
|
|
int i = 0;
|
|
while (true) {
|
|
int i2 = 1;
|
|
if (i < length) {
|
|
boolean z2 = this.mTableObservers[i] > 0;
|
|
boolean[] zArr = this.mTriggerStates;
|
|
if (z2 != zArr[i]) {
|
|
int[] iArr = this.mTriggerStateChanges;
|
|
if (!z2) {
|
|
i2 = 2;
|
|
}
|
|
iArr[i] = i2;
|
|
} else {
|
|
this.mTriggerStateChanges[i] = 0;
|
|
}
|
|
zArr[i] = z2;
|
|
i++;
|
|
} else {
|
|
this.mPendingSync = true;
|
|
this.mNeedsSync = false;
|
|
return this.mTriggerStateChanges;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public boolean onAdded(int... iArr) {
|
|
boolean z2;
|
|
synchronized (this) {
|
|
z2 = false;
|
|
for (int i : iArr) {
|
|
long[] jArr = this.mTableObservers;
|
|
long j = jArr[i];
|
|
jArr[i] = 1 + j;
|
|
if (j == 0) {
|
|
this.mNeedsSync = true;
|
|
z2 = true;
|
|
}
|
|
}
|
|
}
|
|
return z2;
|
|
}
|
|
|
|
public boolean onRemoved(int... iArr) {
|
|
boolean z2;
|
|
synchronized (this) {
|
|
z2 = false;
|
|
for (int i : iArr) {
|
|
long[] jArr = this.mTableObservers;
|
|
long j = jArr[i];
|
|
jArr[i] = j - 1;
|
|
if (j == 1) {
|
|
this.mNeedsSync = true;
|
|
z2 = true;
|
|
}
|
|
}
|
|
}
|
|
return z2;
|
|
}
|
|
|
|
public void onSyncCompleted() {
|
|
synchronized (this) {
|
|
this.mPendingSync = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
public static abstract class Observer {
|
|
public final String[] mTables;
|
|
|
|
public Observer(@NonNull String str, String... strArr) {
|
|
String[] strArr2 = (String[]) Arrays.copyOf(strArr, strArr.length + 1);
|
|
this.mTables = strArr2;
|
|
strArr2[strArr.length] = str;
|
|
}
|
|
|
|
public Observer(@NonNull String[] strArr) {
|
|
this.mTables = (String[]) Arrays.copyOf(strArr, strArr.length);
|
|
}
|
|
|
|
public boolean isRemote() {
|
|
return false;
|
|
}
|
|
|
|
public abstract void onInvalidated(@NonNull Set<String> set);
|
|
}
|
|
|
|
public static class ObserverWrapper {
|
|
public final Observer mObserver;
|
|
private final Set<String> mSingleTableSet;
|
|
public final int[] mTableIds;
|
|
private final String[] mTableNames;
|
|
|
|
public ObserverWrapper(Observer observer, int[] iArr, String[] strArr) {
|
|
this.mObserver = observer;
|
|
this.mTableIds = iArr;
|
|
this.mTableNames = strArr;
|
|
if (iArr.length == 1) {
|
|
HashSet hashSet = new HashSet();
|
|
hashSet.add(strArr[0]);
|
|
this.mSingleTableSet = Collections.unmodifiableSet(hashSet);
|
|
return;
|
|
}
|
|
this.mSingleTableSet = null;
|
|
}
|
|
|
|
public void notifyByTableInvalidStatus(Set<Integer> set) {
|
|
int length = this.mTableIds.length;
|
|
Set<String> set2 = null;
|
|
for (int i = 0; i < length; i++) {
|
|
if (set.contains(Integer.valueOf(this.mTableIds[i]))) {
|
|
if (length == 1) {
|
|
set2 = this.mSingleTableSet;
|
|
} else {
|
|
if (set2 == null) {
|
|
set2 = new HashSet<>(length);
|
|
}
|
|
set2.add(this.mTableNames[i]);
|
|
}
|
|
}
|
|
}
|
|
if (set2 != null) {
|
|
this.mObserver.onInvalidated(set2);
|
|
}
|
|
}
|
|
|
|
public void notifyByTableNames(String[] strArr) {
|
|
Set<String> set = null;
|
|
if (this.mTableNames.length == 1) {
|
|
int length = strArr.length;
|
|
int i = 0;
|
|
while (true) {
|
|
if (i >= length) {
|
|
break;
|
|
} else if (strArr[i].equalsIgnoreCase(this.mTableNames[0])) {
|
|
set = this.mSingleTableSet;
|
|
break;
|
|
} else {
|
|
i++;
|
|
}
|
|
}
|
|
} else {
|
|
HashSet hashSet = new HashSet();
|
|
for (String str : strArr) {
|
|
String[] strArr2 = this.mTableNames;
|
|
int length2 = strArr2.length;
|
|
int i2 = 0;
|
|
while (true) {
|
|
if (i2 >= length2) {
|
|
break;
|
|
}
|
|
String str2 = strArr2[i2];
|
|
if (str2.equalsIgnoreCase(str)) {
|
|
hashSet.add(str2);
|
|
break;
|
|
}
|
|
i2++;
|
|
}
|
|
}
|
|
if (hashSet.size() > 0) {
|
|
set = hashSet;
|
|
}
|
|
}
|
|
if (set != null) {
|
|
this.mObserver.onInvalidated(set);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static class WeakObserver extends Observer {
|
|
public final WeakReference<Observer> mDelegateRef;
|
|
public final InvalidationTracker mTracker;
|
|
|
|
public WeakObserver(InvalidationTracker invalidationTracker, Observer observer) {
|
|
super(observer.mTables);
|
|
this.mTracker = invalidationTracker;
|
|
this.mDelegateRef = new WeakReference<>(observer);
|
|
}
|
|
|
|
@Override // androidx.room.InvalidationTracker.Observer
|
|
public void onInvalidated(@NonNull Set<String> set) {
|
|
Observer observer = this.mDelegateRef.get();
|
|
if (observer == null) {
|
|
this.mTracker.removeObserver(this);
|
|
} else {
|
|
observer.onInvalidated(set);
|
|
}
|
|
}
|
|
}
|
|
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP_PREFIX})
|
|
public InvalidationTracker(RoomDatabase roomDatabase, Map<String, String> map, Map<String, Set<String>> map2, String... strArr) {
|
|
this.mPendingRefresh = new AtomicBoolean(false);
|
|
this.mInitialized = false;
|
|
this.mObserverMap = new SafeIterableMap<>();
|
|
this.mRefreshRunnable = new AnonymousClass1();
|
|
this.mDatabase = roomDatabase;
|
|
this.mObservedTableTracker = new ObservedTableTracker(strArr.length);
|
|
this.mTableIdLookup = new HashMap<>();
|
|
this.mViewTables = map2;
|
|
this.mInvalidationLiveDataContainer = new InvalidationLiveDataContainer(roomDatabase);
|
|
int length = strArr.length;
|
|
this.mTableNames = new String[length];
|
|
for (int i = 0; i < length; i++) {
|
|
String str = strArr[i];
|
|
Locale locale = Locale.US;
|
|
String lowerCase = str.toLowerCase(locale);
|
|
this.mTableIdLookup.put(lowerCase, Integer.valueOf(i));
|
|
String str2 = map.get(strArr[i]);
|
|
if (str2 != null) {
|
|
this.mTableNames[i] = str2.toLowerCase(locale);
|
|
} else {
|
|
this.mTableNames[i] = lowerCase;
|
|
}
|
|
}
|
|
for (Map.Entry<String, String> entry : map.entrySet()) {
|
|
Locale locale2 = Locale.US;
|
|
String lowerCase2 = entry.getValue().toLowerCase(locale2);
|
|
if (this.mTableIdLookup.containsKey(lowerCase2)) {
|
|
String lowerCase3 = entry.getKey().toLowerCase(locale2);
|
|
HashMap<String, Integer> hashMap = this.mTableIdLookup;
|
|
hashMap.put(lowerCase3, hashMap.get(lowerCase2));
|
|
}
|
|
}
|
|
}
|
|
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP_PREFIX})
|
|
public InvalidationTracker(RoomDatabase roomDatabase, String... strArr) {
|
|
this(roomDatabase, new HashMap(), Collections.emptyMap(), strArr);
|
|
}
|
|
|
|
private static void appendTriggerName(StringBuilder sb, String str, String str2) {
|
|
a.k0(sb, "`", "room_table_modification_trigger_", str, "_");
|
|
sb.append(str2);
|
|
sb.append("`");
|
|
}
|
|
|
|
private String[] resolveViews(String[] strArr) {
|
|
HashSet hashSet = new HashSet();
|
|
for (String str : strArr) {
|
|
String lowerCase = str.toLowerCase(Locale.US);
|
|
if (this.mViewTables.containsKey(lowerCase)) {
|
|
hashSet.addAll(this.mViewTables.get(lowerCase));
|
|
} else {
|
|
hashSet.add(str);
|
|
}
|
|
}
|
|
return (String[]) hashSet.toArray(new String[hashSet.size()]);
|
|
}
|
|
|
|
private void startTrackingTable(SupportSQLiteDatabase supportSQLiteDatabase, int i) {
|
|
supportSQLiteDatabase.execSQL("INSERT OR IGNORE INTO room_table_modification_log VALUES(" + i + ", 0)");
|
|
String str = this.mTableNames[i];
|
|
StringBuilder sb = new StringBuilder();
|
|
String[] strArr = TRIGGERS;
|
|
for (String str2 : strArr) {
|
|
sb.setLength(0);
|
|
sb.append("CREATE TEMP TRIGGER IF NOT EXISTS ");
|
|
appendTriggerName(sb, str, str2);
|
|
a.k0(sb, " AFTER ", str2, " ON `", str);
|
|
a.k0(sb, "` BEGIN UPDATE ", "room_table_modification_log", " SET ", "invalidated");
|
|
a.k0(sb, " = 1", " WHERE ", "table_id", " = ");
|
|
sb.append(i);
|
|
sb.append(" AND ");
|
|
sb.append("invalidated");
|
|
sb.append(" = 0");
|
|
sb.append("; END");
|
|
supportSQLiteDatabase.execSQL(sb.toString());
|
|
}
|
|
}
|
|
|
|
private void stopTrackingTable(SupportSQLiteDatabase supportSQLiteDatabase, int i) {
|
|
String str = this.mTableNames[i];
|
|
StringBuilder sb = new StringBuilder();
|
|
String[] strArr = TRIGGERS;
|
|
for (String str2 : strArr) {
|
|
sb.setLength(0);
|
|
sb.append("DROP TRIGGER IF EXISTS ");
|
|
appendTriggerName(sb, str, str2);
|
|
supportSQLiteDatabase.execSQL(sb.toString());
|
|
}
|
|
}
|
|
|
|
private String[] validateAndResolveTableNames(String[] strArr) {
|
|
String[] resolveViews = resolveViews(strArr);
|
|
for (String str : resolveViews) {
|
|
if (!this.mTableIdLookup.containsKey(str.toLowerCase(Locale.US))) {
|
|
throw new IllegalArgumentException(a.u("There is no table with name ", str));
|
|
}
|
|
}
|
|
return resolveViews;
|
|
}
|
|
|
|
@SuppressLint({"RestrictedApi"})
|
|
@WorkerThread
|
|
public void addObserver(@NonNull Observer observer) {
|
|
ObserverWrapper putIfAbsent;
|
|
String[] resolveViews = resolveViews(observer.mTables);
|
|
int[] iArr = new int[resolveViews.length];
|
|
int length = resolveViews.length;
|
|
for (int i = 0; i < length; i++) {
|
|
Integer num = this.mTableIdLookup.get(resolveViews[i].toLowerCase(Locale.US));
|
|
if (num != null) {
|
|
iArr[i] = num.intValue();
|
|
} else {
|
|
StringBuilder L = a.L("There is no table with name ");
|
|
L.append(resolveViews[i]);
|
|
throw new IllegalArgumentException(L.toString());
|
|
}
|
|
}
|
|
ObserverWrapper observerWrapper = new ObserverWrapper(observer, iArr, resolveViews);
|
|
synchronized (this.mObserverMap) {
|
|
putIfAbsent = this.mObserverMap.putIfAbsent(observer, observerWrapper);
|
|
}
|
|
if (putIfAbsent == null && this.mObservedTableTracker.onAdded(iArr)) {
|
|
syncTriggers();
|
|
}
|
|
}
|
|
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP_PREFIX})
|
|
public void addWeakObserver(Observer observer) {
|
|
addObserver(new WeakObserver(this, observer));
|
|
}
|
|
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP_PREFIX})
|
|
@Deprecated
|
|
public <T> LiveData<T> createLiveData(String[] strArr, Callable<T> callable) {
|
|
return createLiveData(strArr, false, callable);
|
|
}
|
|
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP_PREFIX})
|
|
public <T> LiveData<T> createLiveData(String[] strArr, boolean z2, Callable<T> callable) {
|
|
return this.mInvalidationLiveDataContainer.create(validateAndResolveTableNames(strArr), z2, callable);
|
|
}
|
|
|
|
public boolean ensureInitialization() {
|
|
if (!this.mDatabase.isOpen()) {
|
|
return false;
|
|
}
|
|
if (!this.mInitialized) {
|
|
this.mDatabase.getOpenHelper().getWritableDatabase();
|
|
}
|
|
if (this.mInitialized) {
|
|
return true;
|
|
}
|
|
Log.e("ROOM", "database is not initialized even though it is open");
|
|
return false;
|
|
}
|
|
|
|
public void internalInit(SupportSQLiteDatabase supportSQLiteDatabase) {
|
|
synchronized (this) {
|
|
if (this.mInitialized) {
|
|
Log.e("ROOM", "Invalidation tracker is initialized twice :/.");
|
|
return;
|
|
}
|
|
supportSQLiteDatabase.execSQL("PRAGMA temp_store = MEMORY;");
|
|
supportSQLiteDatabase.execSQL("PRAGMA recursive_triggers='ON';");
|
|
supportSQLiteDatabase.execSQL("CREATE TEMP TABLE room_table_modification_log(table_id INTEGER PRIMARY KEY, invalidated INTEGER NOT NULL DEFAULT 0)");
|
|
syncTriggers(supportSQLiteDatabase);
|
|
this.mCleanupStatement = supportSQLiteDatabase.compileStatement("UPDATE room_table_modification_log SET invalidated = 0 WHERE invalidated = 1 ");
|
|
this.mInitialized = true;
|
|
}
|
|
}
|
|
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY})
|
|
@VisibleForTesting(otherwise = 3)
|
|
public void notifyObserversByTableNames(String... strArr) {
|
|
synchronized (this.mObserverMap) {
|
|
Iterator<Map.Entry<Observer, ObserverWrapper>> it = this.mObserverMap.iterator();
|
|
while (it.hasNext()) {
|
|
Map.Entry<Observer, ObserverWrapper> next = it.next();
|
|
if (!next.getKey().isRemote()) {
|
|
next.getValue().notifyByTableNames(strArr);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void refreshVersionsAsync() {
|
|
if (this.mPendingRefresh.compareAndSet(false, true)) {
|
|
this.mDatabase.getQueryExecutor().execute(this.mRefreshRunnable);
|
|
}
|
|
}
|
|
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP_PREFIX})
|
|
@WorkerThread
|
|
public void refreshVersionsSync() {
|
|
syncTriggers();
|
|
this.mRefreshRunnable.run();
|
|
}
|
|
|
|
@SuppressLint({"RestrictedApi"})
|
|
@WorkerThread
|
|
public void removeObserver(@NonNull Observer observer) {
|
|
ObserverWrapper remove;
|
|
synchronized (this.mObserverMap) {
|
|
remove = this.mObserverMap.remove(observer);
|
|
}
|
|
if (remove != null && this.mObservedTableTracker.onRemoved(remove.mTableIds)) {
|
|
syncTriggers();
|
|
}
|
|
}
|
|
|
|
public void startMultiInstanceInvalidation(Context context, String str) {
|
|
this.mMultiInstanceInvalidationClient = new MultiInstanceInvalidationClient(context, str, this, this.mDatabase.getQueryExecutor());
|
|
}
|
|
|
|
public void stopMultiInstanceInvalidation() {
|
|
MultiInstanceInvalidationClient multiInstanceInvalidationClient = this.mMultiInstanceInvalidationClient;
|
|
if (multiInstanceInvalidationClient != null) {
|
|
multiInstanceInvalidationClient.stop();
|
|
this.mMultiInstanceInvalidationClient = null;
|
|
}
|
|
}
|
|
|
|
public void syncTriggers() {
|
|
if (this.mDatabase.isOpen()) {
|
|
syncTriggers(this.mDatabase.getOpenHelper().getWritableDatabase());
|
|
}
|
|
}
|
|
|
|
public void syncTriggers(SupportSQLiteDatabase supportSQLiteDatabase) {
|
|
if (!supportSQLiteDatabase.inTransaction()) {
|
|
while (true) {
|
|
try {
|
|
Lock closeLock = this.mDatabase.getCloseLock();
|
|
closeLock.lock();
|
|
try {
|
|
int[] tablesToSync = this.mObservedTableTracker.getTablesToSync();
|
|
if (tablesToSync == null) {
|
|
closeLock.unlock();
|
|
return;
|
|
}
|
|
int length = tablesToSync.length;
|
|
supportSQLiteDatabase.beginTransaction();
|
|
for (int i = 0; i < length; i++) {
|
|
try {
|
|
int i2 = tablesToSync[i];
|
|
if (i2 == 1) {
|
|
startTrackingTable(supportSQLiteDatabase, i);
|
|
} else if (i2 == 2) {
|
|
stopTrackingTable(supportSQLiteDatabase, i);
|
|
}
|
|
} catch (Throwable th) {
|
|
supportSQLiteDatabase.endTransaction();
|
|
throw th;
|
|
}
|
|
}
|
|
supportSQLiteDatabase.setTransactionSuccessful();
|
|
supportSQLiteDatabase.endTransaction();
|
|
this.mObservedTableTracker.onSyncCompleted();
|
|
} finally {
|
|
closeLock.unlock();
|
|
}
|
|
} catch (SQLiteException | IllegalStateException e) {
|
|
Log.e("ROOM", "Cannot run invalidation tracker. Is the db closed?", e);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|