From 5150e2ad6d07a8b12c6678329d18fdb8acacf7f0 Mon Sep 17 00:00:00 2001 From: vnugent Date: Wed, 27 Sep 2023 01:09:11 -0400 Subject: serializer overhaul, plugin cleanup round 3 or 4, more tests --- lib/Plugins.Runtime/src/AssemblyWatcher.cs | 81 +++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) (limited to 'lib/Plugins.Runtime/src/AssemblyWatcher.cs') diff --git a/lib/Plugins.Runtime/src/AssemblyWatcher.cs b/lib/Plugins.Runtime/src/AssemblyWatcher.cs index 1cf87b0..09b49dc 100644 --- a/lib/Plugins.Runtime/src/AssemblyWatcher.cs +++ b/lib/Plugins.Runtime/src/AssemblyWatcher.cs @@ -22,8 +22,13 @@ * along with VNLib.Plugins.Runtime. If not, see http://www.gnu.org/licenses/. */ +using System.IO; +using System.Threading; using System.Collections.Generic; +using VNLib.Utils; +using VNLib.Utils.Extensions; + namespace VNLib.Plugins.Runtime { internal sealed class AssemblyWatcher : IPluginAssemblyWatcher @@ -36,6 +41,7 @@ namespace VNLib.Plugins.Runtime _watchers = new(); } + /// public void StopWatching(IPluginReloadEventHandler handler) { lock (_lock) @@ -49,6 +55,7 @@ namespace VNLib.Plugins.Runtime } } + /// public void WatchAssembly(IPluginReloadEventHandler handler, IPluginAssemblyLoader loader) { lock(_lock) @@ -65,6 +72,78 @@ namespace VNLib.Plugins.Runtime //Store watcher _watchers.Add(handler, watcher); } - } + } + + private sealed class AsmFileWatcher : VnDisposeable + { + public IPluginReloadEventHandler Handler { get; } + + private readonly IPluginAssemblyLoader _loaderSource; + private readonly Timer _delayTimer; + private readonly FileSystemWatcher _watcher; + + private bool _pause; + + public AsmFileWatcher(IPluginAssemblyLoader LoaderSource, IPluginReloadEventHandler handler) + { + Handler = handler; + _loaderSource = LoaderSource; + + string dir = Path.GetDirectoryName(LoaderSource.Config.AssemblyFile)!; + + //Configure watcher to notify only when the assembly file changes + _watcher = new FileSystemWatcher(dir) + { + Filter = "*.dll", + EnableRaisingEvents = false, + IncludeSubdirectories = true, + NotifyFilter = NotifyFilters.LastWrite, + }; + + //Configure listener + _watcher.Changed += OnFileChanged; + _watcher.Created += OnFileChanged; + + _watcher.EnableRaisingEvents = true; + + //setup delay timer to wait on the config + _delayTimer = new(OnTimeout, this, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); + } + + void OnFileChanged(object sender, FileSystemEventArgs e) + { + //if were already waiting to process an event, we dont need to stage another + if (_pause) + { + return; + } + + //Set pause flag + _pause = true; + + //Restart the timer to trigger reload event on elapsed + _delayTimer.Restart(_loaderSource.Config.ReloadDelay); + } + + private void OnTimeout(object? state) + { + _delayTimer.Stop(); + + //Fire event, let exception crash app + Handler.OnPluginUnloaded(_loaderSource); + + //Clear pause flag + _pause = false; + } + + protected override void Free() + { + _delayTimer.Dispose(); + + //Detach event handler and dispose watcher + _watcher.Changed -= OnFileChanged; + _watcher.Dispose(); + } + } } } -- cgit