diff options
| -rw-r--r-- | Changes | 5 | ||||
| -rw-r--r-- | ev++.h | 1 | ||||
| -rw-r--r-- | ev.c | 85 | ||||
| -rw-r--r-- | ev_vars.h | 1 | ||||
| -rw-r--r-- | ev_wrap.h | 2 | 
5 files changed, 61 insertions, 33 deletions
| @@ -2,7 +2,10 @@ Revision history for libev, a high-performance and full-featured event loop.  WISH? monotonic clocks times/GetTickCount for coarse corrections? -TODO: "ev_stat on nfs" +	- ev_stat watchers will now use inotify as a mere hint on +          kernels <2.6.25, or if the filesystem is not in the +          "known to be good" list. +  3.48 Thu Oct 30 09:02:37 CET 2008  	- further optimise away the EPOLL_CTL_ADD/MOD combo in the epoll            backend by assuming the kernel event mask hasn't changed if @@ -74,6 +74,7 @@ namespace ev {      FORK     = EV_FORK,      ASYNC    = EV_ASYNC,      EMBED    = EV_EMBED, +#   undef ERROR // some systems stupidly #define ERROR      ERROR    = EV_ERROR,    }; @@ -289,6 +289,7 @@ extern "C" {  #if EV_USE_INOTIFY  # include <sys/utsname.h> +# include <sys/statfs.h>  # include <sys/inotify.h>  /* some very old inotify.h headers don't have IN_DONT_FOLLOW */  # ifndef IN_DONT_FOLLOW @@ -2416,8 +2417,9 @@ ev_child_stop (EV_P_ ev_child *w)  #  define lstat(a,b) _stati64 (a,b)  # endif -#define DEF_STAT_INTERVAL 5.0074891 -#define MIN_STAT_INTERVAL 0.1074891 +#define DEF_STAT_INTERVAL  5.0074891 +#define NFS_STAT_INTERVAL 30.1074891 /* for filesystems potentially failing inotify */ +#define MIN_STAT_INTERVAL  0.1074891  static void noinline stat_timer_cb (EV_P_ ev_timer *w_, int revents); @@ -2431,7 +2433,8 @@ infy_add (EV_P_ ev_stat *w)    if (w->wd < 0)      { -      ev_timer_start (EV_A_ &w->timer); /* this is not race-free, so we still need to recheck periodically */ +      w->timer.repeat = w->interval ? w->interval : DEF_STAT_INTERVAL; +      ev_timer_again (EV_A_ &w->timer); /* this is not race-free, so we still need to recheck periodically */        /* monitor some parent directory for speedup hints */        /* note that exceeding the hardcoded path limit is not a correctness issue, */ @@ -2458,10 +2461,26 @@ infy_add (EV_P_ ev_stat *w)          }      }    else -    ev_timer_stop (EV_A_ &w->timer); /* we can watch this in a race-free way */ +    { +      wlist_add (&fs_hash [w->wd & (EV_INOTIFY_HASHSIZE - 1)].head, (WL)w); + +      /* now local changes will be tracked by inotify, but remote changes won't */ +      /* unless the filesystem it known to be local, we therefore still poll */ +      /* also do poll on <2.6.25, but with normal frequency */ +      struct statfs sfs; + +      if (fs_2625 && !statfs (w->path, &sfs)) +        if (sfs.f_type == 0x1373 /* devfs */ +            || sfs.f_type == 0xEF53 /* ext2/3 */ +            || sfs.f_type == 0x3153464a /* jfs */ +            || sfs.f_type == 0x52654973 /* reiser3 */ +            || sfs.f_type == 0x01021994 /* tempfs */ +            || sfs.f_type == 0x58465342 /* xfs */) +          return; -  if (w->wd >= 0) -    wlist_add (&fs_hash [w->wd & (EV_INOTIFY_HASHSIZE - 1)].head, (WL)w); +      w->timer.repeat = w->interval ? w->interval : fs_2625 ? NFS_STAT_INTERVAL : DEF_STAT_INTERVAL; +      ev_timer_again (EV_A_ &w->timer); +    }  }  static void noinline @@ -2524,31 +2543,37 @@ infy_cb (EV_P_ ev_io *w, int revents)  }  void inline_size -infy_init (EV_P) +check_2625 (EV_P)  { -  if (fs_fd != -2) -    return; -    /* kernels < 2.6.25 are borked     * http://www.ussg.indiana.edu/hypermail/linux/kernel/0711.3/1208.html     */ -  { -    struct utsname buf; -    int major, minor, micro; +  struct utsname buf; +  int major, minor, micro; -    fs_fd = -1; +  if (uname (&buf)) +    return; -    if (uname (&buf)) -      return; +  if (sscanf (buf.release, "%d.%d.%d", &major, &minor, µ) != 3) +    return; -    if (sscanf (buf.release, "%d.%d.%d", &major, &minor, µ) != 3) -      return; +  if (major < 2 +      || (major == 2 && minor < 6) +      || (major == 2 && minor == 6 && micro < 25)) +    return; -    if (major < 2 -        || (major == 2 && minor < 6) -        || (major == 2 && minor == 6 && micro < 25)) -      return; -  } +  fs_2625 = 1; +} + +void inline_size +infy_init (EV_P) +{ +  if (fs_fd != -2) +    return; + +  fs_fd = -1; + +  check_2625 (EV_A);    fs_fd = inotify_init (); @@ -2586,7 +2611,7 @@ infy_fork (EV_P)            if (fs_fd >= 0)              infy_add (EV_A_ w); /* re-add, no matter what */            else -            ev_timer_start (EV_A_ &w->timer); +            ev_timer_again (EV_A_ &w->timer);          }      }  } @@ -2651,16 +2676,12 @@ ev_stat_start (EV_P_ ev_stat *w)    if (expect_false (ev_is_active (w)))      return; -  /* since we use memcmp, we need to clear any padding data etc. */ -  memset (&w->prev, 0, sizeof (ev_statdata)); -  memset (&w->attr, 0, sizeof (ev_statdata)); -    ev_stat_stat (EV_A_ w); -  if (w->interval < MIN_STAT_INTERVAL) -    w->interval = w->interval ? MIN_STAT_INTERVAL : DEF_STAT_INTERVAL; +  if (w->interval < MIN_STAT_INTERVAL && w->interval) +    w->interval = MIN_STAT_INTERVAL; -  ev_timer_init (&w->timer, stat_timer_cb, w->interval, w->interval); +  ev_timer_init (&w->timer, stat_timer_cb, 0., w->interval ? w->interval : DEF_STAT_INTERVAL);    ev_set_priority (&w->timer, ev_priority (w));  #if EV_USE_INOTIFY @@ -2670,7 +2691,7 @@ ev_stat_start (EV_P_ ev_stat *w)      infy_add (EV_A_ w);    else  #endif -    ev_timer_start (EV_A_ &w->timer); +    ev_timer_again (EV_A_ &w->timer);    ev_start (EV_A_ (W)w, 1); @@ -156,6 +156,7 @@ VARx(int, asynccnt)  #if EV_USE_INOTIFY || EV_GENWRAP  VARx(int, fs_fd)  VARx(ev_io, fs_w) +VARx(char, fs_2625) /* whether we are running in linux 2.6.25 or newer */  VAR (fs_hash, ANFS fs_hash [EV_INOTIFY_HASHSIZE])  #endif @@ -71,6 +71,7 @@  #define asynccnt ((loop)->asynccnt)  #define fs_fd ((loop)->fs_fd)  #define fs_w ((loop)->fs_w) +#define fs_2625 ((loop)->fs_2625)  #define fs_hash ((loop)->fs_hash)  #else  #undef EV_WRAP_H @@ -144,5 +145,6 @@  #undef asynccnt  #undef fs_fd  #undef fs_w +#undef fs_2625  #undef fs_hash  #endif | 
