From 791d64ceed95bd08f3d5aae00a5a9c3c0dabde8e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 25 Sep 2013 18:41:25 -0400 Subject: [PATCH] removed locking from resolve args --- MediaBrowser.Controller/Entities/BaseItem.cs | 42 ++--- .../Library/LibraryManager.cs | 149 +++++++----------- 2 files changed, 69 insertions(+), 122 deletions(-) diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 6543275a54..497226dbb1 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -304,14 +304,6 @@ namespace MediaBrowser.Controller.Entities /// private ItemResolveArgs _resolveArgs; /// - /// The _resolve args initialized - /// - private bool _resolveArgsInitialized; - /// - /// The _resolve args sync lock - /// - private object _resolveArgsSyncLock = new object(); - /// /// We attach these to the item so that we only ever have to hit the file system once /// (this includes the children of the containing folder) /// @@ -321,26 +313,24 @@ namespace MediaBrowser.Controller.Entities { get { - try + if (_resolveArgs == null) { - LazyInitializer.EnsureInitialized(ref _resolveArgs, ref _resolveArgsInitialized, ref _resolveArgsSyncLock, () => CreateResolveArgs()); - } - catch (IOException ex) - { - Logger.ErrorException("Error creating resolve args for {0}", ex, Path); + try + { + _resolveArgs = CreateResolveArgs(); + } + catch (IOException ex) + { + Logger.ErrorException("Error creating resolve args for {0}", ex, Path); - IsOffline = true; + IsOffline = true; - throw; + throw; + } } return _resolveArgs; } - private set - { - _resolveArgs = value; - _resolveArgsInitialized = value != null; - } } /// @@ -354,12 +344,12 @@ namespace MediaBrowser.Controller.Entities public void ResetResolveArgs() { - ResolveArgs = null; + _resolveArgs = null; } public void ResetResolveArgs(ItemResolveArgs args) { - ResolveArgs = args; + _resolveArgs = args; } /// @@ -759,7 +749,7 @@ namespace MediaBrowser.Controller.Entities if (dbItem != null) { - dbItem.ResolveArgs = video.ResolveArgs; + dbItem.ResetResolveArgs(video.ResolveArgs); video = dbItem; } @@ -820,7 +810,7 @@ namespace MediaBrowser.Controller.Entities if (dbItem != null) { - dbItem.ResolveArgs = audio.ResolveArgs; + dbItem.ResetResolveArgs(audio.ResolveArgs); audio = dbItem; } @@ -878,7 +868,7 @@ namespace MediaBrowser.Controller.Entities if (dbItem != null) { - dbItem.ResolveArgs = item.ResolveArgs; + dbItem.ResetResolveArgs(item.ResolveArgs); item = dbItem; } diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 2ba16ab038..084f9b05c3 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -708,65 +708,6 @@ namespace MediaBrowser.Server.Implementations.Library return obj as T; } - /// - /// Generically retrieves an IBN item - /// - /// - /// The path. - /// The name. - /// The cancellation token. - /// if set to true [allow slow providers]. - /// if set to true [force creation]. - /// Task{``0}. - /// - /// - private async Task GetItemByName(string path, string name, CancellationToken cancellationToken, bool allowSlowProviders = true, bool refreshMetadata = false) - where T : BaseItem, new() - { - if (string.IsNullOrEmpty(path)) - { - throw new ArgumentNullException(); - } - - if (string.IsNullOrEmpty(name)) - { - throw new ArgumentNullException(); - } - - var validFilename = FileSystem.GetValidFilename(name); - - var key = Path.Combine(path, validFilename); - - BaseItem obj; - - if (!_itemsByName.TryGetValue(key, out obj)) - { - var tuple = CreateItemByName(key, name); - - obj = tuple.Item2; - - _itemsByName.AddOrUpdate(key, obj, (keyName, oldValue) => obj); - - try - { - await obj.RefreshMetadata(cancellationToken, tuple.Item1, allowSlowProviders: allowSlowProviders).ConfigureAwait(false); - } - catch (OperationCanceledException) - { - BaseItem removed; - _itemsByName.TryRemove(key, out removed); - - throw; - } - } - else if (refreshMetadata) - { - await obj.RefreshMetadata(cancellationToken, false, allowSlowProviders: allowSlowProviders).ConfigureAwait(false); - } - - return obj as T; - } - /// /// Creates an IBN item based on a given path /// @@ -846,7 +787,7 @@ namespace MediaBrowser.Server.Implementations.Library await item.RefreshMetadata(cancellationToken).ConfigureAwait(false); } - catch (IOException ex) + catch (Exception ex) { _logger.ErrorException("Error validating IBN entry {0}", ex, person.Name); } @@ -963,12 +904,16 @@ namespace MediaBrowser.Server.Implementations.Library progress.Report(2); + var innerProgress = new ActionableProgress(); + + innerProgress.RegisterAction(pct => progress.Report(2 + pct * .13)); + // Run prescan tasks - await RunPrescanTasks(progress, cancellationToken).ConfigureAwait(false); + await RunPrescanTasks(innerProgress, cancellationToken).ConfigureAwait(false); progress.Report(15); - var innerProgress = new ActionableProgress(); + innerProgress = new ActionableProgress(); innerProgress.RegisterAction(pct => progress.Report(15 + pct * .6)); @@ -977,8 +922,12 @@ namespace MediaBrowser.Server.Implementations.Library progress.Report(75); + innerProgress = new ActionableProgress(); + + innerProgress.RegisterAction(pct => progress.Report(75 + pct * .25)); + // Run post-scan tasks - await RunPostScanTasks(progress, cancellationToken).ConfigureAwait(false); + await RunPostScanTasks(innerProgress, cancellationToken).ConfigureAwait(false); progress.Report(100); @@ -995,41 +944,45 @@ namespace MediaBrowser.Server.Implementations.Library /// Task. private async Task RunPrescanTasks(IProgress progress, CancellationToken cancellationToken) { - var prescanTasks = PrescanTasks.ToList(); - var progressDictionary = new Dictionary(); + var tasks = PrescanTasks.ToList(); - var tasks = prescanTasks.Select(i => Task.Run(async () => + var numComplete = 0; + var numTasks = tasks.Count; + + foreach (var task in tasks) { var innerProgress = new ActionableProgress(); + // Prevent access to modified closure + var currentNumComplete = numComplete; + innerProgress.RegisterAction(pct => { - lock (progressDictionary) - { - progressDictionary[i] = pct; - - double percent = progressDictionary.Values.Sum(); - percent /= prescanTasks.Count; - - progress.Report(2 + percent * .13); - } + double innerPercent = (currentNumComplete * 100) + pct; + innerPercent /= numTasks; + progress.Report(innerPercent); }); try { - await i.Run(innerProgress, cancellationToken); + await task.Run(innerProgress, cancellationToken); } catch (OperationCanceledException) { - _logger.Info("Pre-scan task cancelled: {0}", i.GetType().Name); + _logger.Info("Pre-scan task cancelled: {0}", task.GetType().Name); } catch (Exception ex) { - _logger.ErrorException("Error running prescan task", ex); + _logger.ErrorException("Error running pre-scan task", ex); } - })); - await Task.WhenAll(tasks).ConfigureAwait(false); + numComplete++; + double percent = numComplete; + percent /= numTasks; + progress.Report(percent * 100); + } + + progress.Report(100); } /// @@ -1040,41 +993,45 @@ namespace MediaBrowser.Server.Implementations.Library /// Task. private async Task RunPostScanTasks(IProgress progress, CancellationToken cancellationToken) { - var postscanTasks = PostscanTasks.ToList(); - var progressDictionary = new Dictionary(); + var tasks = PostscanTasks.ToList(); - var tasks = postscanTasks.Select(i => Task.Run(async () => + var numComplete = 0; + var numTasks = tasks.Count; + + foreach (var task in tasks) { var innerProgress = new ActionableProgress(); + // Prevent access to modified closure + var currentNumComplete = numComplete; + innerProgress.RegisterAction(pct => { - lock (progressDictionary) - { - progressDictionary[i] = pct; - - double percent = progressDictionary.Values.Sum(); - percent /= postscanTasks.Count; - - progress.Report(75 + percent * .25); - } + double innerPercent = (currentNumComplete * 100) + pct; + innerPercent /= numTasks; + progress.Report(innerPercent); }); try { - await i.Run(innerProgress, cancellationToken); + await task.Run(innerProgress, cancellationToken); } catch (OperationCanceledException) { - _logger.Info("Post-scan task cancelled: {0}", i.GetType().Name); + _logger.Info("Post-scan task cancelled: {0}", task.GetType().Name); } catch (Exception ex) { _logger.ErrorException("Error running postscan task", ex); } - })); - await Task.WhenAll(tasks).ConfigureAwait(false); + numComplete++; + double percent = numComplete; + percent /= numTasks; + progress.Report(percent * 100); + } + + progress.Report(100); } ///