fix(database): integrity check

This commit is contained in:
rhunk 2023-11-23 22:38:12 +01:00
parent 752f87179f
commit 5dbca7e68f
2 changed files with 32 additions and 6 deletions

View File

@ -135,6 +135,7 @@ class SnapEnhance {
mappings.loadFromBridge(bridgeClient) mappings.loadFromBridge(bridgeClient)
mappings.init(androidContext) mappings.init(androidContext)
database.init()
eventDispatcher.init() eventDispatcher.init()
//if mappings aren't loaded, we can't initialize features //if mappings aren't loaded, we can't initialize features
if (!mappings.isMappingsLoaded()) return if (!mappings.isMappingsLoaded()) return

View File

@ -20,8 +20,14 @@ import me.rhunk.snapenhance.core.manager.Manager
class DatabaseAccess( class DatabaseAccess(
private val context: ModContext private val context: ModContext
) : Manager { ) : Manager {
private val mainDb by lazy { openLocalDatabase("main.db") } companion object {
private val arroyoDb by lazy { openLocalDatabase("arroyo.db") } val DATABASES = mapOf(
"main" to "main.db",
"arroyo" to "arroyo.db"
)
}
private val mainDb by lazy { openLocalDatabase("main") }
private val arroyoDb by lazy { openLocalDatabase("arroyo") }
private inline fun <T> SQLiteDatabase.performOperation(crossinline query: SQLiteDatabase.() -> T?): T? { private inline fun <T> SQLiteDatabase.performOperation(crossinline query: SQLiteDatabase.() -> T?): T? {
return runCatching { return runCatching {
@ -71,27 +77,46 @@ class DatabaseAccess(
} ?: emptyMap()).toMutableMap() } ?: emptyMap()).toMutableMap()
} }
private fun openLocalDatabase(fileName: String): SQLiteDatabase? { private fun openLocalDatabase(databaseName: String, writeMode: Boolean = false): SQLiteDatabase? {
val dbPath = context.androidContext.getDatabasePath(fileName) val dbPath = context.androidContext.getDatabasePath(DATABASES[databaseName]!!)
if (!dbPath.exists()) return null if (!dbPath.exists()) return null
return runCatching { return runCatching {
SQLiteDatabase.openDatabase( SQLiteDatabase.openDatabase(
dbPath, dbPath,
OpenParams.Builder() OpenParams.Builder()
.setOpenFlags(SQLiteDatabase.OPEN_READONLY) .setOpenFlags(
if (writeMode) SQLiteDatabase.OPEN_READWRITE or SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING
else SQLiteDatabase.OPEN_READONLY
)
.setErrorHandler { .setErrorHandler {
context.androidContext.deleteDatabase(dbPath.absolutePath) context.androidContext.deleteDatabase(dbPath.absolutePath)
context.softRestartApp() context.softRestartApp()
}.build() }.build()
) )
}.onFailure { }.onFailure {
context.log.error("Failed to open database $fileName!", it) context.log.error("Failed to open database $databaseName!", it)
}.getOrNull() }.getOrNull()
} }
fun hasMain(): Boolean = mainDb?.isOpen == true fun hasMain(): Boolean = mainDb?.isOpen == true
fun hasArroyo(): Boolean = arroyoDb?.isOpen == true fun hasArroyo(): Boolean = arroyoDb?.isOpen == true
override fun init() {
// perform integrity check on databases
DATABASES.forEach { (name, fileName) ->
openLocalDatabase(name, writeMode = true)?.apply {
rawQuery("PRAGMA integrity_check", null).use { query ->
if (!query.moveToFirst() || query.getString(0).lowercase() != "ok") {
context.log.error("Failed to perform integrity check on $fileName")
context.androidContext.deleteDatabase(fileName)
return@apply
}
context.log.verbose("database $fileName integrity check passed")
}
}?.close()
}
}
fun finalize() { fun finalize() {
mainDb?.close() mainDb?.close()
arroyoDb?.close() arroyoDb?.close()