|
@@ -4,6 +4,7 @@ using MediaBrowser.Common.ScheduledTasks;
|
|
|
using MediaBrowser.Controller;
|
|
|
using MediaBrowser.Controller.Configuration;
|
|
|
using MediaBrowser.Controller.Entities;
|
|
|
+using MediaBrowser.Controller.Entities.Movies;
|
|
|
using MediaBrowser.Controller.IO;
|
|
|
using MediaBrowser.Controller.Library;
|
|
|
using MediaBrowser.Controller.Resolvers;
|
|
@@ -73,6 +74,8 @@ namespace MediaBrowser.Server.Implementations.Library
|
|
|
/// <param name="args">The <see cref="ChildrenChangedEventArgs" /> instance containing the event data.</param>
|
|
|
public void ReportLibraryChanged(ChildrenChangedEventArgs args)
|
|
|
{
|
|
|
+ UpdateLibraryCache(args);
|
|
|
+
|
|
|
EventHelper.QueueEventIfNotNull(LibraryChanged, this, args, _logger);
|
|
|
}
|
|
|
#endregion
|
|
@@ -109,7 +112,28 @@ namespace MediaBrowser.Server.Implementations.Library
|
|
|
/// (typically, multiple user roots). We store them here and be sure they all reference a
|
|
|
/// single instance.
|
|
|
/// </summary>
|
|
|
- private ConcurrentDictionary<Guid, BaseItem> ByReferenceItems { get; set; }
|
|
|
+ private ConcurrentDictionary<Guid, BaseItem> ByReferenceItems { get; set; }
|
|
|
+
|
|
|
+ private ConcurrentDictionary<Guid, BaseItem> _libraryItemsCache;
|
|
|
+ private object _libraryItemsCacheSyncLock = new object();
|
|
|
+ private bool _libraryItemsCacheInitialized;
|
|
|
+ private ConcurrentDictionary<Guid, BaseItem> LibraryItemsCache
|
|
|
+ {
|
|
|
+ get
|
|
|
+ {
|
|
|
+ LazyInitializer.EnsureInitialized(ref _libraryItemsCache, ref _libraryItemsCacheInitialized, ref _libraryItemsCacheSyncLock, CreateLibraryItemsCache);
|
|
|
+ return _libraryItemsCache;
|
|
|
+ }
|
|
|
+ set
|
|
|
+ {
|
|
|
+ _libraryItemsCache = value;
|
|
|
+
|
|
|
+ if (value == null)
|
|
|
+ {
|
|
|
+ _libraryItemsCacheInitialized = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
/// <summary>
|
|
|
/// Initializes a new instance of the <see cref="LibraryManager" /> class.
|
|
@@ -219,7 +243,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
|
|
{
|
|
|
// Any number of configuration settings could change the way the library is refreshed, so do that now
|
|
|
_taskManager.CancelIfRunningAndQueue<RefreshMediaLibraryTask>();
|
|
|
-
|
|
|
+
|
|
|
if (refreshPeopleAfterUpdate)
|
|
|
{
|
|
|
_taskManager.CancelIfRunningAndQueue<PeopleValidationTask>();
|
|
@@ -227,6 +251,77 @@ namespace MediaBrowser.Server.Implementations.Library
|
|
|
});
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Creates the library items cache.
|
|
|
+ /// </summary>
|
|
|
+ /// <returns>ConcurrentDictionary{GuidBaseItem}.</returns>
|
|
|
+ private ConcurrentDictionary<Guid, BaseItem> CreateLibraryItemsCache()
|
|
|
+ {
|
|
|
+ var items = RootFolder.RecursiveChildren.ToList();
|
|
|
+
|
|
|
+ items.Add(RootFolder);
|
|
|
+
|
|
|
+ var specialFeatures = items.OfType<Movie>().SelectMany(i => i.SpecialFeatures).ToList();
|
|
|
+ var localTrailers = items.SelectMany(i => i.LocalTrailers).ToList();
|
|
|
+
|
|
|
+ items.AddRange(specialFeatures);
|
|
|
+ items.AddRange(localTrailers);
|
|
|
+
|
|
|
+ // Can't add these right now because there could be separate instances with the same id.
|
|
|
+ //items.AddRange(_userManager.Users.Select(i => i.RootFolder).Distinct().ToList());
|
|
|
+
|
|
|
+ items.AddRange(_userManager.Users.SelectMany(i => i.RootFolder.Children).Where(i => !(i is BasePluginFolder)).Distinct().ToList());
|
|
|
+
|
|
|
+ return new ConcurrentDictionary<Guid,BaseItem>(items.ToDictionary(i => i.Id));
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Updates the library cache.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="args">The <see cref="ChildrenChangedEventArgs"/> instance containing the event data.</param>
|
|
|
+ private void UpdateLibraryCache(ChildrenChangedEventArgs args)
|
|
|
+ {
|
|
|
+ UpdateItemInLibraryCache(args.Folder);
|
|
|
+
|
|
|
+ foreach (var item in args.ItemsAdded)
|
|
|
+ {
|
|
|
+ UpdateItemInLibraryCache(item);
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach (var item in args.ItemsUpdated)
|
|
|
+ {
|
|
|
+ UpdateItemInLibraryCache(item);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Updates the item in library cache.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="item">The item.</param>
|
|
|
+ private void UpdateItemInLibraryCache(BaseItem item)
|
|
|
+ {
|
|
|
+ LibraryItemsCache.AddOrUpdate(item.Id, item, delegate { return item; });
|
|
|
+
|
|
|
+ foreach (var trailer in item.LocalTrailers)
|
|
|
+ {
|
|
|
+ // Prevent access to foreach variable in closure
|
|
|
+ var trailer1 = trailer;
|
|
|
+ LibraryItemsCache.AddOrUpdate(trailer.Id, trailer, delegate { return trailer1; });
|
|
|
+ }
|
|
|
+
|
|
|
+ var movie = item as Movie;
|
|
|
+
|
|
|
+ if (movie != null)
|
|
|
+ {
|
|
|
+ foreach (var special in movie.SpecialFeatures)
|
|
|
+ {
|
|
|
+ // Prevent access to foreach variable in closure
|
|
|
+ Video special1 = special;
|
|
|
+ LibraryItemsCache.AddOrUpdate(special.Id, special, delegate { return special1; });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// Resolves the item.
|
|
|
/// </summary>
|
|
@@ -647,11 +742,6 @@ namespace MediaBrowser.Server.Implementations.Library
|
|
|
|
|
|
// Now validate the entire media library
|
|
|
await RootFolder.ValidateChildren(progress, cancellationToken, recursive: true).ConfigureAwait(false);
|
|
|
-
|
|
|
- //foreach (var user in _userManager.Users)
|
|
|
- //{
|
|
|
- // await user.ValidateMediaLibrary(new Progress<double> { }, cancellationToken).ConfigureAwait(false);
|
|
|
- //}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
@@ -708,32 +798,6 @@ namespace MediaBrowser.Server.Implementations.Library
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- /// <summary>
|
|
|
- /// Finds a library item by Id and UserId.
|
|
|
- /// </summary>
|
|
|
- /// <param name="id">The id.</param>
|
|
|
- /// <param name="userId">The user id.</param>
|
|
|
- /// <param name="userManager">The user manager.</param>
|
|
|
- /// <returns>BaseItem.</returns>
|
|
|
- /// <exception cref="System.ArgumentNullException">id</exception>
|
|
|
- public BaseItem GetItemById(Guid id, Guid userId)
|
|
|
- {
|
|
|
- if (id == Guid.Empty)
|
|
|
- {
|
|
|
- throw new ArgumentNullException("id");
|
|
|
- }
|
|
|
-
|
|
|
- if (userId == Guid.Empty)
|
|
|
- {
|
|
|
- throw new ArgumentNullException("userId");
|
|
|
- }
|
|
|
-
|
|
|
- var user = _userManager.GetUserById(userId);
|
|
|
- var userRoot = user.RootFolder;
|
|
|
-
|
|
|
- return userRoot.FindItemById(id, user);
|
|
|
- }
|
|
|
-
|
|
|
/// <summary>
|
|
|
/// Gets the item by id.
|
|
|
/// </summary>
|
|
@@ -747,7 +811,11 @@ namespace MediaBrowser.Server.Implementations.Library
|
|
|
throw new ArgumentNullException("id");
|
|
|
}
|
|
|
|
|
|
- return RootFolder.FindItemById(id, null);
|
|
|
+ BaseItem item;
|
|
|
+
|
|
|
+ LibraryItemsCache.TryGetValue(id, out item);
|
|
|
+
|
|
|
+ return item;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|