class Ramaze::Reloader::WatchInotify

TODO:

* There seems to be a problem somewhere that I couldn't identify yet, a
  file has to be modified twice initially to make it show up as
  modified here, subsequent changes work just fine.
  The only workaround I could find right now would be to read/write
  every single file, but that would be unexpected, irresponsible, and
  error-prone.

NOTE:

* I have changed from using a Mutex to using a Queue, which uses a
  Mutex internally.

Constants

NOTIFY_MASK
POLL_INTERVAL

Public Class Methods

new() click to toggle source
# File lib/ramaze/reloader/watch_inotify.rb, line 19
def initialize
  @watcher = RInotify.new
  @changed = Queue.new
  @watcher_thread = start_watcher
end

Public Instance Methods

call(cooldown) { || ... } click to toggle source
# File lib/ramaze/reloader/watch_inotify.rb, line 25
def call(cooldown)
  yield
end
changed_files() { |file| ... } click to toggle source

NOTE:

We have to add the changed file again after we got a notification, I
have no idea why, but using IN_ONESHOT should make sure that there is
no memory leak in the C level even if we add a file again.
There is a memory leak however in the watch_descriptors hash, since
rinotify won't synchronize the contents properly and will only add to
the hash, so we have to clean up ourselves.
# File lib/ramaze/reloader/watch_inotify.rb, line 74
def changed_files
  until @changed.empty?
    descriptor = @changed.shift
    file = @watcher.watch_descriptors.delete(descriptor)
    watch(file)
    yield(file)
  end
end
close() click to toggle source
# File lib/ramaze/reloader/watch_inotify.rb, line 61
def close
  @watcher_thread.terminate
  @watcher.close
  true
end
remove_watch(file) click to toggle source

FIXME:

Seems like this won't work due to some bug in the rinotify library.
Would be cool if someone could make a FFI version.
# File lib/ramaze/reloader/watch_inotify.rb, line 57
def remove_watch(file)
  @watcher.rm_watch(file)
end
start_watcher() click to toggle source

TODO: define a finalizer to cleanup? – reloader never calls close

# File lib/ramaze/reloader/watch_inotify.rb, line 31
def start_watcher
  Thread.new{ loop{ watcher_cycle }}
end
watch(file) click to toggle source
# File lib/ramaze/reloader/watch_inotify.rb, line 45
def watch(file)
  return if @watcher.watch_descriptors.has_value?(file)
  return unless File.exist?(file)

  @watcher.add_watch(file, NOTIFY_MASK)
rescue Errno::ENOENT
  retry
end
watcher_cycle() click to toggle source

Not much work here, we just have to empty the event queue and push the descriptors for reloading on next request.

# File lib/ramaze/reloader/watch_inotify.rb, line 37
def watcher_cycle
  return unless @watcher.wait_for_events(POLL_INTERVAL)

  @watcher.each_event do |event|
    @changed.push(event.watch_descriptor)
  end
end