From 92cd71143daa2d49abb0421a9cb641e9bf4489ae Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 24 Jun 2013 21:22:21 -0400 Subject: Only fire metadata savers when appropriate --- .../Library/LibraryManager.cs | 89 +++++++++++++++------- 1 file changed, 61 insertions(+), 28 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Library/LibraryManager.cs') diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index d1b7634fb..0465cb5c3 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -128,6 +128,10 @@ namespace MediaBrowser.Server.Implementations.Library /// The by reference items. private ConcurrentDictionary ByReferenceItems { get; set; } + private IEnumerable _savers; + + private readonly Func _directoryWatchersFactory; + /// /// The _library items cache /// @@ -167,13 +171,14 @@ namespace MediaBrowser.Server.Implementations.Library /// The user manager. /// The configuration manager. /// The user data repository. - public LibraryManager(ILogger logger, ITaskManager taskManager, IUserManager userManager, IServerConfigurationManager configurationManager, IUserDataRepository userDataRepository) + public LibraryManager(ILogger logger, ITaskManager taskManager, IUserManager userManager, IServerConfigurationManager configurationManager, IUserDataRepository userDataRepository, Func directoryWatchersFactory) { _logger = logger; _taskManager = taskManager; _userManager = userManager; ConfigurationManager = configurationManager; _userDataRepository = userDataRepository; + _directoryWatchersFactory = directoryWatchersFactory; ByReferenceItems = new ConcurrentDictionary(); ConfigurationManager.ConfigurationUpdated += ConfigurationUpdated; @@ -191,13 +196,15 @@ namespace MediaBrowser.Server.Implementations.Library /// The item comparers. /// The prescan tasks. /// The postscan tasks. + /// The savers. public void AddParts(IEnumerable rules, IEnumerable pluginFolders, IEnumerable resolvers, IEnumerable introProviders, IEnumerable itemComparers, IEnumerable prescanTasks, - IEnumerable postscanTasks) + IEnumerable postscanTasks, + IEnumerable savers) { EntityResolutionIgnoreRules = rules; PluginFolderCreators = pluginFolders; @@ -206,6 +213,7 @@ namespace MediaBrowser.Server.Implementations.Library Comparers = itemComparers; PrescanTasks = prescanTasks; PostscanTasks = postscanTasks; + _savers = savers; } /// @@ -326,7 +334,7 @@ namespace MediaBrowser.Server.Implementations.Library /// The new name. /// The cancellation token. /// Task. - private Task UpdateSeasonZeroNames(string newName, CancellationToken cancellationToken) + private async Task UpdateSeasonZeroNames(string newName, CancellationToken cancellationToken) { var seasons = RootFolder.RecursiveChildren .OfType() @@ -336,9 +344,16 @@ namespace MediaBrowser.Server.Implementations.Library foreach (var season in seasons) { season.Name = newName; - } - return UpdateItems(seasons, cancellationToken); + try + { + await UpdateItem(season, ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false); + } + catch (Exception ex) + { + _logger.ErrorException("Error saving {0}", ex, season.Path); + } + } } /// @@ -1278,33 +1293,35 @@ namespace MediaBrowser.Server.Implementations.Library } /// - /// Updates the items. + /// Updates the item. /// - /// The items. + /// The item. + /// The update reason. /// The cancellation token. /// Task. - private async Task UpdateItems(IEnumerable items, CancellationToken cancellationToken) + public async Task UpdateItem(BaseItem item, ItemUpdateType updateReason, CancellationToken cancellationToken) { - var list = items.ToList(); + await ItemRepository.SaveItem(item, cancellationToken).ConfigureAwait(false); - await ItemRepository.SaveItems(list, cancellationToken).ConfigureAwait(false); + UpdateItemInLibraryCache(item); - foreach (var item in list) + // If metadata was downloaded or edited, save external metadata + if ((updateReason & ItemUpdateType.MetadataEdit) == ItemUpdateType.MetadataEdit) { - UpdateItemInLibraryCache(item); - OnItemUpdated(item); + await SaveMetadata(item).ConfigureAwait(false); } - } - /// - /// Updates the item. - /// - /// The item. - /// The cancellation token. - /// Task. - public Task UpdateItem(BaseItem item, CancellationToken cancellationToken) - { - return UpdateItems(new[] { item }, cancellationToken); + if (ItemUpdated != null) + { + try + { + ItemUpdated(this, new ItemChangeEventArgs { Item = item }); + } + catch (Exception ex) + { + _logger.ErrorException("Error in ItemUpdated event handler", ex); + } + } } /// @@ -1337,22 +1354,38 @@ namespace MediaBrowser.Server.Implementations.Library return ItemRepository.RetrieveItem(id, type); } + private readonly ConcurrentDictionary _fileLocks = new ConcurrentDictionary(); + /// - /// Called when [item updated]. + /// Saves the metadata. /// /// The item. /// Task. - private void OnItemUpdated(BaseItem item) + private async Task SaveMetadata(BaseItem item) { - if (ItemUpdated != null) + foreach (var saver in _savers.Where(i => i.Supports(item))) { + var path = saver.GetSavePath(item); + + var semaphore = _fileLocks.GetOrAdd(path, key => new SemaphoreSlim(1, 1)); + + var directoryWatchers = _directoryWatchersFactory(); + + await semaphore.WaitAsync().ConfigureAwait(false); + try { - ItemUpdated(this, new ItemChangeEventArgs { Item = item }); + directoryWatchers.TemporarilyIgnore(path); + saver.Save(item, CancellationToken.None); } catch (Exception ex) { - _logger.ErrorException("Error in ItemUpdated event handler", ex); + _logger.ErrorException("Error in metadata saver", ex); + } + finally + { + directoryWatchers.RemoveTempIgnore(path); + semaphore.Release(); } } } -- cgit v1.2.3