From 48f74cab395044a07e1220440cdc816db01b9984 Mon Sep 17 00:00:00 2001 From: Christian Kellner Date: Thu, 18 Feb 2010 15:49:58 +0100 Subject: [PATCH] Move event support in the inotify backend This adds support for G_FILE_MONITOR_SEND_MOVED events when requested by the user to the inotify backend. Last part to fix bug #547890. Based heavily on a patch by Martyn Russel . --- gio/inotify/ginotifydirectorymonitor.c | 7 +++-- gio/inotify/ginotifyfilemonitor.c | 9 ++++++- gio/inotify/inotify-helper.c | 49 +++++++++++++++++++++++++++++----- gio/inotify/inotify-kernel.c | 4 +-- gio/inotify/inotify-path.c | 18 +++++++++++++ gio/inotify/inotify-path.h | 8 +++--- gio/inotify/inotify-sub.c | 6 +++-- gio/inotify/inotify-sub.h | 3 ++- 8 files changed, 86 insertions(+), 18 deletions(-) diff --git a/gio/inotify/ginotifydirectorymonitor.c b/gio/inotify/ginotifydirectorymonitor.c index f6fcde7..dcc97a0 100644 --- a/gio/inotify/ginotifydirectorymonitor.c +++ b/gio/inotify/ginotifydirectorymonitor.c @@ -76,7 +76,8 @@ g_inotify_directory_monitor_constructor (GType type, GInotifyDirectoryMonitor *inotify_monitor; const gchar *dirname = NULL; inotify_sub *sub = NULL; - gboolean ret_ih_startup; /* return value of _ih_startup, for asserting */ + gboolean ret_ih_startup; /* return value of _ih_startup, for asserting */ + gboolean pair_moves; klass = G_INOTIFY_DIRECTORY_MONITOR_CLASS (g_type_class_peek (G_TYPE_INOTIFY_DIRECTORY_MONITOR)); parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass)); @@ -95,7 +96,9 @@ g_inotify_directory_monitor_constructor (GType type, ret_ih_startup = _ih_startup(); g_assert (ret_ih_startup); - sub = _ih_sub_new (dirname, NULL, inotify_monitor); + pair_moves = G_LOCAL_DIRECTORY_MONITOR (obj)->flags & G_FILE_MONITOR_SEND_MOVED; + + sub = _ih_sub_new (dirname, NULL, pair_moves, inotify_monitor); /* FIXME: what to do about errors here? we can't return NULL or another * kind of error and an assertion is probably too hard */ g_assert (sub != NULL); diff --git a/gio/inotify/ginotifyfilemonitor.c b/gio/inotify/ginotifyfilemonitor.c index 8e572ca..f87f079 100644 --- a/gio/inotify/ginotifyfilemonitor.c +++ b/gio/inotify/ginotifyfilemonitor.c @@ -39,6 +39,7 @@ struct _GInotifyFileMonitor gchar *filename; gchar *dirname; inotify_sub *sub; + gboolean pair_moves; }; static gboolean g_inotify_file_monitor_cancel (GFileMonitor* monitor); @@ -90,6 +91,7 @@ g_inotify_file_monitor_constructor (GType type, GInotifyFileMonitor *inotify_monitor; const gchar *filename = NULL; inotify_sub *sub = NULL; + gboolean pair_moves; gboolean ret_ih_startup; /* return value of _ih_startup, for asserting */ klass = G_INOTIFY_FILE_MONITOR_CLASS (g_type_class_peek (G_TYPE_INOTIFY_FILE_MONITOR)); @@ -113,7 +115,12 @@ g_inotify_file_monitor_constructor (GType type, ret_ih_startup = _ih_startup(); g_assert (ret_ih_startup); - sub = _ih_sub_new (inotify_monitor->dirname, inotify_monitor->filename, inotify_monitor); + pair_moves = G_LOCAL_FILE_MONITOR (obj)->flags & G_FILE_MONITOR_SEND_MOVED; + + sub = _ih_sub_new (inotify_monitor->dirname, + inotify_monitor->filename, + pair_moves, + inotify_monitor); /* FIXME: what to do about errors here? we can't return NULL or another * kind of error and an assertion is probably too hard */ diff --git a/gio/inotify/inotify-helper.c b/gio/inotify/inotify-helper.c index 14c60b7..5572f0d 100644 --- a/gio/inotify/inotify-helper.c +++ b/gio/inotify/inotify-helper.c @@ -138,6 +138,32 @@ _ih_sub_cancel (inotify_sub *sub) return TRUE; } +static char * +_ih_fullpath_from_event (ik_event_t *event, char *dirname) +{ + char *fullpath; + + if (event->name) + fullpath = g_strdup_printf ("%s/%s", dirname, event->name); + else + fullpath = g_strdup_printf ("%s/", dirname); + + return fullpath; +} + + +static gboolean +ih_event_is_paired_move (ik_event_t *event) +{ + if (event->pair) + { + ik_event_t *paired = event->pair; + /* intofiy(7): IN_MOVE == IN_MOVED_FROM | IN_MOVED_TO */ + return (event->mask | paired->mask) & IN_MOVE; + } + + return FALSE; +} static void ih_event_callback (ik_event_t *event, @@ -147,22 +173,33 @@ ih_event_callback (ik_event_t *event, GFileMonitorEvent eflags; GFile* parent; GFile* child; + GFile* other; eflags = ih_mask_to_EventFlags (event->mask); parent = g_file_new_for_path (sub->dirname); - if (event->name) - fullpath = g_strdup_printf ("%s/%s", sub->dirname, event->name); - else - fullpath = g_strdup_printf ("%s/", sub->dirname); - + fullpath = _ih_fullpath_from_event (event, sub->dirname); child = g_file_new_for_path (fullpath); g_free (fullpath); + if (ih_event_is_paired_move (event) && sub->pair_moves) + { + char *parent_dir = _ip_get_path_for_wd (event->pair->wd); + fullpath = _ih_fullpath_from_event (event->pair, parent_dir); + other = g_file_new_for_path (fullpath); + g_free (fullpath); + eflags = G_FILE_MONITOR_EVENT_MOVED; + event->pair = NULL; /* prevents the paired event to be emitted as well */ + } + else + other = NULL; + g_file_monitor_emit_event (G_FILE_MONITOR (sub->user_data), - child, NULL, eflags); + child, other, eflags); g_object_unref (child); g_object_unref (parent); + if (other) + g_object_unref (other); } static void diff --git a/gio/inotify/inotify-kernel.c b/gio/inotify/inotify-kernel.c index 6e559a7..d6385f9 100644 --- a/gio/inotify/inotify-kernel.c +++ b/gio/inotify/inotify-kernel.c @@ -32,9 +32,9 @@ #include /* Timings for pairing MOVED_TO / MOVED_FROM events */ -#define PROCESS_EVENTS_TIME 1000 /* milliseconds (1 hz) */ +#define PROCESS_EVENTS_TIME 1000 /* 1 millisecond (1 hz) */ #define DEFAULT_HOLD_UNTIL_TIME 0 /* 0 millisecond */ -#define MOVE_HOLD_UNTIL_TIME 0 /* 0 milliseconds */ +#define MOVE_HOLD_UNTIL_TIME 500 /* 500 microseconds or 0.5 milliseconds */ static int inotify_instance_fd = -1; static GQueue *events_to_process = NULL; diff --git a/gio/inotify/inotify-path.c b/gio/inotify/inotify-path.c index 3327598..9ff20c8 100644 --- a/gio/inotify/inotify-path.c +++ b/gio/inotify/inotify-path.c @@ -420,3 +420,21 @@ ip_event_callback (ik_event_t *event) _ik_event_free (event); } + +const char * +_ip_get_path_for_wd (gint32 wd) +{ + GList *dir_list; + ip_watched_dir_t *dir; + + g_assert (wd >= 0); + dir_list = g_hash_table_lookup (wd_dir_hash, GINT_TO_POINTER (wd)); + if (dir_list) + { + dir = dir_list->data; + if (dir) + return dir->path; + } + + return NULL; +} diff --git a/gio/inotify/inotify-path.h b/gio/inotify/inotify-path.h index c613b9f..327dc70 100644 --- a/gio/inotify/inotify-path.h +++ b/gio/inotify/inotify-path.h @@ -26,8 +26,8 @@ #include "inotify-kernel.h" #include "inotify-sub.h" -gboolean _ip_startup (void (*event_cb)(ik_event_t *event, inotify_sub *sub)); -gboolean _ip_start_watching (inotify_sub *sub); -gboolean _ip_stop_watching (inotify_sub *sub); - +gboolean _ip_startup (void (*event_cb)(ik_event_t *event, inotify_sub *sub)); +gboolean _ip_start_watching (inotify_sub *sub); +gboolean _ip_stop_watching (inotify_sub *sub); +const char * _ip_get_path_for_wd (gint32 wd); #endif diff --git a/gio/inotify/inotify-sub.c b/gio/inotify/inotify-sub.c index 2b71c93..fa2e934 100644 --- a/gio/inotify/inotify-sub.c +++ b/gio/inotify/inotify-sub.c @@ -46,7 +46,8 @@ dup_dirname (const gchar *dirname) inotify_sub* _ih_sub_new (const gchar *dirname, - const gchar *filename, + const gchar *filename, + gboolean pair_moves, gpointer user_data) { inotify_sub *sub = NULL; @@ -54,8 +55,9 @@ _ih_sub_new (const gchar *dirname, sub = g_new0 (inotify_sub, 1); sub->dirname = dup_dirname (dirname); sub->filename = g_strdup (filename); + sub->pair_moves = pair_moves; sub->user_data = user_data; - + IS_W ("new subscription for %s being setup\n", sub->dirname); return sub; diff --git a/gio/inotify/inotify-sub.h b/gio/inotify/inotify-sub.h index 36561e7..7c9b087 100644 --- a/gio/inotify/inotify-sub.h +++ b/gio/inotify/inotify-sub.h @@ -30,9 +30,10 @@ typedef struct gchar* filename; gboolean cancelled; gpointer user_data; + gboolean pair_moves; } inotify_sub; -inotify_sub* _ih_sub_new (const gchar* dirname, const gchar* filename, gpointer user_data); +inotify_sub* _ih_sub_new (const gchar* dirname, const gchar* filename, gboolean pair_moves, gpointer user_data); void _ih_sub_free (inotify_sub* sub); #endif /* __INOTIFY_SUB_H */ -- 2.7.4