Files
BeatSaber/Assets/Script/CacheManager.cs
T

107 lines
3.7 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine;
// 앱 시작 시 캐시 총 용량을 확인하고 1GB 초과 시 LRU 순으로 자동 삭제
public class CacheManager : MonoBehaviour
{
private const long MaxCacheBytes = 1L * 1024 * 1024 * 1024; // 1 GB
private static string CacheRoot => Path.Combine(Application.temporaryCachePath, "beatsaber");
// ── Unity ────────────────────────────────────────────────
private void Start()
{
RunEviction();
}
// ── Public API ───────────────────────────────────────────
public long TotalCacheBytes()
{
if (!Directory.Exists(CacheRoot)) return 0;
return Directory.GetFiles(CacheRoot, "*", SearchOption.AllDirectories)
.Sum(f => new FileInfo(f).Length);
}
// 강제 정리 (UI에서 수동 호출용)
public void RunEviction()
{
if (!Directory.Exists(CacheRoot)) return;
long total = TotalCacheBytes();
if (total <= MaxCacheBytes)
{
Debug.Log($"[CacheManager] 용량 정상: {FormatBytes(total)}");
return;
}
// 곡 폴더를 마지막 접근 시간 오름차순 정렬 (가장 오래된 것부터)
List<SongDirInfo> dirs = GetSongDirs();
dirs.Sort((a, b) => a.lastAccessed.CompareTo(b.lastAccessed));
foreach (SongDirInfo dir in dirs)
{
if (total <= MaxCacheBytes) break;
total -= dir.sizeBytes;
Directory.Delete(dir.path, recursive: true);
SongLibrary.Instance?.MarkSongRemoved(dir.songId);
Debug.Log($"[CacheManager] LRU 삭제: {dir.songId} ({FormatBytes(dir.sizeBytes)})");
}
Debug.Log($"[CacheManager] 정리 완료 → 현재 {FormatBytes(total)}");
}
// ── 내부 구현 ─────────────────────────────────────────────
private List<SongDirInfo> GetSongDirs()
{
var result = new List<SongDirInfo>();
foreach (string dir in Directory.GetDirectories(CacheRoot))
{
long size = Directory.GetFiles(dir, "*", SearchOption.AllDirectories)
.Sum(f => new FileInfo(f).Length);
// 마지막 접근 시간은 SongLibrary 기록 우선, 없으면 파일시스템 참조
DateTime lastAccessed = DateTime.MaxValue;
string songId = Path.GetFileName(dir);
LibraryEntry entry = SongLibrary.Instance?.GetAll()
.Find(e => e.songId == songId);
if (entry != null && DateTime.TryParse(entry.lastAccessedAt, out DateTime t))
lastAccessed = t;
else
lastAccessed = Directory.GetLastAccessTimeUtc(dir);
result.Add(new SongDirInfo
{
songId = songId,
path = dir,
sizeBytes = size,
lastAccessed = lastAccessed
});
}
return result;
}
private static string FormatBytes(long bytes)
{
if (bytes >= 1024 * 1024 * 1024) return $"{bytes / (1024f * 1024 * 1024):F2} GB";
if (bytes >= 1024 * 1024) return $"{bytes / (1024f * 1024):F1} MB";
return $"{bytes / 1024f:F0} KB";
}
private struct SongDirInfo
{
public string songId;
public string path;
public long sizeBytes;
public DateTime lastAccessed;
}
}