diff options
| author | Luke Pulverenti <luke.pulverenti@gmail.com> | 2013-03-31 13:39:28 -0400 |
|---|---|---|
| committer | Luke Pulverenti <luke.pulverenti@gmail.com> | 2013-03-31 13:39:28 -0400 |
| commit | 9f06eb781f5992496a7b1a59fb55b0aa6520261f (patch) | |
| tree | 0ed3bb79646b6495eaa16214a71f87ac18fdf435 /MediaBrowser.Server.Implementations | |
| parent | b7c3bc592f4525428df1ac86d57ffb340a001dc6 (diff) | |
fixes #97 and creates a library dictionary cache to avoid FindById recursion
Diffstat (limited to 'MediaBrowser.Server.Implementations')
5 files changed, 123 insertions, 50 deletions
diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpServer.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpServer.cs index 681b08825..edb227c79 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpServer.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpServer.cs @@ -127,6 +127,8 @@ namespace MediaBrowser.Server.Implementations.HttpServer EndpointHostConfig.Instance.MetadataRedirectPath = "metadata"; } + protected static readonly CultureInfo UsCulture = new CultureInfo("en-US"); + /// <summary> /// Configures the specified container. /// </summary> @@ -184,7 +186,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer if (hasOptions.Options.TryGetValue("Content-Length", out contentLength) && !string.IsNullOrEmpty(contentLength)) { - var length = long.Parse(contentLength); + var length = long.Parse(contentLength, UsCulture); if (length > 0) { diff --git a/MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs b/MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs index a355a2db5..24292f0a1 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs @@ -139,11 +139,11 @@ namespace MediaBrowser.Server.Implementations.HttpServer if (!string.IsNullOrEmpty(vals[0])) { - start = long.Parse(vals[0]); + start = long.Parse(vals[0], UsCulture); } if (!string.IsNullOrEmpty(vals[1])) { - end = long.Parse(vals[1]); + end = long.Parse(vals[1], UsCulture); } _requestedRanges.Add(new KeyValuePair<long, long?>(start, end)); diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index cf12d6ad5..303580a49 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -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>(); @@ -228,6 +252,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> /// <param name="args">The args.</param> @@ -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> @@ -709,32 +799,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> /// <param name="id">The id.</param> @@ -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> diff --git a/MediaBrowser.Server.Implementations/Providers/ProviderManager.cs b/MediaBrowser.Server.Implementations/Providers/ProviderManager.cs index a8239deb4..df6e06174 100644 --- a/MediaBrowser.Server.Implementations/Providers/ProviderManager.cs +++ b/MediaBrowser.Server.Implementations/Providers/ProviderManager.cs @@ -236,7 +236,7 @@ namespace MediaBrowser.Server.Implementations.Providers cancellationToken.ThrowIfCancellationRequested(); - _logger.Info("Running {0} for {1}", provider.GetType().Name, item.Path ?? item.Name ?? "--Unknown--"); + _logger.Debug("Running {0} for {1}", provider.GetType().Name, item.Path ?? item.Name ?? "--Unknown--"); // This provides the ability to cancel just this one provider var innerCancellationTokenSource = new CancellationTokenSource(); @@ -249,7 +249,7 @@ namespace MediaBrowser.Server.Implementations.Providers } catch (OperationCanceledException ex) { - _logger.Info("{0} cancelled for {1}", provider.GetType().Name, item.Name); + _logger.Debug("{0} cancelled for {1}", provider.GetType().Name, item.Name); // If the outer cancellation token is the one that caused the cancellation, throw it if (cancellationToken.IsCancellationRequested && ex.CancellationToken == cancellationToken) @@ -325,8 +325,6 @@ namespace MediaBrowser.Server.Implementations.Providers /// </summary> private void ValidateCurrentlyRunningProviders() { - _logger.Info("Validing currently running providers"); - var enableInternetProviders = ConfigurationManager.Configuration.EnableInternetProviders; var internetProviderExcludeTypes = ConfigurationManager.Configuration.InternetProviderExcludeTypes; diff --git a/MediaBrowser.Server.Implementations/WorldWeatherOnline/WeatherProvider.cs b/MediaBrowser.Server.Implementations/WorldWeatherOnline/WeatherProvider.cs index ae8b1ff97..195bfeee3 100644 --- a/MediaBrowser.Server.Implementations/WorldWeatherOnline/WeatherProvider.cs +++ b/MediaBrowser.Server.Implementations/WorldWeatherOnline/WeatherProvider.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Common.Net; +using System.Globalization; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Weather; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; @@ -181,6 +182,8 @@ namespace MediaBrowser.Server.Implementations.WorldWeatherOnline /// <value>The weather code.</value> public string weatherCode { get; set; } + protected static readonly CultureInfo UsCulture = new CultureInfo("en-US"); + /// <summary> /// To the weather status. /// </summary> @@ -189,9 +192,9 @@ namespace MediaBrowser.Server.Implementations.WorldWeatherOnline { return new WeatherStatus { - TemperatureCelsius = int.Parse(temp_C), - TemperatureFahrenheit = int.Parse(temp_F), - Humidity = int.Parse(humidity), + TemperatureCelsius = int.Parse(temp_C, UsCulture), + TemperatureFahrenheit = int.Parse(temp_F, UsCulture), + Humidity = int.Parse(humidity, UsCulture), Condition = DailyWeatherInfo.GetCondition(weatherCode) }; } @@ -263,6 +266,8 @@ namespace MediaBrowser.Server.Implementations.WorldWeatherOnline /// <value>The windspeed miles.</value> public string windspeedMiles { get; set; } + protected static readonly CultureInfo UsCulture = new CultureInfo("en-US"); + /// <summary> /// To the weather forecast. /// </summary> @@ -271,11 +276,11 @@ namespace MediaBrowser.Server.Implementations.WorldWeatherOnline { return new WeatherForecast { - Date = DateTime.Parse(date), - HighTemperatureCelsius = int.Parse(tempMaxC), - HighTemperatureFahrenheit = int.Parse(tempMaxF), - LowTemperatureCelsius = int.Parse(tempMinC), - LowTemperatureFahrenheit = int.Parse(tempMinF), + Date = DateTime.Parse(date, UsCulture), + HighTemperatureCelsius = int.Parse(tempMaxC, UsCulture), + HighTemperatureFahrenheit = int.Parse(tempMaxF, UsCulture), + LowTemperatureCelsius = int.Parse(tempMinC, UsCulture), + LowTemperatureFahrenheit = int.Parse(tempMinF, UsCulture), Condition = GetCondition(weatherCode) }; } |
