Explorar o código

removed locking from resolve args

Luke Pulverenti %!s(int64=11) %!d(string=hai) anos
pai
achega
791d64ceed

+ 16 - 26
MediaBrowser.Controller/Entities/BaseItem.cs

@@ -304,14 +304,6 @@ namespace MediaBrowser.Controller.Entities
         /// </summary>
         private ItemResolveArgs _resolveArgs;
         /// <summary>
-        /// The _resolve args initialized
-        /// </summary>
-        private bool _resolveArgsInitialized;
-        /// <summary>
-        /// The _resolve args sync lock
-        /// </summary>
-        private object _resolveArgsSyncLock = new object();
-        /// <summary>
         /// 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)
         /// </summary>
@@ -321,26 +313,24 @@ namespace MediaBrowser.Controller.Entities
         {
             get
             {
-                try
-                {
-                    LazyInitializer.EnsureInitialized(ref _resolveArgs, ref _resolveArgsInitialized, ref _resolveArgsSyncLock, () => CreateResolveArgs());
-                }
-                catch (IOException ex)
+                if (_resolveArgs == null)
                 {
-                    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;
-            }
         }
 
         /// <summary>
@@ -354,12 +344,12 @@ namespace MediaBrowser.Controller.Entities
 
         public void ResetResolveArgs()
         {
-            ResolveArgs = null;
+            _resolveArgs = null;
         }
 
         public void ResetResolveArgs(ItemResolveArgs args)
         {
-            ResolveArgs = args;
+            _resolveArgs = args;
         }
 
         /// <summary>
@@ -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;
                 }
 

+ 53 - 96
MediaBrowser.Server.Implementations/Library/LibraryManager.cs

@@ -708,65 +708,6 @@ namespace MediaBrowser.Server.Implementations.Library
             return obj as T;
         }
 
-        /// <summary>
-        /// Generically retrieves an IBN item
-        /// </summary>
-        /// <typeparam name="T"></typeparam>
-        /// <param name="path">The path.</param>
-        /// <param name="name">The name.</param>
-        /// <param name="cancellationToken">The cancellation token.</param>
-        /// <param name="allowSlowProviders">if set to <c>true</c> [allow slow providers].</param>
-        /// <param name="refreshMetadata">if set to <c>true</c> [force creation].</param>
-        /// <returns>Task{``0}.</returns>
-        /// <exception cref="System.ArgumentNullException">
-        /// </exception>
-        private async Task<T> GetItemByName<T>(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<T>(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;
-        }
-
         /// <summary>
         /// Creates an IBN item based on a given path
         /// </summary>
@@ -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<double>();
+
+            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<double>();
+            innerProgress = new ActionableProgress<double>();
 
             innerProgress.RegisterAction(pct => progress.Report(15 + pct * .6));
 
@@ -977,8 +922,12 @@ namespace MediaBrowser.Server.Implementations.Library
 
             progress.Report(75);
 
+            innerProgress = new ActionableProgress<double>();
+
+            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
         /// <returns>Task.</returns>
         private async Task RunPrescanTasks(IProgress<double> progress, CancellationToken cancellationToken)
         {
-            var prescanTasks = PrescanTasks.ToList();
-            var progressDictionary = new Dictionary<ILibraryPrescanTask, double>();
+            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<double>();
 
+                // 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);
         }
 
         /// <summary>
@@ -1040,41 +993,45 @@ namespace MediaBrowser.Server.Implementations.Library
         /// <returns>Task.</returns>
         private async Task RunPostScanTasks(IProgress<double> progress, CancellationToken cancellationToken)
         {
-            var postscanTasks = PostscanTasks.ToList();
-            var progressDictionary = new Dictionary<ILibraryPostScanTask, double>();
+            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<double>();
 
+                // 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);
         }
 
         /// <summary>