rework file cache management, force usage of websocket, add uid comments per server

This commit is contained in:
Stanley Dimant
2022-06-28 23:45:49 +02:00
parent 3ee082d371
commit 71d48b0d8c
7 changed files with 203 additions and 115 deletions

View File

@@ -14,9 +14,13 @@ namespace MareSynchronos.Managers
public class FileCacheManager : IDisposable
{
private readonly IpcManager _ipcManager;
private readonly ConcurrentBag<string> _modifiedFiles = new();
private readonly Configuration _pluginConfiguration;
private FileSystemWatcher? _cacheDirWatcher;
private FileSystemWatcher? _penumbraDirWatcher;
private Task? _rescanTask;
private CancellationTokenSource? _rescanTaskCancellationTokenSource;
private CancellationTokenSource? _rescanTaskRunCancellationTokenSource;
private CancellationTokenSource? _scanCancellationTokenSource;
private Task? _scanTask;
public FileCacheManager(IpcManager ipcManager, Configuration pluginConfiguration)
@@ -32,26 +36,10 @@ namespace MareSynchronos.Managers
_ipcManager.PenumbraDisposed += IpcManagerOnPenumbraDisposed;
}
private void StartWatchersAndScan()
{
if (!_ipcManager.Initialized || !_pluginConfiguration.HasValidSetup) return;
Logger.Debug("Penumbra is active, configuration is valid, starting watchers and scan");
StartWatchers();
StartInitialScan();
}
private void IpcManagerOnPenumbraInitialized(object? sender, EventArgs e)
{
StartWatchersAndScan();
}
private void IpcManagerOnPenumbraDisposed(object? sender, EventArgs e)
{
StopWatchersAndScan();
}
public long CurrentFileProgress { get; private set; }
public long FileCacheSize { get; set; }
public bool IsScanRunning => !_scanTask?.IsCompleted ?? false;
public long TotalFiles { get; private set; }
@@ -83,17 +71,12 @@ namespace MareSynchronos.Managers
_ipcManager.PenumbraInitialized -= IpcManagerOnPenumbraInitialized;
_ipcManager.PenumbraDisposed -= IpcManagerOnPenumbraDisposed;
_rescanTaskCancellationTokenSource?.Cancel();
_rescanTaskRunCancellationTokenSource?.Cancel();
StopWatchersAndScan();
}
private void StopWatchersAndScan()
{
_cacheDirWatcher?.Dispose();
_penumbraDirWatcher?.Dispose();
_scanCancellationTokenSource?.Cancel();
}
public void StartInitialScan()
{
_scanCancellationTokenSource = new CancellationTokenSource();
@@ -102,8 +85,8 @@ namespace MareSynchronos.Managers
public void StartWatchers()
{
if (!_ipcManager.Initialized || !_pluginConfiguration.HasValidSetup) return;
Logger.Debug("Starting File System Watchers");
if (!_ipcManager.Initialized || !_pluginConfiguration.HasValidSetup()) return;
Logger.Verbose("Starting File System Watchers");
_penumbraDirWatcher?.Dispose();
_cacheDirWatcher?.Dispose();
@@ -113,8 +96,9 @@ namespace MareSynchronos.Managers
InternalBufferSize = 1048576
};
_penumbraDirWatcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size;
_penumbraDirWatcher.Deleted += OnDeleted;
_penumbraDirWatcher.Deleted += OnModified;
_penumbraDirWatcher.Changed += OnModified;
_penumbraDirWatcher.Renamed += OnModified;
_penumbraDirWatcher.Filters.Add("*.mtrl");
_penumbraDirWatcher.Filters.Add("*.mdl");
_penumbraDirWatcher.Filters.Add("*.tex");
@@ -127,8 +111,9 @@ namespace MareSynchronos.Managers
InternalBufferSize = 1048576
};
_cacheDirWatcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size;
_cacheDirWatcher.Deleted += OnDeleted;
_cacheDirWatcher.Deleted += OnModified;
_cacheDirWatcher.Changed += OnModified;
_cacheDirWatcher.Renamed += OnModified;
_cacheDirWatcher.Filters.Add("*.mtrl");
_cacheDirWatcher.Filters.Add("*.mdl");
_cacheDirWatcher.Filters.Add("*.tex");
@@ -139,6 +124,16 @@ namespace MareSynchronos.Managers
Task.Run(RecalculateFileCacheSize);
}
private void IpcManagerOnPenumbraDisposed(object? sender, EventArgs e)
{
StopWatchersAndScan();
}
private void IpcManagerOnPenumbraInitialized(object? sender, EventArgs e)
{
StartWatchersAndScan();
}
private bool IsFileLocked(FileInfo file)
{
try
@@ -153,62 +148,10 @@ namespace MareSynchronos.Managers
return false;
}
private void OnDeleted(object sender, FileSystemEventArgs e)
{
var fi = new FileInfo(e.FullPath);
using var db = new FileCacheContext();
var ext = fi.Extension.ToLower();
if (ext is ".mdl" or ".tex" or ".mtrl")
{
Logger.Debug("File deleted: " + e.FullPath);
var fileInDb = db.FileCaches.SingleOrDefault(f => f.Filepath == fi.FullName.ToLower());
if (fileInDb == null) return;
db.Remove(fileInDb);
}
else
{
if (fi.Extension == string.Empty)
{
// this is most likely a folder
var filesToRemove = db.FileCaches.Where(f => f.Filepath.StartsWith(e.FullPath.ToLower())).ToList();
Logger.Debug($"Folder deleted: {e.FullPath}, removing {filesToRemove.Count} files");
db.RemoveRange(filesToRemove);
}
}
db.SaveChanges();
if (e.FullPath.Contains(_pluginConfiguration.CacheFolder, StringComparison.OrdinalIgnoreCase))
{
Task.Run(RecalculateFileCacheSize);
}
}
private void OnModified(object sender, FileSystemEventArgs e)
{
var fi = new FileInfo(e.FullPath);
Logger.Debug("File changed: " + e.FullPath);
using var db = new FileCacheContext();
var modifiedFile = Create(fi.FullName);
var fileInDb = db.FileCaches.SingleOrDefault(f => f.Filepath == fi.FullName.ToLower());
if (fileInDb != null)
db.Remove(fileInDb);
else
{
var files = db.FileCaches.Where(f => f.Hash == modifiedFile.Hash);
foreach (var file in files)
{
if (!File.Exists(file.Filepath)) db.Remove(file.Filepath);
}
}
db.Add(modifiedFile);
db.SaveChanges();
if (e.FullPath.Contains(_pluginConfiguration.CacheFolder, StringComparison.OrdinalIgnoreCase))
{
Task.Run(RecalculateFileCacheSize);
}
_modifiedFiles.Add(e.FullPath);
Task.Run(() => _ = RescanTask());
}
private void RecalculateFileCacheSize()
@@ -227,6 +170,55 @@ namespace MareSynchronos.Managers
}
}
public async Task RescanTask(bool force = false)
{
_rescanTaskRunCancellationTokenSource?.Cancel();
_rescanTaskRunCancellationTokenSource = new CancellationTokenSource();
var token = _rescanTaskRunCancellationTokenSource.Token;
if(!force)
await Task.Delay(TimeSpan.FromSeconds(1), token);
while ((!_rescanTask?.IsCompleted ?? false) && !token.IsCancellationRequested)
{
await Task.Delay(TimeSpan.FromSeconds(1), token);
}
if (token.IsCancellationRequested) return;
PluginLog.Debug("File changes detected, scanning the changes");
if (!_modifiedFiles.Any()) return;
_rescanTaskCancellationTokenSource = new CancellationTokenSource();
_rescanTask = Task.Run(async () =>
{
var listCopy = _modifiedFiles.ToList();
_modifiedFiles.Clear();
await using var db = new FileCacheContext();
foreach (var item in listCopy.Distinct())
{
var fi = new FileInfo(item);
if (!fi.Exists)
{
PluginLog.Verbose("Removed: " + item);
db.RemoveRange(db.FileCaches.Where(f => f.Filepath.ToLower() == item.ToLower()));
}
else
{
PluginLog.Verbose("Changed :" + item);
var fileCache = Create(item);
db.RemoveRange(db.FileCaches.Where(f => f.Hash == fileCache.Hash));
await db.AddAsync(fileCache, _rescanTaskCancellationTokenSource.Token);
}
}
await db.SaveChangesAsync(_rescanTaskCancellationTokenSource.Token);
RecalculateFileCacheSize();
}, _rescanTaskCancellationTokenSource.Token);
}
private async Task StartFileScan(CancellationToken ct)
{
_scanCancellationTokenSource = new CancellationTokenSource();
@@ -341,5 +333,17 @@ namespace MareSynchronos.Managers
_pluginConfiguration.Save();
}
}
private void StartWatchersAndScan()
{
if (!_ipcManager.Initialized || !_pluginConfiguration.HasValidSetup()) return;
Logger.Verbose("Penumbra is active, configuration is valid, starting watchers and scan");
StartWatchers();
StartInitialScan();
}
private void StopWatchersAndScan()
{
_cacheDirWatcher?.Dispose();
}
}
}