From f1a7d9064063d1cc73a0fe9ed3f1fd9b5f5b5f55 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 4 Nov 2013 11:20:44 -0500 Subject: [PATCH 1/2] fix scan stopping and restarting itself multiple times when adding/removing collections --- MediaBrowser.Api/Library/LibraryHelpers.cs | 52 ------------ .../Library/LibraryStructureService.cs | 81 ++++++++++++++----- MediaBrowser.Api/LibraryService.cs | 3 +- MediaBrowser.Controller/Entities/Folder.cs | 8 +- .../IO/DirectoryWatchers.cs | 45 +++++------ .../Library/LibraryManager.cs | 16 +++- 6 files changed, 101 insertions(+), 104 deletions(-) diff --git a/MediaBrowser.Api/Library/LibraryHelpers.cs b/MediaBrowser.Api/Library/LibraryHelpers.cs index 3d0dd4e088..8f6dcfc0db 100644 --- a/MediaBrowser.Api/Library/LibraryHelpers.cs +++ b/MediaBrowser.Api/Library/LibraryHelpers.cs @@ -1,7 +1,6 @@ using MediaBrowser.Common.IO; using MediaBrowser.Controller; using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.IO; using System; using System.IO; using System.Linq; @@ -22,57 +21,6 @@ namespace MediaBrowser.Api.Library /// private const string ShortcutFileSearch = "*" + ShortcutFileExtension; - /// - /// Adds the virtual folder. - /// - /// The file system. - /// The name. - /// Type of the collection. - /// The user. - /// The app paths. - /// There is already a media collection with the name + name + . - public static void AddVirtualFolder(IFileSystem fileSystem, string name, string collectionType, User user, IServerApplicationPaths appPaths) - { - name = fileSystem.GetValidFilename(name); - - var rootFolderPath = user != null ? user.RootFolderPath : appPaths.DefaultUserViewsPath; - var virtualFolderPath = Path.Combine(rootFolderPath, name); - - if (Directory.Exists(virtualFolderPath)) - { - throw new ArgumentException("There is already a media collection with the name " + name + "."); - } - - Directory.CreateDirectory(virtualFolderPath); - - if (!string.IsNullOrEmpty(collectionType)) - { - var path = Path.Combine(virtualFolderPath, collectionType + ".collection"); - - File.Create(path); - } - } - - /// - /// Removes the virtual folder. - /// - /// The name. - /// The user. - /// The app paths. - /// The media folder does not exist - public static void RemoveVirtualFolder(string name, User user, IServerApplicationPaths appPaths) - { - var rootFolderPath = user != null ? user.RootFolderPath : appPaths.DefaultUserViewsPath; - var path = Path.Combine(rootFolderPath, name); - - if (!Directory.Exists(path)) - { - throw new DirectoryNotFoundException("The media folder does not exist"); - } - - Directory.Delete(path, true); - } - /// /// Renames the virtual folder. /// diff --git a/MediaBrowser.Api/Library/LibraryStructureService.cs b/MediaBrowser.Api/Library/LibraryStructureService.cs index 0126586ab7..5738dcb114 100644 --- a/MediaBrowser.Api/Library/LibraryStructureService.cs +++ b/MediaBrowser.Api/Library/LibraryStructureService.cs @@ -1,8 +1,10 @@ -using MediaBrowser.Common.IO; +using System.IO; +using MediaBrowser.Common.IO; using MediaBrowser.Controller; using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; using ServiceStack.ServiceHost; using System; using System.Collections.Generic; @@ -188,6 +190,7 @@ namespace MediaBrowser.Api.Library private readonly IDirectoryWatchers _directoryWatchers; private readonly IFileSystem _fileSystem; + private readonly ILogger _logger; /// /// Initializes a new instance of the class. @@ -196,7 +199,7 @@ namespace MediaBrowser.Api.Library /// The user manager. /// The library manager. /// appPaths - public LibraryStructureService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IDirectoryWatchers directoryWatchers, IFileSystem fileSystem) + public LibraryStructureService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IDirectoryWatchers directoryWatchers, IFileSystem fileSystem, ILogger logger) { if (appPaths == null) { @@ -208,6 +211,7 @@ namespace MediaBrowser.Api.Library _libraryManager = libraryManager; _directoryWatchers = directoryWatchers; _fileSystem = fileSystem; + _logger = logger; } /// @@ -239,19 +243,40 @@ namespace MediaBrowser.Api.Library /// The request. public void Post(AddVirtualFolder request) { + var name = _fileSystem.GetValidFilename(request.Name); + + string rootFolderPath; + + if (string.IsNullOrEmpty(request.UserId)) + { + rootFolderPath = _appPaths.DefaultUserViewsPath; + } + else + { + var user = _userManager.GetUserById(new Guid(request.UserId)); + + rootFolderPath = user.RootFolderPath; + } + + var virtualFolderPath = Path.Combine(rootFolderPath, name); + + if (Directory.Exists(virtualFolderPath)) + { + throw new ArgumentException("There is already a media collection with the name " + name + "."); + } + _directoryWatchers.Stop(); + _directoryWatchers.TemporarilyIgnore(virtualFolderPath); try { - if (string.IsNullOrEmpty(request.UserId)) - { - LibraryHelpers.AddVirtualFolder(_fileSystem, request.Name, request.CollectionType, null, _appPaths); - } - else + Directory.CreateDirectory(virtualFolderPath); + + if (!string.IsNullOrEmpty(request.CollectionType)) { - var user = _userManager.GetUserById(new Guid(request.UserId)); + var path = Path.Combine(virtualFolderPath, request.CollectionType + ".collection"); - LibraryHelpers.AddVirtualFolder(_fileSystem, request.Name, request.CollectionType, user, _appPaths); + File.Create(path); } // Need to add a delay here or directory watchers may still pick up the changes @@ -262,6 +287,7 @@ namespace MediaBrowser.Api.Library finally { _directoryWatchers.Start(); + _directoryWatchers.RemoveTempIgnore(virtualFolderPath); } if (request.RefreshLibrary) @@ -313,29 +339,42 @@ namespace MediaBrowser.Api.Library /// The request. public void Delete(RemoveVirtualFolder request) { + string rootFolderPath; + + if (string.IsNullOrEmpty(request.UserId)) + { + rootFolderPath = _appPaths.DefaultUserViewsPath; + } + else + { + var user = _userManager.GetUserById(new Guid(request.UserId)); + + rootFolderPath = user.RootFolderPath; + } + + var path = Path.Combine(rootFolderPath, request.Name); + + if (!Directory.Exists(path)) + { + throw new DirectoryNotFoundException("The media folder does not exist"); + } + _directoryWatchers.Stop(); + _directoryWatchers.TemporarilyIgnore(path); try { - if (string.IsNullOrEmpty(request.UserId)) - { - LibraryHelpers.RemoveVirtualFolder(request.Name, null, _appPaths); - } - else - { - var user = _userManager.GetUserById(new Guid(request.UserId)); - - LibraryHelpers.RemoveVirtualFolder(request.Name, user, _appPaths); - } + Directory.Delete(path, true); // Need to add a delay here or directory watchers may still pick up the changes - var task = Task.Delay(1000); + var delayTask = Task.Delay(1000); // Have to block here to allow exceptions to bubble - Task.WaitAll(task); + Task.WaitAll(delayTask); } finally { _directoryWatchers.Start(); + _directoryWatchers.RemoveTempIgnore(path); } if (request.RefreshLibrary) diff --git a/MediaBrowser.Api/LibraryService.cs b/MediaBrowser.Api/LibraryService.cs index 202d372e83..aa22643988 100644 --- a/MediaBrowser.Api/LibraryService.cs +++ b/MediaBrowser.Api/LibraryService.cs @@ -495,8 +495,7 @@ namespace MediaBrowser.Api { try { - await - parent.ValidateChildren(new Progress(), CancellationToken.None) + await parent.ValidateChildren(new Progress(), CancellationToken.None) .ConfigureAwait(false); } catch (Exception ex) diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index a4ba146165..7b335b7194 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -1347,12 +1347,14 @@ namespace MediaBrowser.Controller.Entities try { - if (LocationType == LocationType.Remote && string.Equals(Path, path, StringComparison.OrdinalIgnoreCase)) + var locationType = LocationType; + + if (locationType == LocationType.Remote && string.Equals(Path, path, StringComparison.OrdinalIgnoreCase)) { return this; } - - if (LocationType != LocationType.Virtual && ResolveArgs.PhysicalLocations.Contains(path, StringComparer.OrdinalIgnoreCase)) + + if (locationType != LocationType.Virtual && ResolveArgs.PhysicalLocations.Contains(path, StringComparer.OrdinalIgnoreCase)) { return this; } diff --git a/MediaBrowser.Server.Implementations/IO/DirectoryWatchers.cs b/MediaBrowser.Server.Implementations/IO/DirectoryWatchers.cs index a9f83dfffd..9fc622c213 100644 --- a/MediaBrowser.Server.Implementations/IO/DirectoryWatchers.cs +++ b/MediaBrowser.Server.Implementations/IO/DirectoryWatchers.cs @@ -358,39 +358,36 @@ namespace MediaBrowser.Server.Implementations.IO var tempIgnorePaths = _tempIgnoredPaths.Keys.ToList(); - if (e.ChangeType == WatcherChangeTypes.Changed) + // If the parent of an ignored path has a change event, ignore that too + if (tempIgnorePaths.Any(i => { - // If the parent of an ignored path has a change event, ignore that too - if (tempIgnorePaths.Any(i => + if (string.Equals(i, e.FullPath, StringComparison.OrdinalIgnoreCase)) { - if (string.Equals(i, e.FullPath, StringComparison.OrdinalIgnoreCase)) - { - return true; - } + return true; + } - // Go up a level - var parent = Path.GetDirectoryName(i); + // Go up a level + var parent = Path.GetDirectoryName(i); + if (string.Equals(parent, e.FullPath, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + + // Go up another level + if (!string.IsNullOrEmpty(parent)) + { + parent = Path.GetDirectoryName(i); if (string.Equals(parent, e.FullPath, StringComparison.OrdinalIgnoreCase)) { return true; } + } - // Go up another level - if (!string.IsNullOrEmpty(parent)) - { - parent = Path.GetDirectoryName(i); - if (string.Equals(parent, e.FullPath, StringComparison.OrdinalIgnoreCase)) - { - return true; - } - } - - return false; + return false; - })) - { - return; - } + })) + { + return; } if (tempIgnorePaths.Contains(e.FullPath, StringComparer.OrdinalIgnoreCase)) diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 1aa9e5b9c1..9197328bde 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -1430,10 +1430,22 @@ namespace MediaBrowser.Server.Implementations.Library .OfType() .Where(i => { + var locationType = i.LocationType; + + if (locationType == LocationType.Remote || locationType == LocationType.Virtual) + { + return false; + } + + if (string.Equals(i.Path, item.Path, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + try { - return i.LocationType != LocationType.Remote && i.LocationType != LocationType.Virtual && - i.ResolveArgs.PhysicalLocations.Contains(item.Path); + + return i.ResolveArgs.PhysicalLocations.Contains(item.Path); } catch (IOException ex) { From 4b886ea93f3a9c295ff1da36a6cdf33c677de5e5 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 4 Nov 2013 11:26:49 -0500 Subject: [PATCH 2/2] fix multiple scan restarts when renaming collection --- MediaBrowser.Api/Library/LibraryHelpers.cs | 38 -------------- .../Library/LibraryStructureService.cs | 49 +++++++++++++++---- 2 files changed, 40 insertions(+), 47 deletions(-) diff --git a/MediaBrowser.Api/Library/LibraryHelpers.cs b/MediaBrowser.Api/Library/LibraryHelpers.cs index 8f6dcfc0db..d16250ce91 100644 --- a/MediaBrowser.Api/Library/LibraryHelpers.cs +++ b/MediaBrowser.Api/Library/LibraryHelpers.cs @@ -21,44 +21,6 @@ namespace MediaBrowser.Api.Library /// private const string ShortcutFileSearch = "*" + ShortcutFileExtension; - /// - /// Renames the virtual folder. - /// - /// The name. - /// The new name. - /// The user. - /// The app paths. - /// The media collection does not exist - /// There is already a media collection with the name + newPath + . - public static void RenameVirtualFolder(string name, string newName, User user, IServerApplicationPaths appPaths) - { - var rootFolderPath = user != null ? user.RootFolderPath : appPaths.DefaultUserViewsPath; - - var currentPath = Path.Combine(rootFolderPath, name); - var newPath = Path.Combine(rootFolderPath, newName); - - if (!Directory.Exists(currentPath)) - { - throw new DirectoryNotFoundException("The media collection does not exist"); - } - - if (!string.Equals(currentPath, newPath, StringComparison.OrdinalIgnoreCase) && Directory.Exists(newPath)) - { - throw new ArgumentException("There is already a media collection with the name " + newPath + "."); - } - //Only make a two-phase move when changing capitalization - if (string.Equals(currentPath, newPath, StringComparison.OrdinalIgnoreCase)) - { - //Create an unique name - var temporaryName = Guid.NewGuid().ToString(); - var temporaryPath = Path.Combine(rootFolderPath, temporaryName); - Directory.Move(currentPath,temporaryPath); - currentPath = temporaryPath; - } - - Directory.Move(currentPath, newPath); - } - /// /// Deletes a shortcut from within a virtual folder, within either the default view or a user view /// diff --git a/MediaBrowser.Api/Library/LibraryStructureService.cs b/MediaBrowser.Api/Library/LibraryStructureService.cs index 5738dcb114..f3306bb63c 100644 --- a/MediaBrowser.Api/Library/LibraryStructureService.cs +++ b/MediaBrowser.Api/Library/LibraryStructureService.cs @@ -1,5 +1,4 @@ -using System.IO; -using MediaBrowser.Common.IO; +using MediaBrowser.Common.IO; using MediaBrowser.Controller; using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; @@ -8,6 +7,7 @@ using MediaBrowser.Model.Logging; using ServiceStack.ServiceHost; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -302,20 +302,49 @@ namespace MediaBrowser.Api.Library /// The request. public void Post(RenameVirtualFolder request) { + string rootFolderPath; + + if (string.IsNullOrEmpty(request.UserId)) + { + rootFolderPath = _appPaths.DefaultUserViewsPath; + } + else + { + var user = _userManager.GetUserById(new Guid(request.UserId)); + + rootFolderPath = user.RootFolderPath; + } + + var currentPath = Path.Combine(rootFolderPath, request.Name); + var newPath = Path.Combine(rootFolderPath, request.NewName); + + if (!Directory.Exists(currentPath)) + { + throw new DirectoryNotFoundException("The media collection does not exist"); + } + + if (!string.Equals(currentPath, newPath, StringComparison.OrdinalIgnoreCase) && Directory.Exists(newPath)) + { + throw new ArgumentException("There is already a media collection with the name " + newPath + "."); + } + _directoryWatchers.Stop(); + _directoryWatchers.TemporarilyIgnore(currentPath); + _directoryWatchers.TemporarilyIgnore(newPath); try { - if (string.IsNullOrEmpty(request.UserId)) + // Only make a two-phase move when changing capitalization + if (string.Equals(currentPath, newPath, StringComparison.OrdinalIgnoreCase)) { - LibraryHelpers.RenameVirtualFolder(request.Name, request.NewName, null, _appPaths); + //Create an unique name + var temporaryName = Guid.NewGuid().ToString(); + var temporaryPath = Path.Combine(rootFolderPath, temporaryName); + Directory.Move(currentPath, temporaryPath); + currentPath = temporaryPath; } - else - { - var user = _userManager.GetUserById(new Guid(request.UserId)); - LibraryHelpers.RenameVirtualFolder(request.Name, request.NewName, user, _appPaths); - } + Directory.Move(currentPath, newPath); // Need to add a delay here or directory watchers may still pick up the changes var task = Task.Delay(1000); @@ -325,6 +354,8 @@ namespace MediaBrowser.Api.Library finally { _directoryWatchers.Start(); + _directoryWatchers.RemoveTempIgnore(currentPath); + _directoryWatchers.RemoveTempIgnore(newPath); } if (request.RefreshLibrary)