From d600ddc11ad496ab5c8b879b18e6bb1187a05799 Mon Sep 17 00:00:00 2001 From: Jobobby04 Date: Fri, 27 Oct 2023 17:14:38 -0400 Subject: [PATCH] Fix page previews cache --- app/build.gradle.kts | 2 +- .../tachiyomi/data/cache/PagePreviewCache.kt | 12 +-- .../tachiyomi/data/coil/PagePreviewFetcher.kt | 61 +++++++-------- .../kanade/tachiyomi/ui/main/MainActivity.kt | 1 + app/src/main/java/exh/EXHMigrations.kt | 17 +++++ app/src/main/java/exh/debug/DebugFunctions.kt | 74 +++++++++++++------ 6 files changed, 108 insertions(+), 59 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index a5370f5f5..d123fd6f5 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -26,7 +26,7 @@ android { defaultConfig { applicationId = "eu.kanade.tachiyomi.sy" - versionCode = 57 + versionCode = 58 versionName = "1.9.3" buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"") diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/cache/PagePreviewCache.kt b/app/src/main/java/eu/kanade/tachiyomi/data/cache/PagePreviewCache.kt index bbb7c6ba1..9010a9b1d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/cache/PagePreviewCache.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/cache/PagePreviewCache.kt @@ -6,12 +6,13 @@ import com.jakewharton.disklrucache.DiskLruCache import eu.kanade.tachiyomi.source.PagePreviewPage import eu.kanade.tachiyomi.util.storage.DiskUtil import eu.kanade.tachiyomi.util.storage.saveTo -import kotlinx.serialization.decodeFromString import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json -import okhttp3.Response +import logcat.LogPriority +import okio.Source import okio.buffer import okio.sink +import tachiyomi.core.util.system.logcat import tachiyomi.domain.manga.model.Manga import uy.kohesive.injekt.injectLazy import java.io.File @@ -159,7 +160,7 @@ class PagePreviewCache(private val context: Context) { * @throws IOException page error. */ @Throws(IOException::class) - fun putImageToCache(imageUrl: String, response: Response) { + fun putImageToCache(imageUrl: String, source: Source) { // Initialize editor (edits the values for an entry). var editor: DiskLruCache.Editor? = null @@ -169,12 +170,12 @@ class PagePreviewCache(private val context: Context) { editor = diskCache.edit(key) ?: throw IOException("Unable to edit key") // Get OutputStream and write page with Okio. - response.body.source().saveTo(editor.newOutputStream(0)) + source.buffer().saveTo(editor.newOutputStream(0)) diskCache.flush() editor.commit() } finally { - response.body.close() + source.close() editor?.abortUnlessCommitted() } } @@ -207,6 +208,7 @@ class PagePreviewCache(private val context: Context) { // Remove file from cache. diskCache.remove(key) } catch (e: Exception) { + logcat(LogPriority.WARN, e) { "Failed to remove file from cache" } false } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/coil/PagePreviewFetcher.kt b/app/src/main/java/eu/kanade/tachiyomi/data/coil/PagePreviewFetcher.kt index fd5426bbb..f3cb6bc32 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/coil/PagePreviewFetcher.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/coil/PagePreviewFetcher.kt @@ -23,8 +23,6 @@ import okhttp3.Response import okhttp3.internal.http.HTTP_NOT_MODIFIED import okio.Path.Companion.toOkioPath import okio.Source -import okio.buffer -import okio.sink import tachiyomi.core.util.system.logcat import tachiyomi.domain.source.service.SourceManager import uy.kohesive.injekt.injectLazy @@ -39,7 +37,9 @@ import java.io.File class PagePreviewFetcher( private val page: PagePreview, private val options: Options, - private val pagePreviewFileLazy: Lazy, + private val pagePreviewFile: () -> File, + private val isInCache: () -> Boolean, + private val writeToCache: (Source) -> Unit, private val diskCacheKeyLazy: Lazy, private val sourceLazy: Lazy, private val callFactoryLazy: Lazy, @@ -62,14 +62,14 @@ class PagePreviewFetcher( } private suspend fun httpLoader(): FetchResult { - if (pagePreviewFileLazy.value.exists() && options.diskCachePolicy.readEnabled) { - return fileLoader(pagePreviewFileLazy.value) + if (isInCache() && options.diskCachePolicy.readEnabled) { + return fileLoader(pagePreviewFile()) } var snapshot = readFromDiskCache() try { // Fetch from disk cache if (snapshot != null) { - val snapshotPagePreviewCache = moveSnapshotToPagePreviewCache(snapshot, pagePreviewFileLazy.value) + val snapshotPagePreviewCache = moveSnapshotToPagePreviewCache(snapshot) if (snapshotPagePreviewCache != null) { // Read from page preview cache return fileLoader(snapshotPagePreviewCache) @@ -88,7 +88,7 @@ class PagePreviewFetcher( val responseBody = checkNotNull(response.body) { "Null response source" } try { // Read from page preview cache after page preview updated - val responsePagePreviewCache = writeResponseToPagePreviewCache(response, pagePreviewFileLazy.value) + val responsePagePreviewCache = writeResponseToPagePreviewCache(response) if (responsePagePreviewCache != null) { return fileLoader(responsePagePreviewCache) } @@ -153,60 +153,59 @@ class PagePreviewFetcher( return request.build() } - private fun moveSnapshotToPagePreviewCache(snapshot: DiskCache.Snapshot, cacheFile: File): File? { + private fun moveSnapshotToPagePreviewCache(snapshot: DiskCache.Snapshot): File? { return try { diskCacheLazy.value.run { fileSystem.source(snapshot.data).use { input -> - writeSourceToPagePreviewCache(input, cacheFile) + writeSourceToPagePreviewCache(input) } remove(diskCacheKey) } - cacheFile.takeIf { it.exists() } + return if (isInCache()) { + pagePreviewFile() + } else { + null + } } catch (e: Exception) { - logcat(LogPriority.ERROR, e) { "Failed to write snapshot data to page preview cache ${cacheFile.name}" } + logcat(LogPriority.ERROR, e) { "Failed to write snapshot data to page preview cache $diskCacheKey" } null } } - private fun writeResponseToPagePreviewCache(response: Response, cacheFile: File): File? { + private fun writeResponseToPagePreviewCache(response: Response): File? { if (!options.diskCachePolicy.writeEnabled) return null return try { response.peekBody(Long.MAX_VALUE).source().use { input -> - writeSourceToPagePreviewCache(input, cacheFile) + writeSourceToPagePreviewCache(input) + } + return if (isInCache()) { + pagePreviewFile() + } else { + null } - cacheFile.takeIf { it.exists() } } catch (e: Exception) { - logcat(LogPriority.ERROR, e) { "Failed to write response data to page preview cache ${cacheFile.name}" } + logcat(LogPriority.ERROR, e) { "Failed to write response data to page preview cache $diskCacheKey" } null } } - private fun writeSourceToPagePreviewCache(input: Source, cacheFile: File) { - cacheFile.parentFile?.mkdirs() - cacheFile.delete() - try { - cacheFile.sink().buffer().use { output -> - output.writeAll(input) - } - } catch (e: Exception) { - cacheFile.delete() - throw e - } + private fun writeSourceToPagePreviewCache(input: Source) { + writeToCache(input) } private fun readFromDiskCache(): DiskCache.Snapshot? { - return if (options.diskCachePolicy.readEnabled) diskCacheLazy.value[diskCacheKey] else null + return if (options.diskCachePolicy.readEnabled) diskCacheLazy.value.openSnapshot(diskCacheKey) else null } private fun writeToDiskCache( response: Response, ): DiskCache.Snapshot? { - val editor = diskCacheLazy.value.edit(diskCacheKey) ?: return null + val editor = diskCacheLazy.value.openEditor(diskCacheKey) ?: return null try { diskCacheLazy.value.fileSystem.write(editor.data) { response.body.source().readAll(this) } - return editor.commitAndGet() + return editor.commitAndOpenSnapshot() } catch (e: Exception) { try { editor.abort() @@ -232,7 +231,9 @@ class PagePreviewFetcher( return PagePreviewFetcher( page = data, options = options, - pagePreviewFileLazy = lazy { pagePreviewCache.getImageFile(data.imageUrl) }, + pagePreviewFile = { pagePreviewCache.getImageFile(data.imageUrl) }, + isInCache = { pagePreviewCache.isImageInCache(data.imageUrl) }, + writeToCache = { pagePreviewCache.putImageToCache(data.imageUrl, it) }, diskCacheKeyLazy = lazy { PagePreviewKeyer().key(data, options) }, sourceLazy = lazy { sourceManager.get(data.source) as? PagePreviewSource }, callFactoryLazy = callFactoryLazy, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt index e2e848e17..1544e461f 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt @@ -173,6 +173,7 @@ class MainActivity : BaseActivity() { readerPreferences = Injekt.get(), backupPreferences = Injekt.get(), trackerManager = Injekt.get(), + pagePreviewCache = Injekt.get(), ) } else { false diff --git a/app/src/main/java/exh/EXHMigrations.kt b/app/src/main/java/exh/EXHMigrations.kt index aeb66f468..a3af59772 100644 --- a/app/src/main/java/exh/EXHMigrations.kt +++ b/app/src/main/java/exh/EXHMigrations.kt @@ -10,6 +10,7 @@ import eu.kanade.domain.ui.UiPreferences import eu.kanade.tachiyomi.BuildConfig import eu.kanade.tachiyomi.core.security.SecurityPreferences import eu.kanade.tachiyomi.data.backup.BackupCreateJob +import eu.kanade.tachiyomi.data.cache.PagePreviewCache import eu.kanade.tachiyomi.data.library.LibraryUpdateJob import eu.kanade.tachiyomi.data.track.TrackerManager import eu.kanade.tachiyomi.network.NetworkPreferences @@ -39,6 +40,7 @@ import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.contentOrNull import kotlinx.serialization.json.jsonArray import kotlinx.serialization.json.jsonPrimitive +import logcat.LogPriority import tachiyomi.core.preference.PreferenceStore import tachiyomi.core.preference.TriState import tachiyomi.core.preference.getAndSet @@ -99,6 +101,7 @@ object EXHMigrations { readerPreferences: ReaderPreferences, backupPreferences: BackupPreferences, trackerManager: TrackerManager, + pagePreviewCache: PagePreviewCache, ): Boolean { val lastVersionCode = preferenceStore.getInt("eh_last_version_code", 0) val oldVersion = lastVersionCode.get() @@ -559,6 +562,20 @@ object EXHMigrations { uiPreferences.relativeTime().set(false) } } + if (oldVersion under 58) { + pagePreviewCache.clear() + File(context.cacheDir, PagePreviewCache.PARAMETER_CACHE_DIRECTORY).listFiles()?.forEach { + if (it.name == "journal" || it.name.startsWith("journal.")) { + return@forEach + } + + try { + it.delete() + } catch (e: Exception) { + logcat(LogPriority.WARN, e) { "Failed to remove file from cache" } + } + } + } // if (oldVersion under 1) { } (1 is current release version) // do stuff here when releasing changed crap diff --git a/app/src/main/java/exh/debug/DebugFunctions.kt b/app/src/main/java/exh/debug/DebugFunctions.kt index 343179cd3..554a67a67 100644 --- a/app/src/main/java/exh/debug/DebugFunctions.kt +++ b/app/src/main/java/exh/debug/DebugFunctions.kt @@ -8,6 +8,7 @@ import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.domain.ui.UiPreferences import eu.kanade.tachiyomi.core.security.SecurityPreferences import eu.kanade.tachiyomi.data.backup.models.Backup +import eu.kanade.tachiyomi.data.cache.PagePreviewCache import eu.kanade.tachiyomi.data.track.TrackerManager import eu.kanade.tachiyomi.network.NetworkPreferences import eu.kanade.tachiyomi.source.AndroidSourceManager @@ -40,37 +41,64 @@ import java.util.UUID @Suppress("unused") object DebugFunctions { - val app: Application by injectLazy() - val handler: DatabaseHandler by injectLazy() - val prefsStore: PreferenceStore by injectLazy() - val basePrefs: BasePreferences by injectLazy() - val uiPrefs: UiPreferences by injectLazy() - val networkPrefs: NetworkPreferences by injectLazy() - val sourcePrefs: SourcePreferences by injectLazy() - val securityPrefs: SecurityPreferences by injectLazy() - val libraryPrefs: LibraryPreferences by injectLazy() - val readerPrefs: ReaderPreferences by injectLazy() - val backupPrefs: BackupPreferences by injectLazy() - val trackerManager: TrackerManager by injectLazy() - val sourceManager: SourceManager by injectLazy() - val updateManga: UpdateManga by injectLazy() - val getFavorites: GetFavorites by injectLazy() - val getFlatMetadataById: GetFlatMetadataById by injectLazy() - val insertFlatMetadata: InsertFlatMetadata by injectLazy() - val getExhFavoriteMangaWithMetadata: GetExhFavoriteMangaWithMetadata by injectLazy() - val getSearchMetadata: GetSearchMetadata by injectLazy() - val getAllManga: GetAllManga by injectLazy() + private val app: Application by injectLazy() + private val handler: DatabaseHandler by injectLazy() + private val prefsStore: PreferenceStore by injectLazy() + private val basePrefs: BasePreferences by injectLazy() + private val uiPrefs: UiPreferences by injectLazy() + private val networkPrefs: NetworkPreferences by injectLazy() + private val sourcePrefs: SourcePreferences by injectLazy() + private val securityPrefs: SecurityPreferences by injectLazy() + private val libraryPrefs: LibraryPreferences by injectLazy() + private val readerPrefs: ReaderPreferences by injectLazy() + private val backupPrefs: BackupPreferences by injectLazy() + private val trackerManager: TrackerManager by injectLazy() + private val sourceManager: SourceManager by injectLazy() + private val updateManga: UpdateManga by injectLazy() + private val getFavorites: GetFavorites by injectLazy() + private val getFlatMetadataById: GetFlatMetadataById by injectLazy() + private val insertFlatMetadata: InsertFlatMetadata by injectLazy() + private val getExhFavoriteMangaWithMetadata: GetExhFavoriteMangaWithMetadata by injectLazy() + private val getSearchMetadata: GetSearchMetadata by injectLazy() + private val getAllManga: GetAllManga by injectLazy() + private val pagePreviewCache: PagePreviewCache by injectLazy() fun forceUpgradeMigration() { val lastVersionCode = prefsStore.getInt("eh_last_version_code", 0) lastVersionCode.set(1) - EXHMigrations.upgrade(app, prefsStore, basePrefs, uiPrefs, networkPrefs, sourcePrefs, securityPrefs, libraryPrefs, readerPrefs, backupPrefs, trackerManager) + EXHMigrations.upgrade( + context = app, + preferenceStore = prefsStore, + basePreferences = basePrefs, + uiPreferences = uiPrefs, + networkPreferences = networkPrefs, + sourcePreferences = sourcePrefs, + securityPreferences = securityPrefs, + libraryPreferences = libraryPrefs, + readerPreferences = readerPrefs, + backupPreferences = backupPrefs, + trackerManager = trackerManager, + pagePreviewCache = pagePreviewCache, + ) } fun forceSetupJobs() { val lastVersionCode = prefsStore.getInt("eh_last_version_code", 0) lastVersionCode.set(0) - EXHMigrations.upgrade(app, prefsStore, basePrefs, uiPrefs, networkPrefs, sourcePrefs, securityPrefs, libraryPrefs, readerPrefs, backupPrefs, trackerManager) + EXHMigrations.upgrade( + context = app, + preferenceStore = prefsStore, + basePreferences = basePrefs, + uiPreferences = uiPrefs, + networkPreferences = networkPrefs, + sourcePreferences = sourcePrefs, + securityPreferences = securityPrefs, + libraryPreferences = libraryPrefs, + readerPreferences = readerPrefs, + backupPreferences = backupPrefs, + trackerManager = trackerManager, + pagePreviewCache = pagePreviewCache, + ) } fun resetAgedFlagInEXHManga() { @@ -190,7 +218,7 @@ object DebugFunctions { """ { id: ${info.id}, - isPeriodic: ${j.extras["EXTRA_IS_PERIODIC"]}, + isPeriodic: ${j.extras.getBoolean("EXTRA_IS_PERIODIC")}, state: ${info.state.name}, tags: [ ${info.tags.joinToString(separator = ",\n ")}