void Monitor ()
{
var timeout = new timespec { tv_sec = (IntPtr)0, tv_usec = (IntPtr)500000000 };
var eventBuffer = new kevent[32];
var newFds = new List<int> ();
List<PathData> removeQueue = new List<PathData> ();
List<string> rescanQueue = new List<string> ();
int retries = 0;
while (!requestStop) {
var changes = CreateChangeList (ref newFds);
int numEvents = kevent (conn, changes, changes.Length, eventBuffer, eventBuffer.Length, ref timeout);
if (numEvents == -1) {
if (++retries == 3)
throw new IOException (String.Format (
"persistent kevent() error, error code = '{0}'", Marshal.GetLastWin32Error ()));
continue;
}
retries = 0;
for (var i = 0; i < numEvents; i++) {
var kevt = eventBuffer [i];
var pathData = fdsDict [(int)kevt.ident];
if ((kevt.flags & EventFlags.Error) == EventFlags.Error) {
var errMsg = String.Format ("kevent() error watching path '{0}', error code = '{1}'", pathData.Path, kevt.data);
fsw.DispatchErrorEvents (new ErrorEventArgs (new IOException (errMsg)));
continue;
}
if ((kevt.fflags & FilterFlags.VNodeDelete) == FilterFlags.VNodeDelete || (kevt.fflags & FilterFlags.VNodeRevoke) == FilterFlags.VNodeRevoke) {
removeQueue.Add (pathData);
continue;
}
if ((kevt.fflags & FilterFlags.VNodeRename) == FilterFlags.VNodeRename) {
UpdatePath (pathData);
}
if ((kevt.fflags & FilterFlags.VNodeWrite) == FilterFlags.VNodeWrite) {
if (pathData.IsDirectory) //TODO: Check if dirs trigger Changed events on .NET
rescanQueue.Add (pathData.Path);
else
PostEvent (FileAction.Modified, pathData.Path);
}
if ((kevt.fflags & FilterFlags.VNodeAttrib) == FilterFlags.VNodeAttrib || (kevt.fflags & FilterFlags.VNodeExtend) == FilterFlags.VNodeExtend)
PostEvent (FileAction.Modified, pathData.Path);
}
removeQueue.ForEach (Remove);
removeQueue.Clear ();
rescanQueue.ForEach (path => {
Scan (path, true, ref newFds);
});
rescanQueue.Clear ();
}
}