2
0
Эх сурвалжийг харах

faster cleanup of missing episodes

Luke Pulverenti 9 жил өмнө
parent
commit
69622a74a8

+ 16 - 14
MediaBrowser.Controller/Library/ILibraryManager.cs

@@ -25,7 +25,7 @@ namespace MediaBrowser.Controller.Library
         /// <param name="fileInfo">The file information.</param>
         /// <param name="parent">The parent.</param>
         /// <returns>BaseItem.</returns>
-        BaseItem ResolvePath(FileSystemMetadata fileInfo, 
+        BaseItem ResolvePath(FileSystemMetadata fileInfo,
             Folder parent = null);
 
         /// <summary>
@@ -36,9 +36,9 @@ namespace MediaBrowser.Controller.Library
         /// <param name="parent">The parent.</param>
         /// <param name="collectionType">Type of the collection.</param>
         /// <returns>List{``0}.</returns>
-        IEnumerable<BaseItem> ResolvePaths(IEnumerable<FileSystemMetadata> files, 
+        IEnumerable<BaseItem> ResolvePaths(IEnumerable<FileSystemMetadata> files,
             IDirectoryService directoryService,
-            Folder parent, string 
+            Folder parent, string
             collectionType = null);
 
         /// <summary>
@@ -60,7 +60,7 @@ namespace MediaBrowser.Controller.Library
         /// <param name="path">The path.</param>
         /// <returns>BaseItem.</returns>
         BaseItem FindByPath(string path);
-        
+
         /// <summary>
         /// Gets the artist.
         /// </summary>
@@ -156,7 +156,7 @@ namespace MediaBrowser.Controller.Library
         /// <param name="id">The identifier.</param>
         /// <returns>BaseItem.</returns>
         BaseItem GetMemoryItemById(Guid id);
-        
+
         /// <summary>
         /// Gets the intros.
         /// </summary>
@@ -243,6 +243,8 @@ namespace MediaBrowser.Controller.Library
         /// <returns>BaseItem.</returns>
         BaseItem RetrieveItem(Guid id);
 
+        bool IsScanRunning { get; }
+
         /// <summary>
         /// Occurs when [item added].
         /// </summary>
@@ -290,7 +292,7 @@ namespace MediaBrowser.Controller.Library
         /// <param name="path">The path.</param>
         /// <returns>System.String.</returns>
         string GetConfiguredContentType(string path);
-        
+
         /// <summary>
         /// Normalizes the root path list.
         /// </summary>
@@ -332,8 +334,8 @@ namespace MediaBrowser.Controller.Library
         Task<UserView> GetNamedView(User user,
             string name,
             string parentId,
-            string viewType, 
-            string sortName, 
+            string viewType,
+            string sortName,
             CancellationToken cancellationToken);
 
         /// <summary>
@@ -346,8 +348,8 @@ namespace MediaBrowser.Controller.Library
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task&lt;UserView&gt;.</returns>
         Task<UserView> GetNamedView(User user,
-            string name, 
-            string viewType, 
+            string name,
+            string viewType,
             string sortName,
             CancellationToken cancellationToken);
 
@@ -393,7 +395,7 @@ namespace MediaBrowser.Controller.Library
           string viewType,
           string sortName,
           CancellationToken cancellationToken);
-        
+
         /// <summary>
         /// Determines whether [is video file] [the specified path].
         /// </summary>
@@ -477,14 +479,14 @@ namespace MediaBrowser.Controller.Library
         /// <param name="query">The query.</param>
         /// <returns>List&lt;PersonInfo&gt;.</returns>
         List<PersonInfo> GetPeople(InternalPeopleQuery query);
-        
+
         /// <summary>
         /// Gets the people items.
         /// </summary>
         /// <param name="query">The query.</param>
         /// <returns>List&lt;Person&gt;.</returns>
         List<Person> GetPeopleItems(InternalPeopleQuery query);
-        
+
         /// <summary>
         /// Gets all people names.
         /// </summary>
@@ -559,7 +561,7 @@ namespace MediaBrowser.Controller.Library
         /// <param name="query">The query.</param>
         /// <returns>QueryResult&lt;BaseItem&gt;.</returns>
         QueryResult<BaseItem> GetItemsResult(InternalItemsQuery query);
-        
+
         /// <summary>
         /// Ignores the file.
         /// </summary>

+ 13 - 5
MediaBrowser.Providers/TV/MissingEpisodeProvider.cs

@@ -27,6 +27,8 @@ namespace MediaBrowser.Providers.TV
         private readonly IFileSystem _fileSystem;
 
         private readonly CultureInfo _usCulture = new CultureInfo("en-US");
+        private static readonly SemaphoreSlim _resourceLock = new SemaphoreSlim(1, 1);
+        public static bool IsRunning = false;
 
         public MissingEpisodeProvider(ILogger logger, IServerConfigurationManager config, ILibraryManager libraryManager, ILocalizationManager localization, IFileSystem fileSystem)
         {
@@ -37,13 +39,16 @@ namespace MediaBrowser.Providers.TV
             _fileSystem = fileSystem;
         }
 
-        public async Task Run(IEnumerable<IGrouping<string, Series>> series, CancellationToken cancellationToken)
+        public async Task Run(List<IGrouping<string, Series>> series, bool addNewItems, CancellationToken cancellationToken)
         {
+            await _resourceLock.WaitAsync(cancellationToken).ConfigureAwait(false);
+            IsRunning = true;
+
             foreach (var seriesGroup in series)
             {
                 try
                 {
-                    await Run(seriesGroup, cancellationToken).ConfigureAwait(false);
+                    await Run(seriesGroup, addNewItems, cancellationToken).ConfigureAwait(false);
                 }
                 catch (OperationCanceledException)
                 {
@@ -58,9 +63,12 @@ namespace MediaBrowser.Providers.TV
                     _logger.ErrorException("Error in missing episode provider for series id {0}", ex, seriesGroup.Key);
                 }
             }
+
+            IsRunning = false;
+            _resourceLock.Release();
         }
 
-        private async Task Run(IGrouping<string, Series> group, CancellationToken cancellationToken)
+        private async Task Run(IGrouping<string, Series> group, bool addNewItems, CancellationToken cancellationToken)
         {
             var tvdbId = group.Key;
 
@@ -110,7 +118,7 @@ namespace MediaBrowser.Providers.TV
 
             var hasNewEpisodes = false;
 
-            if (_config.Configuration.EnableInternetProviders)
+            if (_config.Configuration.EnableInternetProviders && addNewItems)
             {
                 var seriesConfig = _config.Configuration.MetadataOptions.FirstOrDefault(i => string.Equals(i.ItemType, typeof(Series).Name, StringComparison.OrdinalIgnoreCase));
 
@@ -427,7 +435,7 @@ namespace MediaBrowser.Providers.TV
 
             await season.AddChild(episode, cancellationToken).ConfigureAwait(false);
 
-			await episode.RefreshMetadata(new MetadataRefreshOptions(_fileSystem)
+            await episode.RefreshMetadata(new MetadataRefreshOptions(_fileSystem)
             {
             }, cancellationToken).ConfigureAwait(false);
         }

+ 119 - 8
MediaBrowser.Providers/TV/SeriesPostScanTask.cs

@@ -11,6 +11,10 @@ using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
 using CommonIO;
+using MediaBrowser.Common.ScheduledTasks;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Plugins;
+using MediaBrowser.Model.Tasks;
 
 namespace MediaBrowser.Providers.TV
 {
@@ -46,14 +50,17 @@ namespace MediaBrowser.Providers.TV
 
         private async Task RunInternal(IProgress<double> progress, CancellationToken cancellationToken)
         {
-            var seriesList = _libraryManager.RootFolder
-                .GetRecursiveChildren(i => i is Series)
-                .Cast<Series>()
-                .ToList();
+            var seriesList = _libraryManager.GetItemList(new InternalItemsQuery()
+            {
+                IncludeItemTypes = new[] { typeof(Series).Name },
+                Recursive = true
+
+            }).Cast<Series>().ToList();
 
             var seriesGroups = FindSeriesGroups(seriesList).Where(g => !string.IsNullOrEmpty(g.Key)).ToList();
 
-            await new MissingEpisodeProvider(_logger, _config, _libraryManager, _localization, _fileSystem).Run(seriesGroups, cancellationToken).ConfigureAwait(false);
+            await new MissingEpisodeProvider(_logger, _config, _libraryManager, _localization, _fileSystem)
+                .Run(seriesGroups, true, cancellationToken).ConfigureAwait(false);
 
             var numComplete = 0;
 
@@ -82,7 +89,7 @@ namespace MediaBrowser.Providers.TV
             }
         }
 
-        private IEnumerable<IGrouping<string, Series>> FindSeriesGroups(List<Series> seriesList)
+        internal static IEnumerable<IGrouping<string, Series>> FindSeriesGroups(List<Series> seriesList)
         {
             var links = seriesList.ToDictionary(s => s, s => seriesList.Where(c => c != s && ShareProviderId(s, c)).ToList());
 
@@ -102,7 +109,7 @@ namespace MediaBrowser.Providers.TV
             }
         }
 
-        private void FindAllLinked(Series series, HashSet<Series> visited, IDictionary<Series, List<Series>> linksMap, List<Series> results)
+        private static void FindAllLinked(Series series, HashSet<Series> visited, IDictionary<Series, List<Series>> linksMap, List<Series> results)
         {
             results.Add(series);
             visited.Add(series);
@@ -118,7 +125,7 @@ namespace MediaBrowser.Providers.TV
             }
         }
 
-        private bool ShareProviderId(Series a, Series b)
+        private static bool ShareProviderId(Series a, Series b)
         {
             return a.ProviderIds.Any(id =>
             {
@@ -137,4 +144,108 @@ namespace MediaBrowser.Providers.TV
         }
     }
 
+    public class CleanMissingEpisodesEntryPoint : IServerEntryPoint
+    {
+        private readonly ILibraryManager _libraryManager;
+        private readonly IServerConfigurationManager _config;
+        private readonly ILogger _logger;
+        private readonly ILocalizationManager _localization;
+        private readonly IFileSystem _fileSystem;
+        private readonly object _libraryChangedSyncLock = new object();
+        private const int LibraryUpdateDuration = 180000;
+        private readonly ITaskManager _taskManager;
+
+        public CleanMissingEpisodesEntryPoint(ILibraryManager libraryManager, IServerConfigurationManager config, ILogger logger, ILocalizationManager localization, IFileSystem fileSystem, ITaskManager taskManager)
+        {
+            _libraryManager = libraryManager;
+            _config = config;
+            _logger = logger;
+            _localization = localization;
+            _fileSystem = fileSystem;
+            _taskManager = taskManager;
+        }
+
+        private Timer LibraryUpdateTimer { get; set; }
+
+        public void Run()
+        {
+            _libraryManager.ItemAdded += _libraryManager_ItemAdded;
+        }
+
+        private void _libraryManager_ItemAdded(object sender, ItemChangeEventArgs e)
+        {
+            if (!FilterItem(e.Item))
+            {
+                return;
+            }
+
+            lock (_libraryChangedSyncLock)
+            {
+                if (LibraryUpdateTimer == null)
+                {
+                    LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, LibraryUpdateDuration, Timeout.Infinite);
+                }
+                else
+                {
+                    LibraryUpdateTimer.Change(LibraryUpdateDuration, Timeout.Infinite);
+                }
+            }
+        }
+
+        private async void LibraryUpdateTimerCallback(object state)
+        {
+            if (MissingEpisodeProvider.IsRunning)
+            {
+                return;
+            }
+
+            if (_libraryManager.IsScanRunning)
+            {
+                return ;
+            }
+
+            var seriesList = _libraryManager.GetItemList(new InternalItemsQuery()
+            {
+                IncludeItemTypes = new[] { typeof(Series).Name },
+                Recursive = true
+
+            }).Cast<Series>().ToList();
+
+            var seriesGroups = SeriesPostScanTask.FindSeriesGroups(seriesList).Where(g => !string.IsNullOrEmpty(g.Key)).ToList();
+
+            await new MissingEpisodeProvider(_logger, _config, _libraryManager, _localization, _fileSystem)
+                .Run(seriesGroups, false, CancellationToken.None).ConfigureAwait(false);
+        }
+
+        private bool FilterItem(BaseItem item)
+        {
+            return item is Episode && item.LocationType != LocationType.Virtual;
+        }
+
+        /// <summary>
+        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+        /// </summary>
+        public void Dispose()
+        {
+            Dispose(true);
+        }
+
+        /// <summary>
+        /// Releases unmanaged and - optionally - managed resources.
+        /// </summary>
+        /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
+        protected virtual void Dispose(bool dispose)
+        {
+            if (dispose)
+            {
+                if (LibraryUpdateTimer != null)
+                {
+                    LibraryUpdateTimer.Dispose();
+                    LibraryUpdateTimer = null;
+                }
+
+                _libraryManager.ItemAdded -= _libraryManager_ItemAdded;
+            }
+        }
+    }
 }

+ 3 - 0
MediaBrowser.Server.Implementations/Library/LibraryManager.cs

@@ -143,6 +143,7 @@ namespace MediaBrowser.Server.Implementations.Library
         private readonly Func<ILibraryMonitor> _libraryMonitorFactory;
         private readonly Func<IProviderManager> _providerManagerFactory;
         private readonly Func<IUserViewManager> _userviewManager;
+        public bool IsScanRunning { get; private set; }
 
         /// <summary>
         /// The _library items cache
@@ -1102,6 +1103,7 @@ namespace MediaBrowser.Server.Implementations.Library
         /// <returns>Task.</returns>
         public async Task ValidateMediaLibraryInternal(IProgress<double> progress, CancellationToken cancellationToken)
         {
+            IsScanRunning = true;
             _libraryMonitorFactory().Stop();
 
             try
@@ -1111,6 +1113,7 @@ namespace MediaBrowser.Server.Implementations.Library
             finally
             {
                 _libraryMonitorFactory().Start();
+                IsScanRunning = false;
             }
         }