оптимизация лишних чтений мета-файла

This commit is contained in:
Пытков Роман
2024-12-21 23:49:14 +03:00
parent 577939e953
commit 277abfda52
2 changed files with 71 additions and 44 deletions

View File

@@ -11,6 +11,7 @@ import com.github.nullptroma.wallenc.domain.datatypes.DataPackage
import com.github.nullptroma.wallenc.domain.datatypes.DataPage import com.github.nullptroma.wallenc.domain.datatypes.DataPage
import com.github.nullptroma.wallenc.domain.models.IDirectory import com.github.nullptroma.wallenc.domain.models.IDirectory
import com.github.nullptroma.wallenc.domain.models.IFile import com.github.nullptroma.wallenc.domain.models.IFile
import com.github.nullptroma.wallenc.domain.models.IMetaInfo
import com.github.nullptroma.wallenc.domain.models.IStorageAccessor import com.github.nullptroma.wallenc.domain.models.IStorageAccessor
import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@@ -96,6 +97,9 @@ class LocalStorageAccessor(
callback(child) callback(child)
} }
if (useCallbackForSelf)
callback(dir)
if (maxDepth != 0) { if (maxDepth != 0) {
val nextMaxDepth = if (maxDepth > 0) maxDepth - 1 else maxDepth val nextMaxDepth = if (maxDepth > 0) maxDepth - 1 else maxDepth
for (child in children) { for (child in children) {
@@ -105,9 +109,9 @@ class LocalStorageAccessor(
} }
} }
} }
else if (useCallbackForSelf) {
if (useCallbackForSelf)
callback(dir) callback(dir)
}
} }
/** /**
@@ -117,13 +121,22 @@ class LocalStorageAccessor(
private suspend fun scanStorage( private suspend fun scanStorage(
baseStoragePath: String, baseStoragePath: String,
maxDepth: Int, maxDepth: Int,
fileCallback: suspend (LocalFile) -> Unit = {}, fileCallback: (suspend (File, LocalFile) -> Unit)? = null,
dirCallback: suspend (LocalDirectory) -> Unit = {} dirCallback: (suspend (File, LocalDirectory) -> Unit)? = null
) { ) {
if (!checkAvailable()) if (!checkAvailable())
throw Exception("Not available") throw Exception("Not available")
val basePath = Path(_absolutePath.pathString, baseStoragePath) val basePath = Path(_absolutePath.pathString, baseStoragePath)
val workedFiles = mutableSetOf<String>()
val workedMetaFiles = mutableSetOf<String>()
var count = 0
scanFileSystem(basePath.toFile(), maxDepth, { file -> scanFileSystem(basePath.toFile(), maxDepth, { file ->
// Если парный файл уже был обработан - скип. Это позволит не читать metaFile дважды
if(workedFiles.contains(file.absolutePath) || workedMetaFiles.contains(file.absolutePath)) {
count++
return@scanFileSystem
}
val filePath = Path(file.absolutePath) val filePath = Path(file.absolutePath)
// если это файл с мета-информацией - пропустить // если это файл с мета-информацией - пропустить
@@ -132,46 +145,60 @@ class LocalStorageAccessor(
try { try {
val reader = file.bufferedReader() val reader = file.bufferedReader()
val meta : LocalMetaInfo = _jackson.readValue(reader) val meta : LocalMetaInfo = _jackson.readValue(reader)
val fileInMeta = File(Path(_absolutePath.pathString, meta.path).pathString) val pathString = Path(_absolutePath.pathString, meta.path).pathString
if (!fileInMeta.exists()) val originalFile = File(pathString)
if (!originalFile.exists())
file.delete() file.delete()
// если успешно прочитано - отправить колбек и добавить обработанный файл
workedFiles.add(pathString)
workedMetaFiles.add(file.absolutePath)
if (file.isFile) {
fileCallback?.invoke(originalFile, LocalFile(meta))
} else {
dirCallback?.invoke(originalFile, LocalDirectory(meta, null))
}
} catch (e: JacksonException) { } catch (e: JacksonException) {
file.delete() file.delete()
} }
return@scanFileSystem return@scanFileSystem
} }
else {
val metaFilePath = Path(
if (file.isFile) {
file.absolutePath + META_INFO_POSTFIX
} else {
Path(file.absolutePath, META_INFO_POSTFIX).pathString
}
)
val metaFile = metaFilePath.toFile()
val metaInfo: LocalMetaInfo
val storageFilePath = "/" + filePath.relativeTo(_absolutePath)
val metaFilePath = Path( if (!metaFile.exists()) {
if (file.isFile) { metaInfo = createNewLocalMetaInfo(storageFilePath, filePath.fileSize())
file.absolutePath + META_INFO_POSTFIX _jackson.writeValue(metaFile, metaInfo)
} else { } else {
Path(file.absolutePath, META_INFO_POSTFIX).pathString var readMeta: LocalMetaInfo
try {
val reader = metaFile.bufferedReader()
readMeta = _jackson.readValue(reader)
} catch (e: JacksonException) {
// если файл повреждён - пересоздать
readMeta = createNewLocalMetaInfo(storageFilePath, filePath.fileSize())
_jackson.writeValue(metaFile, readMeta)
}
metaInfo = readMeta
} }
)
val metaFile = metaFilePath.toFile()
val metaInfo: LocalMetaInfo
val storageFilePath = "/" + filePath.relativeTo(_absolutePath)
if (!metaFile.exists()) { workedFiles.add(file.absolutePath)
metaInfo = createNewLocalMetaInfo(storageFilePath, filePath.fileSize()) workedMetaFiles.add(metaFile.absolutePath)
_jackson.writeValue(metaFile, metaInfo) if (file.isFile) {
} else { fileCallback?.invoke(file, LocalFile(metaInfo))
var readMeta: LocalMetaInfo } else {
try { dirCallback?.invoke(file, LocalDirectory(metaInfo, null))
val reader = metaFile.bufferedReader()
readMeta = _jackson.readValue(reader)
} catch (e: JacksonException) {
// если файл повреждён - пересоздать
readMeta = createNewLocalMetaInfo(storageFilePath, filePath.fileSize())
_jackson.writeValue(metaFile, readMeta)
} }
metaInfo = readMeta
}
if (file.isFile) {
fileCallback(LocalFile(metaInfo))
} else {
dirCallback(LocalDirectory(metaInfo, null))
} }
}) })
} }
@@ -206,8 +233,8 @@ class LocalStorageAccessor(
var size = 0L var size = 0L
var numOfFiles = 0 var numOfFiles = 0
scanStorage(baseStoragePath = "/", maxDepth = -1, fileCallback = { scanStorage(baseStoragePath = "/", maxDepth = -1, fileCallback = { _, localFile ->
size += it.metaInfo.size size += localFile.metaInfo.size
numOfFiles++ numOfFiles++
}) })
@@ -220,8 +247,8 @@ class LocalStorageAccessor(
return@withContext listOf() return@withContext listOf()
val list = mutableListOf<IFile>() val list = mutableListOf<IFile>()
scanStorage(baseStoragePath = "/", maxDepth = -1, fileCallback = { scanStorage(baseStoragePath = "/", maxDepth = -1, fileCallback = { _, localFile ->
list.add(it) list.add(localFile)
}) })
return@withContext list return@withContext list
} }
@@ -231,8 +258,8 @@ class LocalStorageAccessor(
return@withContext listOf() return@withContext listOf()
val list = mutableListOf<IFile>() val list = mutableListOf<IFile>()
scanStorage(baseStoragePath = path, maxDepth = 0, fileCallback = { scanStorage(baseStoragePath = path, maxDepth = 0, fileCallback = { _, localFile ->
list.add(it) list.add(localFile)
}) })
return@withContext list return@withContext list
} }
@@ -243,7 +270,7 @@ class LocalStorageAccessor(
val buf = mutableListOf<IFile>() val buf = mutableListOf<IFile>()
var pageNumber = 0 var pageNumber = 0
scanStorage(baseStoragePath = path, maxDepth = 0, fileCallback = { scanStorage(baseStoragePath = path, maxDepth = 0, fileCallback = { _, localFile ->
if(buf.size == DATA_PAGE_LENGTH) { if(buf.size == DATA_PAGE_LENGTH) {
val page = DataPage( val page = DataPage(
list = buf.toList(), list = buf.toList(),
@@ -256,7 +283,7 @@ class LocalStorageAccessor(
emit(page) emit(page)
buf.clear() buf.clear()
} }
buf.add(it) buf.add(localFile)
}) })
// отправка последней страницы // отправка последней страницы
val page = DataPage( val page = DataPage(

View File

@@ -25,9 +25,9 @@ fun LocalVaultScreen(modifier: Modifier = Modifier,
Card(modifier = Modifier.clickable { Card(modifier = Modifier.clickable {
viewModel.printAllFilesToLog(it) viewModel.printAllFilesToLog(it)
}) { }) {
val available = it.isAvailable.collectAsStateWithLifecycle() val available by it.isAvailable.collectAsStateWithLifecycle()
val numOfFiles = it.isAvailable.collectAsStateWithLifecycle() val numOfFiles by it.numberOfFiles.collectAsStateWithLifecycle()
val size = it.isAvailable.collectAsStateWithLifecycle() val size by it.size.collectAsStateWithLifecycle()
Column { Column {
Text(it.uuid.toString()) Text(it.uuid.toString())
Text("IsAvailable: $available") Text("IsAvailable: $available")