Class: Ramaze::Reloader::WatchInotify
- Defined in:
- lib/ramaze/reloader/watch_inotify.rb
Overview
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.
Constant Summary collapse
- POLL_INTERVAL =
seconds
2
- NOTIFY_MASK =
RInotify::MODIFY | RInotify::IN_ONESHOT
Instance Method Summary collapse
- #call(cooldown) ⇒ Object
-
#changed_files ⇒ Object
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.
- #close ⇒ Object
-
#initialize ⇒ WatchInotify
constructor
A new instance of WatchInotify.
-
#remove_watch(file) ⇒ Object
FIXME: Seems like this won’t work due to some bug in the rinotify library.
-
#start_watcher ⇒ Object
TODO: define a finalizer to cleanup? – reloader never calls #close.
- #watch(file) ⇒ Object
-
#watcher_cycle ⇒ Object
Not much work here, we just have to empty the event queue and push the descriptors for reloading on next request.
Constructor Details
#initialize ⇒ WatchInotify
Returns a new instance of WatchInotify.
19 20 21 22 23 |
# File 'lib/ramaze/reloader/watch_inotify.rb', line 19 def initialize @watcher = RInotify.new @changed = Queue.new @watcher_thread = start_watcher end |
Instance Method Details
#call(cooldown) ⇒ Object
25 26 27 |
# File 'lib/ramaze/reloader/watch_inotify.rb', line 25 def call(cooldown) yield end |
#changed_files ⇒ Object
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.
75 76 77 78 79 80 81 82 |
# File 'lib/ramaze/reloader/watch_inotify.rb', line 75 def changed_files until @changed.empty? descriptor = @changed.shift file = @watcher.watch_descriptors.delete(descriptor) watch(file) yield(file) end end |
#close ⇒ Object
62 63 64 65 66 |
# File 'lib/ramaze/reloader/watch_inotify.rb', line 62 def close @watcher_thread.terminate @watcher.close true end |
#remove_watch(file) ⇒ Object
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.
58 59 60 |
# File 'lib/ramaze/reloader/watch_inotify.rb', line 58 def remove_watch(file) @watcher.rm_watch(file) end |
#start_watcher ⇒ Object
TODO: define a finalizer to cleanup? – reloader never calls #close
31 32 33 |
# File 'lib/ramaze/reloader/watch_inotify.rb', line 31 def start_watcher Thread.new{ loop{ watcher_cycle }} end |
#watch(file) ⇒ Object
45 46 47 48 49 50 51 52 |
# 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 ⇒ Object
Not much work here, we just have to empty the event queue and push the descriptors for reloading on next request.
37 38 39 40 41 42 43 |
# 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 |