calculate and display local cache size on cache changes, add clear cache button

This commit is contained in:
Stanley Dimant
2022-06-24 18:53:56 +02:00
parent cc0af38b31
commit f8919abea8
7 changed files with 87 additions and 68 deletions

View File

@@ -1,6 +1,5 @@
using System.Diagnostics; using System.Diagnostics;
using System.Threading; using System.Threading;
using Dalamud.Game.ClientState;
using FFXIVClientStructs.FFXIV.Client.Game.Character; using FFXIVClientStructs.FFXIV.Client.Game.Character;
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
using FFXIVClientStructs.FFXIV.Client.System.Resource; using FFXIVClientStructs.FFXIV.Client.System.Resource;

View File

@@ -1,48 +0,0 @@
using System;
using System.IO;
using System.Threading;
using MareSynchronos.FileCacheDB;
using MareSynchronos.Utils;
namespace MareSynchronos.Factories
{
public class FileCacheFactory
{
public FileCache Create(string file)
{
FileInfo fileInfo = new(file);
if (IsFileLocked(fileInfo))
{
throw new FileLoadException();
}
var sha1Hash = Crypto.GetFileHash(fileInfo.FullName);
return new FileCache()
{
Filepath = fileInfo.FullName,
Hash = sha1Hash,
LastModifiedDate = fileInfo.LastWriteTimeUtc.Ticks.ToString(),
};
}
public void UpdateFileCache(FileCache cache)
{
FileInfo fileInfo = new(cache.Filepath);
cache.Hash = Crypto.GetFileHash(cache.Filepath);
cache.LastModifiedDate = fileInfo.LastWriteTimeUtc.Ticks.ToString();
}
private bool IsFileLocked(FileInfo file)
{
try
{
using var fs = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
}
catch
{
return true;
}
return false;
}
}
}

View File

@@ -177,5 +177,7 @@ namespace MareSynchronos.Managers
} }
}); });
} }
} }
} }

View File

@@ -6,7 +6,6 @@ using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Dalamud.Logging; using Dalamud.Logging;
using MareSynchronos.Factories;
using MareSynchronos.FileCacheDB; using MareSynchronos.FileCacheDB;
using MareSynchronos.Utils; using MareSynchronos.Utils;
@@ -14,19 +13,18 @@ namespace MareSynchronos.Managers
{ {
public class FileCacheManager : IDisposable public class FileCacheManager : IDisposable
{ {
private readonly FileCacheFactory _fileCacheFactory;
private readonly IpcManager _ipcManager; private readonly IpcManager _ipcManager;
private readonly Configuration _pluginConfiguration; private readonly Configuration _pluginConfiguration;
private CancellationTokenSource? _scanCancellationTokenSource; private CancellationTokenSource? _scanCancellationTokenSource;
private Task? _scanTask; private Task? _scanTask;
private FileSystemWatcher? _penumbraDirWatcher; private FileSystemWatcher? _penumbraDirWatcher;
private FileSystemWatcher? _cacheDirWatcher; private FileSystemWatcher? _cacheDirWatcher;
public long FileCacheSize { get; set; }
public FileCacheManager(FileCacheFactory fileCacheFactory, IpcManager ipcManager, Configuration pluginConfiguration) public FileCacheManager(IpcManager ipcManager, Configuration pluginConfiguration)
{ {
Logger.Debug("Creating " + nameof(FileCacheManager)); Logger.Debug("Creating " + nameof(FileCacheManager));
_fileCacheFactory = fileCacheFactory;
_ipcManager = ipcManager; _ipcManager = ipcManager;
_pluginConfiguration = pluginConfiguration; _pluginConfiguration = pluginConfiguration;
@@ -50,12 +48,12 @@ namespace MareSynchronos.Managers
Logger.Debug("File created: " + e.FullPath); Logger.Debug("File created: " + e.FullPath);
try try
{ {
var createdFileCache = _fileCacheFactory.Create(fi.FullName); var createdFileCache = Create(fi.FullName);
db.Add(createdFileCache); db.Add(createdFileCache);
} }
catch (FileLoadException) catch (FileLoadException)
{ {
Logger.Debug("File was still being written to"); Logger.Debug("File was still being written to.");
} }
} }
@@ -71,12 +69,17 @@ namespace MareSynchronos.Managers
foreach (var file in newFiles) foreach (var file in newFiles)
{ {
Logger.Debug("Adding " + file); Logger.Debug("Adding " + file);
db.Add(_fileCacheFactory.Create(file)); db.Add(Create(file));
} }
} }
} }
db.SaveChanges(); db.SaveChanges();
if (e.FullPath.Contains(_pluginConfiguration.CacheFolder, StringComparison.OrdinalIgnoreCase))
{
Task.Run(RecalculateFileCacheSize);
}
} }
private void OnDeleted(object sender, FileSystemEventArgs e) private void OnDeleted(object sender, FileSystemEventArgs e)
@@ -104,6 +107,11 @@ namespace MareSynchronos.Managers
} }
db.SaveChanges(); db.SaveChanges();
if (e.FullPath.Contains(_pluginConfiguration.CacheFolder, StringComparison.OrdinalIgnoreCase))
{
Task.Run(RecalculateFileCacheSize);
}
} }
private void OnModified(object sender, FileSystemEventArgs e) private void OnModified(object sender, FileSystemEventArgs e)
@@ -113,12 +121,17 @@ namespace MareSynchronos.Managers
if (fi.Extension.ToLower() is not ".mdl" or ".tex" or ".mtrl") return; if (fi.Extension.ToLower() is not ".mdl" or ".tex" or ".mtrl") return;
Logger.Debug("File changed: " + e.FullPath); Logger.Debug("File changed: " + e.FullPath);
using var db = new FileCacheContext(); using var db = new FileCacheContext();
var modifiedFile = _fileCacheFactory.Create(fi.FullName); var modifiedFile = Create(fi.FullName);
var fileInDb = db.FileCaches.SingleOrDefault(f => f.Filepath == fi.FullName.ToLower() || modifiedFile.Hash == f.Hash); var fileInDb = db.FileCaches.SingleOrDefault(f => f.Filepath == fi.FullName.ToLower() || modifiedFile.Hash == f.Hash);
if (fileInDb == null) return; if (fileInDb == null) return;
db.Remove(fileInDb); db.Remove(fileInDb);
db.Add(modifiedFile); db.Add(modifiedFile);
db.SaveChanges(); db.SaveChanges();
if (e.FullPath.Contains(_pluginConfiguration.CacheFolder, StringComparison.OrdinalIgnoreCase))
{
Task.Run(RecalculateFileCacheSize);
}
} }
public long CurrentFileProgress { get; private set; } public long CurrentFileProgress { get; private set; }
@@ -185,7 +198,7 @@ namespace MareSynchronos.Managers
} }
FileInfo fileInfo = new(cache.Filepath); FileInfo fileInfo = new(cache.Filepath);
if (fileInfo.LastWriteTimeUtc.Ticks == long.Parse(cache.LastModifiedDate)) return; if (fileInfo.LastWriteTimeUtc.Ticks == long.Parse(cache.LastModifiedDate)) return;
fileCachesToAdd.Add(_fileCacheFactory.Create(cache.Filepath)); fileCachesToAdd.Add(Create(cache.Filepath));
fileCachesToDelete.Add(cache); fileCachesToDelete.Add(cache);
} }
@@ -204,7 +217,7 @@ namespace MareSynchronos.Managers
}, },
file => file =>
{ {
fileCachesToAdd.Add(_fileCacheFactory.Create(file.Key)); fileCachesToAdd.Add(Create(file.Key));
var files = CurrentFileProgress; var files = CurrentFileProgress;
Interlocked.Increment(ref files); Interlocked.Increment(ref files);
@@ -275,6 +288,47 @@ namespace MareSynchronos.Managers
_cacheDirWatcher.Filters.Add("*.tex"); _cacheDirWatcher.Filters.Add("*.tex");
_cacheDirWatcher.Error += _cacheDirWatcher.Error +=
(sender, args) => PluginLog.Error(args.GetException(), "Error in Cache Dir Watcher"); (sender, args) => PluginLog.Error(args.GetException(), "Error in Cache Dir Watcher");
Task.Run(RecalculateFileCacheSize);
}
private void RecalculateFileCacheSize()
{
FileCacheSize = 0;
foreach (var file in Directory.EnumerateFiles(_pluginConfiguration.CacheFolder))
{
FileCacheSize += new FileInfo(file).Length;
}
}
private bool IsFileLocked(FileInfo file)
{
try
{
using var fs = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
}
catch
{
return true;
}
return false;
}
public FileCache Create(string file)
{
FileInfo fileInfo = new(file);
if (IsFileLocked(fileInfo))
{
throw new FileLoadException();
}
var sha1Hash = Crypto.GetFileHash(fileInfo.FullName);
return new FileCache()
{
Filepath = fileInfo.FullName,
Hash = sha1Hash,
LastModifiedDate = fileInfo.LastWriteTimeUtc.Ticks.ToString(),
};
} }
} }
} }

View File

@@ -51,7 +51,7 @@ namespace MareSynchronos
_apiController = new ApiController(_configuration); _apiController = new ApiController(_configuration);
_ipcManager = new IpcManager(_pluginInterface); _ipcManager = new IpcManager(_pluginInterface);
_fileCacheManager = new FileCacheManager(new FileCacheFactory(), _ipcManager, _configuration); _fileCacheManager = new FileCacheManager(_ipcManager, _configuration);
_dalamudUtil = new DalamudUtil(_clientState, _objectTable); _dalamudUtil = new DalamudUtil(_clientState, _objectTable);
_characterCacheManager = new CharacterCacheManager(_clientState, framework, _objectTable, _apiController, _characterCacheManager = new CharacterCacheManager(_clientState, framework, _objectTable, _apiController,
_dalamudUtil, _ipcManager); _dalamudUtil, _ipcManager);

View File

@@ -4,6 +4,7 @@ using Dalamud.Interface.Windowing;
using ImGuiNET; using ImGuiNET;
using MareSynchronos.WebAPI; using MareSynchronos.WebAPI;
using System; using System;
using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using MareSynchronos.Utils; using MareSynchronos.Utils;
@@ -190,7 +191,18 @@ namespace MareSynchronos.UI
{ {
_uiShared.DrawFileScanState(); _uiShared.DrawFileScanState();
_uiShared.DrawCacheDirectorySetting(); _uiShared.DrawCacheDirectorySetting();
_uiShared.DrawParallelScansSetting(); ImGui.Text($"Local cache size: {UiShared.ByteToString(_uiShared.FileCacheSize)}");
ImGui.SameLine();
if (ImGui.Button("Clear local cache"))
{
Task.Run(() =>
{
foreach (var file in Directory.GetFiles(_configuration.CacheFolder))
{
File.Delete(file);
}
});
}
ImGui.TreePop(); ImGui.TreePop();
} }
} }

View File

@@ -15,6 +15,7 @@ namespace MareSynchronos.UI
private readonly ApiController _apiController; private readonly ApiController _apiController;
private readonly FileCacheManager _fileCacheManager; private readonly FileCacheManager _fileCacheManager;
private readonly Configuration _pluginConfiguration; private readonly Configuration _pluginConfiguration;
public long FileCacheSize => _fileCacheManager.FileCacheSize;
public UiShared(IpcManager ipcManager, ApiController apiController, FileCacheManager fileCacheManager, Configuration pluginConfiguration) public UiShared(IpcManager ipcManager, ApiController apiController, FileCacheManager fileCacheManager, Configuration pluginConfiguration)
{ {
@@ -115,16 +116,15 @@ namespace MareSynchronos.UI
public static string ByteToString(long bytes) public static string ByteToString(long bytes)
{ {
double output = bytes; string[] suffix = { "B", "KiB", "MiB", "GiB", "TiB" };
var suffix = new[] { "B", "KiB", "MiB", "GiB" }; int i;
var suffixIdx = 0; double dblSByte = bytes;
while (output / 1024.0 > 1024) for (i = 0; i < suffix.Length && bytes >= 1024; i++, bytes /= 1024)
{ {
output /= 1024.0; dblSByte = bytes / 1024.0;
suffixIdx++;
} }
return output.ToString("0.00") + " " + suffix[suffixIdx]; return $"{dblSByte:0.00} {suffix[i]}";
} }
private int _serverSelectionIndex = 0; private int _serverSelectionIndex = 0;