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
This commit is contained in:
Ryan Lortie 2015-01-17 11:11:22 -05:00
parent 21ab660cf8
commit d682df186e
8 changed files with 171 additions and 719 deletions

View File

@ -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\" \

View File

@ -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 <http://www.gnu.org/licenses/>.
*
* Authors: Alexander Larsson <alexl@redhat.com>
* John McCutchan <john@johnmccutchan.com>
* Sebastian Dröge <slomo@circular-chaos.org>
*/
#include "config.h"
#include <fam.h>
#include <gio/gfilemonitor.h>
#include <gio/gfile.h>
#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);
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*
* Authors: Alexander Larsson <alexl@redhat.com>
* John McCutchan <john@johnmccutchan.com>
* Sebastian Dröge <slomo@circular-chaos.org>
*/
#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__ */

View File

@ -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 <http://www.gnu.org/licenses/>.
*
* Authors: Alexander Larsson <alexl@redhat.com>
* John McCutchan <john@johnmccutchan.com>
* Sebastian Dröge <slomo@circular-chaos.org>
*/
#include <gio/giomodule.h>
#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);
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*
* Authors: Alexander Larsson <alexl@redhat.com>
* John McCutchan <john@johnmccutchan.com>
* Sebastian Dröge <slomo@circular-chaos.org>
*/
#include "config.h"
#include "gfamdirectorymonitor.h"
#include <gio/giomodule.h>
#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);
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*
* Authors: Alexander Larsson <alexl@redhat.com>
* John McCutchan <john@johnmccutchan.com>
* Sebastian Dröge <slomo@circular-chaos.org>
*/
#ifndef __G_FAM_DIRECTORY_MONITOR_H__
#define __G_FAM_DIRECTORY_MONITOR_H__
#include <glib-object.h>
#include <string.h>
#include <gio/glocaldirectorymonitor.h>
#include <gio/giomodule.h>
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__ */

View File

@ -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 <http://www.gnu.org/licenses/>.
*
* Authors: Alexander Larsson <alexl@redhat.com>
* John McCutchan <john@johnmccutchan.com>
* Sebastian Dröge <slomo@circular-chaos.org>
* Author: Ryan Lortie <desrt@desrt.ca>
*/
#include "config.h"
#include "gfamfilemonitor.h"
#include <gio/glocalfilemonitor.h>
#include <gio/giomodule.h>
#include "glib-private.h"
#include <glib-unix.h>
#include <fam.h>
#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);
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*
* Authors: Alexander Larsson <alexl@redhat.com>
* John McCutchan <john@johnmccutchan.com>
* Sebastian Dröge <slomo@circular-chaos.org>
*/
#ifndef __G_FAM_FILE_MONITOR_H__
#define __G_FAM_FILE_MONITOR_H__
#include <glib-object.h>
#include <string.h>
#include <gio/gfilemonitor.h>
#include <gio/glocalfilemonitor.h>
#include <gio/giomodule.h>
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__ */