(DISTFILES): Comment out a few missing files.
[mono-project.git] / mcs / class / System / System.IO / DefaultWatcher.cs
blobb68149c4ca3ed339ebcf8b6a2507da8761c8be9b
1 //
2 // System.IO.DefaultWatcher.cs: default IFileWatcher
3 //
4 // Authors:
5 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
6 //
7 // (c) 2004 Novell, Inc. (http://www.novell.com)
8 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 //
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 //
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System;
32 using System.Collections;
33 using System.IO;
34 using System.Threading;
36 namespace System.IO {
37 class DefaultWatcherData {
38 public FileSystemWatcher FSW;
39 public string Directory;
40 public string FileMask; // If NoWildcards, contains the full path to the file.
41 public bool IncludeSubdirs;
42 public bool Enabled;
43 public bool NoWildcards;
44 public DateTime DisabledTime;
45 public Hashtable Files;
48 class FileData {
49 public string Directory;
50 public FileAttributes Attributes;
51 public bool NotExists;
52 public DateTime CreationTime;
53 public DateTime LastWriteTime;
56 class DefaultWatcher : IFileWatcher
58 static DefaultWatcher instance;
59 static Thread thread;
60 static Hashtable watches;
62 private DefaultWatcher ()
66 public static bool GetInstance (out IFileWatcher watcher)
68 lock (typeof (DefaultWatcher)) {
69 if (instance != null) {
70 watcher = instance;
71 return true;
74 instance = new DefaultWatcher ();
75 watcher = instance;
76 return true;
80 public void StartDispatching (FileSystemWatcher fsw)
82 DefaultWatcherData data;
83 lock (this) {
84 if (watches == null)
85 watches = new Hashtable ();
87 if (thread == null) {
88 thread = new Thread (new ThreadStart (Monitor));
89 thread.IsBackground = true;
90 thread.Start ();
94 lock (watches) {
95 data = (DefaultWatcherData) watches [fsw];
96 if (data == null) {
97 data = new DefaultWatcherData ();
98 data.Files = new Hashtable ();
99 watches [fsw] = data;
102 data.FSW = fsw;
103 data.Directory = fsw.FullPath;
104 data.NoWildcards = !fsw.Pattern.HasWildcard;
105 if (data.NoWildcards)
106 data.FileMask = Path.Combine (data.Directory, fsw.MangledFilter);
107 else
108 data.FileMask = fsw.MangledFilter;
110 data.IncludeSubdirs = fsw.IncludeSubdirectories;
111 data.Enabled = true;
112 data.DisabledTime = DateTime.MaxValue;
113 UpdateDataAndDispatch (data, false);
117 public void StopDispatching (FileSystemWatcher fsw)
119 DefaultWatcherData data;
120 lock (watches) {
121 data = (DefaultWatcherData) watches [fsw];
122 if (data != null) {
123 data.Enabled = false;
124 data.DisabledTime = DateTime.Now;
130 void Monitor ()
132 int zeroes = 0;
134 while (true) {
135 lock (watches) {
136 if (watches.Count > 0) {
137 zeroes = 0;
138 ArrayList removed = null;
139 foreach (DefaultWatcherData data in watches.Values) {
140 bool remove = UpdateDataAndDispatch (data, true);
141 if (remove) {
142 if (removed == null)
143 removed = new ArrayList ();
145 removed.Add (data);
149 if (removed != null) {
150 foreach (DefaultWatcherData data in removed)
151 watches.Remove (data.FSW);
153 removed.Clear ();
154 removed = null;
156 } else {
157 zeroes++;
158 if (zeroes == 20)
159 break;
162 Thread.Sleep (750);
165 lock (this) {
166 thread = null;
170 bool UpdateDataAndDispatch (DefaultWatcherData data, bool dispatch)
172 if (!data.Enabled) {
173 return (data.DisabledTime != DateTime.MaxValue &&
174 (DateTime.Now - data.DisabledTime).TotalSeconds > 5);
177 DoFiles (data, data.Directory, dispatch);
178 return false;
181 static void DispatchEvents (FileSystemWatcher fsw, FileAction action, string filename)
183 RenamedEventArgs renamed = null;
185 lock (fsw) {
186 fsw.DispatchEvents (action, filename, ref renamed);
187 if (fsw.Waiting) {
188 fsw.Waiting = false;
189 System.Threading.Monitor.PulseAll (fsw);
194 static string [] NoStringsArray = new string [0];
195 void DoFiles (DefaultWatcherData data, string directory, bool dispatch)
197 bool direxists = Directory.Exists (directory);
198 if (direxists && data.IncludeSubdirs) {
199 foreach (string d in Directory.GetDirectories (directory))
200 DoFiles (data, d, dispatch);
203 string [] files = null;
204 if (!direxists) {
205 files = NoStringsArray;
206 } else if (!data.NoWildcards) {
207 files = Directory.GetFileSystemEntries (directory, data.FileMask);
208 } else {
209 // The pattern does not have wildcards
210 if (File.Exists (data.FileMask))
211 files = new string [] { data.FileMask };
212 else
213 files = NoStringsArray;
216 /* Set all as untested */
217 foreach (string filename in data.Files.Keys) {
218 FileData fd = (FileData) data.Files [filename];
219 if (fd.Directory == directory)
220 fd.NotExists = true;
223 /* New files */
224 foreach (string filename in files) {
225 FileData fd = (FileData) data.Files [filename];
226 if (fd == null) {
227 try {
228 data.Files.Add (filename, CreateFileData (directory, filename));
229 } catch {
230 // The file might have been removed in the meanwhile
231 data.Files.Remove (filename);
232 continue;
235 if (dispatch)
236 DispatchEvents (data.FSW, FileAction.Added, filename);
237 } else if (fd.Directory == directory) {
238 fd.NotExists = false;
242 if (!dispatch) // We only initialize the file list
243 return;
245 /* Removed files */
246 ArrayList removed = null;
247 foreach (string filename in data.Files.Keys) {
248 FileData fd = (FileData) data.Files [filename];
249 if (fd.NotExists) {
250 if (removed == null)
251 removed = new ArrayList ();
253 removed.Add (filename);
254 DispatchEvents (data.FSW, FileAction.Removed, filename);
258 if (removed != null) {
259 foreach (string filename in removed)
260 data.Files.Remove (filename);
262 removed = null;
265 /* Changed files */
266 foreach (string filename in data.Files.Keys) {
267 FileData fd = (FileData) data.Files [filename];
268 DateTime creation, write;
269 try {
270 creation = File.GetCreationTime (filename);
271 write = File.GetLastWriteTime (filename);
272 } catch {
273 /* Deleted */
274 if (removed == null)
275 removed = new ArrayList ();
277 removed.Add (filename);
278 DispatchEvents (data.FSW, FileAction.Removed, filename);
279 continue;
282 if (creation != fd.CreationTime || write != fd.LastWriteTime) {
283 fd.CreationTime = creation;
284 fd.LastWriteTime = write;
285 DispatchEvents (data.FSW, FileAction.Modified, filename);
289 if (removed != null) {
290 foreach (string filename in removed)
291 data.Files.Remove (filename);
296 static FileData CreateFileData (string directory, string filename)
298 FileData fd = new FileData ();
299 string fullpath = Path.Combine (directory, filename);
300 fd.Directory = directory;
301 fd.Attributes = File.GetAttributes (fullpath);
302 fd.CreationTime = File.GetCreationTime (fullpath);
303 fd.LastWriteTime = File.GetLastWriteTime (fullpath);
304 return fd;