Pārlūkot izejas kodu

Some directory-watcher rework - still not working properly

ebr11 Eric Reed spam 12 gadi atpakaļ
vecāks
revīzija
4e3ce41880

+ 10 - 0
MediaBrowser.Controller/Entities/BaseItem.cs

@@ -2,6 +2,7 @@
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.IO;
 using System;
+using System.Threading.Tasks;
 using System.Collections.Generic;
 using System.Linq;
 
@@ -179,5 +180,14 @@ namespace MediaBrowser.Controller.Entities
                 data.PlaybackPositionTicks = 0;
             }
         }
+
+        /// <summary>
+        /// Do whatever refreshing is necessary when the filesystem pertaining to this item has changed.
+        /// </summary>
+        /// <returns></returns>
+        public virtual Task ChangedExternally()
+        {
+            return Task.Run(() => RefreshMetadata());
+        }
     }
 }

+ 26 - 33
MediaBrowser.Controller/Entities/Folder.cs

@@ -272,7 +272,7 @@ namespace MediaBrowser.Controller.Entities
         }
 
         /// <summary>
-        /// Finds child BaseItems for a given Folder
+        /// Finds child BaseItems for us
         /// </summary>
         protected Task<BaseItem>[] GetChildren(WIN32_FIND_DATA[] fileSystemChildren)
         {
@@ -328,6 +328,26 @@ namespace MediaBrowser.Controller.Entities
             }
         }
 
+        /// <summary>
+        /// Folders need to validate and refresh
+        /// </summary>
+        /// <returns></returns>
+        public override Task ChangedExternally()
+        {
+            return Task.Run(() =>
+                {
+                    if (this.IsRoot)
+                    {
+                        Kernel.Instance.ReloadRoot().ConfigureAwait(false);
+                    }
+                    else
+                    {
+                        RefreshMetadata();
+                        ValidateChildren();
+                    }
+                });
+        }
+
         /// <summary>
         /// Since it can be slow to make all of these calculations at once, this method will provide a way to get them all back together
         /// </summary>
@@ -578,17 +598,8 @@ namespace MediaBrowser.Controller.Entities
                 return result;
             }
 
-            foreach (BaseItem item in ActualChildren)
-            {
-                result = item.FindItemById(id);
-
-                if (result != null)
-                {
-                    return result;
-                }
-            }
-
-            return null;
+            //this should be functionally equivilent to what was here since it is IEnum and works on a thread-safe copy
+            return RecursiveChildren.FirstOrDefault(i => i.Id == id);
         }
 
         /// <summary>
@@ -596,31 +607,13 @@ namespace MediaBrowser.Controller.Entities
         /// </summary>
         public BaseItem FindByPath(string path)
         {
-            if (Path.Equals(path, StringComparison.OrdinalIgnoreCase))
+            if (PhysicalLocations.Contains(path, StringComparer.OrdinalIgnoreCase))
             {
                 return this;
             }
 
-            foreach (BaseItem item in ActualChildren)
-            {
-                var folder = item as Folder;
-
-                if (folder != null)
-                {
-                    var foundItem = folder.FindByPath(path);
-
-                    if (foundItem != null)
-                    {
-                        return foundItem;
-                    }
-                }
-                else if (item.Path.Equals(path, StringComparison.OrdinalIgnoreCase))
-                {
-                    return item;
-                }
-            }
-
-            return null;
+            //this should be functionally equivilent to what was here since it is IEnum and works on a thread-safe copy
+            return RecursiveChildren.FirstOrDefault(i => i.Path.Equals(path, StringComparison.OrdinalIgnoreCase));
         }
     }
 }

+ 32 - 12
MediaBrowser.Controller/IO/DirectoryWatchers.cs

@@ -16,7 +16,7 @@ namespace MediaBrowser.Controller.IO
         private Timer updateTimer;
         private List<string> affectedPaths = new List<string>();
 
-        private const int TimerDelayInSeconds = 5;
+        private const int TimerDelayInSeconds = 30;
 
         public void Start()
         {
@@ -44,12 +44,13 @@ namespace MediaBrowser.Controller.IO
                 var watcher = new FileSystemWatcher(path, "*") { }; 
                 watcher.IncludeSubdirectories = true;
 
-                watcher.Changed += watcher_Changed;
+                //watcher.Changed += watcher_Changed;
 
                 // All the others seem to trigger change events on the parent, so let's keep it simple for now.
-                //watcher.Created += watcher_Changed;
-                //watcher.Deleted += watcher_Changed;
-                //watcher.Renamed += watcher_Changed;
+                //   Actually, we really need to only watch created, deleted and renamed as changed fires too much -ebr
+                watcher.Created += watcher_Changed;
+                watcher.Deleted += watcher_Changed;
+                watcher.Renamed += watcher_Changed;
 
                 watcher.EnableRaisingEvents = true;
                 FileSystemWatchers.Add(watcher);
@@ -58,9 +59,23 @@ namespace MediaBrowser.Controller.IO
 
         void watcher_Changed(object sender, FileSystemEventArgs e)
         {
-            if (!affectedPaths.Contains(e.FullPath))
+            Logger.LogDebugInfo("****** Watcher sees change of type " + e.ChangeType.ToString() + " to " + e.FullPath);
+            lock (affectedPaths)
             {
-                affectedPaths.Add(e.FullPath);
+                if (!affectedPaths.Contains(e.FullPath))
+                {
+                    Logger.LogDebugInfo("****** Adding " + e.FullPath + " to affected paths.");
+                    affectedPaths.Add(e.FullPath);
+                }
+                if (e.ChangeType == WatcherChangeTypes.Renamed)
+                {
+                    var renamedArgs = e as RenamedEventArgs;
+                    if (affectedPaths.Contains(renamedArgs.OldFullPath))
+                    {
+                    Logger.LogDebugInfo("****** Removing " + renamedArgs.OldFullPath + " from affected paths.");
+                    affectedPaths.Remove(renamedArgs.OldFullPath);
+                    }
+                }
             }
 
             if (updateTimer == null)
@@ -77,9 +92,12 @@ namespace MediaBrowser.Controller.IO
         {
             updateTimer.Dispose();
             updateTimer = null;
-
-            List<string> paths = affectedPaths;
-            affectedPaths = new List<string>();
+            List<string> paths;
+            lock (affectedPaths)
+            {
+                paths = affectedPaths;
+                affectedPaths = new List<string>();
+            }
 
             await ProcessPathChanges(paths).ConfigureAwait(false);
         }
@@ -106,14 +124,16 @@ namespace MediaBrowser.Controller.IO
                 return Kernel.Instance.ReloadRoot();
             }
 
-            return Task.WhenAll(itemsToRefresh.Select(i => Kernel.Instance.ReloadItem(i)));
+            foreach (var p in paths) Logger.LogDebugInfo("*********  "+ p + " reports change.");
+            foreach (var i in itemsToRefresh) Logger.LogDebugInfo("*********  "+i.Name + " will be refreshed.");
+            return Task.WhenAll(itemsToRefresh.Select(i => i.ChangedExternally()));
         }
 
         private BaseItem GetAffectedBaseItem(string path)
         {
             BaseItem item = null;
 
-            while (item == null)
+            while (item == null && !string.IsNullOrEmpty(path))
             {
                 item = Kernel.Instance.RootFolder.FindByPath(path);
 

+ 4 - 34
MediaBrowser.Controller/Kernel.cs

@@ -201,10 +201,10 @@ namespace MediaBrowser.Controller
             //Task.Delay(30000); //let's wait and see if more data gets filled in...
             var allChildren = RootFolder.RecursiveChildren;
             Logger.LogDebugInfo(string.Format("Loading complete.  Movies: {0} Episodes: {1} Folders: {2}", allChildren.OfType<Entities.Movies.Movie>().Count(), allChildren.OfType<Entities.TV.Episode>().Count(), allChildren.Where(i => i is Folder && !(i is Series || i is Season)).Count()));
-            foreach (var child in allChildren)
-            {
-                Logger.LogDebugInfo("(" + child.GetType().Name + ") " + child.Name + " (" + child.Path + ")");
-            }
+            //foreach (var child in allChildren)
+            //{
+            //    Logger.LogDebugInfo("(" + child.GetType().Name + ") " + child.Name + " (" + child.Path + ")");
+            //}
         }
 
         /// <summary>
@@ -257,36 +257,6 @@ namespace MediaBrowser.Controller
             return result;
         }
 
-        public async Task ReloadItem(BaseItem item)
-        {
-            var folder = item as Folder;
-
-            if (folder != null && folder.IsRoot)
-            {
-                await ReloadRoot().ConfigureAwait(false);
-            }
-            else
-            {
-                if (!Directory.Exists(item.Path) && !File.Exists(item.Path))
-                {
-                    await ReloadItem(item.Parent).ConfigureAwait(false);
-                    return;
-                }
-
-                BaseItem newItem = await ItemController.GetItem(item.Path, item.Parent).ConfigureAwait(false);
-
-                List<BaseItem> children = item.Parent.Children.ToList();
-
-                int index = children.IndexOf(item);
-
-                children.RemoveAt(index);
-
-                children.Insert(index, newItem);
-
-                //item.Parent.ActualChildren = children.ToArray();
-            }
-        }
-
         /// <summary>
         /// Finds a library item by Id
         /// </summary>

+ 1 - 90
MediaBrowser.Controller/Library/ItemController.cs

@@ -13,21 +13,6 @@ namespace MediaBrowser.Controller.Library
 {
     public class ItemController
     {
-        //private BaseItem ResolveItem(ItemResolveEventArgs args)
-        //{
-        //    // Try first priority resolvers
-        //    for (int i = 0; i < Kernel.Instance.EntityResolvers.Length; i++)
-        //    {
-        //        var item = Kernel.Instance.EntityResolvers[i].ResolvePath(args);
-
-        //        if (item != null)
-        //        {
-        //            return item;
-        //        }
-        //    }
-
-        //    return null;
-        //}
 
         /// <summary>
         /// Resolves a path into a BaseItem
@@ -56,7 +41,7 @@ namespace MediaBrowser.Controller.Library
             }
 
 
-            // Fire BeginResolvePath to see if anyone wants to cancel this operation
+            // Check to see if we should resolve based on our contents
             if (!EntityResolutionHelper.ShouldResolvePathContents(args))
             {
                 return null;
@@ -67,80 +52,6 @@ namespace MediaBrowser.Controller.Library
             return item;
         }
 
-        ///// <summary>
-        ///// Finds child BaseItems for a given Folder
-        ///// </summary>
-        //private Task<BaseItem>[] GetChildren(Folder folder, WIN32_FIND_DATA[] fileSystemChildren, bool allowInternetProviders)
-        //{
-        //    Task<BaseItem>[] tasks = new Task<BaseItem>[fileSystemChildren.Length];
-
-        //    for (int i = 0; i < fileSystemChildren.Length; i++)
-        //    {
-        //        var child = fileSystemChildren[i];
-
-        //        tasks[i] = GetItem(child.Path, folder, child, allowInternetProviders: allowInternetProviders);
-        //    }
-
-        //    return tasks;
-        //}
-
-        ///// <summary>
-        ///// Transforms shortcuts into their actual paths
-        ///// </summary>
-        //private WIN32_FIND_DATA[] FilterChildFileSystemEntries(WIN32_FIND_DATA[] fileSystemChildren, bool flattenShortcuts)
-        //{
-        //    WIN32_FIND_DATA[] returnArray = new WIN32_FIND_DATA[fileSystemChildren.Length];
-        //    List<WIN32_FIND_DATA> resolvedShortcuts = new List<WIN32_FIND_DATA>();
-
-        //    for (int i = 0; i < fileSystemChildren.Length; i++)
-        //    {
-        //        WIN32_FIND_DATA file = fileSystemChildren[i];
-
-        //        // If it's a shortcut, resolve it
-        //        if (Shortcut.IsShortcut(file.Path))
-        //        {
-        //            string newPath = Shortcut.ResolveShortcut(file.Path);
-        //            WIN32_FIND_DATA newPathData = FileData.GetFileData(newPath);
-
-        //            // Find out if the shortcut is pointing to a directory or file
-        //            if (newPathData.IsDirectory)
-        //            {
-        //                // If we're flattening then get the shortcut's children
-
-        //                if (flattenShortcuts)
-        //                {
-        //                    returnArray[i] = file;
-        //                    WIN32_FIND_DATA[] newChildren = FileData.GetFileSystemEntries(newPath, "*").ToArray();
-
-        //                    resolvedShortcuts.AddRange(FilterChildFileSystemEntries(newChildren, false));
-        //                }
-        //                else
-        //                {
-        //                    returnArray[i] = newPathData;
-        //                }
-        //            }
-        //            else
-        //            {
-        //                returnArray[i] = newPathData;
-        //            }
-        //        }
-        //        else
-        //        {
-        //            returnArray[i] = file;
-        //        }
-        //    }
-
-        //    if (resolvedShortcuts.Count > 0)
-        //    {
-        //        resolvedShortcuts.InsertRange(0, returnArray);
-        //        return resolvedShortcuts.ToArray();
-        //    }
-        //    else
-        //    {
-        //        return returnArray;
-        //    }
-        //}
-
         /// <summary>
         /// Gets a Person
         /// </summary>