class DirectoryWatcher::EventableScanner
An Eventable Scanner is one that can be utilized by something that has an Event Loop. It is intended to be subclassed by classes that implement the specific event loop semantics for say EventMachine or Cool.io.
The Events that the EventableScanner is programmed for are:
#on_scan - this
should be called every interval
times #on_modified - If the
event loop can monitor individual files then this should
be called when the file is modified
#on_removed - Similar to #on_modified but called when a file is removed.
Sub classes are required to implement the following:
start_loop_with_attached_scan_timer() - Instance Method This method is to start up the loop, if necessary assign to @loop_thread instance variable the Thread that is controlling the event loop. This method must also assign an object to @timer which is what does the periodic scanning of the globs. This object must respond to +detach()+ so that it may be detached from the event loop. stop_loop() - Instance Method This method must shut down the event loop, or detach these classes from the event loop if we just attached to an existing event loop. Watcher - An Embedded class This is a class that must have a class method +watcher(path,scanner)+ which is used to instantiate a file watcher. The Watcher instance must respond to +detach()+ so that it may be independently detached from the event loop.
Attributes
A Hash of Watcher objects.
Public Class Methods
config - the Configuration instances
# File lib/directory_watcher/eventable_scanner.rb, line 43 def initialize( config ) @config = config @scan_and_queue = DirectoryWatcher::ScanAndQueue.new(config.glob, config.collection_queue) @watchers = {} @stopping = false @timer = nil @loop_thread = nil @paused = false end
Public Instance Methods
The queue on which to put FileStat and Scan items.
# File lib/directory_watcher/eventable_scanner.rb, line 55 def collection_queue @config.collection_queue end
Have we completed up to the #maximum_iterations?
# File lib/directory_watcher/eventable_scanner.rb, line 146 def finished_iterations? self.iterations >= self.maximum_iterations end
The interval at which to scan
# File lib/directory_watcher/eventable_scanner.rb, line 61 def interval @config.interval end
EventableScanners do not join
# File lib/directory_watcher/eventable_scanner.rb, line 119 def join( limit = nil ) end
Setting maximum iterations means hooking into the periodic timer event and counting the number of times it is going on. This also resets the current iterations count
# File lib/directory_watcher/eventable_scanner.rb, line 133 def maximum_iterations=(value) unless value.nil? value = Integer(value) raise ArgumentError, "maximum iterations must be >= 1" unless value >= 1 end @iterations = 0 @maximum_iterations = value end
This callback is invoked by the Watcher instance when it is triggered by the loop for file modifications.
# File lib/directory_watcher/eventable_scanner.rb, line 163 def on_modified(watcher, new_stat) logger.debug "on_modified called" queue_item(new_stat) end
This callback is invoked by the Watcher instance when it is triggered by the loop for file removals
# File lib/directory_watcher/eventable_scanner.rb, line 171 def on_removed(watcher, new_stat) logger.debug "on_removed called" unwatch_file(watcher.path) queue_item(new_stat) end
This callback is invoked by the Timer instance when it is triggered by the Loop. This method will check for added files and stable files and notify the directory watcher accordingly.
# File lib/directory_watcher/eventable_scanner.rb, line 154 def on_scan logger.debug "on_scan called" scan_and_watch_files progress_towards_maximum_iterations end
Pause the scanner.
Pausing the scanner does not stop the scanning per se, it stops items from being sent to the collection queue
# File lib/directory_watcher/eventable_scanner.rb, line 97 def pause logger.debug "pausing scanner" @paused = true end
Is the Scanner currently paused.
# File lib/directory_watcher/eventable_scanner.rb, line 113 def paused? @paused end
Resume the scanner.
This removes the blockage on sending items to the collection queue.
# File lib/directory_watcher/eventable_scanner.rb, line 106 def resume logger.debug "resuming scanner" @paused = false end
Do a single scan and send those items to the collection queue.
# File lib/directory_watcher/eventable_scanner.rb, line 124 def run logger.debug "running scan and queue" @scan_and_queue.scan_and_queue end
Returns true
if the scanner is currently running. Returns
false
if this is not the case.
# File lib/directory_watcher/eventable_scanner.rb, line 68 def running? return !@stopping if @timer return false end
Start up the scanner. If the scanner is already running, nothing happens.
# File lib/directory_watcher/eventable_scanner.rb, line 75 def start return if running? logger.debug "starting scanner" start_loop_with_attached_scan_timer end
Stop the scanner. If the scanner is not running, nothing happens.
# File lib/directory_watcher/eventable_scanner.rb, line 83 def stop return unless running? logger.debug "stoping scanner" @stopping = true teardown_timer_and_watches @stopping = false stop_loop end
Private Instance Methods
Make progress towards maximum iterations. And if we get there, then stop monitoring files.
# File lib/directory_watcher/eventable_scanner.rb, line 235 def progress_towards_maximum_iterations if maximum_iterations then @iterations += 1 stop if finished_iterations? end end
Send the given item to the collection queue
# File lib/directory_watcher/eventable_scanner.rb, line 183 def queue_item( item ) if paused? then logger.debug "Not queueing item, we're paused" else logger.debug "enqueuing #{item} to #{collection_queue}" collection_queue.enq item end end
Run a single scan and turn on watches for all the files found in that scan that do not already have watchers on them.
# File lib/directory_watcher/eventable_scanner.rb, line 196 def scan_and_watch_files logger.debug "scanning and watching files" scan = @scan_and_queue.scan_and_queue scan.results.each do |stat| watch_file(stat.path) end end
Remove the timer and the watches from the event loop
# File lib/directory_watcher/eventable_scanner.rb, line 206 def teardown_timer_and_watches @timer.detach rescue nil @timer = nil @watchers.each_value {|w| w.detach} @watchers.clear end
Remove the watcher instance from our tracking
# File lib/directory_watcher/eventable_scanner.rb, line 227 def unwatch_file( fn ) logger.debug "Unwatching file #{fn}" @watchers.delete(fn) end
Create and return a new Watcher instance for the given filename fn. A watcher will only be created once for a particular fn.
# File lib/directory_watcher/eventable_scanner.rb, line 217 def watch_file( fn ) unless @watchers[fn] then logger.debug "Watching file #{fn}" w = self.class::Watcher.watch(fn, self) @watchers[fn] = w end end