107 lines
3.7 KiB
C#
107 lines
3.7 KiB
C#
|
|
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;
|
||
|
|
}
|
||
|
|
}
|