// (c) 2004 Novell, Inc. (http://www.novell.com)
//
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
using System;
using System.Collections;
using System.IO;
class DefaultWatcherData {
public FileSystemWatcher FSW;
public string Directory;
- public string FileMask;
+ public string FileMask; // If NoWildcards, contains the full path to the file.
public bool IncludeSubdirs;
public bool Enabled;
+ public bool NoWildcards;
public DateTime DisabledTime;
public Hashtable Files;
}
data.FSW = fsw;
data.Directory = fsw.FullPath;
- data.FileMask = fsw.Filter;
+ data.NoWildcards = !fsw.Pattern.HasWildcard;
+ if (data.NoWildcards)
+ data.FileMask = Path.Combine (data.Directory, fsw.MangledFilter);
+ else
+ data.FileMask = fsw.MangledFilter;
+
data.IncludeSubdirs = fsw.IncludeSubdirectories;
data.Enabled = true;
data.DisabledTime = DateTime.MaxValue;
int zeroes = 0;
while (true) {
+ Thread.Sleep (750);
+
+ Hashtable my_watches;
lock (watches) {
- if (watches.Count > 0) {
- zeroes = 0;
- ArrayList removed = null;
- foreach (DefaultWatcherData data in watches.Values) {
- bool remove = UpdateDataAndDispatch (data, true);
- if (remove) {
- if (removed == null)
- removed = new ArrayList ();
-
- removed.Add (data);
- }
- }
-
- if (removed != null) {
- foreach (DefaultWatcherData data in removed)
- watches.Remove (data.FSW);
-
- removed.Clear ();
- removed = null;
- }
- } else {
- zeroes++;
- if (zeroes == 20)
+ if (watches.Count == 0) {
+ if (++zeroes == 20)
break;
+ continue;
+ }
+
+ my_watches = (Hashtable) watches.Clone ();
+ }
+
+ if (watches.Count != 0) {
+ zeroes = 0;
+ foreach (DefaultWatcherData data in my_watches.Values) {
+ bool remove = UpdateDataAndDispatch (data, true);
+ if (remove)
+ lock (watches)
+ watches.Remove (data.FSW);
}
}
- Thread.Sleep (750);
}
lock (this) {
bool UpdateDataAndDispatch (DefaultWatcherData data, bool dispatch)
{
- if (!data.Enabled && data.DisabledTime != DateTime.MaxValue &&
- (DateTime.Now - data.DisabledTime).TotalSeconds > 5) {
- return true; // Will be removed
+ if (!data.Enabled) {
+ return (data.DisabledTime != DateTime.MaxValue &&
+ (DateTime.Now - data.DisabledTime).TotalSeconds > 5);
}
- DoFiles (data, data.Directory, data.FileMask, dispatch);
- if (!data.IncludeSubdirs)
- return false;
+ DoFiles (data, data.Directory, dispatch);
+ return false;
+ }
- foreach (string directory in Directory.GetDirectories (data.Directory)) {
- DoFiles (data, directory, data.FileMask, dispatch);
- }
+ static void DispatchEvents (FileSystemWatcher fsw, FileAction action, string filename)
+ {
+ RenamedEventArgs renamed = null;
- return false;
+ lock (fsw) {
+ fsw.DispatchEvents (action, filename, ref renamed);
+ if (fsw.Waiting) {
+ fsw.Waiting = false;
+ System.Threading.Monitor.PulseAll (fsw);
+ }
+ }
}
- void DoFiles (DefaultWatcherData data, string directory, string filemask, bool dispatch)
+ static string [] NoStringsArray = new string [0];
+ void DoFiles (DefaultWatcherData data, string directory, bool dispatch)
{
- string [] files = Directory.GetFiles (directory, filemask);
+ bool direxists = Directory.Exists (directory);
+ if (direxists && data.IncludeSubdirs) {
+ foreach (string d in Directory.GetDirectories (directory))
+ DoFiles (data, d, dispatch);
+ }
+
+ string [] files = null;
+ if (!direxists) {
+ files = NoStringsArray;
+ } else if (!data.NoWildcards) {
+ files = Directory.GetFileSystemEntries (directory, data.FileMask);
+ } else {
+ // The pattern does not have wildcards
+ if (File.Exists (data.FileMask) || Directory.Exists (data.FileMask))
+ files = new string [] { data.FileMask };
+ else
+ files = NoStringsArray;
+ }
+
/* Set all as untested */
foreach (string filename in data.Files.Keys) {
FileData fd = (FileData) data.Files [filename];
fd.NotExists = true;
}
- RenamedEventArgs renamed = null;
-
/* New files */
foreach (string filename in files) {
FileData fd = (FileData) data.Files [filename];
if (fd == null) {
- data.Files.Add (filename, CreateFileData (directory, filename));
+ try {
+ data.Files.Add (filename, CreateFileData (directory, filename));
+ } catch {
+ // The file might have been removed in the meanwhile
+ data.Files.Remove (filename);
+ continue;
+ }
+
if (dispatch)
- data.FSW.DispatchEvents (FileAction.Added, filename, ref renamed);
+ DispatchEvents (data.FSW, FileAction.Added, filename);
} else if (fd.Directory == directory) {
fd.NotExists = false;
}
removed = new ArrayList ();
removed.Add (filename);
- data.FSW.DispatchEvents (FileAction.Removed, filename, ref renamed);
+ DispatchEvents (data.FSW, FileAction.Removed, filename);
}
}
removed = new ArrayList ();
removed.Add (filename);
- data.FSW.DispatchEvents (FileAction.Removed, filename, ref renamed);
+ DispatchEvents (data.FSW, FileAction.Removed, filename);
continue;
}
if (creation != fd.CreationTime || write != fd.LastWriteTime) {
fd.CreationTime = creation;
fd.LastWriteTime = write;
- data.FSW.DispatchEvents (FileAction.Modified, filename, ref renamed);
+ DispatchEvents (data.FSW, FileAction.Modified, filename);
}
}