Reputation: 1091
I'm trying to monitor the edition of a single file using kqueue
through a wrapper called UKKQueue available here. This wrapper is very simple, here is the test code I'm using:
@implementation FileMonitorTestAppDelegate
@synthesize window;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
fileWatcher = [[UKKQueue alloc] init];
[fileWatcher addPath:@"/Users/bruno/Desktop/SyncTestLog"];
[fileWatcher setDelegate:self];
}
- (void)dealloc {
[fileWatcher release];
}
-(void) watcher: (id<UKFileWatcher>)kq receivedNotification: (NSString*)nm forPath: (NSString*)fpath {
NSLog(@"UKFileWatcher: %@ - notification: %@ - filePath: %@", kq, nm, fpath);
}
@end
The file at /Users/bruno/Desktop/SyncTestLog
is a plain text file. When I edit it using nano
from the terminal the output shows as expected:
2011-08-17 11:46:27.316 FileMonitorTest[1235:707] UKFileWatcher: <UKKQueue: 0x100117da0> - notification: UKKQueueFileWrittenToNotification - filePath: /Users/bruno/Desktop/SyncTestLog
2011-08-17 11:46:27.317 FileMonitorTest[1235:707] UKFileWatcher: <UKKQueue: 0x100117da0> - notification: UKKQueueFileSizeIncreasedNotification - filePath: /Users/bruno/Desktop/SyncTestLog
2011-08-17 11:46:27.751 FileMonitorTest[1235:707] UKFileWatcher: <UKKQueue: 0x100117da0> - notification: UKKQueueFileAttributesChangedNotification - filePath: /Users/bruno/Desktop/SyncTestLog
Now, when I edit it using TextEdit or TextWrangler the monitoring stop reporting changes after the first time I save the file. Heres is the last events reported:
2011-08-17 10:57:45.792 FileMonitorTest[897:707] UKFileWatcher: <UKKQueue: 0x10035ae10> - notification: UKKQueueFileAttributesChangedNotification - filePath: /Users/bruno/Desktop/SyncTestLog
2011-08-17 10:57:46.463 FileMonitorTest[897:707] UKFileWatcher: <UKKQueue: 0x10035ae10> - notification: UKKQueueFileAttributesChangedNotification - filePath: /Users/bruno/Desktop/SyncTestLog
2011-08-17 10:57:54.043 FileMonitorTest[897:707] UKFileWatcher: <UKKQueue: 0x10035ae10> - notification: UKKQueueFileDeletedNotification - filePath: /Users/bruno/Desktop/SyncTestLog
As far as I understand the UKKQueue gets a unix-like file descriptor with open() using the flag O_EVTONLY
. For some reason the TextEdit (and TextWrangler) generate this UKKQueueFileDeletedNotification
notification when save the file.
What I need is keep listening for changes in the file "for ever". I suppose that I can re create the monitor when the UKKQueueFileDeletedNotification
arrives but I'm looking for something more clean.
Thanks
Edit: I'm just found the in the Google Toolbox For Mac a class called GTMFileSystemKQueue that's solve my problem. Still no answer for my question.
Upvotes: 0
Views: 815
Reputation: 3498
The gotcha here is that TextEdit and TextWrangler are using safe save (or ...atomically:YES
) that doesn't write straight to the file, but first writes to a temporary file, then renames files to replace the original path with the file saved at the temporary location.
The effect of this is your kqueue will be monitoring the original file that will have since been deleted by the safe save mechanism.
GTMFileSystemKQueue works because of the acrossReplace
parameter, that watches for delete/rename operations and re-registers the kqueue against the original path. A quick check of UKKQueue and VDKQueue seems to suggest that neither do this.
Upvotes: 1
Reputation: 5779
I have re-written UKKQueue in modern Objective-C. The new class works the same way, it's simply better, faster and streamlined. It also fixes the bug described in this post along with several others.
You can find the new class, VDKQueue, here: http://github.com/bdkjones/VDKQueue
Upvotes: 3