diff options
| author | Luke Pulverenti <luke.pulverenti@gmail.com> | 2014-01-28 16:25:10 -0500 |
|---|---|---|
| committer | Luke Pulverenti <luke.pulverenti@gmail.com> | 2014-01-28 16:25:10 -0500 |
| commit | 7c5b22246357ef6bcd6d74e61a8fe6a8a9d4df3e (patch) | |
| tree | d836be86d9829cf2df9e5d43112ab3e41bdd3889 /MediaBrowser.Server.Implementations/IO | |
| parent | 2ae17a8d528f6a75cd8c91217be4860a13b03715 (diff) | |
Created ILibraryMonitor to replace IDirectoryWatchers
Diffstat (limited to 'MediaBrowser.Server.Implementations/IO')
| -rw-r--r-- | MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs (renamed from MediaBrowser.Server.Implementations/IO/DirectoryWatchers.cs) | 175 |
1 files changed, 54 insertions, 121 deletions
diff --git a/MediaBrowser.Server.Implementations/IO/DirectoryWatchers.cs b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs index 1efc3bc70..e09e66765 100644 --- a/MediaBrowser.Server.Implementations/IO/DirectoryWatchers.cs +++ b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs @@ -1,8 +1,6 @@ -using MediaBrowser.Common.IO; -using MediaBrowser.Common.ScheduledTasks; +using MediaBrowser.Common.ScheduledTasks; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; @@ -18,10 +16,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.IO { - /// <summary> - /// Class DirectoryWatchers - /// </summary> - public class DirectoryWatchers : IDirectoryWatchers + public class LibraryMonitor : ILibraryMonitor { /// <summary> /// The file system watchers @@ -55,7 +50,7 @@ namespace MediaBrowser.Server.Implementations.IO /// Add the path to our temporary ignore list. Use when writing to a path within our listening scope. /// </summary> /// <param name="path">The path.</param> - public void TemporarilyIgnore(string path) + private void TemporarilyIgnore(string path) { _tempIgnoredPaths[path] = path; } @@ -64,7 +59,7 @@ namespace MediaBrowser.Server.Implementations.IO /// Removes the temp ignore. /// </summary> /// <param name="path">The path.</param> - public async void RemoveTempIgnore(string path) + private async void RemoveTempIgnore(string path) { // This is an arbitraty amount of time, but delay it because file system writes often trigger events after RemoveTempIgnore has been called. // Seeing long delays in some situations, especially over the network. @@ -75,6 +70,21 @@ namespace MediaBrowser.Server.Implementations.IO _tempIgnoredPaths.TryRemove(path, out val); } + public void ReportFileSystemChangeBeginning(string path) + { + TemporarilyIgnore(path); + } + + public void ReportFileSystemChangeComplete(string path, bool refreshPath) + { + RemoveTempIgnore(path); + + if (refreshPath) + { + ReportFileSystemChanged(path); + } + } + /// <summary> /// Gets or sets the logger. /// </summary> @@ -90,12 +100,10 @@ namespace MediaBrowser.Server.Implementations.IO private ILibraryManager LibraryManager { get; set; } private IServerConfigurationManager ConfigurationManager { get; set; } - private readonly IFileSystem _fileSystem; - /// <summary> - /// Initializes a new instance of the <see cref="DirectoryWatchers" /> class. + /// Initializes a new instance of the <see cref="LibraryMonitor" /> class. /// </summary> - public DirectoryWatchers(ILogManager logManager, ITaskManager taskManager, ILibraryManager libraryManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem) + public LibraryMonitor(ILogManager logManager, ITaskManager taskManager, ILibraryManager libraryManager, IServerConfigurationManager configurationManager) { if (taskManager == null) { @@ -104,9 +112,8 @@ namespace MediaBrowser.Server.Implementations.IO LibraryManager = libraryManager; TaskManager = taskManager; - Logger = logManager.GetLogger("DirectoryWatchers"); + Logger = logManager.GetLogger(GetType().Name); ConfigurationManager = configurationManager; - _fileSystem = fileSystem; SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged; } @@ -328,31 +335,25 @@ namespace MediaBrowser.Server.Implementations.IO { OnWatcherChanged(e); } - catch (IOException ex) + catch (Exception ex) { - Logger.ErrorException("IOException in watcher changed. Path: {0}", ex, e.FullPath); + Logger.ErrorException("Exception in watcher changed. Path: {0}", ex, e.FullPath); } } private void OnWatcherChanged(FileSystemEventArgs e) { - var name = e.Name; + Logger.Debug("Watcher sees change of type " + e.ChangeType + " to " + e.FullPath); - // Ignore certain files - if (_alwaysIgnoreFiles.Contains(name, StringComparer.OrdinalIgnoreCase)) - { - return; - } + ReportFileSystemChanged(e.FullPath); + } - var nameFromFullPath = Path.GetFileName(e.FullPath); - // Ignore certain files - if (!string.IsNullOrEmpty(nameFromFullPath) && _alwaysIgnoreFiles.Contains(nameFromFullPath, StringComparer.OrdinalIgnoreCase)) - { - return; - } + public void ReportFileSystemChanged(string path) + { + var filename = Path.GetFileName(path); - // Ignore when someone manually creates a new folder - if (e.ChangeType == WatcherChangeTypes.Created && name == "New folder") + // Ignore certain files + if (!string.IsNullOrEmpty(filename) && _alwaysIgnoreFiles.Contains(filename, StringComparer.OrdinalIgnoreCase)) { return; } @@ -362,17 +363,17 @@ namespace MediaBrowser.Server.Implementations.IO // If the parent of an ignored path has a change event, ignore that too if (tempIgnorePaths.Any(i => { - if (string.Equals(i, e.FullPath, StringComparison.OrdinalIgnoreCase)) + if (string.Equals(i, path, StringComparison.OrdinalIgnoreCase)) { - Logger.Debug("Watcher ignoring change to {0}", e.FullPath); + Logger.Debug("Ignoring change to {0}", path); return true; } // Go up a level var parent = Path.GetDirectoryName(i); - if (string.Equals(parent, e.FullPath, StringComparison.OrdinalIgnoreCase)) + if (string.Equals(parent, path, StringComparison.OrdinalIgnoreCase)) { - Logger.Debug("Watcher ignoring change to {0}", e.FullPath); + Logger.Debug("Ignoring change to {0}", path); return true; } @@ -380,17 +381,17 @@ namespace MediaBrowser.Server.Implementations.IO if (!string.IsNullOrEmpty(parent)) { parent = Path.GetDirectoryName(i); - if (string.Equals(parent, e.FullPath, StringComparison.OrdinalIgnoreCase)) + if (string.Equals(parent, path, StringComparison.OrdinalIgnoreCase)) { - Logger.Debug("Watcher ignoring change to {0}", e.FullPath); + Logger.Debug("Ignoring change to {0}", path); return true; } } - if (i.StartsWith(e.FullPath, StringComparison.OrdinalIgnoreCase) || - e.FullPath.StartsWith(i, StringComparison.OrdinalIgnoreCase)) + if (i.StartsWith(path, StringComparison.OrdinalIgnoreCase) || + path.StartsWith(i, StringComparison.OrdinalIgnoreCase)) { - Logger.Debug("Watcher ignoring change to {0}", e.FullPath); + Logger.Debug("Ignoring change to {0}", path); return true; } @@ -401,22 +402,19 @@ namespace MediaBrowser.Server.Implementations.IO return; } - Logger.Info("Watcher sees change of type " + e.ChangeType + " to " + e.FullPath); - - //Since we're watching created, deleted and renamed we always want the parent of the item to be the affected path - var affectedPath = e.FullPath; - - _affectedPaths.AddOrUpdate(affectedPath, affectedPath, (key, oldValue) => affectedPath); + // Avoid implicitly captured closure + var affectedPath = path; + _affectedPaths.AddOrUpdate(path, path, (key, oldValue) => affectedPath); lock (_timerLock) { if (_updateTimer == null) { - _updateTimer = new Timer(TimerStopped, null, TimeSpan.FromSeconds(ConfigurationManager.Configuration.FileWatcherDelay), TimeSpan.FromMilliseconds(-1)); + _updateTimer = new Timer(TimerStopped, null, TimeSpan.FromSeconds(ConfigurationManager.Configuration.RealtimeWatcherDelay), TimeSpan.FromMilliseconds(-1)); } else { - _updateTimer.Change(TimeSpan.FromSeconds(ConfigurationManager.Configuration.FileWatcherDelay), TimeSpan.FromMilliseconds(-1)); + _updateTimer.Change(TimeSpan.FromSeconds(ConfigurationManager.Configuration.RealtimeWatcherDelay), TimeSpan.FromMilliseconds(-1)); } } } @@ -427,24 +425,9 @@ namespace MediaBrowser.Server.Implementations.IO /// <param name="stateInfo">The state info.</param> private async void TimerStopped(object stateInfo) { - lock (_timerLock) - { - // Extend the timer as long as any of the paths are still being written to. - if (_affectedPaths.Any(p => IsFileLocked(p.Key))) - { - Logger.Info("Timer extended."); - _updateTimer.Change(TimeSpan.FromSeconds(ConfigurationManager.Configuration.FileWatcherDelay), TimeSpan.FromMilliseconds(-1)); - return; - } + Logger.Debug("Timer stopped."); - Logger.Info("Timer stopped."); - - if (_updateTimer != null) - { - _updateTimer.Dispose(); - _updateTimer = null; - } - } + DisposeTimer(); var paths = _affectedPaths.Keys.ToList(); _affectedPaths.Clear(); @@ -452,59 +435,16 @@ namespace MediaBrowser.Server.Implementations.IO await ProcessPathChanges(paths).ConfigureAwait(false); } - /// <summary> - /// Try and determine if a file is locked - /// This is not perfect, and is subject to race conditions, so I'd rather not make this a re-usable library method. - /// </summary> - /// <param name="path">The path.</param> - /// <returns><c>true</c> if [is file locked] [the specified path]; otherwise, <c>false</c>.</returns> - private bool IsFileLocked(string path) + private void DisposeTimer() { - try - { - var data = _fileSystem.GetFileSystemInfo(path); - - if (!data.Exists - || data.Attributes.HasFlag(FileAttributes.Directory) - || data.Attributes.HasFlag(FileAttributes.ReadOnly)) - { - return false; - } - } - catch (IOException) - { - return false; - } - - try + lock (_timerLock) { - using (_fileSystem.GetFileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite)) + if (_updateTimer != null) { - //file is not locked - return false; + _updateTimer.Dispose(); + _updateTimer = null; } } - catch (DirectoryNotFoundException) - { - return false; - } - catch (FileNotFoundException) - { - return false; - } - catch (IOException) - { - //the file is unavailable because it is: - //still being written to - //or being processed by another thread - //or does not exist (has already been processed) - Logger.Debug("{0} is locked.", path); - return true; - } - catch - { - return false; - } } /// <summary> @@ -599,14 +539,7 @@ namespace MediaBrowser.Server.Implementations.IO watcher.Dispose(); } - lock (_timerLock) - { - if (_updateTimer != null) - { - _updateTimer.Dispose(); - _updateTimer = null; - } - } + DisposeTimer(); _fileSystemWatchers.Clear(); _affectedPaths.Clear(); |
