aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations/IO/LibraryMonitor.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Emby.Server.Implementations/IO/LibraryMonitor.cs')
-rw-r--r--Emby.Server.Implementations/IO/LibraryMonitor.cs39
1 files changed, 36 insertions, 3 deletions
diff --git a/Emby.Server.Implementations/IO/LibraryMonitor.cs b/Emby.Server.Implementations/IO/LibraryMonitor.cs
index 1bf0f8c76c..e51c863f86 100644
--- a/Emby.Server.Implementations/IO/LibraryMonitor.cs
+++ b/Emby.Server.Implementations/IO/LibraryMonitor.cs
@@ -3,11 +3,13 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Threading;
using System.Threading.Tasks;
using Emby.Server.Implementations.Library;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.IO;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
@@ -21,6 +23,7 @@ namespace Emby.Server.Implementations.IO
private readonly ILibraryManager _libraryManager;
private readonly IServerConfigurationManager _configurationManager;
private readonly IFileSystem _fileSystem;
+ private readonly IDirectoryService _directoryService;
private readonly DotIgnoreIgnoreRule _dotIgnoreIgnoreRule;
/// <summary>
@@ -38,6 +41,12 @@ namespace Emby.Server.Implementations.IO
/// </summary>
private readonly ConcurrentDictionary<string, string> _tempIgnoredPaths = new(StringComparer.OrdinalIgnoreCase);
+ /// <summary>
+ /// Incremented by every <see cref="Stop"/> so watchers still being created on a background
+ /// task can tell that the sweep they should have been caught by has already run.
+ /// </summary>
+ private int _watcherGeneration;
+
private bool _disposed;
/// <summary>
@@ -47,6 +56,7 @@ namespace Emby.Server.Implementations.IO
/// <param name="libraryManager">The library manager.</param>
/// <param name="configurationManager">The configuration manager.</param>
/// <param name="fileSystem">The filesystem.</param>
+ /// <param name="directoryService">The directory service.</param>
/// <param name="appLifetime">The <see cref="IHostApplicationLifetime"/>.</param>
/// <param name="dotIgnoreIgnoreRule">The .ignore rule handler.</param>
public LibraryMonitor(
@@ -54,6 +64,7 @@ namespace Emby.Server.Implementations.IO
ILibraryManager libraryManager,
IServerConfigurationManager configurationManager,
IFileSystem fileSystem,
+ IDirectoryService directoryService,
IHostApplicationLifetime appLifetime,
DotIgnoreIgnoreRule dotIgnoreIgnoreRule)
{
@@ -61,10 +72,11 @@ namespace Emby.Server.Implementations.IO
_logger = logger;
_configurationManager = configurationManager;
_fileSystem = fileSystem;
+ _directoryService = directoryService;
_dotIgnoreIgnoreRule = dotIgnoreIgnoreRule;
appLifetime.ApplicationStarted.Register(Start);
- appLifetime.ApplicationStopping.Register(Stop);
+ appLifetime.ApplicationStopping.Register(Dispose);
}
/// <inheritdoc />
@@ -115,6 +127,11 @@ namespace Emby.Server.Implementations.IO
/// <inheritdoc />
public void Start()
{
+ if (_disposed)
+ {
+ return;
+ }
+
_libraryManager.ItemAdded += OnLibraryManagerItemAdded;
_libraryManager.ItemRemoved += OnLibraryManagerItemRemoved;
@@ -228,6 +245,8 @@ namespace Emby.Server.Implementations.IO
return;
}
+ var generation = Volatile.Read(ref _watcherGeneration);
+
// Creating a FileSystemWatcher over the LAN can take hundreds of milliseconds, so wrap it in a Task to do them all in parallel
Task.Run(() =>
{
@@ -251,7 +270,11 @@ namespace Emby.Server.Implementations.IO
newWatcher.Changed += OnWatcherChanged;
newWatcher.Error += OnWatcherError;
- if (_fileSystemWatchers.TryAdd(path, newWatcher))
+ if (_disposed || Volatile.Read(ref _watcherGeneration) != generation)
+ {
+ DisposeWatcher(newWatcher, false);
+ }
+ else if (_fileSystemWatchers.TryAdd(path, newWatcher))
{
newWatcher.EnableRaisingEvents = true;
_logger.LogInformation("Watching directory {Path}", path);
@@ -352,6 +375,11 @@ namespace Emby.Server.Implementations.IO
{
ArgumentException.ThrowIfNullOrEmpty(path);
+ if (_disposed)
+ {
+ return;
+ }
+
if (IgnorePatterns.ShouldIgnore(path))
{
return;
@@ -363,6 +391,8 @@ namespace Emby.Server.Implementations.IO
return;
}
+ _directoryService.Invalidate(path);
+
// Ignore certain files, If the parent of an ignored path has a change event, ignore that too
foreach (var i in _tempIgnoredPaths.Keys)
{
@@ -445,6 +475,8 @@ namespace Emby.Server.Implementations.IO
/// </summary>
public void Stop()
{
+ Interlocked.Increment(ref _watcherGeneration);
+
_libraryManager.ItemAdded -= OnLibraryManagerItemAdded;
_libraryManager.ItemRemoved -= OnLibraryManagerItemRemoved;
@@ -489,8 +521,9 @@ namespace Emby.Server.Implementations.IO
return;
}
- Stop();
+ // Set before stopping so anything racing us stops handing out new work.
_disposed = true;
+ Stop();
}
}
}