Migrate CacheCleaner to Coroutine

This commit is contained in:
tzugen 2021-11-13 12:06:16 +01:00
parent 97eb753413
commit 00cd4fce44
No known key found for this signature in database
GPG Key ID: 61E9C34BC10EC930
1 changed files with 58 additions and 75 deletions

View File

@ -1,10 +1,13 @@
package org.moire.ultrasonic.util package org.moire.ultrasonic.util
import android.os.AsyncTask
import android.os.StatFs import android.os.StatFs
import java.io.File import java.io.File
import java.util.ArrayList import java.util.ArrayList
import java.util.HashSet import java.util.HashSet
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.koin.java.KoinJavaComponent.inject import org.koin.java.KoinJavaComponent.inject
import org.moire.ultrasonic.data.ActiveServerProvider import org.moire.ultrasonic.data.ActiveServerProvider
import org.moire.ultrasonic.domain.Playlist import org.moire.ultrasonic.domain.Playlist
@ -22,105 +25,85 @@ import timber.log.Timber
/** /**
* Responsible for cleaning up files from the offline download cache on the filesystem. * Responsible for cleaning up files from the offline download cache on the filesystem.
*/ */
class CacheCleaner { class CacheCleaner : CoroutineScope by CoroutineScope(Dispatchers.IO) {
private fun exceptionHandler(tag: String): CoroutineExceptionHandler {
return CoroutineExceptionHandler { _, exception ->
Timber.w(exception, "Exception in CacheCleaner.$tag")
}
}
fun clean() { fun clean() {
try { launch(exceptionHandler("clean")) {
BackgroundCleanup().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR) backgroundCleanup()
} catch (all: Exception) {
// If an exception is thrown, assume we execute correctly the next time
Timber.w(all, "Exception in CacheCleaner.clean")
} }
} }
fun cleanSpace() { fun cleanSpace() {
try { launch(exceptionHandler("cleanSpace")) {
BackgroundSpaceCleanup().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR) backgroundSpaceCleanup()
} catch (all: Exception) {
// If an exception is thrown, assume we execute correctly the next time
Timber.w(all, "Exception in CacheCleaner.cleanSpace")
} }
} }
fun cleanPlaylists(playlists: List<Playlist>) { fun cleanPlaylists(playlists: List<Playlist>) {
launch(exceptionHandler("cleanPlaylists")) {
backgroundPlaylistsCleanup(playlists)
}
}
private fun backgroundCleanup() {
try { try {
BackgroundPlaylistsCleanup().executeOnExecutor( val files: MutableList<File> = ArrayList()
AsyncTask.THREAD_POOL_EXECUTOR, val dirs: MutableList<File> = ArrayList()
playlists
) findCandidatesForDeletion(musicDirectory, files, dirs)
} catch (all: Exception) { sortByAscendingModificationTime(files)
// If an exception is thrown, assume we execute correctly the next time val filesToNotDelete = findFilesToNotDelete()
Timber.w(all, "Exception in CacheCleaner.cleanPlaylists")
deleteFiles(files, filesToNotDelete, getMinimumDelete(files), true)
deleteEmptyDirs(dirs, filesToNotDelete)
} catch (all: RuntimeException) {
Timber.e(all, "Error in cache cleaning.")
} }
} }
private class BackgroundCleanup : AsyncTask<Void?, Void?, Void?>() { private fun backgroundSpaceCleanup() {
override fun doInBackground(vararg params: Void?): Void? { try {
try { val files: MutableList<File> = ArrayList()
Thread.currentThread().name = "BackgroundCleanup" val dirs: MutableList<File> = ArrayList()
val files: MutableList<File> = ArrayList() findCandidatesForDeletion(musicDirectory, files, dirs)
val dirs: MutableList<File> = ArrayList()
findCandidatesForDeletion(musicDirectory, files, dirs)
sortByAscendingModificationTime(files)
val filesToNotDelete = findFilesToNotDelete()
deleteFiles(files, filesToNotDelete, getMinimumDelete(files), true)
deleteEmptyDirs(dirs, filesToNotDelete)
} catch (all: RuntimeException) {
Timber.e(all, "Error in cache cleaning.")
}
return null
}
}
private class BackgroundSpaceCleanup : AsyncTask<Void?, Void?, Void?>() {
override fun doInBackground(vararg params: Void?): Void? {
try {
Thread.currentThread().name = "BackgroundSpaceCleanup"
val files: MutableList<File> = ArrayList()
val dirs: MutableList<File> = ArrayList()
findCandidatesForDeletion(musicDirectory, files, dirs)
val bytesToDelete = getMinimumDelete(files)
if (bytesToDelete <= 0L) return null
val bytesToDelete = getMinimumDelete(files)
if (bytesToDelete > 0L) {
sortByAscendingModificationTime(files) sortByAscendingModificationTime(files)
val filesToNotDelete = findFilesToNotDelete() val filesToNotDelete = findFilesToNotDelete()
deleteFiles(files, filesToNotDelete, bytesToDelete, false) deleteFiles(files, filesToNotDelete, bytesToDelete, false)
} catch (all: RuntimeException) {
Timber.e(all, "Error in cache cleaning.")
} }
return null } catch (all: RuntimeException) {
Timber.e(all, "Error in cache cleaning.")
} }
} }
private class BackgroundPlaylistsCleanup : AsyncTask<List<Playlist>, Void?, Void?>() { private fun backgroundPlaylistsCleanup(vararg params: List<Playlist>) {
override fun doInBackground(vararg params: List<Playlist>): Void? { try {
try { val activeServerProvider = inject<ActiveServerProvider>(
val activeServerProvider = inject<ActiveServerProvider>( ActiveServerProvider::class.java
ActiveServerProvider::class.java )
)
Thread.currentThread().name = "BackgroundPlaylistsCleanup" val server = activeServerProvider.value.getActiveServer().name
val playlistFiles = listFiles(getPlaylistDirectory(server))
val playlists = params[0]
val server = activeServerProvider.value.getActiveServer().name for ((_, name) in playlists) {
val playlistFiles = listFiles(getPlaylistDirectory(server)) playlistFiles.remove(getPlaylistFile(server, name))
val playlists = params[0]
for ((_, name) in playlists) {
playlistFiles.remove(getPlaylistFile(server, name))
}
for (playlist in playlistFiles) {
playlist.delete()
}
} catch (all: RuntimeException) {
Timber.e(all, "Error in playlist cache cleaning.")
} }
return null
for (playlist in playlistFiles) {
playlist.delete()
}
} catch (all: RuntimeException) {
Timber.e(all, "Error in playlist cache cleaning.")
} }
} }