pike.git / lib / modules / Filesystem.pmod / Monitor.pmod / basic.pike

version» Context lines:

pike.git/lib/modules/Filesystem.pmod/Monitor.pmod/basic.pike:10:   //!   //! This module is intended to be used for incremental scanning of   //! a filesystem.   //!   //! Supports FSEvents on MacOS X and Inotify on Linux to provide low overhead monitoring; other   //! systems use a less efficient polling approach.      //   // some necessary setup activities for systems that provide filesystem event monitoring   // - #if constant(Public.System.FSEvents.EventStream) + #if constant(System.FSEvents.EventStream)   #define HAVE_EVENTSTREAM 1   #endif    - #if constant(Public.System.___Inotify) + #if constant(System.Inotify)   #define HAVE_INOTIFY 1   #endif      #if HAVE_EVENTSTREAM    System.FSEvents.EventStream eventstream = System.FSEvents.EventStream(({}), 3.0, System.FSEvents.kFSEventStreamEventIdSinceNow, System.FSEvents.kFSEventStreamCreateFlagNone);    array eventstream_paths = ({});       // This function is called when the FSEvents EventStream detects a change in one of the monitored directories.    void eventstream_callback(string path, int flags, int event_id)    {
pike.git/lib/modules/Filesystem.pmod/Monitor.pmod/basic.pike:258: Inside #if HAVE_EVENTSTREAM
   already_added = 1;    }    if(already_added) return;    eventstream_paths += ({path});    if(eventstream->is_started())    eventstream->stop();    eventstream->add_path(path);    eventstream->start();   #elseif HAVE_INOTIFY    wd = instance->add_watch(path, -  Inotify.IN_MOVED_FROM | Inotify.IN_UNMOUNT | -  Inotify.IN_MOVED_TO | Inotify.IN_MASK_ADD | -  Inotify.IN_MOVE_SELF | Inotify.IN_DELETE | -  Inotify.IN_MOVE | Inotify.IN_MODIFY | -  Inotify.IN_ATTRIB | Inotify.IN_DELETE_SELF | -  Inotify.IN_CREATE); +  System.Inotify.IN_MOVED_FROM | System.Inotify.IN_UNMOUNT | +  System.Inotify.IN_MOVED_TO | System.Inotify.IN_MASK_ADD | +  System.Inotify.IN_MOVE_SELF | System.Inotify.IN_DELETE | +  System.Inotify.IN_MOVE | System.Inotify.IN_MODIFY | +  System.Inotify.IN_ATTRIB | System.Inotify.IN_DELETE_SELF | +  System.Inotify.IN_CREATE);   #endif    }       void destroy()    {   #if HAVE_INOTIFY    instance->rm_watch(wd);   #endif /* HAVE_INOTIFY */    }   
pike.git/lib/modules/Filesystem.pmod/Monitor.pmod/basic.pike:403:    }       protected string _sprintf(int c)    {    return sprintf("Monitor(%O, %O, next: %s, st: %O)",    path, flags, ctime(next_poll) - "\n", st);    }       //! Bump the monitor to an earlier scan time.    //! +  //! @param flags +  //! @int +  //! @value 0 +  //! Don't recurse. +  //! @value 1 +  //! Check all monitors for the entire subtree. +  //! @endint +  //!    //! @param seconds -  //! Number of seconds to bump. Defaults to @expr{30@}. -  void bump(int|void flags, int|void seconds) +  //! Number of seconds from now to run next scan. Defaults to +  //! half of the remaining interval. +  void bump(MonitorFlags|void flags, int|void seconds)    { -  next_poll -= seconds || 30; +  int now = time(1); +  if (seconds) +  next_poll = now + seconds; +  else if (next_poll > now) +  next_poll -= (next_poll - now) / 2;    monitor_queue->adjust(this);       if ((flags & MF_RECURSE) && st->isdir && files) {    // Bump the files in the directory as well.    foreach(files, string file) {    file = canonic_path(Stdio.append_path(path, file));    Monitor m2 = monitors[file];    if (m2) {    m2->bump(flags, seconds);    }
pike.git/lib/modules/Filesystem.pmod/Monitor.pmod/basic.pike:433:    //!    //! @param st    //! New stat for the monitor.    //!    //! This function is called by @[check()] to schedule the    //! next check.    protected void update(Stdio.Stat st)    {    int delta = max_dir_check_interval || global::max_dir_check_interval;    this_program::st = st; -  if (!st || !st->isdir) { -  delta *= file_interval_factor || global::file_interval_factor; -  } -  if (!next_poll) { -  // Attempt to distribute polls evenly at startup. -  delta = 1 + random(delta); -  } +     if (st) { -  int d = 1 + ((time(1) - st->mtime)>>8); +  // Start with a delta proportional to the time since mtime/ctime, +  // but bound this to the max setting. A stat in the future will be +  // adjusted to the max interval. +  int d = +  (stable_time || global::stable_time) + +  ((time(1) - max(st->mtime, st->ctime)) >> 2);    if (d < 0) d = max_dir_check_interval || global::max_dir_check_interval;    if (d < delta) delta = d; -  d = 1 + ((time(1) - st->ctime)>>8); -  if (d < 0) d = max_dir_check_interval || global::max_dir_check_interval; -  if (d < delta) delta = d; +     }    if (last_change <= time(1)) {    // Time until stable.    int d = last_change + (stable_time || global::stable_time) - time(1);    d >>= 1;    if (d < 0) d = 1;    if (d < delta) delta = d; -  +  } else if (!st || !st->isdir) { +  delta *= file_interval_factor || global::file_interval_factor;    } -  +  +  if (!next_poll) { +  // Attempt to distribute polls evenly at startup. +  delta = 1 + random(delta); +  } +     next_poll = time(1) + (delta || 1);    monitor_queue->adjust(this);    }       //! Check if this monitor should be removed automatically.    void check_for_release(int mask, int flags)    {    if ((this_program::flags & mask) == flags) {    m_delete(monitors, path);    release_monitor(this);
pike.git/lib/modules/Filesystem.pmod/Monitor.pmod/basic.pike:702:    monitor(file, orig_flags | MF_AUTO | MF_HARD,    max_dir_check_interval,    file_interval_factor,    stable_time);    check_monitor(monitors[file]);    } else {    file_created(file, file_stat(file, 1));    }    }    } +  update(st);    return 1;    } else {    return 0;    }       // Note: ctime seems to change unexpectedly when running ImageMagick    // on NFS disk so we disable it for the moment [bug 5587].    if ((st->mtime != old_st->mtime) ||    /* (st->ctime != old_st->ctime) || */    (st->size != old_st->size)) {    last_change = time(1); -  +  update(st);    if (status_change(old_st, st, orig_flags, flags)) return 1;    } else if (last_change < time(1) - (stable_time || global::stable_time)) {    last_change = 0x7fffffff;    stable_data_change(path, st);    return 1; -  } else if (st->isdir && status_change(old_st, st, orig_flags, flags)) { +  } else if (last_change != 0x7fffffff && +  st->isdir && status_change(old_st, st, orig_flags, flags)) {    // Directory not stable yet.    last_change = time(1); -  +  update(st);    return 1;    }    return 0;    }   }      //! Canonicalize a path.   //!   //! @param path   //! Path to canonicalize.
pike.git/lib/modules/Filesystem.pmod/Monitor.pmod/basic.pike:772:   //!   //! @param stable_time   //! Override of @[default_stable_time].   protected void create(int|void max_dir_check_interval,    int|void file_interval_factor,    int|void stable_time)   {   #if HAVE_EVENTSTREAM    eventstream->callback_func = eventstream_callback;   #elseif HAVE_INOTIFY -  instance = Inotify._Instance(); -  file = Stdio.File(instance->get_fd(), "r"); +  instance = System.Inotify._Instance(); +  file = Stdio.File(); +  file->assign(instance->fd());    file->set_nonblocking();    file->set_read_callback(inotify_parse);   #endif       if (max_dir_check_interval > 0) {    this_program::max_dir_check_interval = max_dir_check_interval;    }    if (file_interval_factor > 0) {    this_program::file_interval_factor = file_interval_factor;    }