Browse Source

added more direct querying to folder

Luke Pulverenti 11 năm trước cách đây
mục cha
commit
c643dd072e
25 tập tin đã thay đổi với 143 bổ sung124 xóa
  1. 2 2
      MediaBrowser.Api/AlbumsService.cs
  2. 8 9
      MediaBrowser.Api/BaseApiService.cs
  3. 4 15
      MediaBrowser.Api/SearchService.cs
  4. 3 7
      MediaBrowser.Api/SimilarItemsHelper.cs
  5. 2 3
      MediaBrowser.Api/TvShowsService.cs
  6. 1 1
      MediaBrowser.Api/UserLibrary/ArtistsService.cs
  7. 2 19
      MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs
  8. 1 1
      MediaBrowser.Api/UserLibrary/GameGenresService.cs
  9. 1 1
      MediaBrowser.Api/UserLibrary/GenresService.cs
  10. 1 1
      MediaBrowser.Api/UserLibrary/MusicGenresService.cs
  11. 1 1
      MediaBrowser.Api/UserLibrary/PersonsService.cs
  12. 1 1
      MediaBrowser.Api/UserLibrary/StudiosService.cs
  13. 1 3
      MediaBrowser.Api/UserLibrary/UserLibraryService.cs
  14. 1 1
      MediaBrowser.Api/UserLibrary/YearsService.cs
  15. 73 34
      MediaBrowser.Controller/Entities/Folder.cs
  16. 11 6
      MediaBrowser.Mono.userprefs
  17. 1 2
      MediaBrowser.Server.Implementations/Dto/DtoService.cs
  18. 10 4
      MediaBrowser.Server.Implementations/Library/LibraryManager.cs
  19. 1 1
      MediaBrowser.Server.Implementations/Library/Validators/ArtistsValidator.cs
  20. 1 1
      MediaBrowser.Server.Implementations/Library/Validators/GenresValidator.cs
  21. 1 1
      MediaBrowser.Server.Implementations/Library/Validators/MusicGenresValidator.cs
  22. 1 1
      MediaBrowser.Server.Implementations/Library/Validators/PeoplePostScanTask.cs
  23. 1 1
      MediaBrowser.Server.Implementations/Library/Validators/StudiosValidator.cs
  24. 13 7
      MediaBrowser.Server.Mono/Program.cs
  25. 1 1
      MediaBrowser.ServerApplication/MainStartup.cs

+ 2 - 2
MediaBrowser.Api/AlbumsService.cs

@@ -75,7 +75,7 @@ namespace MediaBrowser.Api
             var album1 = (MusicAlbum)item1;
             var album2 = (MusicAlbum)item2;
 
-            var artists1 = album1.RecursiveChildren
+            var artists1 = album1.GetRecursiveChildren()
                 .OfType<Audio>()
                 .SelectMany(i =>
                 {
@@ -92,7 +92,7 @@ namespace MediaBrowser.Api
                 .Distinct(StringComparer.OrdinalIgnoreCase)
                 .ToList();
 
-            var artists2 = album2.RecursiveChildren
+            var artists2 = album2.GetRecursiveChildren()
                 .OfType<Audio>()
                 .SelectMany(i =>
                 {

+ 8 - 9
MediaBrowser.Api/BaseApiService.cs

@@ -122,16 +122,16 @@ namespace MediaBrowser.Api
             return libraryManager.GetPerson(DeSlugPersonName(name, libraryManager));
         }
 
-        protected IEnumerable<BaseItem> GetAllLibraryItems(Guid? userId, IUserManager userManager, ILibraryManager libraryManager)
+        protected IList<BaseItem> GetAllLibraryItems(Guid? userId, IUserManager userManager, ILibraryManager libraryManager)
         {
             if (userId.HasValue)
             {
                 var user = userManager.GetUserById(userId.Value);
 
-                return userManager.GetUserById(userId.Value).RootFolder.GetRecursiveChildren(user);
+                return userManager.GetUserById(userId.Value).RootFolder.GetRecursiveChildren(user, null);
             }
 
-            return libraryManager.RootFolder.RecursiveChildren;
+            return libraryManager.RootFolder.GetRecursiveChildren();
         }
 
         /// <summary>
@@ -147,7 +147,7 @@ namespace MediaBrowser.Api
                 return name;
             }
 
-            return libraryManager.RootFolder.RecursiveChildren
+            return libraryManager.RootFolder.GetRecursiveChildren()
                 .OfType<Audio>()
                 .SelectMany(i =>
                 {
@@ -181,7 +181,7 @@ namespace MediaBrowser.Api
                 return name;
             }
 
-            return libraryManager.RootFolder.RecursiveChildren
+            return libraryManager.RootFolder.GetRecursiveChildren()
                 .SelectMany(i => i.Genres)
                 .Distinct(StringComparer.OrdinalIgnoreCase)
                 .FirstOrDefault(i =>
@@ -200,8 +200,7 @@ namespace MediaBrowser.Api
                 return name;
             }
 
-            return libraryManager.RootFolder.RecursiveChildren
-                .OfType<Game>()
+            return libraryManager.RootFolder.GetRecursiveChildren(i => i is Game)
                 .SelectMany(i => i.Genres)
                 .Distinct(StringComparer.OrdinalIgnoreCase)
                 .FirstOrDefault(i =>
@@ -223,7 +222,7 @@ namespace MediaBrowser.Api
                 return name;
             }
 
-            return libraryManager.RootFolder.RecursiveChildren
+            return libraryManager.RootFolder.GetRecursiveChildren()
                 .SelectMany(i => i.Studios)
                 .Distinct(StringComparer.OrdinalIgnoreCase)
                 .FirstOrDefault(i =>
@@ -245,7 +244,7 @@ namespace MediaBrowser.Api
                 return name;
             }
 
-            return libraryManager.RootFolder.RecursiveChildren
+            return libraryManager.RootFolder.GetRecursiveChildren()
                 .SelectMany(i => i.People)
                 .Select(i => i.Name)
                 .Distinct(StringComparer.OrdinalIgnoreCase)

+ 4 - 15
MediaBrowser.Api/SearchService.cs

@@ -103,18 +103,7 @@ namespace MediaBrowser.Api
         /// <returns>Task{IEnumerable{SearchHintResult}}.</returns>
         private async Task<SearchHintResult> GetSearchHintsAsync(GetSearchHints request)
         {
-            IEnumerable<BaseItem> inputItems;
-
-            if (request.UserId.HasValue)
-            {
-                var user = _userManager.GetUserById(request.UserId.Value);
-
-                inputItems = user.RootFolder.GetRecursiveChildren(user);
-            }
-            else
-            {
-                inputItems = _libraryManager.RootFolder.RecursiveChildren;
-            }
+            var inputItems = GetAllLibraryItems(request.UserId, _userManager, _libraryManager);
 
             var results = await _searchEngine.GetSearchHints(inputItems, request.SearchTerm).ConfigureAwait(false);
 
@@ -180,21 +169,21 @@ namespace MediaBrowser.Api
             {
                 result.Series = season.Series.Name;
 
-                result.EpisodeCount = season.RecursiveChildren.OfType<Episode>().Count();
+                result.EpisodeCount = season.GetRecursiveChildren(i => i is Episode).Count;
             }
 
             var series = item as Series;
 
             if (series != null)
             {
-                result.EpisodeCount = series.RecursiveChildren.OfType<Episode>().Count();
+                result.EpisodeCount = series.GetRecursiveChildren(i => i is Episode).Count;
             }
 
             var album = item as MusicAlbum;
 
             if (album != null)
             {
-                var songs = album.RecursiveChildren.OfType<Audio>().ToList();
+                var songs = album.GetRecursiveChildren().OfType<Audio>().ToList();
 
                 result.SongCount = songs.Count;
                 

+ 3 - 7
MediaBrowser.Api/SimilarItemsHelper.cs

@@ -104,8 +104,8 @@ namespace MediaBrowser.Api
             var fields = request.GetItemFields().ToList();
 
             var inputItems = user == null
-                                 ? libraryManager.RootFolder.RecursiveChildren
-                                 : user.RootFolder.GetRecursiveChildren(user);
+                                 ? libraryManager.RootFolder.GetRecursiveChildren(i => i.Id != item.Id)
+                                 : user.RootFolder.GetRecursiveChildren(user, i => i.Id != item.Id);
 
             var items = GetSimilaritems(item, inputItems, includeInSearch, getSimilarityScore)
                 .ToList();
@@ -139,11 +139,7 @@ namespace MediaBrowser.Api
         {
             inputItems = inputItems.Where(includeInSearch);
 
-            // Avoid implicitly captured closure
-            var currentItem = item;
-
-            return inputItems.Where(i => i.Id != currentItem.Id)
-                .Select(i => new Tuple<BaseItem, int>(i, getSimilarityScore(item, i)))
+            return inputItems.Select(i => new Tuple<BaseItem, int>(i, getSimilarityScore(item, i)))
                 .Where(i => i.Item2 > 2)
                 .OrderByDescending(i => i.Item2)
                 .Select(i => i.Item1);

+ 2 - 3
MediaBrowser.Api/TvShowsService.cs

@@ -157,10 +157,9 @@ namespace MediaBrowser.Api
             var user = _userManager.GetUserById(request.UserId);
 
             var itemsList = user.RootFolder
-                .GetRecursiveChildren(user)
-                .OfType<Series>()
+                .GetRecursiveChildren(user, i => i is Series)
                 .AsParallel()
-                .Select(i => GetNextUp(i, user))
+                .Select(i => GetNextUp((Series)i, user))
                 .ToList();
 
             itemsList = itemsList

+ 1 - 1
MediaBrowser.Api/UserLibrary/ArtistsService.cs

@@ -98,7 +98,7 @@ namespace MediaBrowser.Api.UserLibrary
         /// <returns>System.Object.</returns>
         public object Get(GetArtists request)
         {
-            var result = GetResult(request).Result;
+            var result = GetResult(request);
 
             return ToOptimizedResult(result);
         }

+ 2 - 19
MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs

@@ -53,7 +53,7 @@ namespace MediaBrowser.Api.UserLibrary
         /// </summary>
         /// <param name="request">The request.</param>
         /// <returns>Task{ItemsResult}.</returns>
-        protected async Task<ItemsResult> GetResult(GetItemsByName request)
+        protected ItemsResult GetResult(GetItemsByName request)
         {
             User user = null;
             BaseItem item;
@@ -80,7 +80,7 @@ namespace MediaBrowser.Api.UserLibrary
                 }
                 else
                 {
-                    items = request.Recursive ? folder.RecursiveChildren : folder.Children;
+                    items = request.Recursive ? folder.GetRecursiveChildren() : folder.Children;
                 }
             }
             else
@@ -258,23 +258,6 @@ namespace MediaBrowser.Api.UserLibrary
 
             return dto;
         }
-
-        /// <summary>
-        /// Gets the items.
-        /// </summary>
-        /// <param name="userId">The user id.</param>
-        /// <returns>IEnumerable{BaseItem}.</returns>
-        protected IEnumerable<BaseItem> GetItems(Guid? userId)
-        {
-            if (userId.HasValue)
-            {
-                var user = UserManager.GetUserById(userId.Value);
-
-                return UserManager.GetUserById(userId.Value).RootFolder.GetRecursiveChildren(user);
-            }
-
-            return LibraryManager.RootFolder.RecursiveChildren;
-        }
     }
 
     /// <summary>

+ 1 - 1
MediaBrowser.Api/UserLibrary/GameGenresService.cs

@@ -89,7 +89,7 @@ namespace MediaBrowser.Api.UserLibrary
         /// <returns>System.Object.</returns>
         public object Get(GetGameGenres request)
         {
-            var result = GetResult(request).Result;
+            var result = GetResult(request);
 
             return ToOptimizedResult(result);
         }

+ 1 - 1
MediaBrowser.Api/UserLibrary/GenresService.cs

@@ -93,7 +93,7 @@ namespace MediaBrowser.Api.UserLibrary
         /// <returns>System.Object.</returns>
         public object Get(GetGenres request)
         {
-            var result = GetResult(request).Result;
+            var result = GetResult(request);
 
             return ToOptimizedResult(result);
         }

+ 1 - 1
MediaBrowser.Api/UserLibrary/MusicGenresService.cs

@@ -89,7 +89,7 @@ namespace MediaBrowser.Api.UserLibrary
         /// <returns>System.Object.</returns>
         public object Get(GetMusicGenres request)
         {
-            var result = GetResult(request).Result;
+            var result = GetResult(request);
 
             return ToOptimizedResult(result);
         }

+ 1 - 1
MediaBrowser.Api/UserLibrary/PersonsService.cs

@@ -105,7 +105,7 @@ namespace MediaBrowser.Api.UserLibrary
         /// <returns>System.Object.</returns>
         public object Get(GetPersons request)
         {
-            var result = GetResult(request).Result;
+            var result = GetResult(request);
 
             return ToOptimizedResult(result);
         }

+ 1 - 1
MediaBrowser.Api/UserLibrary/StudiosService.cs

@@ -94,7 +94,7 @@ namespace MediaBrowser.Api.UserLibrary
         /// <returns>System.Object.</returns>
         public object Get(GetStudios request)
         {
-            var result = GetResult(request).Result;
+            var result = GetResult(request);
 
             return ToOptimizedResult(result);
         }

+ 1 - 3
MediaBrowser.Api/UserLibrary/UserLibraryService.cs

@@ -451,9 +451,7 @@ namespace MediaBrowser.Api.UserLibrary
             if (series != null)
             {
                 var dtos = series
-                    .RecursiveChildren
-                    .OfType<Episode>()
-                    .Where(i => i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == 0)
+                    .GetRecursiveChildren(i => i is Episode && i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == 0)
                     .OrderBy(i =>
                     {
                         if (i.PremiereDate.HasValue)

+ 1 - 1
MediaBrowser.Api/UserLibrary/YearsService.cs

@@ -99,7 +99,7 @@ namespace MediaBrowser.Api.UserLibrary
         /// <returns>System.Object.</returns>
         public object Get(GetYears request)
         {
-            var result = GetResult(request).Result;
+            var result = GetResult(request);
 
             return ToOptimizedResult(result);
         }

+ 73 - 34
MediaBrowser.Controller/Entities/Folder.cs

@@ -552,23 +552,7 @@ namespace MediaBrowser.Controller.Entities
         [IgnoreDataMember]
         public IEnumerable<BaseItem> RecursiveChildren
         {
-            get
-            {
-                foreach (var item in Children)
-                {
-                    yield return item;
-
-                    if (item.IsFolder)
-                    {
-                        var subFolder = (Folder)item;
-
-                        foreach (var subitem in subFolder.RecursiveChildren)
-                        {
-                            yield return subitem;
-                        }
-                    }
-                }
-            }
+            get { return GetRecursiveChildren(); }
         }
 
         private List<BaseItem> LoadChildrenInternal()
@@ -686,17 +670,12 @@ namespace MediaBrowser.Controller.Entities
             var currentChildren = ActualChildren.ToDictionary(i => i.Id);
 
             //create a list for our validated children
-            var validChildren = new ConcurrentBag<Tuple<BaseItem, bool>>();
-            var newItems = new ConcurrentBag<BaseItem>();
+            var validChildren = new List<Tuple<BaseItem, bool>>();
+            var newItems = new List<BaseItem>();
 
             cancellationToken.ThrowIfCancellationRequested();
 
-            var options = new ParallelOptions
-            {
-                MaxDegreeOfParallelism = 10
-            };
-
-            Parallel.ForEach(nonCachedChildren, options, child =>
+            foreach (var child in nonCachedChildren)
             {
                 BaseItem currentChild;
 
@@ -725,10 +704,10 @@ namespace MediaBrowser.Controller.Entities
 
                     validChildren.Add(new Tuple<BaseItem, bool>(child, true));
                 }
-            });
+            }
 
             // If any items were added or removed....
-            if (!newItems.IsEmpty || currentChildren.Count != validChildren.Count)
+            if (newItems.Count > 0 || currentChildren.Count != validChildren.Count)
             {
                 var newChildren = validChildren.Select(c => c.Item1).ToList();
 
@@ -793,9 +772,9 @@ namespace MediaBrowser.Controller.Entities
         /// <param name="recursive">if set to <c>true</c> [recursive].</param>
         /// <param name="forceRefreshMetadata">if set to <c>true</c> [force refresh metadata].</param>
         /// <returns>Task.</returns>
-        private async Task RefreshChildren(IEnumerable<Tuple<BaseItem, bool>> children, IProgress<double> progress, CancellationToken cancellationToken, bool? recursive, bool forceRefreshMetadata = false)
+        private async Task RefreshChildren(IList<Tuple<BaseItem, bool>> children, IProgress<double> progress, CancellationToken cancellationToken, bool? recursive, bool forceRefreshMetadata = false)
         {
-            var list = children.ToList();
+            var list = children;
 
             var percentages = new Dictionary<Guid, double>(list.Count);
 
@@ -994,7 +973,7 @@ namespace MediaBrowser.Controller.Entities
         /// <param name="recursive">if set to <c>true</c> [recursive].</param>
         /// <param name="filter">The filter.</param>
         /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
-        private bool AddChildrenToList(User user, bool includeLinkedChildren, List<BaseItem> list, bool recursive, Func<BaseItem,bool> filter)
+        private bool AddChildrenToList(User user, bool includeLinkedChildren, List<BaseItem> list, bool recursive, Func<BaseItem, bool> filter)
         {
             var hasLinkedChildren = false;
 
@@ -1030,7 +1009,7 @@ namespace MediaBrowser.Controller.Entities
                     {
                         continue;
                     }
-                    
+
                     hasLinkedChildren = true;
 
                     if (child.IsVisible(user))
@@ -1056,7 +1035,15 @@ namespace MediaBrowser.Controller.Entities
             return GetRecursiveChildren(user, null, true);
         }
 
-        public IEnumerable<BaseItem> GetRecursiveChildren(User user, Func<BaseItem,bool> filter, bool includeLinkedChildren = true)
+        /// <summary>
+        /// Gets the recursive children.
+        /// </summary>
+        /// <param name="user">The user.</param>
+        /// <param name="filter">The filter.</param>
+        /// <param name="includeLinkedChildren">if set to <c>true</c> [include linked children].</param>
+        /// <returns>IList{BaseItem}.</returns>
+        /// <exception cref="System.ArgumentNullException"></exception>
+        public IList<BaseItem> GetRecursiveChildren(User user, Func<BaseItem, bool> filter, bool includeLinkedChildren = true)
         {
             if (user == null)
             {
@@ -1066,7 +1053,7 @@ namespace MediaBrowser.Controller.Entities
             var initialCount = _lastRecursiveCount == 0 ? _children.Count : _lastRecursiveCount;
             var list = new List<BaseItem>(initialCount);
 
-            var hasLinkedChildren = AddChildrenToList(user, includeLinkedChildren, list, true, null);
+            var hasLinkedChildren = AddChildrenToList(user, includeLinkedChildren, list, true, filter);
 
             _lastRecursiveCount = list.Count;
 
@@ -1077,7 +1064,59 @@ namespace MediaBrowser.Controller.Entities
 
             return list;
         }
-        
+
+        /// <summary>
+        /// Gets the recursive children.
+        /// </summary>
+        /// <returns>IList{BaseItem}.</returns>
+        public IList<BaseItem> GetRecursiveChildren()
+        {
+            return GetRecursiveChildren(null);
+        }
+
+        /// <summary>
+        /// Gets the recursive children.
+        /// </summary>
+        /// <param name="filter">The filter.</param>
+        /// <returns>IEnumerable{BaseItem}.</returns>
+        public IList<BaseItem> GetRecursiveChildren(Func<BaseItem, bool> filter)
+        {
+            var initialCount = _lastRecursiveCount == 0 ? _children.Count : _lastRecursiveCount;
+            var list = new List<BaseItem>(initialCount);
+
+            AddChildrenToList(list, true, filter);
+
+            return list;
+        }
+
+        /// <summary>
+        /// Adds the children to list.
+        /// </summary>
+        /// <param name="list">The list.</param>
+        /// <param name="recursive">if set to <c>true</c> [recursive].</param>
+        /// <param name="filter">The filter.</param>
+        private void AddChildrenToList(List<BaseItem> list, bool recursive, Func<BaseItem, bool> filter)
+        {
+            foreach (var child in Children)
+            {
+                if (filter == null || filter(child))
+                {
+                    list.Add(child);
+                }
+
+                if (recursive)
+                {
+                    var folder = child as Folder;
+
+                    if (folder != null)
+                    {
+                        folder.AddChildrenToList(list, true, filter);
+                    }
+                }
+            }
+        }
+
+
         /// <summary>
         /// Gets the linked children.
         /// </summary>

+ 11 - 6
MediaBrowser.Mono.userprefs

@@ -2,15 +2,20 @@
   <MonoDevelop.Ide.Workspace ActiveConfiguration="Debug|x86" />
   <MonoDevelop.Ide.Workbench ActiveDocument="d:\Development\MediaBrowser\MediaBrowser.ServerApplication\ApplicationHost.cs">
     <Files>
-      <File FileName="d:\Development\MediaBrowser\MediaBrowser.ServerApplication\ApplicationHost.cs" Line="442" Column="10" />
-      <File FileName="MediaBrowser.Server.Mono\Native\ServerAuthorization.cs" Line="1" Column="1" />
-      <File FileName="MediaBrowser.Server.Mono\Native\Autorun.cs" Line="1" Column="1" />
-      <File FileName="MediaBrowser.Server.Mono\Native\Assemblies.cs" Line="1" Column="1" />
-      <File FileName="MediaBrowser.Server.Mono\Program.cs" Line="1" Column="1" />
+      <File FileName="d:\Development\MediaBrowser\MediaBrowser.ServerApplication\ApplicationHost.cs" Line="506" Column="29" />
+      <File FileName="MediaBrowser.Server.Mono\Program.cs" Line="192" Column="1" />
+      <File FileName="MediaBrowser.Server.Mono\Native\NativeApp.cs" Line="24" Column="1" />
+      <File FileName="d:\Development\MediaBrowser\MediaBrowser.Common.Implementations\Logging\NLogger.cs" Line="72" Column="1" />
+      <File FileName="d:\Development\MediaBrowser\MediaBrowser.Common.Implementations\BaseApplicationHost.cs" Line="530" Column="1" />
     </Files>
   </MonoDevelop.Ide.Workbench>
   <MonoDevelop.Ide.DebuggingService.Breakpoints>
-    <BreakpointStore />
+    <BreakpointStore>
+      <Breakpoint file="D:\Development\MediaBrowser\MediaBrowser.Server.Mono\Program.cs" line="177" column="1" />
+      <Breakpoint file="D:\Development\MediaBrowser\MediaBrowser.Server.Mono\Program.cs" line="189" column="1" />
+      <Breakpoint file="D:\Development\MediaBrowser\MediaBrowser.Server.Mono\Native\NativeApp.cs" line="23" column="1" />
+      <Breakpoint file="D:\Development\MediaBrowser\MediaBrowser.Server.Mono\Native\NativeApp.cs" line="15" column="1" />
+    </BreakpointStore>
   </MonoDevelop.Ide.DebuggingService.Breakpoints>
   <MonoDevelop.Ide.DebuggingService.PinnedWatches />
 </Properties>

+ 1 - 2
MediaBrowser.Server.Implementations/Dto/DtoService.cs

@@ -354,8 +354,7 @@ namespace MediaBrowser.Server.Implementations.Dto
             if (!string.IsNullOrEmpty(item.Album))
             {
                 var parentAlbum = _libraryManager.RootFolder
-                    .RecursiveChildren
-                    .OfType<MusicAlbum>()
+                    .GetRecursiveChildren(i => i is MusicAlbum)
                     .FirstOrDefault(i => string.Equals(i.Name, item.Album, StringComparison.OrdinalIgnoreCase));
 
                 if (parentAlbum != null)

+ 10 - 4
MediaBrowser.Server.Implementations/Library/LibraryManager.cs

@@ -337,7 +337,7 @@ namespace MediaBrowser.Server.Implementations.Library
         /// <returns>ConcurrentDictionary{GuidBaseItem}.</returns>
         private ConcurrentDictionary<Guid, BaseItem> CreateLibraryItemsCache()
         {
-            var items = RootFolder.RecursiveChildren.ToList();
+            var items = RootFolder.GetRecursiveChildren();
 
             items.Add(RootFolder);
 
@@ -347,7 +347,10 @@ namespace MediaBrowser.Server.Implementations.Library
                 .Distinct()
                 .ToList();
 
-            items.AddRange(userRootFolders);
+            foreach (var folder in userRootFolders)
+            {
+                items.Add(folder);
+            }
 
             // Get all user collection folders
             // Skip BasePluginFolders because we already got them from RootFolder.RecursiveChildren
@@ -355,7 +358,10 @@ namespace MediaBrowser.Server.Implementations.Library
                             .Where(i => !(i is BasePluginFolder))
                             .ToList();
 
-            items.AddRange(userFolders);
+            foreach (var folder in userFolders)
+            {
+                items.Add(folder);
+            }
 
             var dictionary = new ConcurrentDictionary<Guid, BaseItem>();
 
@@ -770,7 +776,7 @@ namespace MediaBrowser.Server.Implementations.Library
         /// <returns>Task.</returns>
         public async Task ValidatePeople(CancellationToken cancellationToken, IProgress<double> progress)
         {
-            var people = RootFolder.RecursiveChildren
+            var people = RootFolder.GetRecursiveChildren()
                 .SelectMany(c => c.People)
                 .DistinctBy(p => p.Name, StringComparer.OrdinalIgnoreCase)
                 .ToList();

+ 1 - 1
MediaBrowser.Server.Implementations/Library/Validators/ArtistsValidator.cs

@@ -57,7 +57,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
         /// <returns>Task.</returns>
         public async Task Run(IProgress<double> progress, CancellationToken cancellationToken)
         {
-            var allItems = _libraryManager.RootFolder.RecursiveChildren.ToList();
+            var allItems = _libraryManager.RootFolder.GetRecursiveChildren();
 
             var allMusicArtists = allItems.OfType<MusicArtist>().ToList();
             var allSongs = allItems.OfType<Audio>().ToList();

+ 1 - 1
MediaBrowser.Server.Implementations/Library/Validators/GenresValidator.cs

@@ -43,7 +43,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
         public async Task Run(IProgress<double> progress, CancellationToken cancellationToken)
         {
             var userLibraries = _userManager.Users
-                .Select(i => new Tuple<Guid, List<BaseItem>>(i.Id, i.RootFolder.GetRecursiveChildren(i).Where(m => !(m is IHasMusicGenres) && !(m is Game)).ToList()))
+                .Select(i => new Tuple<Guid, IList<BaseItem>>(i.Id, i.RootFolder.GetRecursiveChildren(i, m => !(m is IHasMusicGenres) && !(m is Game))))
                 .ToList();
 
             var masterDictionary = new Dictionary<string, Dictionary<Guid, Dictionary<CountType, int>>>(StringComparer.OrdinalIgnoreCase);

+ 1 - 1
MediaBrowser.Server.Implementations/Library/Validators/MusicGenresValidator.cs

@@ -43,7 +43,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
         public async Task Run(IProgress<double> progress, CancellationToken cancellationToken)
         {
             var userLibraries = _userManager.Users
-                .Select(i => new Tuple<Guid, List<BaseItem>>(i.Id, i.RootFolder.GetRecursiveChildren(i).Where(m => m is IHasMusicGenres).ToList()))
+                .Select(i => new Tuple<Guid, IList<BaseItem>>(i.Id, i.RootFolder.GetRecursiveChildren(i, m => m is IHasMusicGenres)))
                 .ToList();
 
             var masterDictionary = new Dictionary<string, Dictionary<Guid, Dictionary<CountType, int>>>(StringComparer.OrdinalIgnoreCase);

+ 1 - 1
MediaBrowser.Server.Implementations/Library/Validators/PeoplePostScanTask.cs

@@ -49,7 +49,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
         private void RunInternal(IProgress<double> progress, CancellationToken cancellationToken)
         {
             var userLibraries = _userManager.Users
-                .Select(i => new Tuple<Guid, List<BaseItem>>(i.Id, i.RootFolder.GetRecursiveChildren(i).ToList()))
+                .Select(i => new Tuple<Guid, IList<BaseItem>>(i.Id, i.RootFolder.GetRecursiveChildren(i, null)))
                 .ToList();
 
             var masterDictionary = new Dictionary<string, Dictionary<Guid, Dictionary<CountType, int>>>(StringComparer.OrdinalIgnoreCase);

+ 1 - 1
MediaBrowser.Server.Implementations/Library/Validators/StudiosValidator.cs

@@ -42,7 +42,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
         public async Task Run(IProgress<double> progress, CancellationToken cancellationToken)
         {
             var userLibraries = _userManager.Users
-                .Select(i => new Tuple<Guid, List<BaseItem>>(i.Id, i.RootFolder.GetRecursiveChildren(i).ToList()))
+                .Select(i => new Tuple<Guid, IList<BaseItem>>(i.Id, i.RootFolder.GetRecursiveChildren(i, null)))
                 .ToList();
 
             var masterDictionary = new Dictionary<string, Dictionary<Guid, Dictionary<CountType, int>>>(StringComparer.OrdinalIgnoreCase);

+ 13 - 7
MediaBrowser.Server.Mono/Program.cs

@@ -23,6 +23,8 @@ namespace MediaBrowser.Server.Mono
 
 		private static ILogger _logger;
 
+		private static MainWindow _mainWindow;
+
 		public static void Main (string[] args)
 		{
 			Application.Init ();
@@ -42,11 +44,11 @@ namespace MediaBrowser.Server.Mono
 
 			var runningPath = Process.GetCurrentProcess().MainModule.FileName.Replace(Path.DirectorySeparatorChar.ToString(), string.Empty);
 
-			_singleInstanceMutex = new Mutex(true, @"Local\" + runningPath, out createdNew);
-
+			//_singleInstanceMutex = new Mutex(true, @"Local\" + runningPath, out createdNew);
+			createdNew = true;
 			if (!createdNew)
 			{
-				_singleInstanceMutex = null;
+				//_singleInstanceMutex = null;
 				logger.Info("Shutting down because another instance of Media Browser Server is already running.");
 				return;
 			}
@@ -65,7 +67,7 @@ namespace MediaBrowser.Server.Mono
 			{
 				logger.Info("Shutting down");
 
-				ReleaseMutex(logger);
+				//ReleaseMutex(logger);
 
 				_appHost.Dispose();
 			}
@@ -91,9 +93,9 @@ namespace MediaBrowser.Server.Mono
 			Task.WaitAll (task);
 
 			// TODO: Hide splash here
-			MainWindow win = new MainWindow ();
+			_mainWindow = new MainWindow ();
 
-			win.Show ();
+			_mainWindow.Show ();
 
 			Application.Run ();
 		}
@@ -172,16 +174,20 @@ namespace MediaBrowser.Server.Mono
 
 		public static void Shutdown()
 		{
+			_mainWindow.Hide ();
+			_mainWindow.Dispose ();
 			Application.Quit ();
 		}
 
 		public static void Restart()
 		{
 			// Second instance will start first, so release the mutex and dispose the http server ahead of time
-			ReleaseMutex (_logger);
+			//ReleaseMutex (_logger);
 
 			_appHost.Dispose();
 
+			_mainWindow.Hide ();
+			_mainWindow.Dispose ();
 			Application.Quit ();
 		}
 	}

+ 1 - 1
MediaBrowser.ServerApplication/MainStartup.cs

@@ -314,7 +314,7 @@ namespace MediaBrowser.ServerApplication
         {
             var exception = (Exception)e.ExceptionObject;
 
-            _logger.ErrorException("UnhandledException", ex);
+            _logger.ErrorException("UnhandledException", exception);
 
             if (_backgroundService == null)
             {