From d682df186e9cca2b8db0e921450a4db31cf0c467 Mon Sep 17 00:00:00 2001 From: Ryan Lortie Date: Sat, 17 Jan 2015 11:11:22 -0500 Subject: [PATCH] file monitors: rewrite FAM file monitor Completely rewrite the FAM file monitor. Major changes: - now runs in the worker thread - dispatches events in a threadsafe way via GFileMonitorSource - uses unix fd source instead of a GIOChannel - is now simple enough to fit into one short file --- gio/fam/Makefile.am | 10 +- gio/fam/fam-helper.c | 274 --------------------------------- gio/fam/fam-helper.h | 36 ----- gio/fam/fam-module.c | 54 ------- gio/fam/gfamdirectorymonitor.c | 155 ------------------- gio/fam/gfamdirectorymonitor.h | 52 ------- gio/fam/gfamfilemonitor.c | 256 +++++++++++++++++++----------- gio/fam/gfamfilemonitor.h | 53 ------- 8 files changed, 171 insertions(+), 719 deletions(-) delete mode 100644 gio/fam/fam-helper.c delete mode 100644 gio/fam/fam-helper.h delete mode 100644 gio/fam/fam-module.c delete mode 100644 gio/fam/gfamdirectorymonitor.c delete mode 100644 gio/fam/gfamdirectorymonitor.h delete mode 100644 gio/fam/gfamfilemonitor.h diff --git a/gio/fam/Makefile.am b/gio/fam/Makefile.am index 67e0d6766..d064943a3 100644 --- a/gio/fam/Makefile.am +++ b/gio/fam/Makefile.am @@ -5,15 +5,7 @@ module_flags = -export_dynamic -avoid-version -module -no-undefined -export-symb giomodule_LTLIBRARIES = libgiofam.la giomoduledir = $(GIO_MODULE_DIR) -libgiofam_la_SOURCES = \ - fam-helper.c \ - fam-helper.h \ - fam-module.c \ - gfamdirectorymonitor.c \ - gfamdirectorymonitor.h \ - gfamfilemonitor.c \ - gfamfilemonitor.h \ - $(NULL) +libgiofam_la_SOURCES = gfamfilemonitor.c libgiofam_la_CFLAGS = \ -DG_LOG_DOMAIN=\"GLib-GIO\" \ diff --git a/gio/fam/fam-helper.c b/gio/fam/fam-helper.c deleted file mode 100644 index c02d392d9..000000000 --- a/gio/fam/fam-helper.c +++ /dev/null @@ -1,274 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2007 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, see . - * - * Authors: Alexander Larsson - * John McCutchan - * Sebastian Dröge - */ - -#include "config.h" -#include -#include -#include - -#include "fam-helper.h" - -static FAMConnection* fam_connection = NULL; -static gint fam_watch_id = 0; -G_LOCK_DEFINE_STATIC(fam_connection); - -struct _fam_sub -{ - gchar *pathname; - gboolean directory; - gpointer user_data; - gboolean cancelled; - FAMRequest request; -}; - -/* This uses int as the argument type because the - real type differs between implementations: - gamin has "typedef enum FAMCodes {....} FAMCodes;" - fam has "enum FAMCodes { ... }". -*/ -static GFileMonitorEvent -fam_event_to_file_monitor_event (int code) -{ - switch (code) - { - case FAMChanged: - return G_FILE_MONITOR_EVENT_CHANGED; - break; - case FAMDeleted: - return G_FILE_MONITOR_EVENT_DELETED; - break; - case FAMCreated: - return G_FILE_MONITOR_EVENT_CREATED; - break; - default: - return -1; - break; - } -} - -static gboolean -fam_do_iter_unlocked (void) -{ - while (fam_connection != NULL && FAMPending (fam_connection)) - { - FAMEvent ev; - fam_sub* sub = NULL; - gboolean cancelled; - - if (FAMNextEvent (fam_connection, &ev) != 1) - { - FAMClose (fam_connection); - g_free (fam_connection); - g_source_remove (fam_watch_id); - fam_watch_id = 0; - fam_connection = NULL; - return FALSE; - } - - sub = (fam_sub*)ev.userdata; - cancelled = sub->cancelled; - if (ev.code == FAMAcknowledge && cancelled) - { - _fam_sub_free (sub); - continue; - } - - if (cancelled) - continue; - - if (sub->directory) - { - GFileMonitor* monitor = G_FILE_MONITOR (sub->user_data); - GFileMonitorEvent eflags = fam_event_to_file_monitor_event (ev.code); - gchar* path = NULL; - GFile *child, *parent; - - /* unsupported event */ - if (eflags == -1) - continue; - - if (ev.filename[0] == '/') - path = g_strdup (ev.filename); - else - path = g_strdup_printf ("%s/%s", sub->pathname, ev.filename); - - child = g_file_new_for_path (path); - parent = g_file_get_parent (child); - g_file_monitor_emit_event (monitor, child, NULL, eflags); - g_free (path); - g_object_unref (child); - g_object_unref (parent); - } - else - { - GFile *child; - GFileMonitor* monitor = G_FILE_MONITOR (sub->user_data); - GFileMonitorEvent eflags = fam_event_to_file_monitor_event (ev.code); - gchar* path = NULL; - - if (eflags == -1) - continue; - path = g_strdup (ev.filename); - child = g_file_new_for_path (path); - g_file_monitor_emit_event (monitor, child, NULL, eflags); - g_free (path); - g_object_unref (child); - } - } - - return TRUE; -} - -static gboolean -fam_callback (GIOChannel *source, - GIOCondition condition, - gpointer data) -{ - gboolean res; - G_LOCK (fam_connection); - - res = fam_do_iter_unlocked (); - - G_UNLOCK (fam_connection); - return res; -} - -gboolean -_fam_sub_startup (void) -{ - GIOChannel *ioc; - - G_LOCK (fam_connection); - - if (fam_connection == NULL) - { - fam_connection = g_new0 (FAMConnection, 1); - if (FAMOpen2 (fam_connection, "gvfs user") != 0) - { - g_warning ("FAMOpen failed, FAMErrno=%d\n", FAMErrno); - g_free (fam_connection); - fam_connection = NULL; - G_UNLOCK (fam_connection); - return FALSE; - } -#ifdef HAVE_FAM_NO_EXISTS - /* This is a gamin extension that avoids sending all the Exists event for dir monitors */ - FAMNoExists (fam_connection); -#endif - ioc = g_io_channel_unix_new (FAMCONNECTION_GETFD(fam_connection)); - fam_watch_id = g_io_add_watch (ioc, - G_IO_IN | G_IO_HUP | G_IO_ERR, - fam_callback, fam_connection); - g_io_channel_unref (ioc); - } - - G_UNLOCK (fam_connection); - - return TRUE; -} - -void -_fam_sub_shutdown (void) -{ - G_LOCK (fam_connection); - - if (fam_connection != NULL) - { - FAMClose (fam_connection); - g_free (fam_connection); - g_source_remove (fam_watch_id); - fam_watch_id = 0; - fam_connection = NULL; - } - - G_UNLOCK (fam_connection); -} - -fam_sub* -_fam_sub_add (const gchar *pathname, - gboolean directory, - gpointer user_data) -{ - fam_sub *sub; - - if (!_fam_sub_startup ()) - return NULL; - - G_LOCK (fam_connection); - /* We need to queue up incoming messages to avoid blocking on write - * if there are many monitors being canceled */ - fam_do_iter_unlocked (); - - if (fam_connection == NULL) - { - G_UNLOCK (fam_connection); - return NULL; - } - - sub = g_new0 (fam_sub, 1); - sub->pathname = g_strdup (pathname); - sub->directory = directory; - sub->user_data = user_data; - - if (directory) - FAMMonitorDirectory (fam_connection, pathname, &sub->request, sub); - else - FAMMonitorFile (fam_connection, pathname, &sub->request, sub); - - G_UNLOCK (fam_connection); - - return sub; -} - -gboolean -_fam_sub_cancel (fam_sub* sub) -{ - if (sub->cancelled) - return TRUE; - - sub->cancelled = TRUE; - - G_LOCK (fam_connection); - /* We need to queue up incoming messages to avoid blocking on write - * if there are many monitors being canceled */ - fam_do_iter_unlocked (); - - if (fam_connection == NULL) - { - G_UNLOCK (fam_connection); - return FALSE; - } - - FAMCancelMonitor (fam_connection, &sub->request); - - G_UNLOCK (fam_connection); - - return TRUE; -} - -void -_fam_sub_free (fam_sub* sub) -{ - g_free (sub->pathname); - g_free (sub); -} - diff --git a/gio/fam/fam-helper.h b/gio/fam/fam-helper.h deleted file mode 100644 index 030e31576..000000000 --- a/gio/fam/fam-helper.h +++ /dev/null @@ -1,36 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2007 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, see . - * - * Authors: Alexander Larsson - * John McCutchan - * Sebastian Dröge - */ - -#ifndef __FAM_HELPER_H__ -#define __FAM_HELPER_H__ - -typedef struct _fam_sub fam_sub; - -gboolean _fam_sub_startup (void); -void _fam_sub_shutdown (void); -fam_sub* _fam_sub_add (const gchar* pathname, - gboolean directory, - gpointer user_data); -gboolean _fam_sub_cancel (fam_sub* sub); -void _fam_sub_free (fam_sub* sub); - -#endif /* __FAM_HELPER_H__ */ diff --git a/gio/fam/fam-module.c b/gio/fam/fam-module.c deleted file mode 100644 index 71c62bd74..000000000 --- a/gio/fam/fam-module.c +++ /dev/null @@ -1,54 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2007 Red Hat, Inc. - * Copyright (C) 2007 Sebastian Dröge. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, see . - * - * Authors: Alexander Larsson - * John McCutchan - * Sebastian Dröge - */ - -#include -#include "gfamdirectorymonitor.h" -#include "gfamfilemonitor.h" -#include "fam-helper.h" - -void -g_io_module_load (GIOModule *module) -{ - g_fam_file_monitor_register (module); - g_fam_directory_monitor_register (module); -} - -void -g_io_module_unload (GIOModule *module) -{ - _fam_sub_shutdown (); -} - -char ** -g_io_module_query (void) -{ - char *eps[] = { - G_LOCAL_DIRECTORY_MONITOR_EXTENSION_POINT_NAME, - G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME, - G_NFS_DIRECTORY_MONITOR_EXTENSION_POINT_NAME, - G_NFS_FILE_MONITOR_EXTENSION_POINT_NAME, - NULL - }; - return g_strdupv (eps); -} - diff --git a/gio/fam/gfamdirectorymonitor.c b/gio/fam/gfamdirectorymonitor.c deleted file mode 100644 index 627d232b6..000000000 --- a/gio/fam/gfamdirectorymonitor.c +++ /dev/null @@ -1,155 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2007 Red Hat, Inc. - * Copyright (C) 2007 Sebastian Dröge. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, see . - * - * Authors: Alexander Larsson - * John McCutchan - * Sebastian Dröge - */ - -#include "config.h" - -#include "gfamdirectorymonitor.h" -#include - -#include "fam-helper.h" - -struct _GFamDirectoryMonitor -{ - GLocalDirectoryMonitor parent_instance; - fam_sub *sub; -}; - -static gboolean g_fam_directory_monitor_cancel (GFileMonitor* monitor); - -G_DEFINE_DYNAMIC_TYPE (GFamDirectoryMonitor, g_fam_directory_monitor, G_TYPE_LOCAL_DIRECTORY_MONITOR) - -static void -g_fam_directory_monitor_finalize (GObject *object) -{ - GFamDirectoryMonitor *fam_monitor = G_FAM_DIRECTORY_MONITOR (object); - fam_sub *sub = fam_monitor->sub; - - if (sub) { - if (!_fam_sub_cancel (sub)) - g_warning ("Unexpected error cancelling fam monitor"); - - fam_monitor->sub = NULL; - } - - if (G_OBJECT_CLASS (g_fam_directory_monitor_parent_class)->finalize) - (*G_OBJECT_CLASS (g_fam_directory_monitor_parent_class)->finalize) (object); -} - -static GObject * -g_fam_directory_monitor_constructor (GType type, - guint n_construct_properties, - GObjectConstructParam *construct_properties) -{ - GObject *obj; - GFamDirectoryMonitorClass *klass; - GObjectClass *parent_class; - GFamDirectoryMonitor *fam_monitor; - const gchar *dirname = NULL; - fam_sub *sub = NULL; - - klass = G_FAM_DIRECTORY_MONITOR_CLASS (g_type_class_peek (G_TYPE_FAM_DIRECTORY_MONITOR)); - parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass)); - obj = parent_class->constructor (type, - n_construct_properties, - construct_properties); - - fam_monitor = G_FAM_DIRECTORY_MONITOR (obj); - - dirname = G_LOCAL_DIRECTORY_MONITOR (obj)->dirname; - g_assert (dirname != NULL); - - sub = _fam_sub_add (dirname, TRUE, fam_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); - - fam_monitor->sub = sub; - - return obj; -} - -static void -g_fam_directory_monitor_class_finalize (GFamDirectoryMonitorClass *klass) -{ -} - -static gboolean -g_fam_directory_monitor_is_supported (void) -{ - return _fam_sub_startup (); -} - -static void -g_fam_directory_monitor_class_init (GFamDirectoryMonitorClass* klass) -{ - GObjectClass* gobject_class = G_OBJECT_CLASS (klass); - GFileMonitorClass *file_monitor_class = G_FILE_MONITOR_CLASS (klass); - GLocalDirectoryMonitorClass *local_directory_monitor_class = G_LOCAL_DIRECTORY_MONITOR_CLASS (klass); - - gobject_class->finalize = g_fam_directory_monitor_finalize; - gobject_class->constructor = g_fam_directory_monitor_constructor; - file_monitor_class->cancel = g_fam_directory_monitor_cancel; - - local_directory_monitor_class->mount_notify = FALSE; - local_directory_monitor_class->is_supported = g_fam_directory_monitor_is_supported; -} - -static void -g_fam_directory_monitor_init (GFamDirectoryMonitor* monitor) -{ - -} - -static gboolean -g_fam_directory_monitor_cancel (GFileMonitor* monitor) -{ - GFamDirectoryMonitor *fam_monitor = G_FAM_DIRECTORY_MONITOR (monitor); - fam_sub *sub = fam_monitor->sub; - - if (sub) { - if (!_fam_sub_cancel (sub)) - g_warning ("Unexpected error cancelling fam monitor"); - - fam_monitor->sub = NULL; - } - - if (G_FILE_MONITOR_CLASS (g_fam_directory_monitor_parent_class)->cancel) - (*G_FILE_MONITOR_CLASS (g_fam_directory_monitor_parent_class)->cancel) (monitor); - - return TRUE; -} - -void -g_fam_directory_monitor_register (GIOModule *module) -{ - g_fam_directory_monitor_register_type (G_TYPE_MODULE (module)); - g_io_extension_point_implement (G_LOCAL_DIRECTORY_MONITOR_EXTENSION_POINT_NAME, - G_TYPE_FAM_DIRECTORY_MONITOR, - "fam", - 10); - g_io_extension_point_implement (G_NFS_DIRECTORY_MONITOR_EXTENSION_POINT_NAME, - G_TYPE_FAM_DIRECTORY_MONITOR, - "fam", - 10); -} - diff --git a/gio/fam/gfamdirectorymonitor.h b/gio/fam/gfamdirectorymonitor.h deleted file mode 100644 index 240412a85..000000000 --- a/gio/fam/gfamdirectorymonitor.h +++ /dev/null @@ -1,52 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2007 Red Hat, Inc. - * Copyright (C) 2007 Sebastian Dröge. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, see . - * - * Authors: Alexander Larsson - * John McCutchan - * Sebastian Dröge - */ - -#ifndef __G_FAM_DIRECTORY_MONITOR_H__ -#define __G_FAM_DIRECTORY_MONITOR_H__ - -#include -#include -#include -#include - -G_BEGIN_DECLS - -#define G_TYPE_FAM_DIRECTORY_MONITOR (g_fam_directory_monitor_get_type ()) -#define G_FAM_DIRECTORY_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_FAM_DIRECTORY_MONITOR, GFamDirectoryMonitor)) -#define G_FAM_DIRECTORY_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), G_TYPE_FAM_DIRECTORY_MONITOR, GFamDirectoryMonitorClass)) -#define G_IS_FAM_DIRECTORY_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_FAM_DIRECTORY_MONITOR)) -#define G_IS_FAM_DIRECTORY_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_FAM_DIRECTORY_MONITOR)) - -typedef struct _GFamDirectoryMonitor GFamDirectoryMonitor; -typedef struct _GFamDirectoryMonitorClass GFamDirectoryMonitorClass; - -struct _GFamDirectoryMonitorClass { - GLocalDirectoryMonitorClass parent_class; -}; - -GType g_fam_directory_monitor_get_type (void); -void g_fam_directory_monitor_register (GIOModule *module); - -G_END_DECLS - -#endif /* __G_FAM_DIRECTORY_MONITOR_H__ */ diff --git a/gio/fam/gfamfilemonitor.c b/gio/fam/gfamfilemonitor.c index acdbf228b..50474c8e5 100644 --- a/gio/fam/gfamfilemonitor.c +++ b/gio/fam/gfamfilemonitor.c @@ -1,7 +1,5 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2007 Red Hat, Inc. - * Copyright (C) 2007 Sebastian Dröge. +/* + * Copyright © 2015 Canonical Limited * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,138 +14,224 @@ * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, see . * - * Authors: Alexander Larsson - * John McCutchan - * Sebastian Dröge + * Author: Ryan Lortie */ #include "config.h" -#include "gfamfilemonitor.h" +#include #include +#include "glib-private.h" +#include +#include -#include "fam-helper.h" +static GMutex fam_lock; +static gboolean fam_initialised; +static FAMConnection fam_connection; +static GSource *fam_source; -struct _GFamFileMonitor +#define G_TYPE_FAM_FILE_MONITOR (g_fam_file_monitor_get_type ()) +#define G_FAM_FILE_MONITOR(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ + G_TYPE_FAM_FILE_MONITOR, GFamFileMonitor)) + +typedef GLocalFileMonitorClass GFamFileMonitorClass; + +typedef struct { GLocalFileMonitor parent_instance; - fam_sub *sub; -}; -static gboolean g_fam_file_monitor_cancel (GFileMonitor* monitor); + FAMRequest request; +} GFamFileMonitor; +static GType g_fam_file_monitor_get_type (void); G_DEFINE_DYNAMIC_TYPE (GFamFileMonitor, g_fam_file_monitor, G_TYPE_LOCAL_FILE_MONITOR) -static void -g_fam_file_monitor_finalize (GObject *object) +static gboolean +g_fam_file_monitor_callback (gint fd, + GIOCondition condition, + gpointer user_data) { - GFamFileMonitor *fam_monitor = G_FAM_FILE_MONITOR (object); - fam_sub *sub = fam_monitor->sub; + gint64 now = g_source_get_time (fam_source); - if (sub) { - if (!_fam_sub_cancel (sub)) - g_warning ("Unexpected error cancelling fam monitor"); - fam_monitor->sub = NULL; - } + g_mutex_lock (&fam_lock); - if (G_OBJECT_CLASS (g_fam_file_monitor_parent_class)->finalize) - (*G_OBJECT_CLASS (g_fam_file_monitor_parent_class)->finalize) (object); -} + while (FAMPending (&fam_connection)) + { + const gchar *child; + FAMEvent ev; -static GObject * -g_fam_file_monitor_constructor (GType type, - guint n_construct_properties, - GObjectConstructParam *construct_properties) -{ - GObject *obj; - GFamFileMonitorClass *klass; - GObjectClass *parent_class; - GFamFileMonitor *fam_monitor; - const gchar *filename = NULL; - fam_sub *sub = NULL; - - klass = G_FAM_FILE_MONITOR_CLASS (g_type_class_peek (G_TYPE_FAM_FILE_MONITOR)); - parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass)); - obj = parent_class->constructor (type, - n_construct_properties, - construct_properties); + if (FAMNextEvent (&fam_connection, &ev) != 1) + { + /* The daemon died. We're in a really bad situation now + * because we potentially have a bunch of request structures + * outstanding which no longer make any sense to anyone. + * + * The best thing that we can do is do nothing. Notification + * won't work anymore for this process. + */ + g_mutex_unlock (&fam_lock); - fam_monitor = G_FAM_FILE_MONITOR (obj); + g_warning ("Lost connection to FAM (file monitoring) service. Expect no further file monitor events."); - filename = G_LOCAL_FILE_MONITOR (obj)->filename; + return FALSE; + } - g_assert (filename != NULL); + /* We expect ev.filename to be a relative path for children in a + * monitored directory, and an absolute path for a monitored file + * or the directory itself. + */ + if (ev.filename[0] != '/') + child = ev.filename; + else + child = NULL; - sub = _fam_sub_add (filename, FALSE, fam_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); + switch (ev.code) + { + case FAMAcknowledge: + g_source_unref (ev.userdata); + break; - fam_monitor->sub = sub; + case FAMChanged: + g_file_monitor_source_handle_event (ev.userdata, G_FILE_MONITOR_EVENT_CHANGED, child, NULL, NULL, now); + break; - return obj; -} + case FAMDeleted: + g_file_monitor_source_handle_event (ev.userdata, G_FILE_MONITOR_EVENT_DELETED, child, NULL, NULL, now); + break; -static void -g_fam_file_monitor_class_finalize (GFamFileMonitorClass *klass) -{ + case FAMCreated: + g_file_monitor_source_handle_event (ev.userdata, G_FILE_MONITOR_EVENT_CREATED, child, NULL, NULL, now); + break; + + default: + /* unknown type */ + break; + } + } + + g_mutex_unlock (&fam_lock); + + return TRUE; } static gboolean g_fam_file_monitor_is_supported (void) { - return _fam_sub_startup (); + g_mutex_lock (&fam_lock); + + if (!fam_initialised) + { + fam_initialised = FAMOpen2 (&fam_connection, "GLib GIO") == 0; + + if (fam_initialised) + { +#ifdef HAVE_FAM_NO_EXISTS + /* This is a gamin extension that avoids sending all the + * Exists event for dir monitors + */ + FAMNoExists (&fam_connection); +#endif + + fam_source = g_unix_fd_source_new (FAMCONNECTION_GETFD (&fam_connection), G_IO_IN); + g_source_set_callback (fam_source, (GSourceFunc) g_fam_file_monitor_callback, NULL, NULL); + g_source_attach (fam_source, GLIB_PRIVATE_CALL(g_get_worker_context) ()); + } + } + + g_mutex_unlock (&fam_lock); + + g_print ("II %d\n", fam_initialised); + + return fam_initialised; +} + +static gboolean +g_fam_file_monitor_cancel (GFileMonitor *monitor) +{ + GFamFileMonitor *gffm = G_FAM_FILE_MONITOR (monitor); + + g_mutex_lock (&fam_lock); + + g_assert (fam_initialised); + + FAMCancelMonitor (&fam_connection, &gffm->request); + + g_mutex_unlock (&fam_lock); + + return TRUE; } static void -g_fam_file_monitor_class_init (GFamFileMonitorClass* klass) +g_fam_file_monitor_start (GLocalFileMonitor *local_monitor, + const gchar *dirname, + const gchar *basename, + const gchar *filename, + GFileMonitorSource *source) { - GObjectClass* gobject_class = G_OBJECT_CLASS (klass); - GFileMonitorClass *file_monitor_class = G_FILE_MONITOR_CLASS (klass); - GLocalFileMonitorClass *local_file_monitor_class = G_LOCAL_FILE_MONITOR_CLASS (klass); - - gobject_class->finalize = g_fam_file_monitor_finalize; - gobject_class->constructor = g_fam_file_monitor_constructor; - file_monitor_class->cancel = g_fam_file_monitor_cancel; + GFamFileMonitor *gffm = G_FAM_FILE_MONITOR (local_monitor); - local_file_monitor_class->is_supported = g_fam_file_monitor_is_supported; + g_mutex_lock (&fam_lock); + + g_assert (fam_initialised); + + g_source_ref ((GSource *) source); + + if (dirname) + FAMMonitorDirectory (&fam_connection, dirname, &gffm->request, source); + else + FAMMonitorFile (&fam_connection, filename, &gffm->request, source); + + g_mutex_unlock (&fam_lock); } static void g_fam_file_monitor_init (GFamFileMonitor* monitor) { - } -static gboolean -g_fam_file_monitor_cancel (GFileMonitor* monitor) +static void +g_fam_file_monitor_class_init (GFamFileMonitorClass *class) { - GFamFileMonitor *fam_monitor = G_FAM_FILE_MONITOR (monitor); - fam_sub *sub = fam_monitor->sub; + GFileMonitorClass *file_monitor_class = G_FILE_MONITOR_CLASS (class); - if (sub) { - if (!_fam_sub_cancel (sub)) - g_warning ("Unexpected error cancelling fam monitor"); - fam_monitor->sub = NULL; - } + class->is_supported = g_fam_file_monitor_is_supported; + class->start = g_fam_file_monitor_start; + file_monitor_class->cancel = g_fam_file_monitor_cancel; +} - if (G_FILE_MONITOR_CLASS (g_fam_file_monitor_parent_class)->cancel) - (*G_FILE_MONITOR_CLASS (g_fam_file_monitor_parent_class)->cancel) (monitor); - - return TRUE; +static void +g_fam_file_monitor_class_finalize (GFamFileMonitorClass *class) +{ } void -g_fam_file_monitor_register (GIOModule *module) +g_io_module_load (GIOModule *module) { + g_type_module_use (G_TYPE_MODULE (module)); + g_fam_file_monitor_register_type (G_TYPE_MODULE (module)); + g_io_extension_point_implement (G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME, - G_TYPE_FAM_FILE_MONITOR, - "fam", - 10); + G_TYPE_FAM_FILE_MONITOR, "fam", 10); + g_io_extension_point_implement (G_NFS_FILE_MONITOR_EXTENSION_POINT_NAME, - G_TYPE_FAM_FILE_MONITOR, - "fam", - 10); + G_TYPE_FAM_FILE_MONITOR, "fam", 10); } +void +g_io_module_unload (GIOModule *module) +{ + g_assert_not_reached (); +} + +char ** +g_io_module_query (void) +{ + char *eps[] = { + G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME, + G_NFS_FILE_MONITOR_EXTENSION_POINT_NAME, + NULL + }; + + return g_strdupv (eps); +} diff --git a/gio/fam/gfamfilemonitor.h b/gio/fam/gfamfilemonitor.h deleted file mode 100644 index 0d1fd63fd..000000000 --- a/gio/fam/gfamfilemonitor.h +++ /dev/null @@ -1,53 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2007 Red Hat, Inc. - * Copyright (C) 2007 Sebastian Dröge. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, see . - * - * Authors: Alexander Larsson - * John McCutchan - * Sebastian Dröge - */ - -#ifndef __G_FAM_FILE_MONITOR_H__ -#define __G_FAM_FILE_MONITOR_H__ - -#include -#include -#include -#include -#include - -G_BEGIN_DECLS - -#define G_TYPE_FAM_FILE_MONITOR (g_fam_file_monitor_get_type ()) -#define G_FAM_FILE_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_FAM_FILE_MONITOR, GFamFileMonitor)) -#define G_FAM_FILE_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), G_TYPE_FAM_FILE_MONITOR, GFamFileMonitorClass)) -#define G_IS_FAM_FILE_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_FAM_FILE_MONITOR)) -#define G_IS_FAM_FILE_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_FAM_FILE_MONITOR)) - -typedef struct _GFamFileMonitor GFamFileMonitor; -typedef struct _GFamFileMonitorClass GFamFileMonitorClass; - -struct _GFamFileMonitorClass { - GLocalFileMonitorClass parent_class; -}; - -GType g_fam_file_monitor_get_type (void); -void g_fam_file_monitor_register (GIOModule *module); - -G_END_DECLS - -#endif /* __G_FAM_FILE_MONITOR_H__ */