mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-07-09 03:04:24 -04:00
changed ActualChildren to IEnumerable
This commit is contained in:
parent
5b93895c14
commit
8136647a0a
@ -61,7 +61,10 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
//we don't directly validate our children
|
//we don't directly validate our children
|
||||||
//but we do need to clear out the index cache...
|
//but we do need to clear out the index cache...
|
||||||
IndexCache = new ConcurrentDictionary<string, List<BaseItem>>(StringComparer.OrdinalIgnoreCase);
|
if (IndexCache != null)
|
||||||
|
{
|
||||||
|
IndexCache.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
return NullTaskResult;
|
return NullTaskResult;
|
||||||
}
|
}
|
||||||
@ -102,7 +105,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// Our children are actually just references to the ones in the physical root...
|
/// Our children are actually just references to the ones in the physical root...
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The actual children.</value>
|
/// <value>The actual children.</value>
|
||||||
protected override ConcurrentDictionary<Guid, BaseItem> ActualChildren
|
protected override IEnumerable<BaseItem> ActualChildren
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
@ -115,16 +118,14 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
catch (IOException ex)
|
catch (IOException ex)
|
||||||
{
|
{
|
||||||
Logger.ErrorException("Error getting ResolveArgs for {0}", ex, Path);
|
Logger.ErrorException("Error getting ResolveArgs for {0}", ex, Path);
|
||||||
return new ConcurrentDictionary<Guid, BaseItem>();
|
return new BaseItem[] { };
|
||||||
}
|
}
|
||||||
|
|
||||||
var ourChildren =
|
return
|
||||||
LibraryManager.RootFolder.Children
|
LibraryManager.RootFolder.Children
|
||||||
.OfType<Folder>()
|
.OfType<Folder>()
|
||||||
.Where(i => i.Path != null && locationsDicionary.ContainsKey(i.Path))
|
.Where(i => i.Path != null && locationsDicionary.ContainsKey(i.Path))
|
||||||
.SelectMany(c => c.Children);
|
.SelectMany(c => c.Children);
|
||||||
|
|
||||||
return new ConcurrentDictionary<Guid, BaseItem>(ourChildren.ToDictionary(i => i.Id));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,14 +99,11 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
item.DateModified = DateTime.UtcNow;
|
item.DateModified = DateTime.UtcNow;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_children.TryAdd(item.Id, item))
|
_children.Add(item);
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Unable to add " + item.Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
await LibraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
|
await LibraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
await ItemRepository.SaveChildren(Id, _children.Values.ToList().Select(i => i.Id), cancellationToken).ConfigureAwait(false);
|
await ItemRepository.SaveChildren(Id, _children.ToList().Select(i => i.Id), cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -135,18 +132,22 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// <exception cref="System.InvalidOperationException">Unable to remove + item.Name</exception>
|
/// <exception cref="System.InvalidOperationException">Unable to remove + item.Name</exception>
|
||||||
public Task RemoveChild(BaseItem item, CancellationToken cancellationToken)
|
public Task RemoveChild(BaseItem item, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
BaseItem removed;
|
List<BaseItem> newChildren;
|
||||||
|
|
||||||
if (!_children.TryRemove(item.Id, out removed))
|
lock (_childrenSyncLock)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Unable to remove " + item.Name);
|
newChildren = _children.ToList();
|
||||||
|
|
||||||
|
newChildren.Remove(item);
|
||||||
|
|
||||||
|
_children = new ConcurrentBag<BaseItem>(newChildren);
|
||||||
}
|
}
|
||||||
|
|
||||||
item.Parent = null;
|
item.Parent = null;
|
||||||
|
|
||||||
LibraryManager.ReportItemRemoved(item);
|
LibraryManager.ReportItemRemoved(item);
|
||||||
|
|
||||||
return ItemRepository.SaveChildren(Id, _children.Values.ToList().Select(i => i.Id), cancellationToken);
|
return ItemRepository.SaveChildren(Id, newChildren.Select(i => i.Id), cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Indexing
|
#region Indexing
|
||||||
@ -411,9 +412,13 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// <returns>IEnumerable{BaseItem}.</returns>
|
/// <returns>IEnumerable{BaseItem}.</returns>
|
||||||
private IEnumerable<BaseItem> GetIndexedChildren(User user, string indexBy)
|
private IEnumerable<BaseItem> GetIndexedChildren(User user, string indexBy)
|
||||||
{
|
{
|
||||||
List<BaseItem> result;
|
List<BaseItem> result = null;
|
||||||
var cacheKey = user.Name + indexBy;
|
var cacheKey = user.Name + indexBy;
|
||||||
|
|
||||||
|
if (IndexCache != null)
|
||||||
|
{
|
||||||
IndexCache.TryGetValue(cacheKey, out result);
|
IndexCache.TryGetValue(cacheKey, out result);
|
||||||
|
}
|
||||||
|
|
||||||
if (result == null)
|
if (result == null)
|
||||||
{
|
{
|
||||||
@ -438,7 +443,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The index cache
|
/// The index cache
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected ConcurrentDictionary<string, List<BaseItem>> IndexCache = new ConcurrentDictionary<string, List<BaseItem>>(StringComparer.OrdinalIgnoreCase);
|
protected ConcurrentDictionary<string, List<BaseItem>> IndexCache;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Builds the index.
|
/// Builds the index.
|
||||||
@ -449,6 +454,11 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// <returns>List{BaseItem}.</returns>
|
/// <returns>List{BaseItem}.</returns>
|
||||||
protected virtual List<BaseItem> BuildIndex(string indexKey, Func<User, IEnumerable<BaseItem>> indexFunction, User user)
|
protected virtual List<BaseItem> BuildIndex(string indexKey, Func<User, IEnumerable<BaseItem>> indexFunction, User user)
|
||||||
{
|
{
|
||||||
|
if (IndexCache == null)
|
||||||
|
{
|
||||||
|
IndexCache = new ConcurrentDictionary<string, List<BaseItem>>();
|
||||||
|
}
|
||||||
|
|
||||||
return indexFunction != null
|
return indexFunction != null
|
||||||
? IndexCache[user.Name + indexKey] = indexFunction(user).ToList()
|
? IndexCache[user.Name + indexKey] = indexFunction(user).ToList()
|
||||||
: null;
|
: null;
|
||||||
@ -459,7 +469,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The children
|
/// The children
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private ConcurrentDictionary<Guid, BaseItem> _children;
|
private ConcurrentBag<BaseItem> _children;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The _children initialized
|
/// The _children initialized
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -472,22 +482,13 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// Gets or sets the actual children.
|
/// Gets or sets the actual children.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The actual children.</value>
|
/// <value>The actual children.</value>
|
||||||
protected virtual ConcurrentDictionary<Guid, BaseItem> ActualChildren
|
protected virtual IEnumerable<BaseItem> ActualChildren
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
LazyInitializer.EnsureInitialized(ref _children, ref _childrenInitialized, ref _childrenSyncLock, LoadChildrenInternal);
|
LazyInitializer.EnsureInitialized(ref _children, ref _childrenInitialized, ref _childrenSyncLock, LoadChildrenInternal);
|
||||||
return _children;
|
return _children;
|
||||||
}
|
}
|
||||||
private set
|
|
||||||
{
|
|
||||||
_children = value;
|
|
||||||
|
|
||||||
if (value == null)
|
|
||||||
{
|
|
||||||
_childrenInitialized = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -497,10 +498,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public IEnumerable<BaseItem> Children
|
public IEnumerable<BaseItem> Children
|
||||||
{
|
{
|
||||||
get
|
get { return ActualChildren; }
|
||||||
{
|
|
||||||
return ActualChildren.Values.ToArray();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -529,9 +527,9 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConcurrentDictionary<Guid, BaseItem> LoadChildrenInternal()
|
private ConcurrentBag<BaseItem> LoadChildrenInternal()
|
||||||
{
|
{
|
||||||
return new ConcurrentDictionary<Guid, BaseItem>(LoadChildren().ToDictionary(i => i.Id));
|
return new ConcurrentBag<BaseItem>(LoadChildren());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -642,7 +640,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
progress.Report(5);
|
progress.Report(5);
|
||||||
|
|
||||||
//build a dictionary of the current children we have now by Id so we can compare quickly and easily
|
//build a dictionary of the current children we have now by Id so we can compare quickly and easily
|
||||||
var currentChildren = ActualChildren;
|
var currentChildren = ActualChildren.ToDictionary(i => i.Id);
|
||||||
|
|
||||||
//create a list for our validated children
|
//create a list for our validated children
|
||||||
var validChildren = new ConcurrentBag<Tuple<BaseItem, bool>>();
|
var validChildren = new ConcurrentBag<Tuple<BaseItem, bool>>();
|
||||||
@ -694,22 +692,14 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
//that's all the new and changed ones - now see if there are any that are missing
|
//that's all the new and changed ones - now see if there are any that are missing
|
||||||
var itemsRemoved = currentChildren.Values.Except(newChildren).ToList();
|
var itemsRemoved = currentChildren.Values.Except(newChildren).ToList();
|
||||||
|
|
||||||
|
var actualRemovals = new List<BaseItem>();
|
||||||
|
|
||||||
foreach (var item in itemsRemoved)
|
foreach (var item in itemsRemoved)
|
||||||
{
|
{
|
||||||
if (IsRootPathAvailable(item.Path))
|
if (IsRootPathAvailable(item.Path))
|
||||||
{
|
{
|
||||||
item.IsOffline = false;
|
item.IsOffline = false;
|
||||||
|
actualRemovals.Add(item);
|
||||||
BaseItem removed;
|
|
||||||
|
|
||||||
if (!_children.TryRemove(item.Id, out removed))
|
|
||||||
{
|
|
||||||
Logger.Error("Failed to remove {0}", item.Name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LibraryManager.ReportItemRemoved(item);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -719,25 +709,31 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (actualRemovals.Count > 0)
|
||||||
|
{
|
||||||
|
lock (_childrenSyncLock)
|
||||||
|
{
|
||||||
|
_children = new ConcurrentBag<BaseItem>(_children.Except(actualRemovals));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await LibraryManager.CreateItems(newItems, cancellationToken).ConfigureAwait(false);
|
await LibraryManager.CreateItems(newItems, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
foreach (var item in newItems)
|
foreach (var item in newItems)
|
||||||
{
|
{
|
||||||
if (!_children.TryAdd(item.Id, item))
|
_children.Add(item);
|
||||||
{
|
|
||||||
Logger.Error("Failed to add {0}", item.Name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Logger.Debug("** " + item.Name + " Added to library.");
|
Logger.Debug("** " + item.Name + " Added to library.");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
await ItemRepository.SaveChildren(Id, _children.Values.ToList().Select(i => i.Id), cancellationToken).ConfigureAwait(false);
|
await ItemRepository.SaveChildren(Id, _children.ToList().Select(i => i.Id), cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
//force the indexes to rebuild next time
|
//force the indexes to rebuild next time
|
||||||
|
if (IndexCache != null)
|
||||||
|
{
|
||||||
IndexCache.Clear();
|
IndexCache.Clear();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
progress.Report(10);
|
progress.Report(10);
|
||||||
|
|
||||||
@ -949,7 +945,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If indexed is false or the indexing function is null
|
// If indexed is false or the indexing function is null
|
||||||
return children.Where(c => c.IsVisible(user));
|
return children.AsParallel().Where(c => c.IsVisible(user)).AsEnumerable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -970,7 +966,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
if (includeLinkedChildren)
|
if (includeLinkedChildren)
|
||||||
{
|
{
|
||||||
children = children.DistinctBy(i => i.Id);
|
children = children.Distinct();
|
||||||
}
|
}
|
||||||
|
|
||||||
return children;
|
return children;
|
||||||
|
@ -341,7 +341,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||||||
|
|
||||||
items.Add(RootFolder);
|
items.Add(RootFolder);
|
||||||
|
|
||||||
// Need to use DistinctBy Id because there could be multiple instances with the same id
|
// Need to use Distinct because there could be multiple instances with the same id
|
||||||
// due to sharing the default library
|
// due to sharing the default library
|
||||||
var userRootFolders = _userManager.Users.Select(i => i.RootFolder)
|
var userRootFolders = _userManager.Users.Select(i => i.RootFolder)
|
||||||
.Distinct()
|
.Distinct()
|
||||||
@ -357,9 +357,14 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||||||
|
|
||||||
items.AddRange(userFolders);
|
items.AddRange(userFolders);
|
||||||
|
|
||||||
var disctinctItems = items.DistinctBy(i => i.Id).ToList();
|
var dictionary = new ConcurrentDictionary<Guid, BaseItem>();
|
||||||
|
|
||||||
return new ConcurrentDictionary<Guid, BaseItem>(disctinctItems.ToDictionary(i => i.Id));
|
foreach (var item in items)
|
||||||
|
{
|
||||||
|
dictionary[item.Id] = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dictionary;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -72,6 +72,12 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
|
|||||||
|
|
||||||
var numComplete = 0;
|
var numComplete = 0;
|
||||||
|
|
||||||
|
var userLibraries = _userManager.Users
|
||||||
|
.Select(i => new Tuple<Guid, IHasArtist[]>(i.Id, i.RootFolder.GetRecursiveChildren(i).OfType<IHasArtist>().ToArray()))
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
var numArtists = allArtists.Count;
|
||||||
|
|
||||||
foreach (var artist in allArtists)
|
foreach (var artist in allArtists)
|
||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
@ -106,14 +112,14 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
|
|||||||
// Populate counts of items
|
// Populate counts of items
|
||||||
//SetItemCounts(artist, null, allItems.OfType<IHasArtist>());
|
//SetItemCounts(artist, null, allItems.OfType<IHasArtist>());
|
||||||
|
|
||||||
foreach (var user in _userManager.Users.ToArray())
|
foreach (var lib in userLibraries)
|
||||||
{
|
{
|
||||||
SetItemCounts(artist, user.Id, user.RootFolder.GetRecursiveChildren(user).OfType<IHasArtist>().ToArray());
|
SetItemCounts(artist, lib.Item1, lib.Item2);
|
||||||
}
|
}
|
||||||
|
|
||||||
numComplete++;
|
numComplete++;
|
||||||
double percent = numComplete;
|
double percent = numComplete;
|
||||||
percent /= allArtists.Length;
|
percent /= numArtists;
|
||||||
percent *= 20;
|
percent *= 20;
|
||||||
|
|
||||||
progress.Report(80 + percent);
|
progress.Report(80 + percent);
|
||||||
@ -180,7 +186,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
|
|||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <param name="progress">The progress.</param>
|
/// <param name="progress">The progress.</param>
|
||||||
/// <returns>Task{Artist[]}.</returns>
|
/// <returns>Task{Artist[]}.</returns>
|
||||||
private async Task<Artist[]> GetAllArtists(IEnumerable<Audio> allSongs, CancellationToken cancellationToken, IProgress<double> progress)
|
private async Task<ConcurrentBag<Artist>> GetAllArtists(IEnumerable<Audio> allSongs, CancellationToken cancellationToken, IProgress<double> progress)
|
||||||
{
|
{
|
||||||
var allArtists = allSongs
|
var allArtists = allSongs
|
||||||
.SelectMany(i =>
|
.SelectMany(i =>
|
||||||
@ -251,7 +257,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
|
|||||||
|
|
||||||
await Task.WhenAll(tasks).ConfigureAwait(false);
|
await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||||
|
|
||||||
return returnArtists.ToArray();
|
return returnArtists;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user