private void AddDirectory(FullPath directory) { DirectoryWatcherhEntry watcherEntry; lock (_watchersLock) { if (_pollingThread == null) { _pollingThread = new Thread(ThreadLoop) { IsBackground = true }; _pollingThread.Start(); } if (_watchers.TryGetValue(directory, out watcherEntry)) { return; } watcherEntry = new DirectoryWatcherhEntry { Path = directory, DirectoryNameWatcher = _fileSystem.CreateDirectoryWatcher(directory), FileNameWatcher = _fileSystem.CreateDirectoryWatcher(directory), FileWriteWatcher = _fileSystem.CreateDirectoryWatcher(directory), }; _watchers.Add(directory, watcherEntry); } Logger.LogInfo("Starting monitoring directory \"{0}\" for change notifications.", directory); // Note: "DirectoryName" captures directory creation, deletion and rename watcherEntry.DirectoryNameWatcher.NotifyFilter = NotifyFilters.DirectoryName; watcherEntry.DirectoryNameWatcher.Changed += (s, e) => WatcherOnChanged(s, e, PathKind.Directory); watcherEntry.DirectoryNameWatcher.Created += (s, e) => WatcherOnCreated(s, e, PathKind.Directory); watcherEntry.DirectoryNameWatcher.Deleted += (s, e) => WatcherOnDeleted(s, e, PathKind.Directory); watcherEntry.DirectoryNameWatcher.Renamed += (s, e) => WatcherOnRenamed(s, e, PathKind.Directory); // Note: "FileName" captures file creation, deletion and rename watcherEntry.FileNameWatcher.NotifyFilter = NotifyFilters.FileName; watcherEntry.FileNameWatcher.Changed += (s, e) => WatcherOnChanged(s, e, PathKind.File); watcherEntry.FileNameWatcher.Created += (s, e) => WatcherOnCreated(s, e, PathKind.File); watcherEntry.FileNameWatcher.Deleted += (s, e) => WatcherOnDeleted(s, e, PathKind.File); watcherEntry.FileNameWatcher.Renamed += (s, e) => WatcherOnRenamed(s, e, PathKind.File); // Note: "LastWrite" will catch changes to *both* files and directories, i.e. it is // not possible to known which one it is. // For directories, a "LastWrite" change occurs when a child entry (file or directory) is added, // renamed or deleted. // For files, a "LastWrite" change occurs when the file is written to. watcherEntry.FileWriteWatcher.NotifyFilter = NotifyFilters.LastWrite; watcherEntry.FileWriteWatcher.Changed += (s, e) => WatcherOnChanged(s, e, PathKind.FileOrDirectory); watcherEntry.FileWriteWatcher.Created += (s, e) => WatcherOnCreated(s, e, PathKind.FileOrDirectory); watcherEntry.FileWriteWatcher.Deleted += (s, e) => WatcherOnDeleted(s, e, PathKind.FileOrDirectory); watcherEntry.FileWriteWatcher.Renamed += (s, e) => WatcherOnRenamed(s, e, PathKind.FileOrDirectory); foreach (var watcher in new[] { watcherEntry.DirectoryNameWatcher, watcherEntry.FileNameWatcher, watcherEntry.FileWriteWatcher }) { watcher.IncludeSubdirectories = true; // Note: The MSDN documentation says to use less than 64KB // (see https://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.internalbuffersize(v=vs.110).aspx) // "You can set the buffer to 4 KB or larger, but it must not exceed 64 KB." // However, the implementation allows for arbitrary buffer sizes. // Experience has shown that 64KB is small enough that we frequently run into "OverflowException" // exceptions on heavily active file systems (e.g. during a build of a complex project // such as Chromium). // The issue with these exceptions is that the consumer must be extremely conservative // when such errors occur, because we lost track of what happened at the individual // directory/file level. In the case of VsChromium, the server will batch a full re-scan // of the file system, instead of an incremental re-scan, and that can be quite time // consuming (as well as I/O consuming). // In the end, increasing the size of the buffer to 2 MB is the best option to avoid // these issues (2 MB is not that much memory in the grand scheme of things). watcher.InternalBufferSize = 2 * 1024 * 1024; // 2 MB watcher.Error += WatcherOnError; watcher.Start(); } }
public abstract State OnWatcherRemoved(FullPath directory, DirectoryWatcherhEntry watcher);
public override State OnWatcherRemoved(FullPath directory, DirectoryWatcherhEntry watcher) { return(BackToState()); }
public override State OnWatcherAdded(FullPath directory, DirectoryWatcherhEntry watcher) { return(this); }