Просмотр исходного кода

Minor LibraryMonitor improvements

* Enable nullable
* Add a fast return to ReportFileSystemChanged when path should be ignored
* Use Span overloads of Path.* functions where possible
* IFileSystem: remove NormalizePath as Path.TrimEndingDirectorySeparator already checks if it's a root path
Bond_009 1 год назад
Родитель
Сommit
767a42fbdb

+ 1 - 1
Emby.Server.Implementations/ApplicationHost.cs

@@ -157,7 +157,7 @@ namespace Emby.Server.Implementations
             _fileSystemManager = new ManagedFileSystem(LoggerFactory.CreateLogger<ManagedFileSystem>(), applicationPaths);
 
             Logger = LoggerFactory.CreateLogger<ApplicationHost>();
-            _fileSystemManager.AddShortcutHandler(new MbLinkShortcutHandler(_fileSystemManager));
+            _fileSystemManager.AddShortcutHandler(new MbLinkShortcutHandler());
             _deviceId = new DeviceId(ApplicationPaths, LoggerFactory);
 
             ApplicationVersion = typeof(ApplicationHost).Assembly.GetName().Version;

+ 1 - 8
Emby.Server.Implementations/IO/FileRefresher.cs

@@ -85,7 +85,7 @@ namespace Emby.Server.Implementations.IO
             }
         }
 
-        public void ResetPath(string path, string affectedFile)
+        public void ResetPath(string path, string? affectedFile)
         {
             lock (_timerLock)
             {
@@ -148,13 +148,6 @@ namespace Emby.Server.Implementations.IO
                 {
                     item.ChangedExternally();
                 }
-                catch (IOException ex)
-                {
-                    // For now swallow and log.
-                    // Research item: If an IOException occurs, the item may be in a disconnected state (media unavailable)
-                    // Should we remove it from it's parent?
-                    _logger.LogError(ex, "Error refreshing {Name}", item.Name);
-                }
                 catch (Exception ex)
                 {
                     _logger.LogError(ex, "Error refreshing {Name}", item.Name);

+ 35 - 33
Emby.Server.Implementations/IO/LibraryMonitor.cs

@@ -1,5 +1,3 @@
-#nullable disable
-
 #pragma warning disable CS1591
 
 using System;
@@ -160,7 +158,7 @@ namespace Emby.Server.Implementations.IO
         /// </summary>
         /// <param name="sender">The source of the event.</param>
         /// <param name="e">The <see cref="ItemChangeEventArgs"/> instance containing the event data.</param>
-        private void OnLibraryManagerItemRemoved(object sender, ItemChangeEventArgs e)
+        private void OnLibraryManagerItemRemoved(object? sender, ItemChangeEventArgs e)
         {
             if (e.Parent is AggregateFolder)
             {
@@ -173,7 +171,7 @@ namespace Emby.Server.Implementations.IO
         /// </summary>
         /// <param name="sender">The source of the event.</param>
         /// <param name="e">The <see cref="ItemChangeEventArgs"/> instance containing the event data.</param>
-        private void OnLibraryManagerItemAdded(object sender, ItemChangeEventArgs e)
+        private void OnLibraryManagerItemAdded(object? sender, ItemChangeEventArgs e)
         {
             if (e.Parent is AggregateFolder)
             {
@@ -189,19 +187,28 @@ namespace Emby.Server.Implementations.IO
         /// <param name="path">The path.</param>
         /// <returns><c>true</c> if [contains parent folder] [the specified LST]; otherwise, <c>false</c>.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="path"/> is <c>null</c>.</exception>
-        private static bool ContainsParentFolder(IEnumerable<string> lst, string path)
+        private static bool ContainsParentFolder(IReadOnlyList<string> lst, ReadOnlySpan<char> path)
         {
-            ArgumentException.ThrowIfNullOrEmpty(path);
+            if (path.IsEmpty)
+            {
+                throw new ArgumentException("Path can't be empty", nameof(path));
+            }
 
             path = path.TrimEnd(Path.DirectorySeparatorChar);
 
-            return lst.Any(str =>
+            foreach (var str in lst)
             {
                 // this should be a little quicker than examining each actual parent folder...
-                var compare = str.TrimEnd(Path.DirectorySeparatorChar);
+                var compare = str.AsSpan().TrimEnd(Path.DirectorySeparatorChar);
 
-                return path.Equals(compare, StringComparison.OrdinalIgnoreCase) || (path.StartsWith(compare, StringComparison.OrdinalIgnoreCase) && path[compare.Length] == Path.DirectorySeparatorChar);
-            });
+                if (path.Equals(compare, StringComparison.OrdinalIgnoreCase)
+                    || (path.StartsWith(compare, StringComparison.OrdinalIgnoreCase) && path[compare.Length] == Path.DirectorySeparatorChar))
+                {
+                    return true;
+                }
+            }
+
+            return false;
         }
 
         /// <summary>
@@ -349,21 +356,19 @@ namespace Emby.Server.Implementations.IO
         {
             ArgumentException.ThrowIfNullOrEmpty(path);
 
-            var monitorPath = !IgnorePatterns.ShouldIgnore(path);
+            if (IgnorePatterns.ShouldIgnore(path))
+            {
+                return;
+            }
 
             // Ignore certain files, If the parent of an ignored path has a change event, ignore that too
-            if (_tempIgnoredPaths.Keys.Any(i =>
+            foreach (var i in _tempIgnoredPaths.Keys)
             {
-                if (_fileSystem.AreEqual(i, path))
-                {
-                    _logger.LogDebug("Ignoring change to {Path}", path);
-                    return true;
-                }
-
-                if (_fileSystem.ContainsSubPath(i, path))
+                if (_fileSystem.AreEqual(i, path)
+                    || _fileSystem.ContainsSubPath(i, path))
                 {
                     _logger.LogDebug("Ignoring change to {Path}", path);
-                    return true;
+                    return;
                 }
 
                 // Go up a level
@@ -371,20 +376,12 @@ namespace Emby.Server.Implementations.IO
                 if (!string.IsNullOrEmpty(parent) && _fileSystem.AreEqual(parent, path))
                 {
                     _logger.LogDebug("Ignoring change to {Path}", path);
-                    return true;
+                    return;
                 }
-
-                return false;
-            }))
-            {
-                monitorPath = false;
             }
 
-            if (monitorPath)
-            {
-                // Avoid implicitly captured closure
-                CreateRefresher(path);
-            }
+            // Avoid implicitly captured closure
+            CreateRefresher(path);
         }
 
         private void CreateRefresher(string path)
@@ -417,7 +414,7 @@ namespace Emby.Server.Implementations.IO
                     }
 
                     // They are siblings. Rebase the refresher to the parent folder.
-                    if (string.Equals(parentPath, Path.GetDirectoryName(refresher.Path), StringComparison.Ordinal))
+                    if (parentPath is not null && string.Equals(parentPath, Path.GetDirectoryName(refresher.Path), StringComparison.Ordinal))
                     {
                         refresher.ResetPath(parentPath, path);
                         return;
@@ -430,8 +427,13 @@ namespace Emby.Server.Implementations.IO
             }
         }
 
-        private void OnNewRefresherCompleted(object sender, EventArgs e)
+        private void OnNewRefresherCompleted(object? sender, EventArgs e)
         {
+            if (sender is null)
+            {
+                return;
+            }
+
             var refresher = (FileRefresher)sender;
             DisposeRefresher(refresher);
         }

+ 2 - 16
Emby.Server.Implementations/IO/ManagedFileSystem.cs

@@ -485,25 +485,11 @@ namespace Emby.Server.Implementations.IO
                 _isEnvironmentCaseInsensitive ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal);
         }
 
-        /// <inheritdoc />
-        public virtual string NormalizePath(string path)
-        {
-            ArgumentException.ThrowIfNullOrEmpty(path);
-
-            if (path.EndsWith(":\\", StringComparison.OrdinalIgnoreCase))
-            {
-                return path;
-            }
-
-            return Path.TrimEndingDirectorySeparator(path);
-        }
-
         /// <inheritdoc />
         public virtual bool AreEqual(string path1, string path2)
         {
-            return string.Equals(
-                NormalizePath(path1),
-                NormalizePath(path2),
+            return Path.TrimEndingDirectorySeparator(path1).Equals(
+                Path.TrimEndingDirectorySeparator(path2),
                 _isEnvironmentCaseInsensitive ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal);
         }
 

+ 2 - 9
Emby.Server.Implementations/IO/MbLinkShortcutHandler.cs

@@ -8,24 +8,17 @@ namespace Emby.Server.Implementations.IO
 {
     public class MbLinkShortcutHandler : IShortcutHandler
     {
-        private readonly IFileSystem _fileSystem;
-
-        public MbLinkShortcutHandler(IFileSystem fileSystem)
-        {
-            _fileSystem = fileSystem;
-        }
-
         public string Extension => ".mblink";
 
         public string? Resolve(string shortcutPath)
         {
             ArgumentException.ThrowIfNullOrEmpty(shortcutPath);
 
-            if (string.Equals(Path.GetExtension(shortcutPath), ".mblink", StringComparison.OrdinalIgnoreCase))
+            if (Path.GetExtension(shortcutPath.AsSpan()).Equals(".mblink", StringComparison.OrdinalIgnoreCase))
             {
                 var path = File.ReadAllText(shortcutPath);
 
-                return _fileSystem.NormalizePath(path);
+                return Path.TrimEndingDirectorySeparator(path);
             }
 
             return null;

+ 1 - 1
Emby.Server.Implementations/Library/LibraryManager.cs

@@ -608,7 +608,7 @@ namespace Emby.Server.Implementations.Library
             var originalList = paths.ToList();
 
             var list = originalList.Where(i => i.IsDirectory)
-                .Select(i => _fileSystem.NormalizePath(i.FullName))
+                .Select(i => Path.TrimEndingDirectorySeparator(i.FullName))
                 .Distinct(StringComparer.OrdinalIgnoreCase)
                 .ToList();
 

+ 0 - 7
MediaBrowser.Model/IO/IFileSystem.cs

@@ -116,13 +116,6 @@ namespace MediaBrowser.Model.IO
         /// <returns><c>true</c> if [contains sub path] [the specified parent path]; otherwise, <c>false</c>.</returns>
         bool ContainsSubPath(string parentPath, string path);
 
-        /// <summary>
-        /// Normalizes the path.
-        /// </summary>
-        /// <param name="path">The path.</param>
-        /// <returns>System.String.</returns>
-        string NormalizePath(string path);
-
         /// <summary>
         /// Gets the file name without extension.
         /// </summary>

+ 2 - 0
jellyfin.ruleset

@@ -52,6 +52,8 @@
     <Rule Id="SA1204" Action="None" />
     <!-- disable warning SA1309: Fields must not begin with an underscore -->
     <Rule Id="SA1309" Action="None" />
+    <!-- disable warning SA1311: Static readonly fields should begin with upper-case letter -->
+    <Rule Id="SA1311" Action="None" />
     <!-- disable warning SA1413: Use trailing comma in multi-line initializers -->
     <Rule Id="SA1413" Action="None" />
     <!-- disable warning SA1512: Single-line comments must not be followed by blank line -->