removed locking from resolve args

pull/702/head
Luke Pulverenti 11 years ago
parent 262dc6d8cd
commit 791d64ceed

@ -304,14 +304,6 @@ namespace MediaBrowser.Controller.Entities
/// </summary> /// </summary>
private ItemResolveArgs _resolveArgs; private ItemResolveArgs _resolveArgs;
/// <summary> /// <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 /// 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) /// (this includes the children of the containing folder)
/// </summary> /// </summary>
@ -321,26 +313,24 @@ namespace MediaBrowser.Controller.Entities
{ {
get 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; return _resolveArgs;
} }
private set
{
_resolveArgs = value;
_resolveArgsInitialized = value != null;
}
} }
/// <summary> /// <summary>
@ -354,12 +344,12 @@ namespace MediaBrowser.Controller.Entities
public void ResetResolveArgs() public void ResetResolveArgs()
{ {
ResolveArgs = null; _resolveArgs = null;
} }
public void ResetResolveArgs(ItemResolveArgs args) public void ResetResolveArgs(ItemResolveArgs args)
{ {
ResolveArgs = args; _resolveArgs = args;
} }
/// <summary> /// <summary>
@ -759,7 +749,7 @@ namespace MediaBrowser.Controller.Entities
if (dbItem != null) if (dbItem != null)
{ {
dbItem.ResolveArgs = video.ResolveArgs; dbItem.ResetResolveArgs(video.ResolveArgs);
video = dbItem; video = dbItem;
} }
@ -820,7 +810,7 @@ namespace MediaBrowser.Controller.Entities
if (dbItem != null) if (dbItem != null)
{ {
dbItem.ResolveArgs = audio.ResolveArgs; dbItem.ResetResolveArgs(audio.ResolveArgs);
audio = dbItem; audio = dbItem;
} }
@ -878,7 +868,7 @@ namespace MediaBrowser.Controller.Entities
if (dbItem != null) if (dbItem != null)
{ {
dbItem.ResolveArgs = item.ResolveArgs; dbItem.ResetResolveArgs(item.ResolveArgs);
item = dbItem; item = dbItem;
} }

@ -708,65 +708,6 @@ namespace MediaBrowser.Server.Implementations.Library
return obj as T; 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> /// <summary>
/// Creates an IBN item based on a given path /// Creates an IBN item based on a given path
/// </summary> /// </summary>
@ -846,7 +787,7 @@ namespace MediaBrowser.Server.Implementations.Library
await item.RefreshMetadata(cancellationToken).ConfigureAwait(false); await item.RefreshMetadata(cancellationToken).ConfigureAwait(false);
} }
catch (IOException ex) catch (Exception ex)
{ {
_logger.ErrorException("Error validating IBN entry {0}", ex, person.Name); _logger.ErrorException("Error validating IBN entry {0}", ex, person.Name);
} }
@ -963,12 +904,16 @@ namespace MediaBrowser.Server.Implementations.Library
progress.Report(2); progress.Report(2);
var innerProgress = new ActionableProgress<double>();
innerProgress.RegisterAction(pct => progress.Report(2 + pct * .13));
// Run prescan tasks // Run prescan tasks
await RunPrescanTasks(progress, cancellationToken).ConfigureAwait(false); await RunPrescanTasks(innerProgress, cancellationToken).ConfigureAwait(false);
progress.Report(15); progress.Report(15);
var innerProgress = new ActionableProgress<double>(); innerProgress = new ActionableProgress<double>();
innerProgress.RegisterAction(pct => progress.Report(15 + pct * .6)); innerProgress.RegisterAction(pct => progress.Report(15 + pct * .6));
@ -977,8 +922,12 @@ namespace MediaBrowser.Server.Implementations.Library
progress.Report(75); progress.Report(75);
innerProgress = new ActionableProgress<double>();
innerProgress.RegisterAction(pct => progress.Report(75 + pct * .25));
// Run post-scan tasks // Run post-scan tasks
await RunPostScanTasks(progress, cancellationToken).ConfigureAwait(false); await RunPostScanTasks(innerProgress, cancellationToken).ConfigureAwait(false);
progress.Report(100); progress.Report(100);
@ -995,41 +944,45 @@ namespace MediaBrowser.Server.Implementations.Library
/// <returns>Task.</returns> /// <returns>Task.</returns>
private async Task RunPrescanTasks(IProgress<double> progress, CancellationToken cancellationToken) private async Task RunPrescanTasks(IProgress<double> progress, CancellationToken cancellationToken)
{ {
var prescanTasks = PrescanTasks.ToList(); var tasks = PrescanTasks.ToList();
var progressDictionary = new Dictionary<ILibraryPrescanTask, double>();
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>(); var innerProgress = new ActionableProgress<double>();
// Prevent access to modified closure
var currentNumComplete = numComplete;
innerProgress.RegisterAction(pct => innerProgress.RegisterAction(pct =>
{ {
lock (progressDictionary) double innerPercent = (currentNumComplete * 100) + pct;
{ innerPercent /= numTasks;
progressDictionary[i] = pct; progress.Report(innerPercent);
double percent = progressDictionary.Values.Sum();
percent /= prescanTasks.Count;
progress.Report(2 + percent * .13);
}
}); });
try try
{ {
await i.Run(innerProgress, cancellationToken); await task.Run(innerProgress, cancellationToken);
} }
catch (OperationCanceledException) 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) 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> /// <summary>
@ -1040,41 +993,45 @@ namespace MediaBrowser.Server.Implementations.Library
/// <returns>Task.</returns> /// <returns>Task.</returns>
private async Task RunPostScanTasks(IProgress<double> progress, CancellationToken cancellationToken) private async Task RunPostScanTasks(IProgress<double> progress, CancellationToken cancellationToken)
{ {
var postscanTasks = PostscanTasks.ToList(); var tasks = PostscanTasks.ToList();
var progressDictionary = new Dictionary<ILibraryPostScanTask, double>();
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>(); var innerProgress = new ActionableProgress<double>();
// Prevent access to modified closure
var currentNumComplete = numComplete;
innerProgress.RegisterAction(pct => innerProgress.RegisterAction(pct =>
{ {
lock (progressDictionary) double innerPercent = (currentNumComplete * 100) + pct;
{ innerPercent /= numTasks;
progressDictionary[i] = pct; progress.Report(innerPercent);
double percent = progressDictionary.Values.Sum();
percent /= postscanTasks.Count;
progress.Report(75 + percent * .25);
}
}); });
try try
{ {
await i.Run(innerProgress, cancellationToken); await task.Run(innerProgress, cancellationToken);
} }
catch (OperationCanceledException) 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) catch (Exception ex)
{ {
_logger.ErrorException("Error running postscan task", 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> /// <summary>

Loading…
Cancel
Save