[Nautilus-list] fam/imon support, here it is



So I don't remember who has sent messages inquiring about fam support
for Nautilus, but if you're still on the list I have patches you can
try. I wrote them last night...so beware...but I'm tired and grumpy and
want them tested on more machines than just mine :-) The source is
pretty clean if you just want to read over the files.

put the nautilus-monitor.* files in libnautilus-extensions

The other file is a standard patch file.

Better yet, ask my on irc, I'll probably have something more fresh, I
started writing 9 hours ago so things are still pretty up in the air!
Basically I want people to beat on these really hard to see how deadly
they are to Nautilus. Its built in by extending a pre-existing feature,
so I hope for the best :) If you can't tell I've become largely
incoherent, so I'm going to go sleep.

It is know that text-preview doesn't update instantly when you change
files, I'm working on that right now. Also is that monitor
addition/cleanup is not symmetrical yet (this is a NautilusDirectory
problem, I believe, but it needs to be fixed). Any other reports of
problems would be greatly appreciated.

http://oss.sgi.com/projects/fam/ for fam & imon. (click download on the
left hand edge). If people want to try fam w/o imon I'd be interested in
that too...though you want get the blistering performance ;-)

-seth
? nautilus_patch
? cmon.out
? components/services/startup/Makefile
? components/services/startup/Makefile.in
? components/services/startup/nautilus-view/Makefile
? components/services/startup/nautilus-view/Makefile.in
? components/services/startup/nautilus-view/.deps
? components/services/startup/nautilus-view/.libs
? components/services/startup/nautilus-view/nautilus-service-startup-view
? libnautilus-extensions/nautilus-monitor.h
? libnautilus-extensions/nautilus-monitor.c
Index: configure.in
===================================================================
RCS file: /cvs/gnome/nautilus/configure.in,v
retrieving revision 1.155
diff -u -p -r1.155 configure.in
--- configure.in	2000/09/15 08:33:03	1.155
+++ configure.in	2000/09/16 18:02:43
@@ -32,6 +32,10 @@ dnl Check for different mount systems
 AC_CHECK_FUNCS(setmntent endmntent setenv unsetenv putenv)
 AC_CHECK_HEADERS(sys/mnttab.h sys/vfstab.h)
 
+dnl Check for fam (/imon) support
+AC_CHECK_HEADERS(fam.h)
+AC_CHECK_LIB(fam, FAMOpen, [FAM_LIBS="-lfam"])
+AC_SUBST(FAM_LIBS)
 
 dnl Tree view build as executable
 
@@ -467,8 +471,7 @@ if test "$GCC" = "yes" -a "$set_more_war
 	CFLAGS="$CFLAGS \
 	-Wall \
 	-Wchar-subscripts -Wmissing-declarations -Wmissing-prototypes \
-	-Wnested-externs -Wpointer-arith \
-	-Werror"
+	-Wnested-externs -Wpointer-arith"
 
 	for option in -Wsign-promo -Wno-sign-compare; do
 		SAVE_CFLAGS="$CFLAGS"
Index: libnautilus-extensions/Makefile.am
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-extensions/Makefile.am,v
retrieving revision 1.125
diff -u -p -r1.125 Makefile.am
--- libnautilus-extensions/Makefile.am	2000/09/14 18:34:49	1.125
+++ libnautilus-extensions/Makefile.am	2000/09/16 18:02:45
@@ -37,6 +37,7 @@ libnautilus_extensions_la_LDFLAGS=	\
 	$(BONOBO_PRINT_LIBS) 		\
 	$(GHTTP_LIBS) 			\
 	$(VFS_LIBS) 			\
+	$(FAM_LIBS)			\
 	$(XML_LIBS) 			\
 	$(MEDUSA_LIBS) 			\
 	$(LIBPNG) 			\
@@ -96,6 +97,7 @@ libnautilus_extensions_la_SOURCES = 		\
 	nautilus-list.c                         \
 	nautilus-merged-directory.c		\
 	nautilus-mime-actions.c			\
+	nautilus-monitor.c			\
 	nautilus-password-dialog.c		\
 	nautilus-preference.c			\
 	nautilus-preferences-box.c		\
@@ -192,6 +194,7 @@ noinst_HEADERS =				\
 	nautilus-merged-directory.h		\
 	nautilus-metadata.h			\
 	nautilus-mime-actions.h			\
+	nautilus-monitor.h			\
 	nautilus-password-dialog.h		\
 	nautilus-preference.h			\
 	nautilus-preferences-box.h		\
Index: libnautilus-extensions/nautilus-directory-async.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-extensions/nautilus-directory-async.c,v
retrieving revision 1.74
diff -u -p -r1.74 nautilus-directory-async.c
--- libnautilus-extensions/nautilus-directory-async.c	2000/09/14 19:31:03	1.74
+++ libnautilus-extensions/nautilus-directory-async.c	2000/09/16 18:02:46
@@ -32,6 +32,7 @@
 #include "nautilus-glib-extensions.h"
 #include "nautilus-global-preferences.h"
 #include "nautilus-link.h"
+#include "nautilus-monitor.h"
 #include "nautilus-search-uri.h"
 #include "nautilus-string.h"
 #include <gtk/gtkmain.h>
@@ -793,6 +794,8 @@ nautilus_directory_monitor_add_internal 
 	directory->details->monitor_list =
 		g_list_prepend (directory->details->monitor_list, monitor);
 
+	nautilus_monitor_add_directory (directory->details->uri);
+
 	/* Re-send the "files_added" signal for this set of files.
 	 * Old monitorers already know about them, but it's harmless
 	 * to hear about the same files again.
@@ -1040,6 +1043,8 @@ nautilus_directory_monitor_remove_intern
 
 	remove_monitor (directory, file, client);
 
+	nautilus_monitor_remove (directory->details->uri);
+
 	nautilus_directory_async_state_changed (directory);
 }
 
@@ -1643,6 +1648,7 @@ start_monitoring_file_list (NautilusDire
 		 DIRECTORY_LOAD_ITEMS_PER_CALLBACK,               /* items_per_notification */
 		 directory_load_callback,                         /* callback */
 		 directory);
+
 }
 
 /* Stop monitoring the file list if it is being monitored. */
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-

   nautilus-monitor.c: file and directory change monitoring for nautilus
 
   Copyright (C) 2000 Eazel, Inc.
  
   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation; either version 2 of the
   License, or (at your option) any later version.
  
   This program 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
   General Public License for more details.
  
   You should have received a copy of the GNU General Public
   License along with this program; if not, write to the
   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.
  
   Author: Seth Nickell <seth eazel com>
*/

#include <glib.h>

#if !HAVE_FAM_H
#include <fam.h>
#endif

#include <libgnomevfs/gnome-vfs-types.h>
#include <libgnomevfs/gnome-vfs-uri.h>
#include <stdio.h>
#include <string.h>

#include "nautilus-directory-notify.h"
#include "nautilus-file.h"
#include "nautilus-monitor.h"

#if !HAVE_FAM_H

static FAMConnection  *fam_connection;

static gboolean  tried_connection = FALSE;
static gboolean  connection_valid = TRUE;
static GList    *monitoring_list  = NULL;

typedef struct {
	char *uri;
	FAMRequest request;
} URIRequest;


/* FORWARD DECLARATIONS */
static void  nautilus_monitor_process_fam_notifications (gpointer data, gint fd, GdkInputCondition condition);


/* establish the initial connection with fam, called the first time the fam_connection */
/* object is "used" by one of the subfunctions                                         */
static gboolean
nautilus_monitor_establish_connection ()
{
	gboolean connection_valid;
	
	fam_connection = g_malloc0(sizeof(FAMConnection));

	/*  Connect to fam  */
	if (FAMOpen2(fam_connection, "Nautilus") != 0) {
		printf ("FAM_DEBUG: Nautilus failed to establish a link to the file alteration monitor\n");
		g_free(fam_connection);
		fam_connection = NULL;
		connection_valid = FALSE;
	} else {
		/* register our callback into the gtk loop */
		gdk_input_add(FAMCONNECTION_GETFD(fam_connection), GDK_INPUT_READ, 
			      nautilus_monitor_process_fam_notifications, NULL);
		connection_valid = TRUE;
	}

	return connection_valid;
}

/* singleton object, instantiate and connect if it doesn't already exist */
/* otherwise just pass back a reference to the existing fam_connection   */
static FAMConnection *
nautilus_monitor_get_fam ()
{
	if (tried_connection) {
		return fam_connection;
	} else {
		connection_valid = nautilus_monitor_establish_connection();
		tried_connection = TRUE;
		return fam_connection;
	}
}

/* give a request, find what path was used to create it */
static const char *
nautilus_monitor_find_path_from_request (GList *list, FAMRequest request) {
	URIRequest *uri_request;
	GList *p;
	gboolean found = FALSE;

	for (p = list; (p != NULL) && (!found); p = p->next) {
		uri_request = (URIRequest *)p->data;
		if (uri_request->request.reqnum == request.reqnum) {
			found = TRUE;
		}
	}
	if (found) {
		return uri_request->uri;
	} else {
		return NULL;
	}
}

/* given a path, find the registered "request" that deals with it */
static const FAMRequest
nautilus_monitor_find_request_from_path (GList *list, const char *path) {
	URIRequest *uri_request;
	GList *p;
	gboolean found = FALSE;
	FAMRequest fr;

	for (p = list; (p != NULL) && (!found); p = p->next) {
		uri_request = (URIRequest *)p->data;
		if (strcmp (uri_request->uri, path) == 0) {
			found = TRUE;
		}
	}
	if (found) {
		return uri_request->request;
	} else {
		fr.reqnum = -1;
		return fr;
	}
}

/* delete first entry found in list that matches path */
static void
nautilus_monitor_delete_first_request_found (GList *list, const char *path) {
	URIRequest *uri_request;
	GList *p, *last;
	gboolean found = FALSE;

	for (p = list; (p != NULL) && (!found); p = p->next) {
		uri_request = (URIRequest *)p->data;
		if (strcmp (uri_request->uri, path) == 0) {
			found = TRUE;
		}
	        last = p;
	}
	if (found) {
		g_free (uri_request->uri);
		g_free (uri_request);
		g_list_remove_link (list, last);
	}
}

static char *
nautilus_monitor_get_uri (char * file_name, FAMRequest fr)
{
	const char *base_uri;
	char *uri_string;

	/* FAM doesn't tell us when something is a full path, and when its just partial */
	/* so we have to look and see if it starts with a /                             */

	if (file_name[0] == '/') {
		uri_string = g_strdup_printf ("file://%s", file_name);
	} else {
		/* lookup the directory registry that was used for this file notification */
		/* and tack that on as a base uri fragment                                */
		base_uri = nautilus_monitor_find_path_from_request (monitoring_list, fr);
		uri_string = g_strdup_printf ("%s/%s", base_uri, file_name);
	}
	return uri_string;
}

static void
nautilus_monitor_process_fam_notifications (gpointer data, gint fd, GdkInputCondition condition)
{
	FAMConnection *fam;
	FAMEvent fam_event;	
	NautilusFile *file;
	char *uri_string;
	GList *uri_list;

	/* get singleton object */
	fam = nautilus_monitor_get_fam ();

        /*  We want to read as many events as are available. */
        while (FAMPending(fam)) {

		if (FAMNextEvent(fam, &fam_event) != 1) {
			printf ("FAM-DEBUG: Nautilus' link to fam died\n");
			gdk_input_remove(fd);
			FAMClose(fam);
			g_free(fam);
			connection_valid = FALSE;
			return;
		}
		
		switch (fam_event.code) {
		case FAMChanged:
			uri_string = nautilus_monitor_get_uri (fam_event.filename, fam_event.fr);
			printf ("FAMChanged : %s\n", uri_string);

			file = nautilus_file_get (uri_string);
			nautilus_file_changed (file);

			nautilus_file_unref (file);
			break;
		case FAMDeleted:
			uri_string = nautilus_monitor_get_uri (fam_event.filename, fam_event.fr);
			printf ("FAMDeleted : %s\n", uri_string);

			uri_list = NULL;
			uri_list = g_list_append (uri_list, uri_string);

			nautilus_directory_notify_files_removed (uri_list);

			g_free (uri_string);
			g_list_free (uri_list);
			break;
		case FAMCreated:		
			uri_string = nautilus_monitor_get_uri (fam_event.filename, fam_event.fr);
			printf ("FAMCreated : %s\n", uri_string);

			uri_list = NULL;
			uri_list = g_list_append (uri_list, uri_string);			

			nautilus_directory_notify_files_added (uri_list);
			
			g_free (uri_string);
			g_list_free (uri_list);
			break;
		case FAMStartExecuting:
		case FAMStopExecuting:
		case FAMAcknowledge:
		case FAMExists:
		case FAMEndExist:
		case FAMMoved:
		}
	}
}

#endif /* !HAVE_FAM_H */



void
nautilus_monitor_add_file (const char *uri_string)
{

#if !HAVE_FAM_H

	const char *uri_scheme;
	char *path_name;
	GnomeVFSURI *uri;
	FAMConnection *fam;
	URIRequest *uri_request;
	
	/* get singleton object for connection */
	fam = nautilus_monitor_get_fam ();

	/* only try connecting once */
	if (!connection_valid) return;
	
	uri = gnome_vfs_uri_new (uri_string);
	uri_scheme = gnome_vfs_uri_get_scheme (uri);

	/* remove crufty entries registered for this URI */
	/* FIXME: this breaks multiple windows? */
	/* nautilus_monitor_remove (uri_string); */

	/* we only know how to deal with things on the local filesystem for now */
	if (strcmp (uri_scheme, "file") == 0) {
		uri_request = g_new (URIRequest,1);
		path_name = strdup (gnome_vfs_uri_get_path (uri));
		FAMMonitorFile(fam, path_name, &uri_request->request, 0);

		printf ("ADDED : %d) file monitor for %s\n", uri_request->request.reqnum, uri_string);
		uri_request->uri = strdup (uri_string);
		/* add this URI to the "Things we watch" list */
		monitoring_list = g_list_append (monitoring_list, uri_request);
	}

	g_free (path_name);
	gnome_vfs_uri_unref (uri);

#endif /* !HAVE_FAM_H */

}



void
nautilus_monitor_add_directory (const char *uri_string)
{

#if !HAVE_FAM_H

	const char *uri_scheme;
	char *path_name;
	GnomeVFSURI *uri;
	FAMConnection *fam;
	URIRequest *uri_request;

	fam = nautilus_monitor_get_fam ();

	/* only try connection once */
	if (!connection_valid) return;
	
	uri = gnome_vfs_uri_new (uri_string);
	uri_scheme = gnome_vfs_uri_get_scheme (uri);

	/* remove crufty entries registered for this URI */
	/* FIXME: this breaks multiple windows? */
	/* nautilus_monitor_remove (uri_string); */

	/* we only know how to deal with things on the local filesystem for now */
	if (strcmp (uri_scheme, "file") == 0) {
	        uri_request = g_new (URIRequest, 1);
		path_name = strdup (gnome_vfs_uri_get_path (uri));
		FAMMonitorDirectory(fam, path_name, &uri_request->request, 0);

		printf ("ADDED : %d) directory monitor for %s\n", uri_request->request.reqnum, uri_string);
                uri_request->uri = strdup (uri_string);
		/* add this uri to our list of "things we watch" */
		monitoring_list = g_list_append (monitoring_list, uri_request);
	}

      	g_free (path_name);
	gnome_vfs_uri_unref (uri);

#endif /* !HAVE_FAM_H */

}

void
nautilus_monitor_remove (const char *uri)
{	

#if !HAVE_FAM_H

	FAMConnection *fam;
	FAMRequest request, request2;
	GnomeVFSURI *real_uri;
	const char *uri_scheme;
	int code;

	fam = nautilus_monitor_get_fam ();

	/* only try connecting once */
	if (!connection_valid) return;

	real_uri = gnome_vfs_uri_new (uri);
	uri_scheme = gnome_vfs_uri_get_scheme (real_uri);
	gnome_vfs_uri_unref (real_uri);

	if (strcmp (uri_scheme, "file") == 0) {
		/* keep looking for entries and deleting them */
		request = nautilus_monitor_find_request_from_path (monitoring_list, uri);
		while (request.reqnum != -1) {
			request2 = request;
			code = FAMCancelMonitor (fam, &request);
			printf ("REMOVED : %d) directory monitor for %s (return %d)\n", request2.reqnum, uri, code);
			nautilus_monitor_delete_first_request_found (monitoring_list, uri);
			request = nautilus_monitor_find_request_from_path (monitoring_list, uri);
		}
	}

#endif /* !HAVE_FAM_H */

}
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-

   nautilus-monitor.h: file and directory change monitoring for nautilus
 
   Copyright (C) 2000 Eazel, Inc.
  
   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation; either version 2 of the
   License, or (at your option) any later version.
  
   This program 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
   General Public License for more details.
  
   You should have received a copy of the GNU General Public
   License along with this program; if not, write to the
   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.
  
   Author: Seth Nickell <seth eazel com>
*/

#include <glib.h>
#include <gtk/gtk.h>

void      nautilus_monitor_add_file                       (const char *uri_string);
void      nautilus_monitor_add_directory                  (const char *uri_string);
void      nautilus_monitor_remove                         (const char *uri_string);


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