mirror of
				https://gitlab.gnome.org/GNOME/glib.git
				synced 2025-10-31 00:12:19 +01:00 
			
		
		
		
	Build test subdir after . Remove gdirectorymonitor.[ch]
2008-01-07 Alexander Larsson <alexl@redhat.com> * Makefile.am: Build test subdir after . Remove gdirectorymonitor.[ch] * gdirectorymonitor.[ch]: * gfilemonitor.c: * gfile.[ch]: * gio.h: Remove GDirectoryMonitor and make GFileMonitor the baseclass for both file and directory monitors. Lift the more generic rate limiting code from GDirectoryMonitor into GFileMonitor. * fam/fam-helper.c: * fam/gfamdirectorymonitor.[ch]: * inotify/ginotifydirectorymonitor.[ch]: * inotify/inotify-helper.c: * glocaldirectorymonitor.[ch]: * glocalfile.c: * gvolumemonitor.c: Update for the removed GDirectoryMonitor. * gmemoryoutputstream.c: Remove ununsed variable svn path=/trunk/; revision=6262
This commit is contained in:
		
				
					committed by
					
						 Alexander Larsson
						Alexander Larsson
					
				
			
			
				
	
			
			
			
						parent
						
							052c660452
						
					
				
				
					commit
					e23140cbb4
				
			| @@ -1,3 +1,31 @@ | ||||
| 2008-01-07  Alexander Larsson  <alexl@redhat.com> | ||||
|  | ||||
|         * Makefile.am: | ||||
| 	Build test subdir after . | ||||
| 	Remove gdirectorymonitor.[ch] | ||||
| 	 | ||||
|         * gdirectorymonitor.[ch]: | ||||
|         * gfilemonitor.c: | ||||
|         * gfile.[ch]: | ||||
|         * gio.h: | ||||
| 	Remove GDirectoryMonitor and make | ||||
| 	GFileMonitor the baseclass for both file and | ||||
| 	directory monitors. Lift the more generic | ||||
| 	rate limiting code from GDirectoryMonitor | ||||
| 	into GFileMonitor. | ||||
| 	 | ||||
|         * fam/fam-helper.c: | ||||
|         * fam/gfamdirectorymonitor.[ch]: | ||||
|         * inotify/ginotifydirectorymonitor.[ch]: | ||||
|         * inotify/inotify-helper.c: | ||||
|         * glocaldirectorymonitor.[ch]: | ||||
|         * glocalfile.c: | ||||
|         * gvolumemonitor.c: | ||||
| 	Update for the removed GDirectoryMonitor. | ||||
| 	 | ||||
|         * gmemoryoutputstream.c: | ||||
| 	Remove ununsed variable | ||||
|  | ||||
| 2008-01-07  Alexander Larsson  <alexl@redhat.com> | ||||
|  | ||||
|         * gmemoryinputstream.c: | ||||
|   | ||||
| @@ -2,7 +2,7 @@ include $(top_srcdir)/Makefile.decl | ||||
|  | ||||
| NULL = | ||||
|  | ||||
| SUBDIRS=tests | ||||
| SUBDIRS= | ||||
|  | ||||
| if OS_UNIX | ||||
| SUBDIRS += xdgmime | ||||
| @@ -123,6 +123,8 @@ appinfo_sources += gwin32appinfo.c gwin32appinfo.h | ||||
| platform_libadd += -lshlwapi | ||||
| endif | ||||
|  | ||||
| SUBDIRS += tests | ||||
|  | ||||
| libgio_2_0_la_SOURCES =		\ | ||||
| 	gappinfo.c 		\ | ||||
| 	gasynchelper.c 		\ | ||||
| @@ -135,7 +137,6 @@ libgio_2_0_la_SOURCES =		\ | ||||
| 	gcontenttypeprivate.h 	\ | ||||
| 	gdatainputstream.c 	\ | ||||
| 	gdataoutputstream.c 	\ | ||||
| 	gdirectorymonitor.c 	\ | ||||
| 	gdrive.c 		\ | ||||
| 	gdummyfile.h 		\ | ||||
| 	gdummyfile.c 		\ | ||||
| @@ -213,7 +214,6 @@ gio_headers =			\ | ||||
| 	gcontenttype.h 		\ | ||||
| 	gdatainputstream.h 	\ | ||||
| 	gdataoutputstream.h 	\ | ||||
| 	gdirectorymonitor.h 	\ | ||||
| 	gdrive.h 		\ | ||||
| 	gfile.h 		\ | ||||
| 	gfileattribute.h 	\ | ||||
|   | ||||
| @@ -25,7 +25,6 @@ | ||||
| #include "config.h" | ||||
| #include <fam.h> | ||||
| #include <gio/gfilemonitor.h> | ||||
| #include <gio/gdirectorymonitor.h> | ||||
|  | ||||
| #include "fam-helper.h" | ||||
|  | ||||
| @@ -92,7 +91,7 @@ fam_do_iter_unlocked (void) | ||||
|      | ||||
|     if (sub->directory) | ||||
|       { | ||||
| 	GDirectoryMonitor* monitor = G_DIRECTORY_MONITOR (sub->user_data); | ||||
| 	GFileMonitor* monitor = G_FILE_MONITOR (sub->user_data); | ||||
| 	GFileMonitorEvent eflags = fam_event_to_file_monitor_event (ev.code); | ||||
| 	gchar* path = NULL; | ||||
| 	GFile *child, *parent; | ||||
| @@ -108,7 +107,7 @@ fam_do_iter_unlocked (void) | ||||
|  | ||||
| 	child = g_file_new_for_path (path); | ||||
| 	parent = g_file_get_parent (child); | ||||
| 	g_directory_monitor_emit_event (monitor, child, NULL, eflags); | ||||
| 	g_file_monitor_emit_event (monitor, child, NULL, eflags); | ||||
| 	g_free (path); | ||||
| 	g_object_unref (child); | ||||
| 	g_object_unref (parent); | ||||
|   | ||||
| @@ -36,7 +36,7 @@ struct _GFamDirectoryMonitor | ||||
|   fam_sub *sub; | ||||
| }; | ||||
|  | ||||
| static gboolean g_fam_directory_monitor_cancel (GDirectoryMonitor* monitor); | ||||
| static gboolean g_fam_directory_monitor_cancel (GFileMonitor* monitor); | ||||
|  | ||||
| G_DEFINE_DYNAMIC_TYPE (GFamDirectoryMonitor, g_fam_directory_monitor, G_TYPE_LOCAL_DIRECTORY_MONITOR) | ||||
|  | ||||
| @@ -106,12 +106,12 @@ static void | ||||
| g_fam_directory_monitor_class_init (GFamDirectoryMonitorClass* klass) | ||||
| { | ||||
|   GObjectClass* gobject_class = G_OBJECT_CLASS (klass); | ||||
|   GDirectoryMonitorClass *directory_monitor_class = G_DIRECTORY_MONITOR_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; | ||||
|   directory_monitor_class->cancel = g_fam_directory_monitor_cancel; | ||||
|   file_monitor_class->cancel = g_fam_directory_monitor_cancel; | ||||
|  | ||||
|   local_directory_monitor_class->prio = 10; | ||||
|   local_directory_monitor_class->mount_notify = FALSE; | ||||
| @@ -125,7 +125,7 @@ g_fam_directory_monitor_init (GFamDirectoryMonitor* monitor) | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| g_fam_directory_monitor_cancel (GDirectoryMonitor* monitor) | ||||
| g_fam_directory_monitor_cancel (GFileMonitor* monitor) | ||||
| { | ||||
|   GFamDirectoryMonitor *fam_monitor = G_FAM_DIRECTORY_MONITOR (monitor); | ||||
|   fam_sub *sub = fam_monitor->sub; | ||||
| @@ -138,8 +138,8 @@ g_fam_directory_monitor_cancel (GDirectoryMonitor* monitor) | ||||
|     fam_monitor->sub = NULL; | ||||
|   } | ||||
|  | ||||
|   if (G_DIRECTORY_MONITOR_CLASS (g_fam_directory_monitor_parent_class)->cancel) | ||||
|     (*G_DIRECTORY_MONITOR_CLASS (g_fam_directory_monitor_parent_class)->cancel) (monitor); | ||||
|   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; | ||||
| } | ||||
|   | ||||
| @@ -28,7 +28,6 @@ | ||||
|  | ||||
| #include <glib-object.h> | ||||
| #include <string.h> | ||||
| #include <gio/gdirectorymonitor.h> | ||||
| #include "glocaldirectorymonitor.h" | ||||
| #include "giomodule.h" | ||||
|  | ||||
|   | ||||
| @@ -1,589 +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, write to the | ||||
|  * Free Software Foundation, Inc., 59 Temple Place, Suite 330, | ||||
|  * Boston, MA 02111-1307, USA. | ||||
|  * | ||||
|  * Author: Alexander Larsson <alexl@redhat.com> | ||||
|  */ | ||||
|  | ||||
| #include <config.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "gdirectorymonitor.h" | ||||
| #include "gio-marshal.h" | ||||
| #include "gfile.h" | ||||
| #include "gvfs.h" | ||||
| #include "glibintl.h" | ||||
|  | ||||
| #include "gioalias.h" | ||||
|  | ||||
| /** | ||||
|  * SECTION:gdirectorymonitor | ||||
|  * @short_description: Directory Monitor | ||||
|  * @include: gio.h | ||||
|  * @see_also: #GFileMonitor | ||||
|  *  | ||||
|  * Monitors a directory for changes to files in it. | ||||
|  * | ||||
|  **/ | ||||
|  | ||||
| enum { | ||||
|   CHANGED, | ||||
|   LAST_SIGNAL | ||||
| }; | ||||
|  | ||||
| G_DEFINE_ABSTRACT_TYPE (GDirectoryMonitor, g_directory_monitor, G_TYPE_OBJECT); | ||||
|  | ||||
| typedef struct { | ||||
|   GFile *file; | ||||
|   guint32 last_sent_change_time; /* 0 == not sent */ | ||||
|   guint32 send_delayed_change_at; /* 0 == never */ | ||||
|   guint32 send_virtual_changes_done_at; /* 0 == never */ | ||||
| } RateLimiter; | ||||
|  | ||||
| struct _GDirectoryMonitorPrivate { | ||||
|   gboolean cancelled; | ||||
|   int rate_limit_msec; | ||||
|  | ||||
|   GHashTable *rate_limiter; | ||||
|    | ||||
|   GSource *timeout; | ||||
|   guint32 timeout_fires_at; | ||||
| }; | ||||
|  | ||||
| enum { | ||||
|   PROP_0, | ||||
|   PROP_RATE_LIMIT, | ||||
|   PROP_CANCELLED | ||||
| }; | ||||
|  | ||||
| #define DEFAULT_RATE_LIMIT_MSECS 800 | ||||
| #define DEFAULT_VIRTUAL_CHANGES_DONE_DELAY_SECS 2 | ||||
|  | ||||
| static guint signals[LAST_SIGNAL] = { 0 }; | ||||
|  | ||||
| static void | ||||
| rate_limiter_free (RateLimiter *limiter) | ||||
| { | ||||
|   g_object_unref (limiter->file); | ||||
|   g_free (limiter); | ||||
| } | ||||
|  | ||||
| static void | ||||
| g_directory_monitor_set_property (GObject      *object, | ||||
|                                   guint         prop_id, | ||||
|                                   const GValue *value, | ||||
|                                   GParamSpec   *pspec) | ||||
| { | ||||
|   GDirectoryMonitor *monitor; | ||||
|  | ||||
|   monitor = G_DIRECTORY_MONITOR (object); | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_RATE_LIMIT: | ||||
|       g_directory_monitor_set_rate_limit (monitor, g_value_get_int (value)); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| g_directory_monitor_get_property (GObject    *object, | ||||
|                                   guint       prop_id, | ||||
|                                   GValue     *value, | ||||
|                                   GParamSpec *pspec) | ||||
| { | ||||
|   GDirectoryMonitor *monitor; | ||||
|   GDirectoryMonitorPrivate *priv; | ||||
|  | ||||
|   monitor = G_DIRECTORY_MONITOR (object); | ||||
|   priv = monitor->priv; | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_RATE_LIMIT: | ||||
|       g_value_set_int (value, priv->rate_limit_msec); | ||||
|       break; | ||||
|  | ||||
|     case PROP_CANCELLED: | ||||
|       g_value_set_boolean (value, priv->cancelled); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| g_directory_monitor_finalize (GObject *object) | ||||
| { | ||||
|   GDirectoryMonitor *monitor; | ||||
|  | ||||
|   monitor = G_DIRECTORY_MONITOR (object); | ||||
|  | ||||
|   if (monitor->priv->timeout) | ||||
|     { | ||||
|       g_source_destroy (monitor->priv->timeout); | ||||
|       g_source_unref (monitor->priv->timeout); | ||||
|     } | ||||
|  | ||||
|   g_hash_table_destroy (monitor->priv->rate_limiter); | ||||
|    | ||||
|   if (G_OBJECT_CLASS (g_directory_monitor_parent_class)->finalize) | ||||
|     (*G_OBJECT_CLASS (g_directory_monitor_parent_class)->finalize) (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| g_directory_monitor_dispose (GObject *object) | ||||
| { | ||||
|   GDirectoryMonitor *monitor; | ||||
|    | ||||
|   monitor = G_DIRECTORY_MONITOR (object); | ||||
|  | ||||
|   /* Make sure we cancel on last unref */ | ||||
|   if (!monitor->priv->cancelled) | ||||
|     g_directory_monitor_cancel (monitor); | ||||
|    | ||||
|   if (G_OBJECT_CLASS (g_directory_monitor_parent_class)->dispose) | ||||
|     (*G_OBJECT_CLASS (g_directory_monitor_parent_class)->dispose) (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| g_directory_monitor_class_init (GDirectoryMonitorClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class; | ||||
|    | ||||
|   g_type_class_add_private (klass, sizeof (GDirectoryMonitorPrivate)); | ||||
|    | ||||
|   object_class = G_OBJECT_CLASS (klass); | ||||
|   object_class->finalize = g_directory_monitor_finalize; | ||||
|   object_class->dispose = g_directory_monitor_dispose; | ||||
|   object_class->get_property = g_directory_monitor_get_property; | ||||
|   object_class->set_property = g_directory_monitor_set_property; | ||||
|  | ||||
|   /** | ||||
|    * GDirectoryMonitor::changed: | ||||
|    * @monitor: the #GDirectoryMonitor | ||||
|    * @child: the #GFile which changed | ||||
|    * @other_file: the other #GFile which changed | ||||
|    * @event_type: a #GFileMonitorEvent indicating what the event was | ||||
|    * | ||||
|    * Emitted when a child file changes. | ||||
|    */ | ||||
|   signals[CHANGED] = | ||||
|     g_signal_new (I_("changed"), | ||||
| 		  G_TYPE_DIRECTORY_MONITOR, | ||||
| 		  G_SIGNAL_RUN_LAST, | ||||
| 		  G_STRUCT_OFFSET (GDirectoryMonitorClass, changed), | ||||
| 		  NULL, NULL, | ||||
| 		  _gio_marshal_VOID__OBJECT_OBJECT_INT, | ||||
| 		  G_TYPE_NONE, 3, | ||||
| 		  G_TYPE_FILE, G_TYPE_FILE, G_TYPE_INT); | ||||
|  | ||||
|   g_object_class_install_property (object_class, | ||||
|                                    PROP_RATE_LIMIT, | ||||
|                                    g_param_spec_int ("rate-limit", | ||||
|                                                      P_("Rate limit"), | ||||
|                                                      P_("The limit of the monitor to watch for changes, in milliseconds"), | ||||
|                                                      0, G_MAXINT, | ||||
|                                                      DEFAULT_RATE_LIMIT_MSECS, | ||||
|                                                      G_PARAM_READWRITE| | ||||
|                                                      G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)); | ||||
|  | ||||
|   g_object_class_install_property (object_class, | ||||
|                                    PROP_CANCELLED, | ||||
|                                    g_param_spec_boolean ("cancelled", | ||||
|                                                          P_("Cancelled"), | ||||
|                                                          P_("Whether the monitor has been cancelled"), | ||||
|                                                          FALSE, | ||||
|                                                          G_PARAM_READABLE| | ||||
|                                                          G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)); | ||||
|  | ||||
| } | ||||
|  | ||||
| static void | ||||
| g_directory_monitor_init (GDirectoryMonitor *monitor) | ||||
| { | ||||
|   monitor->priv = G_TYPE_INSTANCE_GET_PRIVATE (monitor, | ||||
| 					       G_TYPE_DIRECTORY_MONITOR, | ||||
| 					       GDirectoryMonitorPrivate); | ||||
|  | ||||
|   monitor->priv->rate_limit_msec = DEFAULT_RATE_LIMIT_MSECS; | ||||
|   monitor->priv->rate_limiter = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, | ||||
| 						       NULL, (GDestroyNotify) rate_limiter_free); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * g_directory_monitor_cancel: | ||||
|  * @monitor: a #GDirectoryMonitor. | ||||
|  * | ||||
|  * Cancels the monitoring activity on @monitor. Note that | ||||
|  * the monitor is automatically cancelled when finalized. | ||||
|  * | ||||
|  * It is safe to call this multiple times. | ||||
|  *  | ||||
|  * Returns: %TRUE if the monitor was cancelled successfully. %FALSE otherwise. | ||||
|  **/ | ||||
| gboolean | ||||
| g_directory_monitor_cancel (GDirectoryMonitor *monitor) | ||||
| { | ||||
|   GDirectoryMonitorClass *class; | ||||
|  | ||||
|   g_return_val_if_fail (G_IS_DIRECTORY_MONITOR (monitor), FALSE); | ||||
|    | ||||
|   if (monitor->priv->cancelled) | ||||
|     return TRUE; | ||||
|    | ||||
|   monitor->priv->cancelled = TRUE; | ||||
|   g_object_notify (G_OBJECT (monitor), "cancelled"); | ||||
|    | ||||
|   class = G_DIRECTORY_MONITOR_GET_CLASS (monitor); | ||||
|   return (* class->cancel) (monitor); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * g_directory_monitor_set_rate_limit: | ||||
|  * @monitor: a #GDirectoryMonitor. | ||||
|  * @limit_msecs: the change rate limit of the directory monitor in milliseconds. | ||||
|  * | ||||
|  * Report same consecutive changes of the same type at most once each @limit_msecs milliseconds. | ||||
|  **/ | ||||
| void | ||||
| g_directory_monitor_set_rate_limit (GDirectoryMonitor *monitor, | ||||
| 				    int                limit_msecs) | ||||
| { | ||||
|   GDirectoryMonitorPrivate *priv; | ||||
|   g_return_if_fail (G_IS_DIRECTORY_MONITOR (monitor)); | ||||
|   priv = monitor->priv; | ||||
|   if (priv->rate_limit_msec != limit_msecs) | ||||
|     { | ||||
|       monitor->priv->rate_limit_msec = limit_msecs; | ||||
|       g_object_notify (G_OBJECT (monitor), "rate-limit"); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * g_directory_monitor_is_cancelled: | ||||
|  * @monitor: a #GDirectoryMonitor. | ||||
|  *  | ||||
|  * Checks whether @monitor is cancelled. | ||||
|  * | ||||
|  * Returns: %TRUE if the monitor on the directory was cancelled.  | ||||
|  *     %FALSE otherwise. | ||||
|  **/ | ||||
| gboolean | ||||
| g_directory_monitor_is_cancelled (GDirectoryMonitor *monitor) | ||||
| { | ||||
|   g_return_val_if_fail (G_IS_DIRECTORY_MONITOR (monitor), FALSE); | ||||
|  | ||||
|   return monitor->priv->cancelled; | ||||
| } | ||||
|  | ||||
| static guint32 | ||||
| get_time_msecs (void) | ||||
| { | ||||
|   return g_thread_gettime() / (1000 * 1000); | ||||
| } | ||||
|  | ||||
| static guint32 | ||||
| time_difference (guint32 from, guint32 to) | ||||
| { | ||||
|   if (from > to) | ||||
|     return 0; | ||||
|   return to - from; | ||||
| } | ||||
|  | ||||
| static RateLimiter * | ||||
| new_limiter (GDirectoryMonitor *monitor, | ||||
| 	     GFile             *file) | ||||
| { | ||||
|   RateLimiter *limiter; | ||||
|  | ||||
|   limiter = g_new0 (RateLimiter, 1); | ||||
|   limiter->file = g_object_ref (file); | ||||
|   g_hash_table_insert (monitor->priv->rate_limiter, file, limiter); | ||||
|    | ||||
|   return limiter; | ||||
| } | ||||
|  | ||||
| static void | ||||
| rate_limiter_send_virtual_changes_done_now (GDirectoryMonitor *monitor,  | ||||
|                                             RateLimiter       *limiter) | ||||
| { | ||||
|   if (limiter->send_virtual_changes_done_at != 0) | ||||
|     { | ||||
|       g_signal_emit (monitor, signals[CHANGED], 0, limiter->file, NULL, G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT); | ||||
|       limiter->send_virtual_changes_done_at = 0; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| rate_limiter_send_delayed_change_now (GDirectoryMonitor *monitor,  | ||||
|                                       RateLimiter       *limiter,  | ||||
|                                       guint32            time_now) | ||||
| { | ||||
|   if (limiter->send_delayed_change_at != 0) | ||||
|     { | ||||
|       g_signal_emit (monitor, signals[CHANGED], 0, limiter->file, NULL, G_FILE_MONITOR_EVENT_CHANGED); | ||||
|       limiter->send_delayed_change_at = 0; | ||||
|       limiter->last_sent_change_time = time_now; | ||||
|     } | ||||
| } | ||||
|  | ||||
| typedef struct { | ||||
|   guint32 min_time; | ||||
|   guint32 time_now; | ||||
|   GDirectoryMonitor *monitor; | ||||
| } ForEachData; | ||||
|  | ||||
| static gboolean | ||||
| calc_min_time (GDirectoryMonitor *monitor,  | ||||
|                RateLimiter       *limiter,  | ||||
|                guint32            time_now,  | ||||
|                guint32           *min_time) | ||||
| { | ||||
|   gboolean delete_me; | ||||
|   guint32 expire_at; | ||||
|  | ||||
|   delete_me = TRUE; | ||||
|  | ||||
|   if (limiter->last_sent_change_time != 0) | ||||
|     { | ||||
|       /* Set a timeout at 2*rate limit so that we can clear out the change from the hash eventualy */ | ||||
|       expire_at = limiter->last_sent_change_time + 2 * monitor->priv->rate_limit_msec; | ||||
|  | ||||
|       if (time_difference (time_now, expire_at) > 0) | ||||
| 	{ | ||||
| 	  delete_me = FALSE; | ||||
| 	  *min_time = MIN (*min_time, | ||||
| 			   time_difference (time_now, expire_at)); | ||||
| 	} | ||||
|     } | ||||
|  | ||||
|   if (limiter->send_delayed_change_at != 0) | ||||
|     { | ||||
|       delete_me = FALSE; | ||||
|       *min_time = MIN (*min_time, | ||||
| 		       time_difference (time_now, limiter->send_delayed_change_at)); | ||||
|     } | ||||
|  | ||||
|   if (limiter->send_virtual_changes_done_at != 0) | ||||
|     { | ||||
|       delete_me = FALSE; | ||||
|       *min_time = MIN (*min_time, | ||||
| 		       time_difference (time_now, limiter->send_virtual_changes_done_at)); | ||||
|     } | ||||
|  | ||||
|   return delete_me; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| foreach_rate_limiter_fire (gpointer key, | ||||
| 			   gpointer value, | ||||
| 			   gpointer user_data) | ||||
| { | ||||
|   RateLimiter *limiter = value; | ||||
|   ForEachData *data = user_data; | ||||
|  | ||||
|   if (limiter->send_delayed_change_at != 0 && | ||||
|       time_difference (data->time_now, limiter->send_delayed_change_at) == 0) | ||||
|     rate_limiter_send_delayed_change_now (data->monitor, limiter, data->time_now); | ||||
|  | ||||
|   if (limiter->send_virtual_changes_done_at != 0 && | ||||
|       time_difference (data->time_now, limiter->send_virtual_changes_done_at) == 0) | ||||
|     rate_limiter_send_virtual_changes_done_now (data->monitor, limiter); | ||||
|  | ||||
|   return calc_min_time (data->monitor, limiter, data->time_now, &data->min_time); | ||||
| } | ||||
|  | ||||
| static gboolean  | ||||
| rate_limiter_timeout (gpointer timeout_data) | ||||
| { | ||||
|   GDirectoryMonitor *monitor = timeout_data; | ||||
|   ForEachData data; | ||||
|   GSource *source; | ||||
|    | ||||
|   data.min_time = G_MAXUINT32; | ||||
|   data.monitor = monitor; | ||||
|   data.time_now = get_time_msecs (); | ||||
|   g_hash_table_foreach_remove (monitor->priv->rate_limiter, | ||||
| 			       foreach_rate_limiter_fire, | ||||
| 			       &data); | ||||
|  | ||||
|   /* Remove old timeout */ | ||||
|   if (monitor->priv->timeout) | ||||
|     { | ||||
|       g_source_destroy (monitor->priv->timeout); | ||||
|       g_source_unref (monitor->priv->timeout); | ||||
|       monitor->priv->timeout = NULL; | ||||
|       monitor->priv->timeout_fires_at = 0; | ||||
|     } | ||||
|    | ||||
|   /* Set up new timeout */ | ||||
|   if (data.min_time != G_MAXUINT32) | ||||
|     { | ||||
|       source = g_timeout_source_new (data.min_time + 1); /* + 1 to make sure we've really passed the time */ | ||||
|       g_source_set_callback (source, rate_limiter_timeout, monitor, NULL); | ||||
|       g_source_attach (source, NULL); | ||||
|        | ||||
|       monitor->priv->timeout = source; | ||||
|       monitor->priv->timeout_fires_at = data.time_now + data.min_time;  | ||||
|     } | ||||
|    | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| foreach_rate_limiter_update (gpointer key, | ||||
| 			     gpointer value, | ||||
| 			     gpointer user_data) | ||||
| { | ||||
|   RateLimiter *limiter = value; | ||||
|   ForEachData *data = user_data; | ||||
|  | ||||
|   return calc_min_time (data->monitor, limiter, data->time_now, &data->min_time); | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_rate_limiter_timeout (GDirectoryMonitor *monitor,  | ||||
|                              guint              new_time) | ||||
| { | ||||
|   ForEachData data; | ||||
|   GSource *source; | ||||
|    | ||||
|   if (monitor->priv->timeout_fires_at != 0 && new_time != 0 && | ||||
|       time_difference (new_time, monitor->priv->timeout_fires_at) == 0) | ||||
|     return; /* Nothing to do, we already fire earlier than that */ | ||||
|  | ||||
|   data.min_time = G_MAXUINT32; | ||||
|   data.monitor = monitor; | ||||
|   data.time_now = get_time_msecs (); | ||||
|   g_hash_table_foreach_remove (monitor->priv->rate_limiter, | ||||
| 			       foreach_rate_limiter_update, | ||||
| 			       &data); | ||||
|  | ||||
|   /* Remove old timeout */ | ||||
|   if (monitor->priv->timeout) | ||||
|     { | ||||
|       g_source_destroy (monitor->priv->timeout); | ||||
|       g_source_unref (monitor->priv->timeout); | ||||
|       monitor->priv->timeout_fires_at = 0; | ||||
|       monitor->priv->timeout = NULL; | ||||
|     } | ||||
|  | ||||
|   /* Set up new timeout */ | ||||
|   if (data.min_time != G_MAXUINT32) | ||||
|     { | ||||
|       source = g_timeout_source_new (data.min_time + 1);  /* + 1 to make sure we've really passed the time */ | ||||
|       g_source_set_callback (source, rate_limiter_timeout, monitor, NULL); | ||||
|       g_source_attach (source, NULL); | ||||
|        | ||||
|       monitor->priv->timeout = source; | ||||
|       monitor->priv->timeout_fires_at = data.time_now + data.min_time;  | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * g_directory_monitor_emit_event: | ||||
|  * @monitor: a #GDirectoryMonitor. | ||||
|  * @child: a #GFile. | ||||
|  * @other_file: a #GFile. | ||||
|  * @event_type: a set of #GFileMonitorEvent flags. | ||||
|  *  | ||||
|  * Emits the #GDirectoryMonitor::changed signal if a change | ||||
|  * has taken place. Should be called from directory monitor  | ||||
|  * implementations only. | ||||
|  **/ | ||||
| void | ||||
| g_directory_monitor_emit_event (GDirectoryMonitor *monitor, | ||||
| 				GFile             *child, | ||||
| 				GFile             *other_file, | ||||
| 				GFileMonitorEvent  event_type) | ||||
| { | ||||
|   guint32 time_now, since_last; | ||||
|   gboolean emit_now; | ||||
|   RateLimiter *limiter; | ||||
|  | ||||
|   g_return_if_fail (G_IS_DIRECTORY_MONITOR (monitor)); | ||||
|   g_return_if_fail (G_IS_FILE (child)); | ||||
|  | ||||
|   limiter = g_hash_table_lookup (monitor->priv->rate_limiter, child); | ||||
|  | ||||
|   if (event_type != G_FILE_MONITOR_EVENT_CHANGED) | ||||
|     { | ||||
|       if (limiter) | ||||
| 	{ | ||||
| 	  rate_limiter_send_delayed_change_now (monitor, limiter, get_time_msecs ()); | ||||
| 	  if (event_type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT) | ||||
| 	    limiter->send_virtual_changes_done_at = 0; | ||||
| 	  else | ||||
| 	    rate_limiter_send_virtual_changes_done_now (monitor, limiter); | ||||
| 	  update_rate_limiter_timeout (monitor, 0); | ||||
| 	} | ||||
|       g_signal_emit (monitor, signals[CHANGED], 0, child, other_file, event_type); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       /* Changed event, rate limit */ | ||||
|       time_now = get_time_msecs (); | ||||
|       emit_now = TRUE; | ||||
|        | ||||
|       if (limiter) | ||||
| 	{ | ||||
| 	  since_last = time_difference (limiter->last_sent_change_time, time_now); | ||||
| 	  if (since_last < monitor->priv->rate_limit_msec) | ||||
| 	    { | ||||
| 	      /* We ignore this change, but arm a timer so that we can fire it later if we | ||||
| 		 don't get any other events (that kill this timeout) */ | ||||
| 	      emit_now = FALSE; | ||||
| 	      if (limiter->send_delayed_change_at == 0) | ||||
| 		{ | ||||
| 		  limiter->send_delayed_change_at = time_now + monitor->priv->rate_limit_msec; | ||||
| 		  update_rate_limiter_timeout (monitor, limiter->send_delayed_change_at); | ||||
| 		} | ||||
| 	    } | ||||
| 	} | ||||
|  | ||||
|       if (limiter == NULL) | ||||
| 	limiter = new_limiter (monitor, child); | ||||
|        | ||||
|       if (emit_now) | ||||
| 	{ | ||||
| 	  g_signal_emit (monitor, signals[CHANGED], 0, child, other_file, event_type); | ||||
|  | ||||
| 	  limiter->last_sent_change_time = time_now; | ||||
| 	  limiter->send_delayed_change_at = 0; | ||||
| 	  /* Set a timeout of 2*rate limit so that we can clear out the change from the hash eventualy */ | ||||
| 	  update_rate_limiter_timeout (monitor, time_now + 2 * monitor->priv->rate_limit_msec); | ||||
| 	} | ||||
|  | ||||
|       /* Schedule a virtual change done. This is removed if we get a real one, and | ||||
| 	 postponed if we get more change events. */ | ||||
|  | ||||
|       limiter->send_virtual_changes_done_at = time_now + DEFAULT_VIRTUAL_CHANGES_DONE_DELAY_SECS * 1000; | ||||
|       update_rate_limiter_timeout (monitor, limiter->send_virtual_changes_done_at); | ||||
|     } | ||||
| } | ||||
|  | ||||
| #define __G_DIRECTORY_MONITOR_C__ | ||||
| #include "gioaliasdef.c" | ||||
| @@ -1,97 +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, write to the | ||||
|  * Free Software Foundation, Inc., 59 Temple Place, Suite 330, | ||||
|  * Boston, MA 02111-1307, USA. | ||||
|  * | ||||
|  * Author: Alexander Larsson <alexl@redhat.com> | ||||
|  */ | ||||
|  | ||||
| #if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION) | ||||
| #error "Only <gio/gio.h> can be included directly." | ||||
| #endif | ||||
|  | ||||
| #ifndef __G_DIRECTORY_MONITOR_H__ | ||||
| #define __G_DIRECTORY_MONITOR_H__ | ||||
|  | ||||
| #include <glib-object.h> | ||||
| #include <gio/gfile.h> | ||||
| #include <gio/gfilemonitor.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define G_TYPE_DIRECTORY_MONITOR         (g_directory_monitor_get_type ()) | ||||
| #define G_DIRECTORY_MONITOR(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_DIRECTORY_MONITOR, GDirectoryMonitor)) | ||||
| #define G_DIRECTORY_MONITOR_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_DIRECTORY_MONITOR, GDirectoryMonitorClass)) | ||||
| #define G_IS_DIRECTORY_MONITOR(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DIRECTORY_MONITOR)) | ||||
| #define G_IS_DIRECTORY_MONITOR_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_DIRECTORY_MONITOR)) | ||||
| #define G_DIRECTORY_MONITOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_DIRECTORY_MONITOR, GDirectoryMonitorClass)) | ||||
|  | ||||
| typedef struct _GDirectoryMonitorClass	 GDirectoryMonitorClass; | ||||
| typedef struct _GDirectoryMonitorPrivate GDirectoryMonitorPrivate; | ||||
|  | ||||
| /** | ||||
|  * GDirectoryMonitor: | ||||
|  * @parent_instance: The parent class.  | ||||
|  *  | ||||
|  * Implements a monitor on the given #GFile that points to a directory. | ||||
|  **/ | ||||
| struct _GDirectoryMonitor | ||||
| { | ||||
|   GObject parent_instance; | ||||
|  | ||||
|   /*< private >*/ | ||||
|   GDirectoryMonitorPrivate *priv; | ||||
| }; | ||||
|  | ||||
| struct _GDirectoryMonitorClass | ||||
| { | ||||
|   GObjectClass parent_class; | ||||
|    | ||||
|   /* Signals */ | ||||
|   void (* changed) (GDirectoryMonitor* monitor, | ||||
| 		    GFile *child, | ||||
| 		    GFile *other_file, | ||||
| 		    GFileMonitorEvent event_type); | ||||
|    | ||||
|   /* Virtual Table */ | ||||
|   gboolean	(*cancel)(GDirectoryMonitor* monitor); | ||||
|  | ||||
|   /*< private >*/ | ||||
|   /* Padding for future expansion */ | ||||
|   void (*_g_reserved1) (void); | ||||
|   void (*_g_reserved2) (void); | ||||
|   void (*_g_reserved3) (void); | ||||
|   void (*_g_reserved4) (void); | ||||
|   void (*_g_reserved5) (void); | ||||
| }; | ||||
|  | ||||
| GType g_directory_monitor_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| gboolean g_directory_monitor_cancel         (GDirectoryMonitor *monitor); | ||||
| gboolean g_directory_monitor_is_cancelled   (GDirectoryMonitor *monitor); | ||||
| void     g_directory_monitor_set_rate_limit (GDirectoryMonitor *monitor, | ||||
| 					     int                limit_msecs); | ||||
|  | ||||
| /* For implementations */ | ||||
| void g_directory_monitor_emit_event (GDirectoryMonitor      *monitor, | ||||
| 				     GFile                  *child, | ||||
| 				     GFile                  *other_file, | ||||
| 				     GFileMonitorEvent       event_type); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __G_DIRECTORY_MONITOR_H__ */ | ||||
| @@ -3246,10 +3246,10 @@ g_file_eject_mountable_finish (GFile         *file, | ||||
|  * triggering the cancellable object from another thread. If the operation | ||||
|  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.  | ||||
|  *  | ||||
|  * Returns: a #GDirectoryMonitor for the given @file,  | ||||
|  * Returns: a #GFileMonitor for the given @file,  | ||||
|  * or %NULL on error. | ||||
|  **/ | ||||
| GDirectoryMonitor* | ||||
| GFileMonitor* | ||||
| g_file_monitor_directory (GFile             *file, | ||||
| 			  GFileMonitorFlags  flags, | ||||
| 			  GCancellable      *cancellable) | ||||
|   | ||||
							
								
								
									
										19
									
								
								gio/gfile.h
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								gio/gfile.h
									
									
									
									
									
								
							| @@ -104,7 +104,7 @@ typedef enum { | ||||
|  * @G_FILE_MONITOR_NONE: No flags set. | ||||
|  * @G_FILE_MONITOR_WATCH_MOUNTS: Watch for mount events.  | ||||
|  * | ||||
|  * Flags used to set what a #GFileMonitor or #GDirectoryMonitor will watch for.  | ||||
|  * Flags used to set what a #GFileMonitor will watch for.  | ||||
|  */ | ||||
| typedef enum  { | ||||
|   G_FILE_MONITOR_NONE = 0, | ||||
| @@ -120,7 +120,6 @@ typedef enum  { | ||||
|  **/ | ||||
| typedef struct _GFile         		GFile; /* Dummy typedef */ | ||||
| typedef struct _GFileIface    		GFileIface; | ||||
| typedef struct _GDirectoryMonitor       GDirectoryMonitor; | ||||
| typedef struct _GFileMonitor            GFileMonitor; | ||||
|  | ||||
| /** | ||||
| @@ -242,7 +241,7 @@ typedef gboolean (* GFileReadMoreCallback) (const char *file_contents, | ||||
|  * @eject_mountable_finish: Finishes an eject operation. | ||||
|  * @mount_enclosing_volume: Mounts a specified location.  | ||||
|  * @mount_enclosing_volume_finish: Finishes mounting a specified location. | ||||
|  * @monitor_dir: Creates a #GDirectoryMonitor for the location. | ||||
|  * @monitor_dir: Creates a #GFileMonitor for the location. | ||||
|  * @monitor_file: Creates a #GFileMonitor for the location. | ||||
|  *  | ||||
|  * An interface for writing VFS file handles.   | ||||
| @@ -517,7 +516,7 @@ struct _GFileIface | ||||
| 					     GAsyncResult *result, | ||||
| 					     GError **error); | ||||
|    | ||||
|   GDirectoryMonitor* (*monitor_dir)         (GFile                  *file, | ||||
|   GFileMonitor*      (*monitor_dir)         (GFile                  *file, | ||||
| 					     GFileMonitorFlags       flags, | ||||
| 					     GCancellable           *cancellable); | ||||
|  | ||||
| @@ -793,12 +792,12 @@ gboolean                g_file_copy_attributes            (GFile | ||||
| 							   GError                    **error); | ||||
|  | ||||
|  | ||||
| GDirectoryMonitor* g_file_monitor_directory          (GFile                  *file, | ||||
| 						      GFileMonitorFlags       flags, | ||||
| 						      GCancellable           *cancellable); | ||||
| GFileMonitor*      g_file_monitor_file               (GFile                  *file, | ||||
| 						      GFileMonitorFlags       flags, | ||||
| 						      GCancellable           *cancellable); | ||||
| GFileMonitor*           g_file_monitor_directory          (GFile                  *file, | ||||
| 							   GFileMonitorFlags       flags, | ||||
| 							   GCancellable           *cancellable); | ||||
| GFileMonitor*           g_file_monitor_file               (GFile                  *file, | ||||
| 							   GFileMonitorFlags       flags, | ||||
| 							   GCancellable           *cancellable); | ||||
|  | ||||
|  | ||||
| /* Utilities */ | ||||
|   | ||||
| @@ -34,9 +34,8 @@ | ||||
|  * SECTION:gfilemonitor | ||||
|  * @short_description: File Monitor | ||||
|  * @include: gio.h | ||||
|  * @see_also: #GDirectoryMonitor | ||||
|  * | ||||
|  * Monitors a file for changes. | ||||
|  * Monitors a file or directory for changes. | ||||
|  *  | ||||
|  **/ | ||||
|  | ||||
| @@ -47,19 +46,22 @@ enum { | ||||
|  | ||||
| G_DEFINE_ABSTRACT_TYPE (GFileMonitor, g_file_monitor, G_TYPE_OBJECT); | ||||
|  | ||||
| typedef struct { | ||||
|   GFile *file; | ||||
|   guint32 last_sent_change_time; /* 0 == not sent */ | ||||
|   guint32 send_delayed_change_at; /* 0 == never */ | ||||
|   guint32 send_virtual_changes_done_at; /* 0 == never */ | ||||
| } RateLimiter; | ||||
|  | ||||
| struct _GFileMonitorPrivate { | ||||
|   gboolean cancelled; | ||||
|   int rate_limit_msec; | ||||
|  | ||||
|   /* Rate limiting change events */ | ||||
|   guint32 last_sent_change_time; /* Some monotonic clock in msecs */ | ||||
|   GFile *last_sent_change_file; | ||||
|    | ||||
|   guint send_delayed_change_timeout; | ||||
|   GHashTable *rate_limiter; | ||||
|  | ||||
|   /* Virtual CHANGES_DONE_HINT emission */ | ||||
|   GSource *virtual_changes_done_timeout; | ||||
|   GFile *virtual_changes_done_file; | ||||
|   GSource *timeout; | ||||
|   guint32 timeout_fires_at; | ||||
| }; | ||||
|  | ||||
| enum { | ||||
| @@ -123,6 +125,12 @@ g_file_monitor_get_property (GObject    *object, | ||||
|  | ||||
| static guint signals[LAST_SIGNAL] = { 0 }; | ||||
|  | ||||
| static void | ||||
| rate_limiter_free (RateLimiter *limiter) | ||||
| { | ||||
|   g_object_unref (limiter->file); | ||||
|   g_slice_free (RateLimiter, limiter); | ||||
| } | ||||
|  | ||||
| static void | ||||
| g_file_monitor_finalize (GObject *object) | ||||
| @@ -131,17 +139,13 @@ g_file_monitor_finalize (GObject *object) | ||||
|  | ||||
|   monitor = G_FILE_MONITOR (object); | ||||
|  | ||||
|   if (monitor->priv->last_sent_change_file) | ||||
|     g_object_unref (monitor->priv->last_sent_change_file); | ||||
|   if (monitor->priv->timeout) | ||||
|     { | ||||
|       g_source_destroy (monitor->priv->timeout); | ||||
|       g_source_unref (monitor->priv->timeout); | ||||
|     } | ||||
|  | ||||
|   if (monitor->priv->send_delayed_change_timeout != 0) | ||||
|     g_source_remove (monitor->priv->send_delayed_change_timeout); | ||||
|  | ||||
|   if (monitor->priv->virtual_changes_done_file) | ||||
|     g_object_unref (monitor->priv->virtual_changes_done_file); | ||||
|  | ||||
|   if (monitor->priv->virtual_changes_done_timeout) | ||||
|     g_source_destroy (monitor->priv->virtual_changes_done_timeout); | ||||
|   g_hash_table_destroy (monitor->priv->rate_limiter); | ||||
|    | ||||
|   if (G_OBJECT_CLASS (g_file_monitor_parent_class)->finalize) | ||||
|     (*G_OBJECT_CLASS (g_file_monitor_parent_class)->finalize) (object); | ||||
| @@ -221,6 +225,8 @@ g_file_monitor_init (GFileMonitor *monitor) | ||||
| 					       G_TYPE_FILE_MONITOR, | ||||
| 					       GFileMonitorPrivate); | ||||
|   monitor->priv->rate_limit_msec = DEFAULT_RATE_LIMIT_MSECS; | ||||
|   monitor->priv->rate_limiter = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, | ||||
| 						       NULL, (GDestroyNotify) rate_limiter_free); | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -279,7 +285,9 @@ g_file_monitor_set_rate_limit (GFileMonitor *monitor, | ||||
| 			       int           limit_msecs) | ||||
| { | ||||
|   GFileMonitorPrivate *priv; | ||||
|    | ||||
|   g_return_if_fail (G_IS_FILE_MONITOR (monitor)); | ||||
|    | ||||
|   priv = monitor->priv; | ||||
|   if (priv->rate_limit_msec != limit_msecs) | ||||
|     { | ||||
| @@ -304,189 +312,279 @@ time_difference (guint32 from, guint32 to) | ||||
|  | ||||
| /* Change event rate limiting support: */ | ||||
|  | ||||
| static void | ||||
| update_last_sent_change (GFileMonitor *monitor, GFile *file, guint32 time_now) | ||||
| static RateLimiter * | ||||
| new_limiter (GFileMonitor *monitor, | ||||
| 	     GFile             *file) | ||||
| { | ||||
|   if (monitor->priv->last_sent_change_file != file) | ||||
|     { | ||||
|       if (monitor->priv->last_sent_change_file) | ||||
| 	{ | ||||
| 	  g_object_unref (monitor->priv->last_sent_change_file); | ||||
| 	  monitor->priv->last_sent_change_file = NULL; | ||||
| 	} | ||||
|       if (file) | ||||
| 	monitor->priv->last_sent_change_file = g_object_ref (file); | ||||
|     } | ||||
|   RateLimiter *limiter; | ||||
|  | ||||
|   limiter = g_slice_new0 (RateLimiter); | ||||
|   limiter->file = g_object_ref (file); | ||||
|   g_hash_table_insert (monitor->priv->rate_limiter, file, limiter); | ||||
|    | ||||
|   monitor->priv->last_sent_change_time = time_now; | ||||
|   return limiter; | ||||
| } | ||||
|  | ||||
| static void | ||||
| send_delayed_change_now (GFileMonitor *monitor) | ||||
| rate_limiter_send_virtual_changes_done_now (GFileMonitor *monitor,  | ||||
|                                             RateLimiter  *limiter) | ||||
| { | ||||
|   if (monitor->priv->send_delayed_change_timeout) | ||||
|   if (limiter->send_virtual_changes_done_at != 0) | ||||
|     { | ||||
|       g_signal_emit (monitor, signals[CHANGED], 0, | ||||
| 		     monitor->priv->last_sent_change_file, NULL, | ||||
| 		     G_FILE_MONITOR_EVENT_CHANGED); | ||||
|        | ||||
|       g_source_remove (monitor->priv->send_delayed_change_timeout); | ||||
|       monitor->priv->send_delayed_change_timeout = 0; | ||||
|  | ||||
|       /* Same file, new last_sent time */ | ||||
|       monitor->priv->last_sent_change_time = get_time_msecs (); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| delayed_changed_event_timeout (gpointer data) | ||||
| { | ||||
|   GFileMonitor *monitor = data; | ||||
|  | ||||
|   send_delayed_change_now (monitor); | ||||
|    | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| schedule_delayed_change (GFileMonitor *monitor, GFile *file, guint32 delay_msec) | ||||
| { | ||||
|   if (monitor->priv->send_delayed_change_timeout == 0) /* Only set the timeout once */ | ||||
|     { | ||||
|       monitor->priv->send_delayed_change_timeout =  | ||||
| 	g_timeout_add (delay_msec, delayed_changed_event_timeout, monitor); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| cancel_delayed_change (GFileMonitor *monitor) | ||||
| { | ||||
|   if (monitor->priv->send_delayed_change_timeout != 0) | ||||
|     { | ||||
|       g_source_remove (monitor->priv->send_delayed_change_timeout); | ||||
|       monitor->priv->send_delayed_change_timeout = 0; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* Virtual changes_done_hint support: */ | ||||
|  | ||||
| static void | ||||
| send_virtual_changes_done_now (GFileMonitor *monitor) | ||||
| { | ||||
|   if (monitor->priv->virtual_changes_done_timeout) | ||||
|     { | ||||
|       g_signal_emit (monitor, signals[CHANGED], 0, | ||||
| 		     monitor->priv->virtual_changes_done_file, NULL, | ||||
| 		     limiter->file, NULL, | ||||
| 		     G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT); | ||||
|        | ||||
|       g_source_destroy (monitor->priv->virtual_changes_done_timeout); | ||||
|       monitor->priv->virtual_changes_done_timeout = NULL; | ||||
|  | ||||
|       g_object_unref (monitor->priv->virtual_changes_done_file); | ||||
|       monitor->priv->virtual_changes_done_file = NULL; | ||||
|       limiter->send_virtual_changes_done_at = 0; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| virtual_changes_done_timeout (gpointer data) | ||||
| static void | ||||
| rate_limiter_send_delayed_change_now (GFileMonitor *monitor,  | ||||
|                                       RateLimiter *limiter,  | ||||
|                                       guint32 time_now) | ||||
| { | ||||
|   GFileMonitor *monitor = data; | ||||
|  | ||||
|   send_virtual_changes_done_now (monitor); | ||||
|    | ||||
|   return FALSE; | ||||
|   if (limiter->send_delayed_change_at != 0) | ||||
|     { | ||||
|       g_signal_emit (monitor, signals[CHANGED], 0, | ||||
| 		     limiter->file, NULL, | ||||
| 		     G_FILE_MONITOR_EVENT_CHANGED); | ||||
|       limiter->send_delayed_change_at = 0; | ||||
|       limiter->last_sent_change_time = time_now; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| schedule_virtual_change_done (GFileMonitor *monitor, GFile *file) | ||||
| typedef struct { | ||||
|   guint32 min_time; | ||||
|   guint32 time_now; | ||||
|   GFileMonitor *monitor; | ||||
| } ForEachData; | ||||
|  | ||||
| static gboolean | ||||
| calc_min_time (GFileMonitor *monitor,  | ||||
|                RateLimiter *limiter,  | ||||
|                guint32 time_now,  | ||||
|                guint32 *min_time) | ||||
| { | ||||
|   gboolean delete_me; | ||||
|   guint32 expire_at; | ||||
|  | ||||
|   delete_me = TRUE; | ||||
|  | ||||
|   if (limiter->last_sent_change_time != 0) | ||||
|     { | ||||
|       /* Set a timeout at 2*rate limit so that we can clear out the change from the hash eventualy */ | ||||
|       expire_at = limiter->last_sent_change_time + 2 * monitor->priv->rate_limit_msec; | ||||
|  | ||||
|       if (time_difference (time_now, expire_at) > 0) | ||||
| 	{ | ||||
| 	  delete_me = FALSE; | ||||
| 	  *min_time = MIN (*min_time, | ||||
| 			   time_difference (time_now, expire_at)); | ||||
| 	} | ||||
|     } | ||||
|  | ||||
|   if (limiter->send_delayed_change_at != 0) | ||||
|     { | ||||
|       delete_me = FALSE; | ||||
|       *min_time = MIN (*min_time, | ||||
| 		       time_difference (time_now, limiter->send_delayed_change_at)); | ||||
|     } | ||||
|  | ||||
|   if (limiter->send_virtual_changes_done_at != 0) | ||||
|     { | ||||
|       delete_me = FALSE; | ||||
|       *min_time = MIN (*min_time, | ||||
| 		       time_difference (time_now, limiter->send_virtual_changes_done_at)); | ||||
|     } | ||||
|  | ||||
|   return delete_me; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| foreach_rate_limiter_fire (gpointer key, | ||||
| 			   gpointer value, | ||||
| 			   gpointer user_data) | ||||
| { | ||||
|   RateLimiter *limiter = value; | ||||
|   ForEachData *data = user_data; | ||||
|  | ||||
|   if (limiter->send_delayed_change_at != 0 && | ||||
|       time_difference (data->time_now, limiter->send_delayed_change_at) == 0) | ||||
|     rate_limiter_send_delayed_change_now (data->monitor, limiter, data->time_now); | ||||
|    | ||||
|   if (limiter->send_virtual_changes_done_at != 0 && | ||||
|       time_difference (data->time_now, limiter->send_virtual_changes_done_at) == 0) | ||||
|     rate_limiter_send_virtual_changes_done_now (data->monitor, limiter); | ||||
|    | ||||
|   return calc_min_time (data->monitor, limiter, data->time_now, &data->min_time); | ||||
| } | ||||
|  | ||||
| static gboolean  | ||||
| rate_limiter_timeout (gpointer timeout_data) | ||||
| { | ||||
|   GFileMonitor *monitor = timeout_data; | ||||
|   ForEachData data; | ||||
|   GSource *source; | ||||
|    | ||||
|   source = g_timeout_source_new_seconds (DEFAULT_VIRTUAL_CHANGES_DONE_DELAY_SECS); | ||||
|   data.min_time = G_MAXUINT32; | ||||
|   data.monitor = monitor; | ||||
|   data.time_now = get_time_msecs (); | ||||
|   g_hash_table_foreach_remove (monitor->priv->rate_limiter, | ||||
| 			       foreach_rate_limiter_fire, | ||||
| 			       &data); | ||||
|    | ||||
|   g_source_set_callback (source, virtual_changes_done_timeout, monitor, NULL); | ||||
|   g_source_attach (source, NULL); | ||||
|   monitor->priv->virtual_changes_done_timeout = source; | ||||
|   monitor->priv->virtual_changes_done_file = g_object_ref (file); | ||||
|   g_source_unref (source); | ||||
|   /* Remove old timeout */ | ||||
|   if (monitor->priv->timeout) | ||||
|     { | ||||
|       g_source_destroy (monitor->priv->timeout); | ||||
|       g_source_unref (monitor->priv->timeout); | ||||
|       monitor->priv->timeout = NULL; | ||||
|       monitor->priv->timeout_fires_at = 0; | ||||
|     } | ||||
|    | ||||
|   /* Set up new timeout */ | ||||
|   if (data.min_time != G_MAXUINT32) | ||||
|     { | ||||
|       source = g_timeout_source_new (data.min_time + 1); /* + 1 to make sure we've really passed the time */ | ||||
|       g_source_set_callback (source, rate_limiter_timeout, monitor, NULL); | ||||
|       g_source_attach (source, NULL); | ||||
|        | ||||
|       monitor->priv->timeout = source; | ||||
|       monitor->priv->timeout_fires_at = data.time_now + data.min_time;  | ||||
|     } | ||||
|    | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| foreach_rate_limiter_update (gpointer key, | ||||
| 			     gpointer value, | ||||
| 			     gpointer user_data) | ||||
| { | ||||
|   RateLimiter *limiter = value; | ||||
|   ForEachData *data = user_data; | ||||
|  | ||||
|   return calc_min_time (data->monitor, limiter, data->time_now, &data->min_time); | ||||
| } | ||||
|  | ||||
| static void | ||||
| cancel_virtual_changes_done (GFileMonitor *monitor) | ||||
| update_rate_limiter_timeout (GFileMonitor *monitor,  | ||||
|                              guint new_time) | ||||
| { | ||||
|   if (monitor->priv->virtual_changes_done_timeout) | ||||
|   ForEachData data; | ||||
|   GSource *source; | ||||
|    | ||||
|   if (monitor->priv->timeout_fires_at != 0 && new_time != 0 && | ||||
|       time_difference (new_time, monitor->priv->timeout_fires_at) == 0) | ||||
|     return; /* Nothing to do, we already fire earlier than that */ | ||||
|  | ||||
|   data.min_time = G_MAXUINT32; | ||||
|   data.monitor = monitor; | ||||
|   data.time_now = get_time_msecs (); | ||||
|   g_hash_table_foreach_remove (monitor->priv->rate_limiter, | ||||
| 			       foreach_rate_limiter_update, | ||||
| 			       &data); | ||||
|  | ||||
|   /* Remove old timeout */ | ||||
|   if (monitor->priv->timeout) | ||||
|     { | ||||
|       g_source_destroy (monitor->priv->virtual_changes_done_timeout); | ||||
|       monitor->priv->virtual_changes_done_timeout = NULL; | ||||
|       g_source_destroy (monitor->priv->timeout); | ||||
|       g_source_unref (monitor->priv->timeout); | ||||
|       monitor->priv->timeout_fires_at = 0; | ||||
|       monitor->priv->timeout = NULL; | ||||
|     } | ||||
|  | ||||
|   /* Set up new timeout */ | ||||
|   if (data.min_time != G_MAXUINT32) | ||||
|     { | ||||
|       source = g_timeout_source_new (data.min_time + 1);  /* + 1 to make sure we've really passed the time */ | ||||
|       g_source_set_callback (source, rate_limiter_timeout, monitor, NULL); | ||||
|       g_source_attach (source, NULL); | ||||
|        | ||||
|       g_object_unref (monitor->priv->virtual_changes_done_file); | ||||
|       monitor->priv->virtual_changes_done_file = NULL; | ||||
|       monitor->priv->timeout = source; | ||||
|       monitor->priv->timeout_fires_at = data.time_now + data.min_time;  | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * g_file_monitor_emit_event: | ||||
|  * @monitor: a #GFileMonitor. | ||||
|  * @file: a #GFile. | ||||
|  * @child: a #GFile. | ||||
|  * @other_file: a #GFile. | ||||
|  * @event_type: a #GFileMonitorEvent | ||||
|  *  | ||||
|  * Emits a file monitor event. This is mainly necessary for implementations | ||||
|  * of GFileMonitor. | ||||
|  * @event_type: a set of #GFileMonitorEvent flags. | ||||
|  *  | ||||
|  * Emits the #GFileMonitor::changed signal if a change | ||||
|  * has taken place. Should be called from file monitor  | ||||
|  * implementations only. | ||||
|  **/ | ||||
| void | ||||
| g_file_monitor_emit_event (GFileMonitor *monitor, | ||||
| 			   GFile *file, | ||||
| 			   GFile *child, | ||||
| 			   GFile *other_file, | ||||
| 			   GFileMonitorEvent event_type) | ||||
| { | ||||
|   guint32 time_now, since_last; | ||||
|   gboolean emit_now; | ||||
|   RateLimiter *limiter; | ||||
|  | ||||
|   g_return_if_fail (G_IS_FILE_MONITOR (monitor)); | ||||
|   g_return_if_fail (G_IS_FILE (file)); | ||||
|   g_return_if_fail (G_IS_FILE (child)); | ||||
|  | ||||
|   limiter = g_hash_table_lookup (monitor->priv->rate_limiter, child); | ||||
|  | ||||
|   if (event_type != G_FILE_MONITOR_EVENT_CHANGED) | ||||
|     { | ||||
|       send_delayed_change_now (monitor); | ||||
|       update_last_sent_change (monitor, NULL, 0); | ||||
|       if (event_type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT) | ||||
| 	cancel_virtual_changes_done (monitor); | ||||
|       else | ||||
| 	send_virtual_changes_done_now (monitor); | ||||
|       g_signal_emit (monitor, signals[CHANGED], 0, file, other_file, event_type); | ||||
|       if (limiter) | ||||
| 	{ | ||||
| 	  rate_limiter_send_delayed_change_now (monitor, limiter, get_time_msecs ()); | ||||
| 	  if (event_type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT) | ||||
| 	    limiter->send_virtual_changes_done_at = 0; | ||||
| 	  else | ||||
| 	    rate_limiter_send_virtual_changes_done_now (monitor, limiter); | ||||
| 	  update_rate_limiter_timeout (monitor, 0); | ||||
| 	} | ||||
|       g_signal_emit (monitor, signals[CHANGED], 0, child, other_file, event_type); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       /* Changed event, rate limit */ | ||||
|       time_now = get_time_msecs (); | ||||
|       emit_now = TRUE; | ||||
|        | ||||
|       if (monitor->priv->last_sent_change_file) | ||||
|       if (limiter) | ||||
| 	{ | ||||
| 	  since_last = time_difference (monitor->priv->last_sent_change_time, time_now); | ||||
| 	  since_last = time_difference (limiter->last_sent_change_time, time_now); | ||||
| 	  if (since_last < monitor->priv->rate_limit_msec) | ||||
| 	    { | ||||
| 	      /* We ignore this change, but arm a timer so that we can fire it later if we | ||||
| 		 don't get any other events (that kill this timeout) */ | ||||
| 	      emit_now = FALSE; | ||||
| 	      schedule_delayed_change (monitor, file, | ||||
| 				       monitor->priv->rate_limit_msec - since_last); | ||||
| 	      if (limiter->send_delayed_change_at == 0) | ||||
| 		{ | ||||
| 		  limiter->send_delayed_change_at = time_now + monitor->priv->rate_limit_msec; | ||||
| 		  update_rate_limiter_timeout (monitor, limiter->send_delayed_change_at); | ||||
| 		} | ||||
| 	    } | ||||
| 	} | ||||
|        | ||||
|       if (limiter == NULL) | ||||
| 	limiter = new_limiter (monitor, child); | ||||
|        | ||||
|       if (emit_now) | ||||
| 	{ | ||||
| 	  g_signal_emit (monitor, signals[CHANGED], 0, file, other_file, event_type); | ||||
| 	  g_signal_emit (monitor, signals[CHANGED], 0, child, other_file, event_type); | ||||
| 	   | ||||
| 	  cancel_delayed_change (monitor); | ||||
| 	  update_last_sent_change (monitor, file, time_now); | ||||
| 	  limiter->last_sent_change_time = time_now; | ||||
| 	  limiter->send_delayed_change_at = 0; | ||||
| 	  /* Set a timeout of 2*rate limit so that we can clear out the change from the hash eventualy */ | ||||
| 	  update_rate_limiter_timeout (monitor, time_now + 2 * monitor->priv->rate_limit_msec); | ||||
| 	} | ||||
|  | ||||
|        | ||||
|       /* Schedule a virtual change done. This is removed if we get a real one, and | ||||
| 	 postponed if we get more change events. */ | ||||
|       cancel_virtual_changes_done (monitor); | ||||
|       schedule_virtual_change_done (monitor, file); | ||||
|        | ||||
|       limiter->send_virtual_changes_done_at = time_now + DEFAULT_VIRTUAL_CHANGES_DONE_DELAY_SECS * 1000; | ||||
|       update_rate_limiter_timeout (monitor, limiter->send_virtual_changes_done_at); | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -36,7 +36,6 @@ | ||||
| #include <gio/gthemedicon.h> | ||||
| #include <gio/gseekable.h> | ||||
| #include <gio/gfilemonitor.h> | ||||
| #include <gio/gdirectorymonitor.h> | ||||
| #include <gio/gbufferedinputstream.h> | ||||
| #include <gio/gbufferedoutputstream.h> | ||||
| #include <gio/gdatainputstream.h> | ||||
|   | ||||
| @@ -24,7 +24,6 @@ | ||||
|  | ||||
| #include "glocaldirectorymonitor.h" | ||||
| #include "gunixmounts.h" | ||||
| #include "gdirectorymonitor.h" | ||||
| #include "giomodule-priv.h" | ||||
| #include "glibintl.h" | ||||
|  | ||||
| @@ -38,10 +37,10 @@ enum | ||||
|   PROP_DIRNAME | ||||
| }; | ||||
|  | ||||
| static gboolean g_local_directory_monitor_cancel (GDirectoryMonitor* monitor); | ||||
| static gboolean g_local_directory_monitor_cancel (GFileMonitor* monitor); | ||||
| static void mounts_changed (GUnixMountMonitor *mount_monitor, gpointer user_data); | ||||
|  | ||||
| G_DEFINE_ABSTRACT_TYPE (GLocalDirectoryMonitor, g_local_directory_monitor, G_TYPE_DIRECTORY_MONITOR) | ||||
| G_DEFINE_ABSTRACT_TYPE (GLocalDirectoryMonitor, g_local_directory_monitor, G_TYPE_FILE_MONITOR) | ||||
|  | ||||
| static void | ||||
| g_local_directory_monitor_finalize (GObject* object) | ||||
| @@ -140,13 +139,13 @@ static void | ||||
| g_local_directory_monitor_class_init (GLocalDirectoryMonitorClass* klass) | ||||
| { | ||||
|   GObjectClass* gobject_class = G_OBJECT_CLASS (klass); | ||||
|   GDirectoryMonitorClass *dir_monitor_class = G_DIRECTORY_MONITOR_CLASS (klass); | ||||
|   GFileMonitorClass *file_monitor_class = G_FILE_MONITOR_CLASS (klass); | ||||
|    | ||||
|   gobject_class->finalize = g_local_directory_monitor_finalize; | ||||
|   gobject_class->set_property = g_local_directory_monitor_set_property; | ||||
|   gobject_class->constructor = g_local_directory_monitor_constructor; | ||||
|  | ||||
|   dir_monitor_class->cancel = g_local_directory_monitor_cancel; | ||||
|   file_monitor_class->cancel = g_local_directory_monitor_cancel; | ||||
|  | ||||
|   g_object_class_install_property (gobject_class,  | ||||
|                                    PROP_DIRNAME, | ||||
| @@ -193,9 +192,9 @@ mounts_changed (GUnixMountMonitor *mount_monitor, | ||||
|       if (local_monitor->was_mounted && !is_mounted) | ||||
|         { | ||||
|           file = g_file_new_for_path (local_monitor->dirname); | ||||
|           g_directory_monitor_emit_event (G_DIRECTORY_MONITOR (local_monitor), | ||||
|                                           file, NULL, | ||||
|                                           G_FILE_MONITOR_EVENT_UNMOUNTED); | ||||
|           g_file_monitor_emit_event (G_FILE_MONITOR (local_monitor), | ||||
| 				     file, NULL, | ||||
| 				     G_FILE_MONITOR_EVENT_UNMOUNTED); | ||||
|           g_object_unref (file); | ||||
|         } | ||||
|       local_monitor->was_mounted = is_mounted; | ||||
| @@ -274,15 +273,15 @@ get_default_local_directory_monitor (gpointer data) | ||||
|  * @dirname: filename of the directory to monitor. | ||||
|  * @flags: #GFileMonitorFlags. | ||||
|  *  | ||||
|  * Returns: new #GDirectoryMonitor for the given @dirname. | ||||
|  * Returns: new #GFileMonitor for the given @dirname. | ||||
|  **/ | ||||
| GDirectoryMonitor* | ||||
| GFileMonitor* | ||||
| _g_local_directory_monitor_new (const char*       dirname, | ||||
| 				GFileMonitorFlags flags) | ||||
| { | ||||
|   static GOnce once_init = G_ONCE_INIT; | ||||
|   GTypeClass *type_class; | ||||
|   GDirectoryMonitor *monitor; | ||||
|   GFileMonitor *monitor; | ||||
|   GType type; | ||||
|  | ||||
|   type_class = NULL; | ||||
| @@ -291,7 +290,7 @@ _g_local_directory_monitor_new (const char*       dirname, | ||||
|  | ||||
|   monitor = NULL; | ||||
|   if (type != G_TYPE_INVALID) | ||||
|     monitor = G_DIRECTORY_MONITOR (g_object_new (type, "dirname", dirname, NULL)); | ||||
|     monitor = G_FILE_MONITOR (g_object_new (type, "dirname", dirname, NULL)); | ||||
|  | ||||
|   /* This is non-null on first pass here. Unref the class now. | ||||
|    * This is to avoid unloading the module and then loading it | ||||
| @@ -306,7 +305,7 @@ _g_local_directory_monitor_new (const char*       dirname, | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| g_local_directory_monitor_cancel (GDirectoryMonitor* monitor) | ||||
| g_local_directory_monitor_cancel (GFileMonitor* monitor) | ||||
| { | ||||
|   GLocalDirectoryMonitor *local_monitor = G_LOCAL_DIRECTORY_MONITOR (monitor); | ||||
|  | ||||
|   | ||||
| @@ -24,7 +24,7 @@ | ||||
| #define __G_LOCAL_DIRECTORY_MONITOR_H__ | ||||
|  | ||||
| #include <glib-object.h> | ||||
| #include <gio/gdirectorymonitor.h> | ||||
| #include <gio/gfilemonitor.h> | ||||
|  | ||||
| #include "gunixmounts.h" | ||||
|  | ||||
| @@ -41,7 +41,7 @@ typedef struct _GLocalDirectoryMonitorClass GLocalDirectoryMonitorClass; | ||||
|  | ||||
| struct _GLocalDirectoryMonitor | ||||
| { | ||||
|   GDirectoryMonitor parent_instance; | ||||
|   GFileMonitor parent_instance; | ||||
|   gchar *dirname; | ||||
|   /* For mount emulation */ | ||||
|   GUnixMountMonitor *mount_monitor; | ||||
| @@ -49,7 +49,7 @@ struct _GLocalDirectoryMonitor | ||||
| }; | ||||
|  | ||||
| struct _GLocalDirectoryMonitorClass { | ||||
|   GDirectoryMonitorClass parent_class; | ||||
|   GFileMonitorClass parent_class; | ||||
|   gint prio; | ||||
|   char *name; /* Not used atm */ | ||||
|   gboolean mount_notify; | ||||
| @@ -58,8 +58,8 @@ struct _GLocalDirectoryMonitorClass { | ||||
|  | ||||
| GType g_local_directory_monitor_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| GDirectoryMonitor* _g_local_directory_monitor_new (const char* dirname, | ||||
| 						   GFileMonitorFlags flags); | ||||
| GFileMonitor* _g_local_directory_monitor_new (const char* dirname, | ||||
| 					      GFileMonitorFlags flags); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
|   | ||||
| @@ -1851,7 +1851,7 @@ g_local_file_move (GFile                  *source, | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static GDirectoryMonitor* | ||||
| static GFileMonitor* | ||||
| g_local_file_monitor_dir (GFile             *file, | ||||
| 			  GFileMonitorFlags  flags, | ||||
| 			  GCancellable      *cancellable) | ||||
|   | ||||
| @@ -273,7 +273,7 @@ array_resize (GMemoryOutputStream  *ostream, | ||||
| { | ||||
|   GMemoryOutputStreamPrivate *priv; | ||||
|   gpointer data; | ||||
|   gsize len, increment; | ||||
|   gsize len; | ||||
|  | ||||
|   priv = ostream->priv; | ||||
|  | ||||
|   | ||||
| @@ -31,7 +31,7 @@ | ||||
|  * SECTION:gvolumemonitor | ||||
|  * @short_description: Volume Monitor | ||||
|  * @include: gio.h | ||||
|  * @see_also: #GDirectoryMonitor, #GFileMonitor | ||||
|  * @see_also: #GFileMonitor | ||||
|  *  | ||||
|  * #GVolumeMonitor is for listing the user interesting devices and volumes | ||||
|  * on the computer. In other words, what a file selector or file manager | ||||
|   | ||||
| @@ -39,7 +39,7 @@ struct _GInotifyDirectoryMonitor | ||||
|   inotify_sub *sub; | ||||
| }; | ||||
|  | ||||
| static gboolean g_inotify_directory_monitor_cancel (GDirectoryMonitor* monitor); | ||||
| static gboolean g_inotify_directory_monitor_cancel (GFileMonitor* monitor); | ||||
|  | ||||
| #define g_inotify_directory_monitor_get_type _g_inotify_directory_monitor_get_type | ||||
| G_DEFINE_TYPE (GInotifyDirectoryMonitor, g_inotify_directory_monitor, G_TYPE_LOCAL_DIRECTORY_MONITOR) | ||||
| @@ -109,7 +109,7 @@ static void | ||||
| g_inotify_directory_monitor_class_init (GInotifyDirectoryMonitorClass* klass) | ||||
| { | ||||
|   GObjectClass* gobject_class = G_OBJECT_CLASS (klass); | ||||
|   GDirectoryMonitorClass *directory_monitor_class = G_DIRECTORY_MONITOR_CLASS (klass); | ||||
|   GFileMonitorClass *directory_monitor_class = G_FILE_MONITOR_CLASS (klass); | ||||
|   GLocalDirectoryMonitorClass *local_directory_monitor_class = G_LOCAL_DIRECTORY_MONITOR_CLASS (klass); | ||||
|    | ||||
|   gobject_class->finalize = g_inotify_directory_monitor_finalize; | ||||
| @@ -128,7 +128,7 @@ g_inotify_directory_monitor_init (GInotifyDirectoryMonitor* monitor) | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| g_inotify_directory_monitor_cancel (GDirectoryMonitor* monitor) | ||||
| g_inotify_directory_monitor_cancel (GFileMonitor* monitor) | ||||
| { | ||||
|   GInotifyDirectoryMonitor *inotify_monitor = G_INOTIFY_DIRECTORY_MONITOR (monitor); | ||||
|   inotify_sub *sub = inotify_monitor->sub; | ||||
| @@ -139,8 +139,8 @@ g_inotify_directory_monitor_cancel (GDirectoryMonitor* monitor) | ||||
|     inotify_monitor->sub = NULL; | ||||
|   } | ||||
|  | ||||
|   if (G_DIRECTORY_MONITOR_CLASS (g_inotify_directory_monitor_parent_class)->cancel) | ||||
|     (*G_DIRECTORY_MONITOR_CLASS (g_inotify_directory_monitor_parent_class)->cancel) (monitor); | ||||
|   if (G_FILE_MONITOR_CLASS (g_inotify_directory_monitor_parent_class)->cancel) | ||||
|     (*G_FILE_MONITOR_CLASS (g_inotify_directory_monitor_parent_class)->cancel) (monitor); | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|   | ||||
| @@ -28,7 +28,6 @@ | ||||
|  | ||||
| #include <glib-object.h> | ||||
| #include <string.h> | ||||
| #include <gio/gdirectorymonitor.h> | ||||
| #include "glocaldirectorymonitor.h" | ||||
| #include "giomodule.h" | ||||
|  | ||||
|   | ||||
| @@ -43,7 +43,6 @@ | ||||
| #endif | ||||
| #include <gio/glocalfile.h> | ||||
| #include <gio/gfilemonitor.h> | ||||
| #include <gio/gdirectorymonitor.h> | ||||
| #include "inotify-helper.h" | ||||
| #include "inotify-missing.h" | ||||
| #include "inotify-path.h" | ||||
| @@ -168,18 +167,8 @@ ih_event_callback (ik_event_t *event, inotify_sub *sub) | ||||
|   child = g_file_new_for_path (fullpath); | ||||
|   g_free (fullpath); | ||||
|  | ||||
|   if (G_IS_DIRECTORY_MONITOR (sub->user_data)) | ||||
|     { | ||||
|       GDirectoryMonitor* monitor = G_DIRECTORY_MONITOR (sub->user_data); | ||||
|       g_directory_monitor_emit_event (monitor,  | ||||
| 				      child, NULL, eflags); | ||||
|     } | ||||
|   else if (G_IS_FILE_MONITOR (sub->user_data)) | ||||
|     { | ||||
|       GFileMonitor* monitor = G_FILE_MONITOR (sub->user_data); | ||||
|       g_file_monitor_emit_event (monitor, | ||||
| 				 child, NULL, eflags); | ||||
|     } | ||||
|   g_file_monitor_emit_event (G_FILE_MONITOR (sub->user_data), | ||||
| 			     child, NULL, eflags); | ||||
|  | ||||
|   g_object_unref (child); | ||||
|   g_object_unref (parent); | ||||
| @@ -217,17 +206,8 @@ ih_not_missing_callback (inotify_sub *sub) | ||||
|   child = g_file_new_for_path (fullpath); | ||||
|   g_free (fullpath); | ||||
|  | ||||
|   if (G_IS_DIRECTORY_MONITOR (sub->user_data)) | ||||
|     { | ||||
|       GDirectoryMonitor* monitor = G_DIRECTORY_MONITOR (sub->user_data); | ||||
|       g_directory_monitor_emit_event (monitor, child, NULL, eflags); | ||||
|     } | ||||
|   else if (G_IS_FILE_MONITOR (sub->user_data)) | ||||
|     { | ||||
|       GFileMonitor* monitor = G_FILE_MONITOR (sub->user_data); | ||||
|       g_file_monitor_emit_event (monitor, | ||||
| 				 child, NULL, eflags); | ||||
|     } | ||||
|   g_file_monitor_emit_event (G_FILE_MONITOR (sub->user_data), | ||||
| 			     child, NULL, eflags); | ||||
|  | ||||
|   g_object_unref (child); | ||||
|   g_object_unref (parent); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user