Its time fot Google Summer of Code midterm evaluations and here I will summarize the current project status.
All the planned functionality is implemented:
- File and directory monitoring, supported events are
- Monitoring for files and directories which do not exist yet;
- Monitoring cancellation.
G_FILE_MONITOR_EVENT_UNMOUNTEDevents are not supported;
- Pair moves (i.e. when a
CREATEDevents for a file move) are not supported;
- Backend opens a file descriptor for each monitored entry, so the observed file's FS can not be unmounted.
All the issues pointed by you and Glib guys were resolved and merged into my kqueue/master branch.
- Make the kqueue backend behave more like an inotify one, if there will be significant differences;
- Fixes and further improvements (i.e. more error handling and robustness);
- Tests. I have not found the monitor tests in Glib test suite, so I am going to write my own.
Brief design overview
Backend runs an additional thread, a kqueue thread, where themonitoring is performed.
When user creates a
GFileMonitor instance for a file, backend tries to open that file and if the file is not found, the backend pushes itinto a missing files list.
If the file was found, the backend pushes its FD to a queue and then sends a signal (via a socket) to the kqueue thread. The kqueue thread wakes up and takes this descriptor for the further
When a call to the
kevent() returns, the kqueue thread searches for signalled descriptors, marshals and writes it into a local socket.
This socket is watched by Glib in its main event loop. Backend reads the notifications coming from a kqueue thread, converts kqueue filter flags into GIO event flags and then emits the
"changed" signal on the appropriate
Backend periodically traverses the missing files list (if it is notempty) and tries to start monitoring on each entry. If the file hasappeared on the FS and the monitoring has started successfully, the backend removes this entry from the missing files list. Otherwise, it will repeat checking on missing files until the user will cancel the monitoring on the appropriate
libinotify compatibility library
I have just finally took the general design decisions, so it is planned to works like follows.
On each call to
inotify_init1() a new thread and a new kqueue will be created. The kqueue will sleep on the monitored descriptors in that thread, like in the gio/kqueue backend. A socketpair will be created and one of its descriptors will be returned to a user as an inotify interface, and another one will be used by the kqueue thread.
The tricky ones are
inotify_rm_watch() functions. The both return a value to an end user, indicating a failure or a success. These functions will push an object (representing the operation requested) to a special internal queue (separate for each kqueue thread). Then an appropriate kqueue thread will be awakened and will perform the requested operation (add/modify/remove an entry). The kqueue thread will also put the operation status (success or failure, an identificator of an added watch, etc) to a per-operation storage so it than could be used in the
inotify_rm_watch() functions as return values.
The problem is in the implementation of this scheme and in that
inotify_rm_watch() functions should sleep while the kqueue thread will perform the requested operations.
I have decided to use
SIMPLEQ for a queue and pthread barriers for thread synchronization, so the implementation now looks clear for me.
The inotify emulation library will not support some kinds of events, like
IN_OPEN and so on, because kqueue has no analogues to it. Some other events, like
IN_MOVED_TO (for a directory) I will try to simulate with caching and diffing the directory's contents between notifications.
Also, in Linux a user can determine the total count of pending notifications on the inotify's file descriptor with
fcntl(). With an userspace emulation it will not be possible to do the same on BSDs, I think.