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