From 8f2bab4c487a76f105cf39acc80e273a3f79b51a Mon Sep 17 00:00:00 2001 From: M66B <259573+M66B@users.noreply.github.com> Date: Thu, 2 May 2024 08:49:53 +0200 Subject: [PATCH] Revert "Updated ROOM patch" This reverts commit b8250fe6a045cfe5f4a1b99df8ee68e7ab9566c2. --- .../java/androidx/room/InvalidationTracker.kt | 10 +- .../androidx/room/RoomTrackingLiveData.kt | 117 +++++------- .../room/paging/LimitOffsetDataSource.java | 4 +- patches/roomkt.patch | 171 ------------------ 4 files changed, 54 insertions(+), 248 deletions(-) delete mode 100644 patches/roomkt.patch diff --git a/app/src/main/java/androidx/room/InvalidationTracker.kt b/app/src/main/java/androidx/room/InvalidationTracker.kt index 76cf95815c..38067b702f 100644 --- a/app/src/main/java/androidx/room/InvalidationTracker.kt +++ b/app/src/main/java/androidx/room/InvalidationTracker.kt @@ -405,14 +405,10 @@ open class InvalidationTracker @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX private fun checkUpdatedTable(): Set { val invalidatedTableIds = buildSet { - try { - database.query(SimpleSQLiteQuery(SELECT_UPDATED_TABLES_SQL)).useCursor { cursor -> - while (cursor.moveToNext()) { - add(cursor.getInt(0)) - } + database.query(SimpleSQLiteQuery(SELECT_UPDATED_TABLES_SQL)).useCursor { cursor -> + while (cursor.moveToNext()) { + add(cursor.getInt(0)) } - } catch (ex: Throwable) { - eu.faircode.email.Log.w(ex) } } if (invalidatedTableIds.isNotEmpty()) { diff --git a/app/src/main/java/androidx/room/RoomTrackingLiveData.kt b/app/src/main/java/androidx/room/RoomTrackingLiveData.kt index fc53a72171..171b57d16e 100644 --- a/app/src/main/java/androidx/room/RoomTrackingLiveData.kt +++ b/app/src/main/java/androidx/room/RoomTrackingLiveData.kt @@ -54,79 +54,62 @@ internal class RoomTrackingLiveData ( val invalid = AtomicBoolean(true) val computing = AtomicBoolean(false) val registeredObserver = AtomicBoolean(false) - val queued = eu.faircode.email.ObjectHolder(0) - val lock = Object() val refreshRunnable = Runnable { - eu.faircode.email.Log.i("MMM Refresh") - synchronized(lock) { - queued.value-- - if (queued.value < 0) { - eu.faircode.email.Log.e("$computeFunction queued=$queued.value") - queued.value = 0 - } - } - eu.faircode.email.Log.i("MMM Refreshing") - - if (registeredObserver.compareAndSet(false, true)) { - database.invalidationTracker.addWeakObserver(observer) - } - - var value: T? = null - var computed = false - synchronized(computeFunction) { - var retry = 0 - while (!computed) { - try { - value = computeFunction.call() - computed = true - } catch (e: Throwable) { - if (++retry > 5) { - eu.faircode.email.Log.e(e) - break - } - eu.faircode.email.Log.w(e) - try { - Thread.sleep(2000L) - } catch (ignored: InterruptedException) { - } - } - } - } - if (computed) { - postValue(value) - } - eu.faircode.email.Log.i("MMM Refreshed") - } + if (registeredObserver.compareAndSet(false, true)) { + database.invalidationTracker.addWeakObserver(observer) + } + var computed: Boolean + do { + computed = false + // compute can happen only in 1 thread but no reason to lock others. + if (computing.compareAndSet(false, true)) { + // as long as it is invalid, keep computing. + try { + var value: T? = null + while (invalid.compareAndSet(true, false)) { + computed = true + try { + value = computeFunction.call() + } catch (e: Exception) { + throw RuntimeException( + "Exception while computing database live data.", + e + ) + } + } + if (computed) { + postValue(value) + } + } finally { + // release compute lock + computing.set(false) + } + } + // check invalid after releasing compute lock to avoid the following scenario. + // Thread A runs compute() + // Thread A checks invalid, it is false + // Main thread sets invalid to true + // Thread B runs, fails to acquire compute lock and skips + // Thread A releases compute lock + // We've left invalid in set state. The check below recovers. + } while (computed && invalid.get()) + } val invalidationRunnable = Runnable { - val isActive = hasActiveObservers() - if (invalid.compareAndSet(false, true)) { - if (isActive) { - eu.faircode.email.Log.i("MMM Invalidate") - synchronized(lock) { - if (queued.value > 0) { - eu.faircode.email.Log.persist(eu.faircode.email.EntityLog.Type.Debug, "$computeFunction queued=$queued.value") - } else { - queued.value++ - queryExecutor.execute(refreshRunnable) - } - eu.faircode.email.Log.i("MMM Invalidated") - } - } - } - } + val isActive = hasActiveObservers() + if (invalid.compareAndSet(false, true)) { + if (isActive) { + queryExecutor.execute(refreshRunnable) + } + } + } @Suppress("UNCHECKED_CAST") override fun onActive() { - super.onActive() - container.onActive(this as LiveData) - eu.faircode.email.Log.i("MMM Active") - synchronized(lock) { - queued.value++ - queryExecutor.execute(refreshRunnable) - } - eu.faircode.email.Log.i("MMM Actived") - } + super.onActive() + container.onActive(this as LiveData) + queryExecutor.execute(refreshRunnable) + } @Suppress("UNCHECKED_CAST") override fun onInactive() { diff --git a/app/src/main/java/androidx/room/paging/LimitOffsetDataSource.java b/app/src/main/java/androidx/room/paging/LimitOffsetDataSource.java index 077ae233e8..2b5c391dbc 100644 --- a/app/src/main/java/androidx/room/paging/LimitOffsetDataSource.java +++ b/app/src/main/java/androidx/room/paging/LimitOffsetDataSource.java @@ -153,7 +153,7 @@ public abstract class LimitOffsetDataSource extends androidx.paging.Positiona @NonNull LoadInitialCallback callback) { registerObserverIfNecessary(); List list = Collections.emptyList(); - int totalCount = 0; + int totalCount; int firstLoadPosition = 0; RoomSQLiteQuery sqLiteQuery = null; Cursor cursor = null; @@ -171,8 +171,6 @@ public abstract class LimitOffsetDataSource extends androidx.paging.Positiona mDb.setTransactionSuccessful(); list = rows; } - } catch (Throwable ex) { - eu.faircode.email.Log.w(ex); } finally { if (cursor != null) { cursor.close(); diff --git a/patches/roomkt.patch b/patches/roomkt.patch deleted file mode 100644 index adb762da47..0000000000 --- a/patches/roomkt.patch +++ /dev/null @@ -1,171 +0,0 @@ -diff --git a/app/src/main/java/androidx/room/InvalidationTracker.kt b/app/src/main/java/androidx/room/InvalidationTracker.kt -index 38067b702f..76cf95815c 100644 ---- a/app/src/main/java/androidx/room/InvalidationTracker.kt -+++ b/app/src/main/java/androidx/room/InvalidationTracker.kt -@@ -405,10 +405,14 @@ open class InvalidationTracker @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX - - private fun checkUpdatedTable(): Set { - val invalidatedTableIds = buildSet { -- database.query(SimpleSQLiteQuery(SELECT_UPDATED_TABLES_SQL)).useCursor { cursor -> -- while (cursor.moveToNext()) { -- add(cursor.getInt(0)) -+ try { -+ database.query(SimpleSQLiteQuery(SELECT_UPDATED_TABLES_SQL)).useCursor { cursor -> -+ while (cursor.moveToNext()) { -+ add(cursor.getInt(0)) -+ } - } -+ } catch (ex: Throwable) { -+ eu.faircode.email.Log.w(ex) - } - } - if (invalidatedTableIds.isNotEmpty()) { -diff --git a/app/src/main/java/androidx/room/RoomTrackingLiveData.kt b/app/src/main/java/androidx/room/RoomTrackingLiveData.kt -index 171b57d16e..e253e98eee 100644 ---- a/app/src/main/java/androidx/room/RoomTrackingLiveData.kt -+++ b/app/src/main/java/androidx/room/RoomTrackingLiveData.kt -@@ -54,62 +54,72 @@ internal class RoomTrackingLiveData ( - val invalid = AtomicBoolean(true) - val computing = AtomicBoolean(false) - val registeredObserver = AtomicBoolean(false) -+ val queued = eu.faircode.email.ObjectHolder(0) -+ val lock = Object() - val refreshRunnable = Runnable { -- if (registeredObserver.compareAndSet(false, true)) { -- database.invalidationTracker.addWeakObserver(observer) -- } -- var computed: Boolean -- do { -- computed = false -- // compute can happen only in 1 thread but no reason to lock others. -- if (computing.compareAndSet(false, true)) { -- // as long as it is invalid, keep computing. -- try { -- var value: T? = null -- while (invalid.compareAndSet(true, false)) { -- computed = true -- try { -- value = computeFunction.call() -- } catch (e: Exception) { -- throw RuntimeException( -- "Exception while computing database live data.", -- e -- ) -- } -- } -- if (computed) { -- postValue(value) -- } -- } finally { -- // release compute lock -- computing.set(false) -- } -- } -- // check invalid after releasing compute lock to avoid the following scenario. -- // Thread A runs compute() -- // Thread A checks invalid, it is false -- // Main thread sets invalid to true -- // Thread B runs, fails to acquire compute lock and skips -- // Thread A releases compute lock -- // We've left invalid in set state. The check below recovers. -- } while (computed && invalid.get()) -- } -+ synchronized(lock) { -+ queued.value-- -+ if (queued.value < 0) { -+ eu.faircode.email.Log.e("$computeFunction queued=$queued.value") -+ queued.value = 0 -+ } -+ } -+ -+ if (registeredObserver.compareAndSet(false, true)) { -+ database.invalidationTracker.addWeakObserver(observer) -+ } -+ -+ var value: T? = null -+ var computed = false -+ synchronized(computeFunction) { -+ var retry = 0 -+ while (!computed) { -+ try { -+ value = computeFunction.call() -+ computed = true -+ } catch (e: Throwable) { -+ if (++retry > 5) { -+ eu.faircode.email.Log.e(e) -+ break -+ } -+ eu.faircode.email.Log.w(e) -+ try { -+ Thread.sleep(2000L) -+ } catch (ignored: InterruptedException) { -+ } -+ } -+ } -+ } -+ if (computed) { -+ postValue(value) -+ } -+ } - - val invalidationRunnable = Runnable { -- val isActive = hasActiveObservers() -- if (invalid.compareAndSet(false, true)) { -- if (isActive) { -- queryExecutor.execute(refreshRunnable) -- } -- } -- } -+ val isActive = hasActiveObservers() -+ if (invalid.compareAndSet(false, true)) { -+ if (isActive) { -+ synchronized(lock) { -+ if (queued.value > 0) { -+ eu.faircode.email.Log.persist(eu.faircode.email.EntityLog.Type.Debug, "$computeFunction queued=$queued.value") -+ } else { -+ queued.value++ -+ queryExecutor.execute(refreshRunnable) -+ } -+ } -+ } -+ } -+ } - - @Suppress("UNCHECKED_CAST") - override fun onActive() { -- super.onActive() -- container.onActive(this as LiveData) -- queryExecutor.execute(refreshRunnable) -- } -+ super.onActive() -+ container.onActive(this as LiveData) -+ synchronized(lock) { -+ queued.value++ -+ queryExecutor.execute(refreshRunnable) -+ } -+ } - - @Suppress("UNCHECKED_CAST") - override fun onInactive() { -diff --git a/app/src/main/java/androidx/room/paging/LimitOffsetDataSource.java b/app/src/main/java/androidx/room/paging/LimitOffsetDataSource.java -index 2b5c391dbc..077ae233e8 100644 ---- a/app/src/main/java/androidx/room/paging/LimitOffsetDataSource.java -+++ b/app/src/main/java/androidx/room/paging/LimitOffsetDataSource.java -@@ -153,7 +153,7 @@ public abstract class LimitOffsetDataSource extends androidx.paging.Positiona - @NonNull LoadInitialCallback callback) { - registerObserverIfNecessary(); - List list = Collections.emptyList(); -- int totalCount; -+ int totalCount = 0; - int firstLoadPosition = 0; - RoomSQLiteQuery sqLiteQuery = null; - Cursor cursor = null; -@@ -171,6 +171,8 @@ public abstract class LimitOffsetDataSource extends androidx.paging.Positiona - mDb.setTransactionSuccessful(); - list = rows; - } -+ } catch (Throwable ex) { -+ eu.faircode.email.Log.w(ex); - } finally { - if (cursor != null) { - cursor.close();