Re: Rox's directory caching
Stephen Watson <[email protected]> Fri, 29 Aug 2008 12:46:59 +0100
| Newsgroups | gmane.comp.desktop.rox.devel |
|---|---|
| Message-ID | <[email protected]> |
Stephen Watson <[email protected]> wrote: > "Thomas Leonard" <[email protected]> wrote: > > > >> 2008/8/17 Stephen Watson <[email protected]>: > > >> > dnotify stopped working for me when I upgraded from SuSE 10.2 to > 11.0. > > > As > > >> > far as I can tell it compiles with dnotify support, it just doesn't > > > notice > > >> > when the directory changes. > > Maybe it's in a separate package? The Ubuntu command comes from the > > "dnotify" package. > > No such package in SuSE 11. There's an iwatch for inotify but nothing for > dnotify. I wonder if SuSE have given up on dnotify. This patch adds inotify support, overriding the dnotify support at compile time. -- Stephen Watson http://www.kerofin.demon.co.uk/ If you read this on a mailing list, send any reply back to the list and not to me. Not even CC. Forget the shooty dog thing. ------------------------------------------------------------------------- This SF.Net email is sponsored by the Moblin Your Move Developer's challenge Build the coolest Linux based applications with Moblin SDK & win great prizes Grand prize is a trip for two to an Open Source event anywhere in the world http://moblin-contest.org/redirect.php?banner_id=100&url=/ _______________________________________________ rox-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/rox-devel
0011-Use-inotify-to-monitor-directories-when-available-i.patch
(application/octet-stream, 9.9 KB)
From e97ee6b37a8d62145e0034aafd4da797e57f16b2 Mon Sep 17 00:00:00 2001 From: Stephen Watson <[email protected]> Date: Fri, 22 Aug 2008 22:19:04 +0100 Subject: [PATCH] Use inotify to monitor directories when available, in preference to dnotify. --- ROX-Filer/src/action.c | 2 +- ROX-Filer/src/config.h.in | 1 + ROX-Filer/src/configure.in | 2 +- ROX-Filer/src/dir.c | 143 +++++++++++++++++++++++++++++++++++++------- ROX-Filer/src/dir.h | 20 +++++-- ROX-Filer/src/main.c | 7 ++ 6 files changed, 145 insertions(+), 30 deletions(-) diff --git a/ROX-Filer/src/action.c b/ROX-Filer/src/action.c index e4f7dce..7179519 100644 --- a/ROX-Filer/src/action.c +++ b/ROX-Filer/src/action.c @@ -818,7 +818,7 @@ static GUIside *start_action(GtkWidget *abox, ActionChild *func, gpointer data, quiet = autoq; - dir_drop_all_dnotifies(); + dir_drop_all_notifies(); /* Reset the SIGCHLD handler */ act.sa_handler = SIG_DFL; diff --git a/ROX-Filer/src/config.h.in b/ROX-Filer/src/config.h.in index d5bbc01..5bb2428 100644 --- a/ROX-Filer/src/config.h.in +++ b/ROX-Filer/src/config.h.in @@ -20,6 +20,7 @@ #undef HAVE_SYS_VFS_H #undef HAVE_SYS_STATVFS_H #undef HAVE_LIBINTL_H +#undef HAVE_SYS_INOTIFY_H #undef HAVE_MBRTOWC #undef HAVE_WCTYPE_H diff --git a/ROX-Filer/src/configure.in b/ROX-Filer/src/configure.in index c47db4b..a9ab9d2 100644 --- a/ROX-Filer/src/configure.in +++ b/ROX-Filer/src/configure.in @@ -164,7 +164,7 @@ 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/ucred.h sys/mntent.h apsymbols.h apbuild/apsymbols.h sys/statvfs.h sys/vfs.h wctype.h libintl.h sys/inotify.h) 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.])] diff --git a/ROX-Filer/src/dir.c b/ROX-Filer/src/dir.c index fa820cf..1172c2e 100644 --- a/ROX-Filer/src/dir.c +++ b/ROX-Filer/src/dir.c @@ -69,11 +69,18 @@ #include "usericons.h" #include "main.h" +#ifdef USE_NOTIFY +static GHashTable *notify_fd_to_dir = NULL; +#endif +#ifdef USE_INOTIFY +# include <sys/inotify.h> +GIOChannel *inotify_channel; +static int inotify_fd; +#endif #ifdef USE_DNOTIFY /* Newer Linux kernels can tell us when the directories we are watching * change, using the dnotify system. */ -static GHashTable *dnotify_fd_to_dir = NULL; gboolean dnotify_wakeup_flag = FALSE; static int dnotify_last_fd = -1; #endif @@ -94,9 +101,14 @@ 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 +#ifdef USE_NOTIFY static void dir_rescan_soon(Directory *dir); +# ifdef USE_INOTIFY +static gboolean inotify_handler(GIOChannel *source, GIOCondition condition, + gpointer udata); +# else static void dnotify_handler(int sig, siginfo_t *si, void *data); +# endif #endif /**************************************************************** @@ -108,8 +120,16 @@ void dir_init(void) dir_cache = g_fscache_new((GFSLoadFunc) dir_new, (GFSUpdateFunc) update, NULL); - /* Check for dnotify support in the kernel */ -#ifdef USE_DNOTIFY +#ifdef USE_NOTIFY + notify_fd_to_dir = g_hash_table_new(NULL, NULL); + +# ifdef USE_INOTIFY + inotify_fd = inotify_init(); + inotify_channel = g_io_channel_unix_new(inotify_fd); + g_io_add_watch(inotify_channel, G_IO_IN, inotify_handler, NULL); +# endif + +# ifdef USE_DNOTIFY { struct sigaction act; @@ -126,8 +146,8 @@ void dir_init(void) act.sa_flags = 0; sigaction(SIGIO, &act, NULL); - dnotify_fd_to_dir = g_hash_table_new(NULL, NULL); } +# endif #endif } @@ -151,21 +171,45 @@ void dir_attach(Directory *dir, DirCallback callback, gpointer data) user->callback = callback; user->data = data; +#ifdef USE_INOTIFY + if (!dir->users) + { + int fd; + + if (dir->notify_fd != -1) + g_warning("dir_attach: inotify error\n"); + + fd = inotify_add_watch( inotify_fd, + dir->pathname, + IN_CREATE | IN_DELETE | IN_MOVE | + IN_ATTRIB); + + g_return_if_fail(g_hash_table_lookup(notify_fd_to_dir, + GINT_TO_POINTER(fd)) == NULL); + if (fd != -1) + { + + dir->notify_fd = fd; + g_hash_table_insert(notify_fd_to_dir, + GINT_TO_POINTER(fd), dir); + } + } +#endif #ifdef USE_DNOTIFY if (!dir->users) { int fd; - if (dir->dnotify_fd != -1) + if (dir->notify_fd != -1) g_warning("dir_attach: dnotify error\n"); fd = open(dir->pathname, O_RDONLY); - g_return_if_fail(g_hash_table_lookup(dnotify_fd_to_dir, + g_return_if_fail(g_hash_table_lookup(notify_fd_to_dir, GINT_TO_POINTER(fd)) == NULL); if (fd != -1) { - dir->dnotify_fd = fd; - g_hash_table_insert(dnotify_fd_to_dir, + dir->notify_fd = fd; + g_hash_table_insert(notify_fd_to_dir, GINT_TO_POINTER(fd), dir); fcntl(fd, F_SETSIG, SIGRTMIN); fcntl(fd, F_NOTIFY, DN_CREATE | DN_DELETE | DN_RENAME | @@ -217,14 +261,22 @@ void dir_detach(Directory *dir, DirCallback callback, gpointer data) /* May stop scanning if noone's watching */ set_idle_callback(dir); -#ifdef USE_DNOTIFY - if (!dir->users && dir->dnotify_fd != -1) +#ifdef USE_NOTIFY + if (!dir->users && dir->notify_fd != -1) { - close(dir->dnotify_fd); - g_hash_table_remove(dnotify_fd_to_dir, - GINT_TO_POINTER(dir->dnotify_fd)); - dir->dnotify_fd = -1; +# ifdef USE_DNOTIFY + close(dir->notify_fd); +# endif + g_hash_table_remove(notify_fd_to_dir, + GINT_TO_POINTER(dir->notify_fd)); + dir->notify_fd = -1; } +# ifdef USE_INOTIFY + if (dir->inotify_source) { + g_source_remove(dir->inotify_source); + dir->inotify_source = 0; + } +# endif #endif return; } @@ -268,20 +320,26 @@ void dir_check_this(const guchar *path) g_free(real_path); } -#ifdef USE_DNOTIFY -static void drop_dnotify(gpointer key, gpointer value, gpointer data) +#ifdef USE_NOTIFY +static void drop_notify(gpointer key, gpointer value, gpointer data) { +#ifdef USE_INOTIFY + inotify_rm_watch(inotify_fd, GPOINTER_TO_INT(key)); +#endif +#ifdef USE_DNOTIFY close(GPOINTER_TO_INT(key)); +#endif } #endif /* Used when we fork an action child, otherwise we can't delete or unmount - * any directory which we're watching! + * any directory which we're watching via dnotify! inotify does not have + * this problem */ -void dir_drop_all_dnotifies(void) +void dir_drop_all_notifies(void) { #ifdef USE_DNOTIFY - g_hash_table_foreach(dnotify_fd_to_dir, drop_dnotify, NULL); + g_hash_table_foreach(notify_fd_to_dir, drop_notify, NULL); #endif } @@ -502,7 +560,7 @@ void dnotify_wakeup(void) * INTERNAL FUNCTIONS * ****************************************************************/ -#ifdef USE_DNOTIFY +#ifdef USE_NOTIFY static gint rescan_soon_timeout(gpointer data) { Directory *dir = (Directory *) data; @@ -899,8 +957,11 @@ static void directory_init(GTypeInstance *object, gpointer gclass) dir->pathname = NULL; dir->error = NULL; dir->rescan_timeout = -1; -#ifdef USE_DNOTIFY - dir->dnotify_fd = -1; +#ifdef USE_NOTIFY + dir->notify_fd = -1; +#endif +#ifdef USE_INOTIFY + dir->inotify_source = 0; #endif dir->new_items = g_ptr_array_new(); @@ -1080,3 +1141,39 @@ static void dnotify_handler(int sig, siginfo_t *si, void *data) write(to_wakeup_pipe, "\0", 1); /* Wake up! */ } #endif + +#ifdef USE_INOTIFY +static gboolean inotify_handler(GIOChannel *source, GIOCondition condition, + gpointer udata) +{ + int fd = g_io_channel_unix_get_fd(source); + Directory *dir; + char buf[sizeof(struct inotify_event)+1024]; + int len, i = 0; + + len = read(fd, buf, sizeof(buf)); + if (len<0) + { + if (errno != EINTR) + perror("read"); + return TRUE; + } + else if (!len) + return TRUE; + + while (i<len) + { + struct inotify_event *event=(struct inotify_event *) (buf+i); + + dir = g_hash_table_lookup(notify_fd_to_dir, + GINT_TO_POINTER(event->wd)); + if (dir) + dir_rescan_soon(dir); + + i += sizeof(*event)+event->len; + } + + + return TRUE; +} +#endif diff --git a/ROX-Filer/src/dir.h b/ROX-Filer/src/dir.h index a66e413..deb71aa 100644 --- a/ROX-Filer/src/dir.h +++ b/ROX-Filer/src/dir.h @@ -13,9 +13,14 @@ #include <signal.h> #include <fcntl.h> -/* Check for dnotify support */ -#if defined(DN_MULTISHOT) && defined(SIGRTMIN) +/* Check for [id]notify support */ +#if defined(HAVE_SYS_INOTIFY_H) +# define USE_INOTIFY +#elif defined(DN_MULTISHOT) && defined(SIGRTMIN) # define USE_DNOTIFY +#endif +#if defined(USE_INOTIFY) || defined(USE_DNOTIFY) +#define USE_NOTIFY extern gboolean dnotify_wakeup_flag; #endif @@ -84,8 +89,11 @@ struct _Directory gint rescan_timeout; /* See dir_rescan_soon() */ -#ifdef USE_DNOTIFY - int dnotify_fd; /* -1 if not watching */ +#ifdef USE_NOTIFY + int notify_fd; /* -1 if not watching */ +#endif +#ifdef USE_INOTIFY + guint inotify_source; #endif }; @@ -98,8 +106,10 @@ void dir_check_this(const guchar *path); DirItem *dir_update_item(Directory *dir, const gchar *leafname); void dir_merge_new(Directory *dir); void dir_force_update_path(const gchar *path); +#if defined(USE_DNOTIFY) void dnotify_wakeup(void); -void dir_drop_all_dnotifies(void); +#endif +void dir_drop_all_notifies(void); void dir_queue_recheck(Directory *dir, DirItem *item); #endif /* _DIR_H */ diff --git a/ROX-Filer/src/main.c b/ROX-Filer/src/main.c index 3f3949e..f8463ae 100644 --- a/ROX-Filer/src/main.c +++ b/ROX-Filer/src/main.c @@ -695,6 +695,13 @@ static void show_features(void) _("No") #endif ); + g_print("%s... %s\n", _("Inotify support"), +#ifdef USE_INOTIFY + _("Yes") +#else + _("No") +#endif + ); g_print("%s... %s\n", _("Dnotify support"), #ifdef USE_DNOTIFY _("Yes") -- 1.5.4.5