[glib/wip/desrt/gfilemonitor: 45/52] inotify: send CHANGES_DONE when new files 'appear'
- From: Ryan Lortie <desrt src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/wip/desrt/gfilemonitor: 45/52] inotify: send CHANGES_DONE when new files 'appear'
- Date: Tue, 10 Mar 2015 15:24:11 +0000 (UTC)
commit 83e2ef8fd023db94f88a25422ef484433077088e
Author: Ryan Lortie <desrt desrt ca>
Date: Thu Jan 15 11:08:35 2015 -0500
inotify: send CHANGES_DONE when new files 'appear'
We generally assume that an IN_CREATE event is the start of a series of
events in which another process is doing this:
fd = creat (...) -> IN_CREATE
write (fd, ..) -> IN_MODIFY
write (fd, ..) -> IN_MODIFY
close (fd) -> IN_CLOSE_WRITE
and as such, we use the CHANGES_DONE_HINT event after CREATED in order
to show when this sequence of events has completed (ie: when we receive
IN_CLOSE_WRITE when the user closes the file).
Renaming a file into place is handled by IN_MOVED_FROM so we don't have
to worry about that.
There are many other cases, however, where a new file 'appears' in a
directory in its completed form already, and the kernel reports
IN_CREATE. Examples include mkdir, mknod, and the creation of
hardlinks. In these cases, there is no corresponding IN_CLOSE_WRITE
event and the CHANGES_DONE_HINT will have to be emitted by an arbitrary
timeout.
Try to detect some of these cases and report CHANGES_DONE_HINT
immediately.
This is not perfect. There are some cases that will not be reliably
detected. An example is if the user makes a hardlink and then
immediately deletes the original (before we can stat the new file).
Another example is if the user creates a file with O_TMPFILE. In both
of these cases, CHANGES_DONE_HINT will still eventually be delivered via
the timeout.
gio/inotify/inotify-helper.c | 39 ++++++++++++++++++++++++++++++++++++++-
1 files changed, 38 insertions(+), 1 deletions(-)
---
diff --git a/gio/inotify/inotify-helper.c b/gio/inotify/inotify-helper.c
index 843db26..9e52f60 100644
--- a/gio/inotify/inotify-helper.c
+++ b/gio/inotify/inotify-helper.c
@@ -27,6 +27,7 @@
#include <time.h>
#include <string.h>
#include <sys/ioctl.h>
+#include <sys/stat.h>
/* Just include the local header to stop all the pain */
#include <sys/inotify.h>
#include <gio/glocalfilemonitor.h>
@@ -197,13 +198,49 @@ ih_event_callback (ik_event_t *event,
/* unpaired event -- no 'other' field */
g_file_monitor_source_handle_event (sub->user_data, ih_mask_to_EventFlags (event->mask),
event->name, NULL, NULL, event->timestamp);
+
+ if (event->mask & IN_CREATE)
+ {
+ const gchar *parent_dir;
+ gchar *fullname;
+ struct stat buf;
+ gint s;
+
+ /* The kernel reports IN_CREATE for two types of events:
+ *
+ * - creat(), in which case IN_CLOSE_WRITE will come soon; or
+ * - link(), mkdir(), mknod(), etc., in which case it won't
+ *
+ * We can attempt to detect the second case and send the
+ * CHANGES_DONE immediately so that the user isn't left waiting.
+ *
+ * The detection for link() is not 100% reliable since the link
+ * count could be 1 if the original link was deleted or if
+ * O_TMPFILE was being used, but in that case the virtual
+ * CHANGES_DONE will be emitted to close the loop.
+ */
+
+ parent_dir = _ip_get_path_for_wd (event->wd);
+ fullname = _ih_fullpath_from_event (event, parent_dir, NULL);
+ s = stat (fullname, &buf);
+ g_free (fullname);
+
+ /* if it doesn't look like the result of creat()... */
+ if (s != 0 || !S_ISREG (buf.st_mode) || buf.st_nlink != 1)
+ g_file_monitor_source_handle_event (sub->user_data, G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT,
+ event->name, NULL, NULL, event->timestamp);
+ }
}
static void
ih_not_missing_callback (inotify_sub *sub)
{
+ gint now = g_get_monotonic_time ();
+
g_file_monitor_source_handle_event (sub->user_data, G_FILE_MONITOR_EVENT_CREATED,
- sub->filename, NULL, NULL, g_get_monotonic_time ());
+ sub->filename, NULL, NULL, now);
+ g_file_monitor_source_handle_event (sub->user_data, G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT,
+ sub->filename, NULL, NULL, now);
}
/* Transforms a inotify event to a GVFS event. */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]