FAM/gamin support for ROX-Filer
Ben Morrow <[email protected]>
| Newsgroups | gmane.comp.desktop.rox.devel |
|---|---|
| Message-ID | <[email protected]> |
For the benefit of those of us not on Linux, I've patched ROX-Filer to use FAM to watch for changes. This patch also increases the rescan timeout to 5 seconds, as I found that having a filer window rescan every half second (because something is continuously changing) causes it to start eating all the CPU. I don't know if this isn't an issue with dnotify for some reason, or if this should be made a config option. Tested on FreeBSD with gamin 0.1.9. Ben ------------------------------------------------------------------------- Check out the new SourceForge.net Marketplace. It's the best place to buy or sell services for just about anything Open Source. http://sourceforge.net/services/buy/index.php _______________________________________________ rox-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/rox-devel
fam.patch
(text/x-diff, 9.1 KB)
diff --git a/ROX-Filer/src/config.h.in b/ROX-Filer/src/config.h.in
index d5bbc01..00c4b0c 100644
--- a/ROX-Filer/src/config.h.in
+++ b/ROX-Filer/src/config.h.in
@@ -33,6 +33,10 @@
#undef HAVE_SYS_XATTR_H
#undef HAVE_ATTR_XATTR_H
+#undef HAVE_FAM_H
+#undef HAVE_FAM
+#undef HAVE_FAMNOEXISTS
+
/* Enable extensions - used for dnotify support */
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
diff --git a/ROX-Filer/src/configure.in b/ROX-Filer/src/configure.in
index 12a31f7..97ccb05 100644
--- a/ROX-Filer/src/configure.in
+++ b/ROX-Filer/src/configure.in
@@ -94,6 +94,16 @@ ROX_REQUIRE(libxml-2.0, 2.0.0)
ROX_REQUIRE(libglade-2.0, 2.0.0)
ROX_REQUIRE(shared-mime-info, 0.14)
+AC_MSG_CHECKING(if gamin is installed)
+if "$PKG_CONFIG" gamin ; then
+ AC_MSG_RESULT(yes)
+ CPPFLAGS="$CPPFLAGS `$PKG_CONFIG --cflags gamin`"
+ CFLAGS="$CFLAGS `$PKG_CONFIG --cflags gamin`"
+ LIBS="$LDFLAGS `$PKG_CONFIG --libs gamin`"
+else
+ AC_MSG_RESULT(no)
+fi
+
GTK_VERSION=`"$PKG_CONFIG" --modversion gtk+-2.0`
AC_DEFINE_UNQUOTED(GTK_VERSION, "$GTK_VERSION")
@@ -112,6 +122,7 @@ if test x$no_x = xyes ; then
fi
LIBS="$LIBS $X_LIBS -lX11 $X_EXTRA_LIBS"
CFLAGS="$CFLAGS $X_CFLAGS"
+CPPFLAGS="$CPPFLAGS $X_CFLAGS"
dnl Does file(1) support '-b' ?
AC_MSG_CHECKING(whether file -b works)
@@ -157,7 +168,15 @@ dnl Checks for header files.
AC_HEADER_DIRENT
AC_HEADER_STDC
AC_HEADER_SYS_WAIT
-AC_CHECK_HEADERS(fcntl.h sys/time.h unistd.h mntent.h sys/ucred.h sys/mntent.h apsymbols.h apbuild/apsymbols.h sys/statvfs.h sys/vfs.h wctype.h libintl.h)
+AC_CHECK_HEADERS(fcntl.h sys/time.h unistd.h mntent.h sys/param.h sys/types.h sys/mntent.h apsymbols.h apbuild/apsymbols.h sys/statvfs.h sys/vfs.h wctype.h libintl.h)
+AC_CHECK_HEADERS([sys/ucred.h], [], [],
+[#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+])
AC_CHECK_HEADER([X11/SM/SMlib.h], [],
[AC_MSG_ERROR([Session management library (libsm) missing. It is part of the X server distribution. Try installing the libsm-dev package.])]
@@ -181,6 +200,11 @@ dnl Check for extended attribute support
AC_CHECK_FUNCS(attropen getxattr)
AC_CHECK_HEADERS(attr/xattr.h sys/xattr.h)
+dnl Check for FAM/gamin support
+AC_CHECK_HEADERS(fam.h)
+AC_SEARCH_LIBS([FAMOpen], [fam], [AC_DEFINE(HAVE_FAM)], [])
+AC_CHECK_FUNCS(FAMNoExists)
+
dnl Extract version info from AppInfo.xml
AC_MSG_CHECKING(extracting version information)
[
diff --git a/ROX-Filer/src/dir.c b/ROX-Filer/src/dir.c
index fa820cf..1d7124d 100644
--- a/ROX-Filer/src/dir.c
+++ b/ROX-Filer/src/dir.c
@@ -94,8 +94,10 @@ static GPtrArray *hash_to_array(GHashTable *hash);
static void dir_force_update_item(Directory *dir, const gchar *leaf);
static Directory *dir_new(const char *pathname);
static void dir_rescan(Directory *dir);
-#ifdef USE_DNOTIFY
+#if defined(USE_DNOTIFY) || defined(HAVE_FAM)
static void dir_rescan_soon(Directory *dir);
+#endif
+#ifdef USE_DNOTIFY
static void dnotify_handler(int sig, siginfo_t *si, void *data);
#endif
@@ -173,6 +175,24 @@ void dir_attach(Directory *dir, DirCallback callback, gpointer data)
}
}
#endif
+
+#ifdef HAVE_FAM
+ if (fam_open && !dir->users)
+ {
+ FAMRequest fr;
+
+ if (dir->fam_reqnum != -1)
+ g_warning("dir_attach: fam error\n");
+
+ if (FAMMonitorDirectory(
+ &fam_conn, dir->pathname,
+ &fr, dir
+ ) == 0)
+ {
+ dir->fam_reqnum = fr.reqnum;
+ }
+ }
+#endif
dir->users = g_list_prepend(dir->users, user);
@@ -226,6 +246,25 @@ void dir_detach(Directory *dir, DirCallback callback, gpointer data)
dir->dnotify_fd = -1;
}
#endif
+
+#ifdef HAVE_FAM
+ if (!dir->users && dir->fam_reqnum != -1)
+ {
+ FAMRequest fr;
+
+ if (fam_open)
+ {
+ fr.reqnum = dir->fam_reqnum;
+ if (FAMCancelMonitor(&fam_conn, &fr) < 0)
+ g_warning("dir_detach: FAMCancelMonitor failed\n");
+ }
+ else {
+ g_warning("dir_detach: fam not open\n");
+ }
+ dir->fam_reqnum = -1;
+ }
+#endif
+
return;
}
}
@@ -498,11 +537,36 @@ void dnotify_wakeup(void)
}
#endif
+#ifdef HAVE_FAM
+void fam_wakeup(void)
+{
+ FAMEvent ev;
+
+ while (FAMPending(&fam_conn))
+ {
+ if (FAMNextEvent(&fam_conn, &ev) < 0)
+ g_warning("fam_wakeup: fam error\n");
+
+ switch (ev.code) {
+ case FAMChanged:
+ case FAMDeleted:
+ case FAMCreated:
+ case FAMMoved:
+ dir_rescan_soon(ev.userdata);
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+#endif
+
/****************************************************************
* INTERNAL FUNCTIONS *
****************************************************************/
-#ifdef USE_DNOTIFY
+#if defined(USE_DNOTIFY) || defined(HAVE_FAM)
static gint rescan_soon_timeout(gpointer data)
{
Directory *dir = (Directory *) data;
@@ -522,7 +586,7 @@ static void dir_rescan_soon(Directory *dir)
{
if (dir->rescan_timeout != -1)
return;
- dir->rescan_timeout = g_timeout_add(500, rescan_soon_timeout, dir);
+ dir->rescan_timeout = g_timeout_add(5000, rescan_soon_timeout, dir);
}
#endif
@@ -902,6 +966,9 @@ static void directory_init(GTypeInstance *object, gpointer gclass)
#ifdef USE_DNOTIFY
dir->dnotify_fd = -1;
#endif
+#ifdef HAVE_FAM
+ dir->fam_reqnum = -1;
+#endif
dir->new_items = g_ptr_array_new();
dir->up_items = g_ptr_array_new();
diff --git a/ROX-Filer/src/dir.h b/ROX-Filer/src/dir.h
index a66e413..5a1de8e 100644
--- a/ROX-Filer/src/dir.h
+++ b/ROX-Filer/src/dir.h
@@ -14,7 +14,7 @@
#include <fcntl.h>
/* Check for dnotify support */
-#if defined(DN_MULTISHOT) && defined(SIGRTMIN)
+#if !defined(HAVE_FAM) && defined(DN_MULTISHOT) && defined(SIGRTMIN)
# define USE_DNOTIFY
extern gboolean dnotify_wakeup_flag;
#endif
@@ -87,6 +87,10 @@ struct _Directory
#ifdef USE_DNOTIFY
int dnotify_fd; /* -1 if not watching */
#endif
+
+#ifdef HAVE_FAM
+ int fam_reqnum; /* -1 if not watching */
+#endif
};
void dir_init(void);
@@ -99,6 +103,7 @@ DirItem *dir_update_item(Directory *dir, const gchar *leafname);
void dir_merge_new(Directory *dir);
void dir_force_update_path(const gchar *path);
void dnotify_wakeup(void);
+void fam_wakeup(void);
void dir_drop_all_dnotifies(void);
void dir_queue_recheck(Directory *dir, DirItem *item);
diff --git a/ROX-Filer/src/main.c b/ROX-Filer/src/main.c
index 0522fee..1abfe79 100644
--- a/ROX-Filer/src/main.c
+++ b/ROX-Filer/src/main.c
@@ -88,6 +88,11 @@ const gchar *show_user_message = NULL;
int home_dir_len;
const char *home_dir, *app_dir;
+#ifdef HAVE_FAM
+FAMConnection fam_conn;
+int fam_open = 0;
+#endif
+
GtkTooltips *tooltips = NULL;
#define COPYING \
@@ -618,6 +623,23 @@ int main(int argc, char **argv)
/* If the pipe is full then we're going to get woken up anyway... */
set_blocking(to_wakeup_pipe, FALSE);
+ /* Set up fam */
+#ifdef HAVE_FAM
+ if (FAMOpen(&fam_conn) == 0)
+ {
+ fam_open = 1;
+
+#ifdef HAVE_FAMNOEXISTS
+ FAMNoExists(&fam_conn);
+#endif
+
+ gdk_input_add_full(
+ FAMCONNECTION_GETFD(&fam_conn), GDK_INPUT_READ,
+ wake_up_cb, NULL, NULL
+ );
+ }
+#endif
+
/* Let child processes die */
act.sa_handler = child_died;
sigemptyset(&act.sa_mask);
@@ -651,6 +673,10 @@ int main(int argc, char **argv)
if (number_of_windows > 0)
gtk_main();
+#ifdef HAVE_FAM
+ FAMClose(&fam_conn);
+#endif
+
return EXIT_SUCCESS;
}
@@ -701,6 +727,13 @@ static void show_features(void)
#else
_("No")
#endif
+ );
+ g_print("%s... %s\n", _("FAM support"),
+#ifdef HAVE_FAM
+ _("Yes")
+#else
+ _("No")
+#endif
);
g_print("%s... %s\n", _("Binary compatibility"),
#if defined(HAVE_APSYMBOLS_H) || defined(HAVE_APBUILD_APSYMBOLS_H)
@@ -808,6 +841,11 @@ static void wake_up_cb(gpointer data, gint source, GdkInputCondition condition)
{
char buf[BUFLEN];
+#ifdef HAVE_FAM
+ if (source == FAMCONNECTION_GETFD(&fam_conn))
+ fam_wakeup();
+ else
+#endif
read(source, buf, BUFLEN);
if (child_died_flag)
diff --git a/ROX-Filer/src/main.h b/ROX-Filer/src/main.h
index 44262ca..83d2313 100644
--- a/ROX-Filer/src/main.h
+++ b/ROX-Filer/src/main.h
@@ -9,6 +9,10 @@
#include <sys/types.h>
#include <gtk/gtk.h>
+#ifdef HAVE_FAM_H
+#include <fam.h>
+#endif
+
typedef struct _Callback Callback;
typedef void (*CallbackFn)(gpointer data);
@@ -33,6 +37,11 @@ extern int home_dir_len;
extern const char *home_dir, *app_dir;
extern Option o_dnd_no_hostnames;
+#ifdef HAVE_FAM
+extern FAMConnection fam_conn;
+extern int fam_open;
+#endif
+
/* Prototypes */
int main(int argc, char **argv);
void on_child_death(gint child, CallbackFn callback, gpointer data);