PATCH: use gnome-vfs for monitoring files



Hi,

This patch uses the gnome-vfs monitoring API to watch files for changes,
instead of that of libnautilus-private/nautilus-monitor.[ch].  This is
needed so that I can implement monitors for the applications:// and
start-here:// vfs methods, and have the nautilus view refresh nicely.

nautilus-monitor.[ch] is left around only for nautilus_monitor_active(),
which is needed so nautilus can tell if it manually needs to refresh the
newly changed-to directory, or let FAM deal with notifying it.  It works
by creating a monitor for the user's desktop directory, and immediately
removing it.  If this was successful, FAM is assumed to be operational.

This also adds an idle handler so as to avoid calling
nautilus_file_changes_consume_changes() after every change event, so we
aren't overrun with refresh operations.

Monitoring seems to work just as well as the current code for me, but
this patch could probably use some extra eyes.

-Alex

-- 
"I don't find excessive sanity a virtue."
? autom4te.cache
? desktop-links-use-uris.diff
? stamp-h1
? use-vfs-monitors.diff
? components/tree/nautilus-tree-model.c.flc
? libnautilus/nautilus-view.c.flc
? libnautilus-private/nautilus-directory-async.c.flc
? libnautilus-private/nautilus-metafile.c.flc
? src/nautilus-sidebar.c.flc
? src/nautilus-window.c.flc
? src/file-manager/fm-desktop-icon-view.c.flc
? src/file-manager/fm-directory-view.c.flc
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/nautilus/ChangeLog,v
retrieving revision 1.5311
diff -u -r1.5311 ChangeLog
--- ChangeLog	20 May 2002 23:53:05 -0000	1.5311
+++ ChangeLog	21 May 2002 04:12:13 -0000
@@ -1,5 +1,27 @@
 2002-05-20  Alex Graveley  <alex ximian com>
 
+	* libnautilus-private/nautilus-monitor.[ch]: Remove everything
+	except nautilus_monitor_active(), which checks if FAM can be used
+	by creating a monitor for the user's desktop directory.
+
+	* libnautilus-private/nautilus-directory-async.c
+	(call_consume_changes_idle_cb): New idle handler to call
+	nautilus_file_changes_consume_changes(), so multiple file change
+	have a chance of being chunked together.
+	(monitor_notify_cb): New function to process events from the
+	gnome-vfs monitor on a file or directory.
+	(nautilus_directory_monitor_add_internal): Use
+	gnome_vfs_monitor_add().
+	(nautilus_directory_monitor_remove_internal): Use
+	gnome_vfs_monitor_cancel().
+
+	* libnautilus-private/nautilus-directory.c
+	(nautilus_directory_finalize): Use gnome_vfs_monitor_cancel().
+
+	* libnautilus-private/nautilus-file.c (finalize): Ditto.
+
+2002-05-20  Alex Graveley  <alex ximian com>
+
 	* libnautilus-private/nautilus-link-desktop-file.c
 	(nautilus_link_desktop_file_local_create): Force saving of desktop
 	file to counteract bug in libgnome-desktop.
Index: libnautilus-private/nautilus-directory-async.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-directory-async.c,v
retrieving revision 1.185
diff -u -r1.185 nautilus-directory-async.c
--- libnautilus-private/nautilus-directory-async.c	10 May 2002 18:49:04 -0000	1.185
+++ libnautilus-private/nautilus-directory-async.c	21 May 2002 04:12:13 -0000
@@ -28,6 +28,7 @@
 #include "nautilus-directory-notify.h"
 #include "nautilus-directory-private.h"
 #include "nautilus-file-attributes.h"
+#include "nautilus-file-changes-queue.h"
 #include "nautilus-file-private.h"
 #include "nautilus-file-utilities.h"
 #include "nautilus-global-preferences.h"
@@ -584,6 +585,47 @@
 
 }
 
+static gboolean call_consume_changes_idle_id = 0;
+
+static gboolean
+call_consume_changes_idle_cb (gpointer not_used)
+{
+	nautilus_file_changes_consume_changes (TRUE);
+	call_consume_changes_idle_id = 0;
+	return FALSE;
+}
+
+static void 
+monitor_notify_cb (GnomeVFSMonitorHandle    *handle,
+		   const gchar              *monitor_uri,
+		   const gchar              *info_uri,
+		   GnomeVFSMonitorEventType  event_type,
+		   gpointer                  user_data)
+{
+	switch (event_type) {
+	case GNOME_VFS_MONITOR_EVENT_CHANGED:
+		nautilus_file_changes_queue_file_changed (info_uri);
+		break;
+	case GNOME_VFS_MONITOR_EVENT_DELETED:
+		nautilus_file_changes_queue_file_removed (info_uri);
+		break;
+	case GNOME_VFS_MONITOR_EVENT_CREATED:
+		nautilus_file_changes_queue_file_added (info_uri);
+		break;
+
+	/* None of the following are supported yet */
+	case GNOME_VFS_MONITOR_EVENT_STARTEXECUTING:
+	case GNOME_VFS_MONITOR_EVENT_STOPEXECUTING:
+	case GNOME_VFS_MONITOR_EVENT_METADATA_CHANGED:
+		break;
+	}
+
+	if (call_consume_changes_idle_id == 0) {
+		call_consume_changes_idle_id = 
+			g_idle_add (call_consume_changes_idle_cb, NULL);
+	}
+}
+
 void
 nautilus_directory_monitor_add_internal (NautilusDirectory *directory,
 					 NautilusFile *file,
@@ -624,12 +666,20 @@
 	/* Start the "real" monitoring (FAM or whatever). */
 	if (file == NULL) {
 		if (directory->details->monitor == NULL) {
-			directory->details->monitor = nautilus_monitor_directory (directory->details->uri);
+			gnome_vfs_monitor_add (&directory->details->monitor,
+					       directory->details->uri,
+					       GNOME_VFS_MONITOR_DIRECTORY,
+					       monitor_notify_cb,
+					       NULL);
 		}
 	} else {
 		if (file->details->monitor == NULL) {
 			file_uri = nautilus_file_get_uri (file);
-			file->details->monitor = nautilus_monitor_file (file_uri);
+			gnome_vfs_monitor_add (&file->details->monitor,
+					       file_uri,
+					       GNOME_VFS_MONITOR_FILE,
+					       monitor_notify_cb,
+					       NULL);
 			g_free (file_uri);
 		}
 	}
@@ -1087,13 +1137,13 @@
 	if (file == NULL) {
 		if (directory->details->monitor != NULL
 		    && !find_any_monitor (directory, NULL)) {
-			nautilus_monitor_cancel (directory->details->monitor);
+			gnome_vfs_monitor_cancel (directory->details->monitor);
 			directory->details->monitor = NULL;
 		}
 	} else {
 		if (file->details->monitor != NULL
 		    && !find_any_monitor (directory, file)) {
-			nautilus_monitor_cancel (file->details->monitor);
+			gnome_vfs_monitor_cancel (file->details->monitor);
 			file->details->monitor = NULL;
 		}
 	}
Index: libnautilus-private/nautilus-directory-private.h
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-directory-private.h,v
retrieving revision 1.87
diff -u -r1.87 nautilus-directory-private.h
--- libnautilus-private/nautilus-directory-private.h	21 Feb 2002 19:26:46 -0000	1.87
+++ libnautilus-private/nautilus-directory-private.h	21 May 2002 04:12:13 -0000
@@ -60,7 +60,7 @@
 	GList *call_when_ready_list;
 	GList *monitor_list;
 
-	NautilusMonitor *monitor;
+	GnomeVFSMonitorHandle *monitor;
 
 	NautilusIdleQueue *idle_queue;
 	NautilusMetafileMonitor *metafile_monitor;
Index: libnautilus-private/nautilus-directory.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-directory.c,v
retrieving revision 1.236
diff -u -r1.236 nautilus-directory.c
--- libnautilus-private/nautilus-directory.c	7 Mar 2002 19:36:01 -0000	1.236
+++ libnautilus-private/nautilus-directory.c	21 May 2002 04:12:13 -0000
@@ -42,6 +42,7 @@
 #include <gtk/gtkmain.h>
 #include <gtk/gtksignal.h>
 #include <libgnomevfs/gnome-vfs-utils.h>
+#include <libgnomevfs/gnome-vfs-ops.h>
 
 enum {
 	FILES_ADDED,
@@ -178,7 +179,7 @@
 	}
 
 	if (directory->details->monitor != NULL) {
-		nautilus_monitor_cancel (directory->details->monitor);
+		gnome_vfs_monitor_cancel (directory->details->monitor);
 	}
 
 	if (directory->details->metafile_monitor != NULL) {
Index: libnautilus-private/nautilus-file-private.h
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-file-private.h,v
retrieving revision 1.43
diff -u -r1.43 nautilus-file-private.h
--- libnautilus-private/nautilus-file-private.h	14 Mar 2002 02:58:56 -0000	1.43
+++ libnautilus-private/nautilus-file-private.h	21 May 2002 04:12:13 -0000
@@ -66,7 +66,7 @@
 	GnomeVFSFileInfo *info;
 	GnomeVFSResult get_info_error;
 
-	NautilusMonitor *monitor;
+	GnomeVFSMonitorHandle *monitor;
 	
 	guint directory_count;
 
Index: libnautilus-private/nautilus-file.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-file.c,v
retrieving revision 1.290
diff -u -r1.290 nautilus-file.c
--- libnautilus-private/nautilus-file.c	17 May 2002 19:58:03 -0000	1.290
+++ libnautilus-private/nautilus-file.c	21 May 2002 04:12:13 -0000
@@ -49,6 +49,7 @@
 #include <libgnome/gnome-macros.h>
 #include <libgnomevfs/gnome-vfs-file-info.h>
 #include <libgnomevfs/gnome-vfs-mime-handlers.h>
+#include <libgnomevfs/gnome-vfs-ops.h>
 #include <libgnomevfs/gnome-vfs-utils.h>
 #include <libxml/parser.h>
 #include <pwd.h>
@@ -396,7 +397,7 @@
 	g_assert (file->details->operations_in_progress == NULL);
 
 	if (file->details->monitor != NULL) {
-		nautilus_monitor_cancel (file->details->monitor);
+		gnome_vfs_monitor_cancel (file->details->monitor);
 	}
 
 	nautilus_async_destroying_file (file);
Index: libnautilus-private/nautilus-file.h
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-file.h,v
retrieving revision 1.88
diff -u -r1.88 nautilus-file.h
--- libnautilus-private/nautilus-file.h	9 May 2002 19:49:32 -0000	1.88
+++ libnautilus-private/nautilus-file.h	21 May 2002 04:12:13 -0000
@@ -27,6 +27,7 @@
 
 #include <gtk/gtkobject.h>
 #include <libgnomevfs/gnome-vfs-types.h>
+#include <libgnomevfs/gnome-vfs-monitor.h>
 
 /* NautilusFile is an object used to represent a single element of a
  * NautilusDirectory. It's lightweight and relies on NautilusDirectory
Index: libnautilus-private/nautilus-monitor.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-monitor.c,v
retrieving revision 1.20
diff -u -r1.20 nautilus-monitor.c
--- libnautilus-private/nautilus-monitor.c	7 Mar 2002 04:17:50 -0000	1.20
+++ libnautilus-private/nautilus-monitor.c	21 May 2002 04:12:13 -0000
@@ -25,339 +25,41 @@
 
 #include <config.h>
 #include "nautilus-monitor.h"
+#include "nautilus-file-utilities.h"
 
-#include <eel/eel-glib-extensions.h>
-
-#ifdef HAVE_LIBFAM
-
-#include "nautilus-file-changes-queue.h"
-#include "nautilus-volume-monitor.h"
-#include <fam.h>
-#include <gdk/gdk.h>
-#include <gmodule.h>
 #include <libgnome/gnome-util.h>
 #include <libgnomevfs/gnome-vfs-utils.h>
+#include <libgnomevfs/gnome-vfs-ops.h>
 
-struct NautilusMonitor {
-	FAMRequest request;
-};
-
-static gboolean got_connection;
-
-static gboolean process_fam_notifications (GIOChannel *channel,
-					   GIOCondition cond,
-					   gpointer callback_data);
-
-/* singleton object, instantiate and connect if it doesn't already exist */
-static FAMConnection *
-get_fam_connection (void)
-{
-	static gboolean tried_connection;
-	static FAMConnection connection;
-	GIOChannel *ioc;
-	
-	/* Only try once. */
-        if (tried_connection) {
-		if (!got_connection) {
-			return NULL;
-		}
-	} else {
-                tried_connection = TRUE;
-		if (FAMOpen2 (&connection, "Nautilus") != 0) {
-			return NULL;
-		}
-
-		/* Make the main loop's select function watch the FAM
-                 * connection's file descriptor for us.
-		 */
-		ioc = g_io_channel_unix_new (FAMCONNECTION_GETFD (&connection));
-		g_io_add_watch (ioc, G_IO_IN | G_IO_HUP, process_fam_notifications, NULL);
-		g_io_channel_unref (ioc);
-
-		got_connection = TRUE;
-	}
-	return &connection;
-}
-
-static GHashTable *
-get_request_hash_table (void)
-{
-	static GHashTable *table;
-
-	if (table == NULL) {
-		table = eel_g_hash_table_new_free_at_exit
-			(NULL, NULL, "nautilus-monitor.c: FAM requests");
-	}
-	return table;
-}
-
-static char *
-get_event_uri (const FAMEvent *event)
+static void 
+fake_monitor_notify_cb (GnomeVFSMonitorHandle    *handle,
+			const gchar              *monitor_uri,
+			const gchar              *info_uri,
+			GnomeVFSMonitorEventType  event_type,
+			gpointer                  user_data)
 {
-        const char *base_path;
-	char *path, *uri;
-
-        /* FAM doesn't tell us when something is a full path and when
-	 * it's just partial so we have to look and see if it starts
-	 * with a /.
-	 */
-        if (event->filename[0] == '/') {
-                return gnome_vfs_get_uri_from_local_path (event->filename);
-        }
-
-	/* Look up the directory registry that was used for this file
-	 * notification and tack that on.
-	 */
-	base_path = g_hash_table_lookup (get_request_hash_table (),
-					 GINT_TO_POINTER (FAMREQUEST_GETREQNUM (&event->fr)));
-
-	/* base_path can be NULL if we've cancelled the monitor but still have
-	 * some change notifications in our queue. Just return NULL In that case.
-	 */
-	if (base_path == NULL) {
-		return NULL;
-	}
-
-	path = g_build_filename (base_path, event->filename, NULL);
-	uri = gnome_vfs_get_uri_from_local_path (path);
-	g_free (path);
-        return uri;
 }
 
-static gboolean
-process_fam_notifications (GIOChannel *channel,
-			   GIOCondition cond,
-			   gpointer callback_data)
-{
-        FAMConnection *connection;
-        FAMEvent event;
-	char *uri;
-
-        connection = get_fam_connection ();
-	g_return_val_if_fail (connection != NULL, FALSE);
-
-        /* Process all the pending events right now. */
-
-        while (FAMPending (connection)) {
-                if (FAMNextEvent (connection, &event) != 1) {
-                        g_warning ("connection to FAM died");
-                        FAMClose (connection);
-                        got_connection = FALSE;
-                        return FALSE;
-                }
-
-                switch (event.code) {
-                case FAMChanged:
-			uri = get_event_uri (&event);
-			if (uri == NULL) {
-				break;
-			}
-                        nautilus_file_changes_queue_file_changed (uri);
-			g_free (uri);
-                        break;
-
-                case FAMDeleted:
-			uri = get_event_uri (&event);
-			if (uri == NULL) {
-				break;
-			}
-                        nautilus_file_changes_queue_file_removed (uri);
-			g_free (uri);
-                        break;
-
-                case FAMCreated:                
-			uri = get_event_uri (&event);
-			if (uri == NULL) {
-				break;
-			}
-                        nautilus_file_changes_queue_file_added (uri);
-			g_free (uri);
-                        break;
-
-                case FAMStartExecuting:
-			/* Emitted when a file you are monitoring is
-			 * executed. This should work for both
-			 * binaries and shell scripts. Nautilus is not
-			 * doing anything with this yet.
-			 */
-			break;
-
-                case FAMStopExecuting:
-			/* Emitted when a file you are monitoring
-			 * ceases execution. Nautilus is not doing
-			 * anything with this yet.
-			 */
-			break;
-
-                case FAMAcknowledge:
-			/* Called in response to a successful
-			 * CancelMonitor. We don't need to do anything
-			 * with this information.
-			 */
-			break;
-
-                case FAMExists:
-			/* Emitted when you start monitoring a
-			 * directory. It tells you what's in the
-			 * directory. Unhandled because Nautilus
-			 * already handles this by calling
-			 * gnome_vfs_directory_load, which gives us
-			 * more information than merely the file name.
-			 */
-			break;
-
-                case FAMEndExist:
-			/* Emitted at the end of a FAMExists stream. */
-			break;
-
-                case FAMMoved:
-			/* FAMMoved doesn't need to be handled because
-			 * FAM never seems to generate this event on
-			 * Linux systems (with or without kernel
-			 * support). Instead it generates a FAMDeleted
-			 * followed by a FAMCreated.
-			 */
-			g_warning ("unexpected FAMMoved notification");
-			break;
-                }
-        }
-
-	nautilus_file_changes_consume_changes (TRUE);
-	
-	return TRUE;
-}
-
-static gboolean
-path_is_on_readonly_volume (const char *path)
-{
-	NautilusVolumeMonitor *volume_monitor;
-	NautilusVolume *volume;
-
-	volume_monitor = nautilus_volume_monitor_get ();
-	volume = nautilus_volume_monitor_get_volume_for_path (volume_monitor, path);
-	return (volume != NULL) && nautilus_volume_is_read_only (volume);
-}
-
-#endif /* HAVE_LIBFAM */
-
 gboolean
 nautilus_monitor_active (void)
 {
-#ifndef HAVE_LIBFAM
-	return FALSE;
-#else
-	return get_fam_connection () != NULL;
-#endif
-}
-
-NautilusMonitor *
-nautilus_monitor_file (const char *uri)
-{
-#ifndef HAVE_LIBFAM
-	return NULL;
-#else
-        FAMConnection *connection;
-        char *path;
-	NautilusMonitor *monitor;
-
-        connection = get_fam_connection ();
-	if (connection == NULL) {
-		return NULL;
-	}
-
-	path = gnome_vfs_get_local_path_from_uri (uri);
-	if (path == NULL) {
-		return NULL;
-	}
-
-	/* Check to see if the file system is readonly. If so, don't monitor --
-	 * there is no point, and we'll just keep the file system busy for
-	 * no reason, preventing unmounting
-	 */
-        if (path_is_on_readonly_volume (path)) {
-		g_free (path);
-		return NULL;
-	}
+	char *desktop_directory, *uri;
+	GnomeVFSResult result;
+	GnomeVFSMonitorHandle *handle;
 	
-	monitor = g_new0 (NautilusMonitor, 1);
-	FAMMonitorFile (connection, path, &monitor->request, NULL);
-
-	g_free (path);
-
-	return monitor;
-#endif
-}
-
-
-
-NautilusMonitor *
-nautilus_monitor_directory (const char *uri)
-{
-#ifndef HAVE_LIBFAM
-	return NULL;
-#else
-        FAMConnection *connection;
-        char *path;
-	NautilusMonitor *monitor;
-
-        connection = get_fam_connection ();
-	if (connection == NULL) {
-		return NULL;
-	}
-
-	path = gnome_vfs_get_local_path_from_uri (uri);
-	if (path == NULL) {
-		return NULL;
-	}
-        
-	/* Check to see if the file system is readonly. If so, don't monitor --
-	 * there is no point, and we'll just keep the file system busy for
-	 * no reason, preventing unmounting
-	 */
-        if (path_is_on_readonly_volume (path)) {
-		g_free (path);
-		return NULL;
-	}
-	
-	monitor = g_new0 (NautilusMonitor, 1);
-	FAMMonitorDirectory (connection, path, &monitor->request, NULL);
-
-	g_assert (g_hash_table_lookup (get_request_hash_table (),
-				       GINT_TO_POINTER (FAMREQUEST_GETREQNUM (&monitor->request))) == NULL);
-
-	g_hash_table_insert (get_request_hash_table (),
-			     GINT_TO_POINTER (FAMREQUEST_GETREQNUM (&monitor->request)),
-			     path);
-
-	return monitor;
-#endif
-}
-
-void
-nautilus_monitor_cancel (NautilusMonitor *monitor)
-{       
-#ifndef HAVE_LIBFAM
-	g_return_if_fail (monitor == NULL);
-#else
-        FAMConnection *connection;
-	int reqnum;
-	char *path;
-
-	if (monitor == NULL) {
-		return;
-	}
+	desktop_directory = nautilus_get_desktop_directory ();
+	uri = gnome_vfs_get_uri_from_local_path (desktop_directory);
 
-	reqnum = FAMREQUEST_GETREQNUM (&monitor->request);
-	path = g_hash_table_lookup (get_request_hash_table (),
-				    GINT_TO_POINTER (reqnum));
-	g_hash_table_remove (get_request_hash_table (),
-			     GINT_TO_POINTER (reqnum));
-	g_free (path);
+	result = gnome_vfs_monitor_add (&handle,
+					uri,
+					GNOME_VFS_MONITOR_DIRECTORY,
+					fake_monitor_notify_cb,
+					NULL);
+	if (result == GNOME_VFS_OK)
+		gnome_vfs_monitor_cancel (handle);
 
-        connection = get_fam_connection ();
-	g_return_if_fail (connection != NULL);
+	g_free (desktop_directory);
+	g_free (uri);
 
-	FAMCancelMonitor (connection, &monitor->request);
-	g_free (monitor);
-#endif
+	return result == GNOME_VFS_OK;
 }
Index: libnautilus-private/nautilus-monitor.h
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-monitor.h,v
retrieving revision 1.6
diff -u -r1.6 nautilus-monitor.h
--- libnautilus-private/nautilus-monitor.h	21 Feb 2002 19:26:47 -0000	1.6
+++ libnautilus-private/nautilus-monitor.h	21 May 2002 04:12:13 -0000
@@ -28,11 +28,6 @@
 
 #include <glib/gtypes.h>
 
-typedef struct NautilusMonitor NautilusMonitor;
-
 gboolean         nautilus_monitor_active    (void);
-NautilusMonitor *nautilus_monitor_file      (const char      *uri);
-NautilusMonitor *nautilus_monitor_directory (const char      *uri);
-void             nautilus_monitor_cancel    (NautilusMonitor *monitor);
 
 #endif /* NAUTILUS_MONITOR_H */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]