Its time fot Google Summer of Code midterm evaluations and here I will summarize the current project status.
GIO/kqueue backend
All the planned functionality is implemented:
File and directory monitoring, supported events are
G_FILE_MONITOR_EVENT_CREATED
G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED
G_FILE_MONITOR_EVENT_CHANGED
G_FILE_MONITOR_EVENT_MOVED
G_FILE_MONITOR_EVENT_DELETED
- Monitoring for files and directories which do not exist yet;
Monitoring cancellation.
Current limitations
G_FILE_MONITOR_EVENT_PRE_UNMOUNT
andG_FILE_MONITOR_EVENT_UNMOUNTED
events are not supported;- Pair moves (i.e. when a
GFileMonitor
emitsDELETED
andCREATED
events 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.
Furher plans
- 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 kevent()
.
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 GFileMonitor
instances.
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 GFileMonitor
instance.
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_init()
or 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_add_watch()
and 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_add_watch()
and inotify_rm_watch()
functions as return values.
The problem is in the implementation of this scheme and in that inotify_add_watch()
and 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_CLOSE[_XXX]
, IN_OPEN
and so on, because kqueue has no analogues to it. Some other events, like IN_MOVED_FROM
or 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.