mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 14:20:20 +00:00
Improve media index
This commit is contained in:
@@ -53,6 +53,203 @@ private final class CacheUsageStatsState {
|
||||
}
|
||||
|
||||
func _internal_collectCacheUsageStats(account: Account, peerId: PeerId? = nil, additionalCachePaths: [String] = [], logFilesPath: String? = nil) -> Signal<CacheUsageStatsResult, NoError> {
|
||||
if "".isEmpty {
|
||||
return account.postbox.mediaBox.collectAllResourceUsage()
|
||||
|> mapToSignal { resourceList -> Signal<CacheUsageStatsResult, NoError> in
|
||||
return account.postbox.mediaBox.storageBox.get(ids: resourceList.compactMap { item -> Data? in
|
||||
return item.id?.data(using: .utf8)
|
||||
})
|
||||
|> mapToSignal { entries -> Signal<CacheUsageStatsResult, NoError> in
|
||||
return account.postbox.transaction { transaction -> CacheUsageStatsResult in
|
||||
var media: [PeerId: [PeerCacheUsageCategory: [MediaId: Int64]]] = [:]
|
||||
var mediaResourceIds: [MediaId: [MediaResourceId]] = [:]
|
||||
|
||||
media.removeAll()
|
||||
mediaResourceIds.removeAll()
|
||||
|
||||
let mediaBox = account.postbox.mediaBox
|
||||
|
||||
var totalSize: Int64 = 0
|
||||
var mediaSize: Int64 = 0
|
||||
|
||||
var processedResourceIds = Set<String>()
|
||||
|
||||
for entry in entries {
|
||||
let resourceId = MediaResourceId(String(data: entry.id, encoding: .utf8)!)
|
||||
let resourceSize = mediaBox.resourceUsage(id: resourceId)
|
||||
if resourceSize != 0 {
|
||||
totalSize += resourceSize
|
||||
|
||||
for reference in entry.references {
|
||||
if let message = transaction.getMessage(MessageId(peerId: reference.peerId, namespace: MessageId.Namespace(reference.messageNamespace), id: reference.messageId)) {
|
||||
for mediaItem in message.media {
|
||||
guard let mediaId = mediaItem.id else {
|
||||
continue
|
||||
}
|
||||
var category: PeerCacheUsageCategory?
|
||||
if let _ = mediaItem as? TelegramMediaImage {
|
||||
category = .image
|
||||
} else if let mediaItem = mediaItem as? TelegramMediaFile {
|
||||
if mediaItem.isMusic || mediaItem.isVoice {
|
||||
category = .audio
|
||||
} else if mediaItem.isVideo {
|
||||
category = .video
|
||||
} else {
|
||||
category = .file
|
||||
}
|
||||
}
|
||||
if let category = category {
|
||||
mediaSize += resourceSize
|
||||
processedResourceIds.insert(resourceId.stringRepresentation)
|
||||
|
||||
media[reference.peerId, default: [:]][category, default: [:]][mediaId, default: 0] += resourceSize
|
||||
if let index = mediaResourceIds.index(forKey: mediaId) {
|
||||
if !mediaResourceIds[index].value.contains(resourceId) {
|
||||
mediaResourceIds[mediaId]?.append(resourceId)
|
||||
}
|
||||
} else {
|
||||
mediaResourceIds[mediaId] = [resourceId]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var peers: [PeerId: Peer] = [:]
|
||||
for peerId in media.keys {
|
||||
if let peer = transaction.getPeer(peerId) {
|
||||
peers[peer.id] = peer
|
||||
}
|
||||
}
|
||||
|
||||
var tempPaths: [String] = []
|
||||
var tempSize: Int64 = 0
|
||||
#if os(iOS)
|
||||
if let enumerator = FileManager.default.enumerator(at: URL(fileURLWithPath: NSTemporaryDirectory()), includingPropertiesForKeys: [.isDirectoryKey, .fileAllocatedSizeKey, .isSymbolicLinkKey]) {
|
||||
for url in enumerator {
|
||||
if let url = url as? URL {
|
||||
if let isDirectoryValue = (try? url.resourceValues(forKeys: Set([.isDirectoryKey])))?.isDirectory, isDirectoryValue {
|
||||
tempPaths.append(url.path)
|
||||
} else if let fileSizeValue = (try? url.resourceValues(forKeys: Set([.fileAllocatedSizeKey])))?.fileAllocatedSize {
|
||||
tempPaths.append(url.path)
|
||||
|
||||
if let isSymbolicLinkValue = (try? url.resourceValues(forKeys: Set([.isSymbolicLinkKey])))?.isSymbolicLink, isSymbolicLinkValue {
|
||||
} else {
|
||||
tempSize += Int64(fileSizeValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
var immutableSize: Int64 = 0
|
||||
if let files = try? FileManager.default.contentsOfDirectory(at: URL(fileURLWithPath: account.basePath + "/postbox/db"), includingPropertiesForKeys: [URLResourceKey.fileSizeKey], options: []) {
|
||||
for url in files {
|
||||
if let fileSize = (try? url.resourceValues(forKeys: Set([.fileSizeKey])))?.fileSize {
|
||||
immutableSize += Int64(fileSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
if let logFilesPath = logFilesPath, let files = try? FileManager.default.contentsOfDirectory(at: URL(fileURLWithPath: logFilesPath), includingPropertiesForKeys: [URLResourceKey.fileSizeKey], options: []) {
|
||||
for url in files {
|
||||
if let fileSize = (try? url.resourceValues(forKeys: Set([.fileSizeKey])))?.fileSize {
|
||||
immutableSize += Int64(fileSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for additionalPath in additionalCachePaths {
|
||||
if let enumerator = FileManager.default.enumerator(at: URL(fileURLWithPath: additionalPath), includingPropertiesForKeys: [.isDirectoryKey, .fileAllocatedSizeKey, .isSymbolicLinkKey]) {
|
||||
for url in enumerator {
|
||||
if let url = url as? URL {
|
||||
if let isDirectoryValue = (try? url.resourceValues(forKeys: Set([.isDirectoryKey])))?.isDirectory, isDirectoryValue {
|
||||
} else if let fileSizeValue = (try? url.resourceValues(forKeys: Set([.fileAllocatedSizeKey])))?.fileAllocatedSize {
|
||||
tempPaths.append(url.path)
|
||||
|
||||
if let isSymbolicLinkValue = (try? url.resourceValues(forKeys: Set([.isSymbolicLinkKey])))?.isSymbolicLink, isSymbolicLinkValue {
|
||||
} else {
|
||||
tempSize += Int64(fileSizeValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var otherSize: Int64 = 0
|
||||
var otherPaths: [String] = []
|
||||
|
||||
for (id, name, size) in resourceList {
|
||||
if size == 0 {
|
||||
continue
|
||||
}
|
||||
if let id = id, processedResourceIds.contains(id) {
|
||||
continue
|
||||
}
|
||||
otherSize += size
|
||||
otherPaths.append(name)
|
||||
}
|
||||
|
||||
var cacheSize: Int64 = 0
|
||||
let basePath = account.postbox.mediaBox.basePath
|
||||
if let enumerator = FileManager.default.enumerator(at: URL(fileURLWithPath: basePath + "/cache"), includingPropertiesForKeys: [.fileSizeKey], options: [.skipsHiddenFiles, .skipsSubdirectoryDescendants], errorHandler: nil) {
|
||||
loop: for url in enumerator {
|
||||
if let url = url as? URL {
|
||||
if let value = (try? url.resourceValues(forKeys: Set([.fileSizeKey])))?.fileSize, value != 0 {
|
||||
otherPaths.append("cache/" + url.lastPathComponent)
|
||||
cacheSize += Int64(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func processRecursive(directoryPath: String, subdirectoryPath: String) {
|
||||
if let enumerator = FileManager.default.enumerator(at: URL(fileURLWithPath: directoryPath), includingPropertiesForKeys: [.fileSizeKey, .isDirectoryKey], options: [.skipsHiddenFiles, .skipsSubdirectoryDescendants], errorHandler: nil) {
|
||||
loop: for url in enumerator {
|
||||
if let url = url as? URL {
|
||||
if let isDirectory = (try? url.resourceValues(forKeys: Set([.isDirectoryKey])))?.isDirectory, isDirectory {
|
||||
processRecursive(directoryPath: url.path, subdirectoryPath: subdirectoryPath + "/\(url.lastPathComponent)")
|
||||
} else if let value = (try? url.resourceValues(forKeys: Set([.fileSizeKey])))?.fileSize, value != 0 {
|
||||
otherPaths.append("\(subdirectoryPath)/" + url.lastPathComponent)
|
||||
cacheSize += Int64(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
processRecursive(directoryPath: basePath + "/animation-cache", subdirectoryPath: "animation-cache")
|
||||
|
||||
if let enumerator = FileManager.default.enumerator(at: URL(fileURLWithPath: basePath + "/short-cache"), includingPropertiesForKeys: [.fileSizeKey], options: [.skipsHiddenFiles, .skipsSubdirectoryDescendants], errorHandler: nil) {
|
||||
loop: for url in enumerator {
|
||||
if let url = url as? URL {
|
||||
if let value = (try? url.resourceValues(forKeys: Set([.fileSizeKey])))?.fileSize, value != 0 {
|
||||
otherPaths.append("short-cache/" + url.lastPathComponent)
|
||||
cacheSize += Int64(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return .result(CacheUsageStats(
|
||||
media: media,
|
||||
mediaResourceIds: mediaResourceIds,
|
||||
peers: peers,
|
||||
otherSize: otherSize,
|
||||
otherPaths: otherPaths,
|
||||
cacheSize: 0,
|
||||
tempPaths: tempPaths,
|
||||
tempSize: tempSize,
|
||||
immutableSize: immutableSize
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let initialState = CacheUsageStatsState()
|
||||
if let peerId = peerId {
|
||||
initialState.lowerBound = MessageIndex.lowerBound(peerId: peerId)
|
||||
@@ -277,7 +474,8 @@ func _internal_collectCacheUsageStats(account: Account, peerId: PeerId? = nil, a
|
||||
|
||||
let signal = (fetch |> mapToSignal { mediaByPeer, mediaRefs, updatedLowerBound -> Signal<CacheUsageStatsResult, CollectCacheUsageStatsError> in
|
||||
return process(mediaByPeer, mediaRefs, updatedLowerBound)
|
||||
}) |> restart
|
||||
})
|
||||
|> restart
|
||||
|
||||
return signal |> `catch` { error in
|
||||
switch error {
|
||||
|
||||
Reference in New Issue
Block a user