2 // System.IO.FAM.cs: interface with libfam
5 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 // (c) 2004 Novell, Inc. (http://www.novell.com)
11 using System.Collections;
12 using System.ComponentModel;
13 using System.Runtime.CompilerServices;
14 using System.Runtime.InteropServices;
16 using System.Threading;
19 struct FAMConnection {
41 public FileSystemWatcher FSW;
42 public string Directory;
43 public string FileMask;
44 public bool IncludeSubdirs;
46 public FAMRequest Request;
49 class FAMWatcher : IFileWatcher
52 static FAMWatcher instance;
53 static Hashtable watches;
54 static Hashtable requests;
55 static FAMConnection conn;
63 public static bool GetInstance (out IFileWatcher watcher)
65 lock (typeof (FAMWatcher)) {
71 if (instance != null) {
76 watches = new Hashtable ();
77 requests = new Hashtable ();
78 if (FAMOpen (out conn) == -1) {
84 instance = new FAMWatcher ();
90 public void StartDispatching (FileSystemWatcher fsw)
95 thread = new Thread (new ThreadStart (Monitor));
96 thread.IsBackground = true;
100 data = (FAMData) watches [fsw];
104 data = new FAMData ();
106 data.Directory = fsw.FullPath;
107 data.FileMask = fsw.Filter;
108 data.IncludeSubdirs = fsw.IncludeSubdirectories;
111 StartMonitoringDirectory (data);
112 watches [fsw] = data;
113 requests [data.Request.ReqNum] = data;
118 static void StartMonitoringDirectory (FAMData data)
121 if (FAMMonitorDirectory (ref conn, data.Directory, out fr, IntPtr.Zero) == -1)
122 throw new Win32Exception ();
127 public void StopDispatching (FileSystemWatcher fsw)
131 data = (FAMData) watches [fsw];
135 StopMonitoringDirectory (data);
136 watches.Remove (fsw);
137 requests.Remove (data.Request.ReqNum);
138 if (watches.Count == 0)
143 static void StopMonitoringDirectory (FAMData data)
146 if (FAMCancelMonitor (ref conn, ref data.Request) == -1)
147 throw new Win32Exception ();
155 haveEvents = FAMPending (ref conn);
158 if (haveEvents > 0) {
171 const NotifyFilters changed = NotifyFilters.Attributes |
172 NotifyFilters.LastAccess |
174 NotifyFilters.LastWrite;
176 void ProcessEvents ()
183 FileSystemWatcher fsw;
185 if (InternalFAMNextEvent (ref conn, out filename,
186 out code, out requestNumber) != 1)
190 switch ((FAMCodes) code) {
191 case FAMCodes.Changed:
192 case FAMCodes.Deleted:
193 case FAMCodes.Created:
194 found = requests.ContainsKey (requestNumber);
197 case FAMCodes.StartExecuting:
198 case FAMCodes.StopExecuting:
199 case FAMCodes.Acknowledge:
200 case FAMCodes.Exists:
201 case FAMCodes.EndExist:
210 FAMData data = (FAMData) requests [requestNumber];
215 NotifyFilters flt = fsw.NotifyFilter;
216 RenamedEventArgs renamed = null;
218 if (code == (int) FAMCodes.Changed && (flt & changed) != 0)
219 fa = FileAction.Modified;
220 else if (code == (int) FAMCodes.Deleted)
221 fa = FileAction.Removed;
222 else if (code == (int) FAMCodes.Created)
223 fa = FileAction.Added;
226 if (filename != data.Directory && !fsw.Pattern.IsMatch (filename))
230 fsw.DispatchEvents (fa, filename, ref renamed);
233 System.Threading.Monitor.PulseAll (fsw);
238 } while (FAMPending (ref conn) > 0);
243 extern static int FAMOpen (out FAMConnection fc);
246 extern static int FAMClose (ref FAMConnection fc);
249 extern static int FAMMonitorDirectory (ref FAMConnection fc, string filename,
250 out FAMRequest fr, IntPtr user_data);
253 extern static int FAMCancelMonitor (ref FAMConnection fc, ref FAMRequest fr);
255 [MethodImplAttribute(MethodImplOptions.InternalCall)]
256 extern static int InternalFAMNextEvent (ref FAMConnection fc, out string filename,
257 out int code, out int reqnum);
260 extern static int FAMPending (ref FAMConnection fc);