Class Sinotify::Notifier

  1. lib/sinotify/notifier.rb
Parent: Object

Watch a directory or file for events like create, modify, delete, etc. (See Sinotify::Event for full list).

See the synopsis section in the README.txt for example usage.

Included modules

  1. Cosell

Attributes

etypes [RW]
file_or_dir_name [RW]
logger [RW]
recurse [RW]
recurse_throttle [RW]

Public class methods

new (file_or_dir_name, opts = {})

Required Args

file_or_dir_name: the file/directory to watch

Options:

:recurse => (true|false)
  whether to automatically create watches on sub directories
  default: true if file_or_dir_name is a directory, else false
  raises if true and file_or_dir_name is not a directory

:recurse_throttle =>
  When recursing, a background thread drills down into all the child directories
  creating notifiers on them. The recurse_throttle tells the notifier how far
  to recurse before sleeping for 0.1 seconds, so that drilling down does not hog
  the system on large directorie hierarchies.
  default is 10

:etypes =>
  which inotify file system event types to listen for (eg :create, :delete, etc)
  See docs for Sinotify::Event for list of event types.
  default is [:create, :modify, :delete]
  Use :all_events to trace everything (although this may be more than you bargained for).

:logger =>
  Where to log errors to. Default is Logger.new(STDOUT).

:announcement_throttle =>
  How many events can be announced at a time before the queue goes back to sleep for a cycle.
  (ie. Cosell's 'announcements_per_cycle')

:announcements_sleep_time =>
  How long the queue should sleep for before announcing the next batch of queued up
  Sinotify::Events (ie. Cosell's 'sleep_time')
[show source]
# File lib/sinotify/notifier.rb, line 49
    def initialize(file_or_dir_name, opts = {})

      initialize_cosell!  # init the announcements framework

      raise "Could not find #{file_or_dir_name}" unless File.exist?(file_or_dir_name)
      self.file_or_dir_name = file_or_dir_name

      # by default, recurse if directory?. If opts[:recurse] was true and passed in,
      # make sure the watch is on a directory
      self.recurse = opts[:recurse].nil?? self.on_directory? : opts[:recurse] 
      raise "Cannot recurse, #{file_or_dir_name} is not a directory" if self.recurse? && !self.on_directory?

      # how many directories at a time to register. 
      self.recurse_throttle = opts[:recurse_throttle] || 10 

      self.etypes = Array( opts[:etypes] || [:create, :modify, :delete] )
      validate_etypes!

      self.prim_notifier = Sinotify::PrimNotifier.new

      # setup async announcements queue (part of the Cosell mixin)
      @logger = opts[:logger] || Logger.new(STDOUT)
      sleep_time = opts[:announcements_sleep_time] || 0.05 
      announcement_throttle = opts[:announcement_throttle] || 50 
      self.queue_announcements!(:sleep_time => sleep_time, 
                                :logger => @logger,
                                :announcements_per_cycle => announcement_throttle)

      self.closed = false

      # initialize a few variables just to shut up the ruby warnings
      # Apparently the lazy init idiom using ||= is no longer approved of. Shame that.
      @spy_logger = nil
      @spy_logger_level = nil
      @watch_thread = nil
    end

Public instance methods

all_directories_being_watched ()

Return a list of files/directories currently being watched. Will only contain one entry unless this notifier was setup on a directory with the option :recurse => true.

[show source]
# File lib/sinotify/notifier.rb, line 143
    def all_directories_being_watched
      self.watches.values.collect{|w| w.path }.sort
    end
close! ()

Close this notifier. Notifiers cannot be reopened after close!.

[show source]
# File lib/sinotify/notifier.rb, line 118
    def close!
      @closed = true
      self.remove_all_watches
    end
on_directory? ()

whether this watch is on a directory

[show source]
# File lib/sinotify/notifier.rb, line 105
    def on_directory?
      File.directory?(self.file_or_dir_name)
    end
on_event (&block)

Sugar.

Equivalent of calling cosell’s

self.when_announcing(Sinotify::Event) do |event|
  do_something_with_event(event)
end

becomes

self.on_event { |event| do_something_with_event(event) }

Since this class only announces one kind of event, it made sense to provide a more terse version of that statement.

[show source]
# File lib/sinotify/notifier.rb, line 100
    def on_event &block
      self.when_announcing(Sinotify::Event, &block)
    end
recurse? ()

Whether this notifier watches all the files in all of the subdirectories of the directory being watched.

[show source]
# File lib/sinotify/notifier.rb, line 153
    def recurse?
      self.recurse
    end
spy! (opts = {})

Log a message every time a prim_event comes in (will be logged even if it is considered ‘noise’), and log a message whenever an event is announced. Overrides Cosell’s spy! method (and uses cosell’s spy! to log announced events).

Options:

:logger => The log to log to. Default is a logger on STDOUT
:level => The log level to log with. Default is :info
:spy_on_prim_events => Spy on PrimEvents (raw inotify events) too
[show source]
# File lib/sinotify/notifier.rb, line 132
    def spy!(opts = {})
      self.spy_on_prim_events = opts[:spy_on_prim_events].eql?(true)
      self.spy_logger = opts[:logger] || Logger.new(STDOUT)
      self.spy_logger_level = opts[:level] || :info
      opts[:on] = Sinotify::Event
      opts[:preface_with] = "Sinotify::Notifier Event Spy"
      super(opts)
    end
to_s ()
[show source]
# File lib/sinotify/notifier.rb, line 157
    def to_s
      "Sinotify::Notifier[#{self.file_or_dir_name}, :watches => #{self.watches.size}]"
    end
watch! ()

Start watching for inotify file system events.

[show source]
# File lib/sinotify/notifier.rb, line 110
    def watch!
      raise "Cannot reopen an inotifier. Create a new one instead" if self.closed?
      self.add_all_directories_in_background
      self.start_prim_event_loop_thread
      return self
    end
watches ()
[show source]
# File lib/sinotify/notifier.rb, line 147
    def watches
      @watches ||= {}
    end