class FileWatch::Ext::FileTail
Public Instance Methods
subscribe(&block)
click to toggle source
# File lib/filewatch/ext/filetail.rb, line 8 def subscribe(&block) # subscribe(stat_interval = 1, discover_interval = 5, &block) @watch.subscribe(@opts[:stat_interval], @opts[:discover_interval]) do |event, path| case event when :create, :create_initial if @files.member?(path) @logger.debug("#{event} for #{path}: already exists in @files") next end if _open_file(path, event) _read_file(path, &block) end when :modify _open_file(path, event) if @opts[:eof_close] if !@files.member?(path) @logger.debug(":modify for #{path}, does not exist in @files") if _open_file(path, event) _read_file(path, &block) end else _read_file(path, &block) end when :delete @logger.debug(":delete for #{path}, deleted from @files") _read_file(path, &block) if !@opts[:eof_close] _progressdb_delete(path, &block) if @opts[:progressdb] && @opts[:progressdb_del] @files[path].close if !@opts[:eof_close] @files.delete(path) _sincedb_delete(path) @statcache.delete(path) else @logger.warn("unknown event type #{event} for #{path}") end end # @watch.subscribe end
Private Instance Methods
_open_file(path, event)
click to toggle source
# File lib/filewatch/ext/filetail.rb, line 49 def _open_file(path, event) @logger.debug("_open_file: #{path}: opening") begin if @iswindows && defined? JRUBY_VERSION @files[path] = Java::RubyFileExt::getRubyFile(path) else @files[path] = File.open(path) end rescue # don't emit this message too often. if a file that we can't # read is changing a lot, we'll try to open it more often, # and might be spammy. now = Time.now.to_i if now - @lastwarn[path] > OPEN_WARN_INTERVAL @logger.warn("failed to open #{path}: #{$!}") @lastwarn[path] = now else @logger.debug("(warn supressed) failed to open #{path}: #{$!}") end @files.delete(path) return false end stat = File::Stat.new(path) if @iswindows fileId = Winhelper.GetWindowsUniqueFileIdentifier(path) inode = [fileId, stat.dev_major, stat.dev_minor] else inode = [stat.ino.to_s, stat.dev_major, stat.dev_minor] end @statcache[path] = inode if @sincedb.member?(inode) last_size = @sincedb[inode][:pos] @logger.debug("#{path}: sincedb last value #{@sincedb[inode]}, cur size #{stat.size}") if last_size <= stat.size @logger.debug("#{path}: sincedb: seeking to #{last_size}") @files[path].sysseek(last_size, IO::SEEK_SET) else @logger.debug("#{path}: last value size is greater than current value, starting over") @sincedb[inode] = {:size => stat.size, :pos => 0} end elsif (event == :create || event == :create_initial) && @files[path] # TODO(sissel): Allow starting at beginning of the file. if @opts[:start_new_files_at] == :beginning @logger.debug("#{path}: initial create, no sincedb, seeking to beginning of file") @files[path].sysseek(0, IO::SEEK_SET) @sincedb[inode] = {:size => stat.size, :pos => 0} else # seek to end @logger.debug("#{path}: initial create, no sincedb, seeking to end #{stat.size}") @files[path].sysseek(stat.size, IO::SEEK_SET) @sincedb[inode] = {:size => stat.size, :pos => stat.size} end else @logger.debug("#{path}: staying at position 0, no sincedb") end return true end
_read_file(path) { |path, data, :log| ... }
click to toggle source
# File lib/filewatch/ext/filetail.rb, line 112 def _read_file(path, &block) # BufferedTokenizer is now in codec changed = false loop do begin data = @files[path].sysread(32768) changed = true yield(path, data, :log) @sincedb[@statcache[path]][:pos] = @files[path].pos _check_sincedb(false, path, &block) rescue EOFError _check_sincedb(true, path, &block) if changed _close_file(path) if @opts[:eof_close] @logger.debug("End of file reached for #{path}") break rescue Errno::EWOULDBLOCK, Errno::EINTR break end end end