class EventMachine::FileGlobWatch
A file glob pattern watcher for EventMachine
.
If you are unfamiliar with globs, see Wikipedia: en.wikipedia.org/wiki/Glob_(programming)
Any glob supported by Dir#glob will work with this class.
This class will allow you to get notified whenever a file is created or deleted that matches your glob.
If you are subclassing, here are the methods you should implement:
file_found(path) file_deleted(path)
See alsoe
Public Class Methods
Watch a glob
-
glob - a string path or glob, such as “/var/log/*.log”
-
interval - number of seconds between scanning the glob for changes
# File lib/event_machine/tail/globwatcher.rb, line 36 def initialize(glob, interval=60) @glob = glob @files = Hash.new @watches = Hash.new @logger = Logger.new(STDOUT) @logger.level = ($DEBUG and Logger::DEBUG or Logger::WARN) @interval = interval start end
Public Instance Methods
This method is called when a file is deleted.
-
path - the string path of the file deleted
You must implement this in your subclass or module for it to work with EventMachine::watch_glob
# File lib/event_machine/tail/globwatcher.rb, line 91 def file_deleted(path) raise NotImplementedError.new("#{self.class.name}#file_deleted is not "\ "implemented. Did you forget to implement this in your subclass or "\ "module?") end
This method is called when a new file is found
-
path - the string path of the file found
You must implement this in your subclass or module for it to work with EventMachine::watch_glob
# File lib/event_machine/tail/globwatcher.rb, line 78 def file_found(path) raise NotImplementedError.new("#{self.class.name}#file_found is not "\ "implemented. Did you forget to implement this in your subclass or "\ "module?") end
This method may be called to start watching
# File lib/event_machine/tail/globwatcher.rb, line 56 def start # We periodically check here because it is easier than writing our own glob # parser (so we can smartly watch globs like /foo/*/bar*/*.log) # # Reasons to fix this - # This will likely perform badly on globs that result in a large number of # files. EM.next_tick do find_files @find_files_interval = EM.add_periodic_timer(@interval) do find_files end end # EM.next_tick end
This method may be called to stop watching TODO(sissel): make 'stop' stop all active watches, too?
# File lib/event_machine/tail/globwatcher.rb, line 49 def stop @find_files_interval.cancel if @find_files_interval end
Private Instance Methods
# File lib/event_machine/tail/globwatcher.rb, line 98 def find_files @logger.info("Searching for files in #{@glob}") list = Dir.glob(@glob) known_files = @files.clone list.each do |path| fileinfo = FileInfo.new(path) rescue next # Skip files that have the same inode (renamed or hardlinked) known_files.delete(fileinfo.stat.ino) next if @files.include?(fileinfo.stat.ino) track(fileinfo) file_found(path) end # Report missing files. known_files.each do |inode, fileinfo| remove(fileinfo) end end
Remove a file from being watched and notify file_deleted
()
# File lib/event_machine/tail/globwatcher.rb, line 121 def remove(fileinfo) @files.delete(fileinfo.stat.ino) @watches.delete(fileinfo.path) file_deleted(fileinfo.path) end
Add a file to watch and notify file_found
()
# File lib/event_machine/tail/globwatcher.rb, line 129 def track(fileinfo) @files[fileinfo.stat.ino] = fileinfo # If EventMachine::watch_file fails, that's ok, I guess. # We'll still find the file 'missing' from the next glob attempt. #begin # EM currently has a bug that only the first handler for a watch_file # on each file gets events. This causes globtails to never get data # since the glob is watching the file already. # Until we fix that, let's skip file watching here. #@watches[path] = EventMachine::watch_file(path, FileWatcher, self) do |path| # remove(path) #end #rescue Errno::EACCES => e #@logger.warn(e) #end end