Re: PATCH: use gnome-vfs for monitoring files



Hi,

Second try.  Brings back the nautilus-monitor apis, so we can check for
a read-only volume.  Also caches result of nautilus_monitor_active().

-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.5314
diff -u -r1.5314 ChangeLog
--- ChangeLog	21 May 2002 18:24:16 -0000	1.5314
+++ ChangeLog	21 May 2002 21:12:50 -0000
@@ -1,3 +1,12 @@
+2002-05-21  Alex Graveley  <alex ximian com>
+
+	* libnautilus-private/nautilus-monitor.[ch]: Convert to using
+	gnome-vfs monitors.  nautilus_monitor_active() now checks if FAM
+	can be used by creating a monitor for the user's desktop
+	directory, and caches this if successful.  Adds an idle handler to
+	call nautilus_file_changes_consume_changes(), so multiple file
+	changes have a chance of being chunked together.
+
 2002-05-21  Frank Worsley  <fworsley shaw ca>
 
 	* libnautilus-private/nautilus-link-desktop-file.c:
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 21:12:50 -0000
@@ -25,206 +25,44 @@
 
 #include <config.h>
 #include "nautilus-monitor.h"
-
-#include <eel/eel-glib-extensions.h>
-
-#ifdef HAVE_LIBFAM
-
 #include "nautilus-file-changes-queue.h"
+#include "nautilus-file-utilities.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;
+	GnomeVFSMonitorHandle *handle;
 };
 
-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)
+gboolean
+nautilus_monitor_active (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);
+	static gboolean tried_monitor = FALSE;
+	static gboolean monitor_success;
 
-		got_connection = TRUE;
-	}
-	return &connection;
-}
+	if (tried_monitor == FALSE) {
+		char *desktop_directory, *uri;
+		NautilusMonitor *monitor;
+	
+		desktop_directory = nautilus_get_desktop_directory ();
+		uri = gnome_vfs_get_uri_from_local_path (desktop_directory);
 
-static GHashTable *
-get_request_hash_table (void)
-{
-	static GHashTable *table;
+		monitor = nautilus_monitor_directory (uri);
+		monitor_success = (monitor != NULL);
 
-	if (table == NULL) {
-		table = eel_g_hash_table_new_free_at_exit
-			(NULL, NULL, "nautilus-monitor.c: FAM requests");
-	}
-	return table;
-}
+		if (monitor != NULL)
+			nautilus_monitor_cancel (monitor);
 
-static char *
-get_event_uri (const FAMEvent *event)
-{
-        const char *base_path;
-	char *path, *uri;
+		g_free (desktop_directory);
+		g_free (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;
+		tried_monitor = TRUE;
 	}
 
-	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;
+	return monitor_success;
 }
 
 static gboolean
@@ -234,130 +72,103 @@
 	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);
+	volume = nautilus_volume_monitor_get_volume_for_path (volume_monitor, 
+							      path);
+	if (volume != NULL)
+		return nautilus_volume_is_read_only (volume);
+	else
+		return FALSE;
 }
 
-#endif /* HAVE_LIBFAM */
+static gboolean call_consume_changes_idle_id = 0;
 
-gboolean
-nautilus_monitor_active (void)
+static gboolean
+call_consume_changes_idle_cb (gpointer not_used)
 {
-#ifndef HAVE_LIBFAM
+	nautilus_file_changes_consume_changes (TRUE);
+	call_consume_changes_idle_id = 0;
 	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;
+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);
 	}
+}
 
-	path = gnome_vfs_get_local_path_from_uri (uri);
-	if (path == NULL) {
-		return NULL;
-	}
+static NautilusMonitor *
+monitor_add_internal (const char *uri, gboolean is_directory)
+{
+	gchar *path;
+	NautilusMonitor *ret;
+	GnomeVFSResult result;
 
-	/* 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)) {
+	path = gnome_vfs_get_local_path_from_uri (uri);
+	if (path && path_is_on_readonly_volume (path)) {
 		g_free (path);
 		return NULL;
 	}
-	
-	monitor = g_new0 (NautilusMonitor, 1);
-	FAMMonitorFile (connection, path, &monitor->request, NULL);
-
 	g_free (path);
 
-	return monitor;
-#endif
-}
+	ret = g_new0 (NautilusMonitor, 1);
 
+	result = gnome_vfs_monitor_add (&ret->handle,
+					uri,
+					is_directory == TRUE ?  
+						GNOME_VFS_MONITOR_DIRECTORY :
+						GNOME_VFS_MONITOR_FILE,
+					monitor_notify_cb,
+					NULL);
+	if (result != GNOME_VFS_OK) {
+		g_free (ret);
+		return NULL;
+	}
 
+	return ret;
+}
 
 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_add_internal (uri, TRUE);
+}
 
-	return monitor;
-#endif
+NautilusMonitor *
+nautilus_monitor_file (const char *uri)
+{
+	return monitor_add_internal (uri, FALSE);
 }
 
-void
+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;
-	}
-
-	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);
-
-        connection = get_fam_connection ();
-	g_return_if_fail (connection != NULL);
+{
+	if (monitor->handle != NULL)
+		gnome_vfs_monitor_cancel (monitor->handle);
 
-	FAMCancelMonitor (connection, &monitor->request);
 	g_free (monitor);
-#endif
 }


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