Other measurments against deadlocks

This commit is contained in:
Jonas Lochmann 2020-07-06 02:00:00 +02:00
parent 838006f40e
commit ae8509c8b8
No known key found for this signature in database
GPG key ID: 8B8C9AEE10FA5B36
5 changed files with 28 additions and 15 deletions

View file

@ -21,6 +21,7 @@ import androidx.room.Database
import androidx.room.InvalidationTracker
import androidx.room.Room
import androidx.room.RoomDatabase
import io.timelimit.android.async.Threads
import io.timelimit.android.data.dao.DerivedDataDao
import io.timelimit.android.data.invalidation.Observer
import io.timelimit.android.data.invalidation.Table
@ -28,6 +29,7 @@ import io.timelimit.android.data.invalidation.TableUtil
import io.timelimit.android.data.model.*
import java.lang.ref.WeakReference
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
@Database(entities = [
User::class,
@ -113,6 +115,7 @@ abstract class RoomDatabase: RoomDatabase(), io.timelimit.android.data.Database
DatabaseMigrations.MIGRATE_TO_V30,
DatabaseMigrations.MIGRATE_TO_V31
)
.setQueryExecutor(Threads.database)
.build()
}
}
@ -157,21 +160,21 @@ abstract class RoomDatabase: RoomDatabase(), io.timelimit.android.data.Database
val latch = CountDownLatch(1)
try {
queryExecutor.execute { latch.await() }
queryExecutor.execute { latch.await(5, TimeUnit.SECONDS) }
// without requesting a async refresh, no sync refresh will happen
invalidationTracker.refreshVersionsAsync()
invalidationTracker.refreshVersionsSync()
openHelper.readableDatabase.beginTransaction()
try {
synchronized(transactionCommitListeners) { transactionCommitListeners.toList() }.forEach { it() }
} finally {
openHelper.readableDatabase.endTransaction()
}
} finally {
latch.countDown()
}
openHelper.readableDatabase.beginTransaction()
try {
synchronized(transactionCommitListeners) { transactionCommitListeners.toList() }.forEach { it() }
} finally {
openHelper.readableDatabase.endTransaction()
}
}
}

View file

@ -1,5 +1,5 @@
/*
* TimeLimit Copyright <C> 2019 Jonas Lochmann
* TimeLimit Copyright <C> 2019 - 2020 Jonas Lochmann
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -19,6 +19,7 @@ import android.content.Context
import android.util.Log
import androidx.core.util.AtomicFile
import io.timelimit.android.BuildConfig
import io.timelimit.android.async.Threads
import io.timelimit.android.coroutines.executeAndWait
import io.timelimit.android.data.RoomDatabase
import kotlinx.coroutines.runBlocking
@ -81,8 +82,9 @@ class DatabaseBackup(private val context: Context) {
try {
jsonFile.openRead().use { inputStream ->
DatabaseBackupLowlevel.restoreFromBackupJson(database, inputStream)
Threads.database.executeAndWait {
DatabaseBackupLowlevel.restoreFromBackupJson(database, inputStream)
}
}
if (BuildConfig.DEBUG) {

View file

@ -43,7 +43,9 @@ fun <K, V> DataCacheUserInterface<K, V>.openLive(key: K, executor: Executor): Li
override fun onInactive() {
super.onInactive()
cache.close(key, listener)
executor.execute {
cache.close(key, listener)
}
}
}
}

View file

@ -43,7 +43,9 @@ fun <V> SingleItemDataCacheUserInterface<V>.openLive(executor: Executor): LiveDa
override fun onInactive() {
super.onInactive()
cache.close(listener)
executor.execute {
cache.close(listener)
}
}
}
}

View file

@ -41,6 +41,8 @@ class SuspendAppsLogic(private val appLogic: AppLogic): Observer {
private val pendingSync = AtomicBoolean(true)
private val executor = Executors.newSingleThreadExecutor()
private var lastSuspendedApps: List<String>? = null
private val userAndDeviceRelatedDataLive = appLogic.database.derivedDataDao().getUserAndDeviceRelatedDataLive()
private var didLoadUserAndDeviceRelatedData = false
private val backgroundRunnable = Runnable {
while (pendingSync.getAndSet(false)) {
@ -67,7 +69,7 @@ class SuspendAppsLogic(private val appLogic: AppLogic): Observer {
appLogic.database.registerWeakObserver(arrayOf(Table.App), WeakReference(this))
appLogic.platformIntegration.getBatteryStatusLive().observeForever { batteryStatus = it; triggerUpdate() }
appLogic.realTimeLogic.registerTimeModificationListener { triggerUpdate() }
appLogic.database.derivedDataDao().getUserAndDeviceRelatedDataLive().observeForever { triggerUpdate() }
userAndDeviceRelatedDataLive.observeForever { didLoadUserAndDeviceRelatedData = true; triggerUpdate() }
}
override fun onInvalidated(tables: Set<Table>) {
@ -75,7 +77,9 @@ class SuspendAppsLogic(private val appLogic: AppLogic): Observer {
}
private fun updateBlockingSync() {
val userAndDeviceRelatedData = appLogic.database.derivedDataDao().getUserAndDeviceRelatedDataSync()
if (!didLoadUserAndDeviceRelatedData) return
val userAndDeviceRelatedData = userAndDeviceRelatedDataLive.value
val isRestrictedUser = userAndDeviceRelatedData?.userRelatedData?.user?.type == UserType.Child
val enableBlockingAtSystemLevel = userAndDeviceRelatedData?.deviceRelatedData?.isExperimentalFlagSetSync(ExperimentalFlags.SYSTEM_LEVEL_BLOCKING) ?: false