Lines 232-239
Link Here
|
232 |
conn = -1; |
232 |
conn = -1; |
233 |
} |
233 |
} |
234 |
|
234 |
|
235 |
if (!thread.Join (2000)) |
235 |
while (!thread.Join (2000)) |
236 |
thread.Abort (); |
236 |
thread.Interrupt (); |
237 |
|
237 |
|
238 |
requestStop = false; |
238 |
requestStop = false; |
239 |
started = false; |
239 |
started = false; |
Lines 374-394
Link Here
|
374 |
while (!requestStop) { |
374 |
while (!requestStop) { |
375 |
var changes = CreateChangeList (ref newFds); |
375 |
var changes = CreateChangeList (ref newFds); |
376 |
|
376 |
|
377 |
// We are calling an icall, so have to marshal manually |
377 |
int numEvents = kevent_notimeout (conn, changes, changes.Length, eventBuffer, eventBuffer.Length, IntPtr.Zero); |
378 |
// Marshal in |
|
|
379 |
int ksize = Marshal.SizeOf<kevent> (); |
380 |
var changesNative = Marshal.AllocHGlobal (ksize * changes.Length); |
381 |
for (int i = 0; i < changes.Length; ++i) |
382 |
Marshal.StructureToPtr (changes [i], changesNative + (i * ksize), false); |
383 |
var eventBufferNative = Marshal.AllocHGlobal (ksize * eventBuffer.Length); |
384 |
|
385 |
int numEvents = kevent_notimeout (ref conn, changesNative, changes.Length, eventBufferNative, eventBuffer.Length); |
386 |
|
387 |
// Marshal out |
388 |
Marshal.FreeHGlobal (changesNative); |
389 |
for (int i = 0; i < numEvents; ++i) |
390 |
eventBuffer [i] = Marshal.PtrToStructure<kevent> (eventBufferNative + (i * ksize)); |
391 |
Marshal.FreeHGlobal (eventBufferNative); |
392 |
|
378 |
|
393 |
if (numEvents == -1) { |
379 |
if (numEvents == -1) { |
394 |
// Stop () signals us to stop by closing the connection |
380 |
// Stop () signals us to stop by closing the connection |
Lines 401-406
Link Here
|
401 |
|
387 |
|
402 |
continue; |
388 |
continue; |
403 |
} |
389 |
} |
|
|
390 |
|
404 |
retries = 0; |
391 |
retries = 0; |
405 |
|
392 |
|
406 |
for (var i = 0; i < numEvents; i++) { |
393 |
for (var i = 0; i < numEvents; i++) { |
Lines 428-435
Link Here
|
428 |
} |
415 |
} |
429 |
|
416 |
|
430 |
if ((kevt.fflags & FilterFlags.VNodeRename) == FilterFlags.VNodeRename) { |
417 |
if ((kevt.fflags & FilterFlags.VNodeRename) == FilterFlags.VNodeRename) { |
431 |
UpdatePath (pathData); |
418 |
/* We can simply remove the entire subtree here, as |
432 |
} |
419 |
the move will trigger a directory update and thus |
|
|
420 |
a re-scan at the new location, which will cause any |
421 |
children to be re-added. */ |
422 |
removeQueue.Add (pathData); |
423 |
if (pathData.IsDirectory) { |
424 |
var prefix = pathData.Path + Path.DirectorySeparatorChar; |
425 |
foreach (var path in pathsDict.Keys) |
426 |
if (path.StartsWith (prefix)) { |
427 |
removeQueue.Add (pathsDict [path]); |
428 |
} |
429 |
} |
430 |
PostEvent (FileAction.RenamedOldName, pathData.Path); |
431 |
} |
433 |
|
432 |
|
434 |
if ((kevt.fflags & FilterFlags.VNodeWrite) == FilterFlags.VNodeWrite) { |
433 |
if ((kevt.fflags & FilterFlags.VNodeWrite) == FilterFlags.VNodeWrite) { |
435 |
if (pathData.IsDirectory) //TODO: Check if dirs trigger Changed events on .NET |
434 |
if (pathData.IsDirectory) //TODO: Check if dirs trigger Changed events on .NET |
Lines 626-631
Link Here
|
626 |
if (action == FileAction.RenamedNewName) { |
625 |
if (action == FileAction.RenamedNewName) { |
627 |
string newName = (newPath.Length > fullPathNoLastSlash.Length) ? newPath.Substring (fullPathNoLastSlash.Length + 1) : String.Empty; |
626 |
string newName = (newPath.Length > fullPathNoLastSlash.Length) ? newPath.Substring (fullPathNoLastSlash.Length + 1) : String.Empty; |
628 |
renamed = new RenamedEventArgs (WatcherChangeTypes.Renamed, fsw.Path, newName, name); |
627 |
renamed = new RenamedEventArgs (WatcherChangeTypes.Renamed, fsw.Path, newName, name); |
|
|
628 |
} else if (action == FileAction.RenamedOldName) { |
629 |
renamed = new RenamedEventArgs (WatcherChangeTypes.Renamed, fsw.Path, null, name); |
629 |
} |
630 |
} |
630 |
|
631 |
|
631 |
fsw.DispatchEvents (action, name, ref renamed); |
632 |
fsw.DispatchEvents (action, name, ref renamed); |
Lines 695-702
Link Here
|
695 |
[DllImport ("libc", SetLastError=true)] |
696 |
[DllImport ("libc", SetLastError=true)] |
696 |
extern static int kevent (int kq, [In]kevent[] ev, int nchanges, [Out]kevent[] evtlist, int nevents, [In] ref timespec time); |
697 |
extern static int kevent (int kq, [In]kevent[] ev, int nchanges, [Out]kevent[] evtlist, int nevents, [In] ref timespec time); |
697 |
|
698 |
|
698 |
[MethodImplAttribute(MethodImplOptions.InternalCall)] |
699 |
[DllImport ("libc", EntryPoint="kevent", SetLastError=true)] |
699 |
extern static int kevent_notimeout (ref int kq, IntPtr ev, int nchanges, IntPtr evtlist, int nevents); |
700 |
extern static int kevent_notimeout (int kq, [In]kevent[] ev, int nchanges, [Out]kevent[] evtlist, int nevents, IntPtr ptr); |
700 |
} |
701 |
} |
701 |
|
702 |
|
702 |
class KeventWatcher : IFileWatcher |
703 |
class KeventWatcher : IFileWatcher |