The file system events API supports two types of event streams: per-disk event streams and a per-host event streams. Before you can create a stream, you must decide which type of stream to create: a per-host event stream or a per-disk event stream. You can create these streams by calling the functions FSEventStreamCreate and FSEventStreamCreateRelativeToDevice, respectively.
A per-host event stream consists of events whose IDs are increasing with respect to other events on that host. These IDs are guaranteed to be unique with one exception: if additional disks are added from another computer that was also running Mac OS X v10.5 or later, historical IDs may conflict between these volumes. Any new events will automatically start after the highest-numbered historical ID for any attached drive.
A per-disk event stream, by contrast, consists of events whose IDs are increasing with respect to previous events on that disk. It does not have any relationship with other events on other disks, and thus you must create a separate event stream for each physical device that you wish to monitor.
In general, if you are writing software that requires persistence, you should use per-disk streams to avoid any confusion due to ID conflicts. By contrast, per-host streams are most convenient if you are monitoring for changes in a directory or tree of directories during normal execution, such as watching a queue directory.
Note: Because disks can be modified by computers running earlier versions of Mac OS X (or potentially other operating systems), you should treat the events list as advisory rather than a definitive list of all changes to the volume. If a disk is modified by a computer running a previous version of Mac OS X, the historical log is discarded.
For example, backup software should still periodically perform a full sweep of any volume to ensure that no changes fall through the cracks.
If you are monitoring files on the root file system, either stream mechanism will behave similarly.
For example, the following snippet shows how to create an event stream:
/* Define variables and create a CFArray object containing |
CFString objects containing paths to watch. |
*/ |
CFStringRef mypath = CFSTR("/path/to/scan"); |
CFArrayRef pathsToWatch = CFArrayCreate(NULL, (const void **)&mypath, 1, NULL); |
void *callbackInfo = NULL; // could put stream-specific data here. |
FSEventStreamRef stream; |
CFAbsoluteTime latency = 3.0; /* Latency in seconds */ |
/* Create the stream, passing in a callback, |
stream = FSEventStreamCreate(NULL, |
&myCallbackFunction, |
callbackInfo, |
pathsToWatch, |
kFSEventStreamEventIdSinceNow, /* Or a previous event ID */ |
latency, |
kFSEventStreamCreateFlagNone /* Flags explained in reference */ |
); |
Once you have created an event stream, you must schedule it on your application’s run loop. To do this, call FSEventStreamScheduleWithRunLoop, passing in the newly-created stream, a reference to your run loop, and a run loop mode. For more information about run loops, read Run Loops.
If you don’t already have a run loop, you will need to devote a thread to this task. After creating a thread using your API of choice, call CFRunLoopGetCurrent to allocate an initial run loop for that thread. Any future calls to CFRunLoopGetCurrent will return the same run loop.
For example, the following snippet shows how to schedule a stream, called stream, on the current thread’s run loop (not yet running):
FSEventStreamRef stream; |
/* Create the stream before calling this. */ |
FSEventStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); |
The final step in setting up an event stream is to call FSEventStreamStart. This function tells the event stream to begin sending events. Its sole parameter is the event stream to start.
Once the event stream has been created and scheduled, if your run loop is not already running, you should start it by calling CFRunLoopRun.
Last updated: 2008-03-11