class FileWatch::Ext::XlsTail

Public Class Methods

new(opts={}) click to toggle source
Calls superclass method FileWatch::Ext::TailBase::new
# File lib/filewatch/ext/xlstail.rb, line 8
def initialize(opts={})
  @pos = {}
  super
end

Public Instance Methods

subscribe(&block) click to toggle source
# File lib/filewatch/ext/xlstail.rb, line 14
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
      @logger.debug(":modify for #{path}")
    when :delete
      @logger.debug(":delete for #{path}, deleted from @files")

      _progressdb_delete(path, &block) if @opts[:progressdb] && @opts[:progressdb_del]

      @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/xlstail.rb, line 54
def _open_file(path, event)
  @logger.debug("_open_file: #{path}: opening")
  begin
    #Spreadsheet.client_encoding = 'UTF-8'
    @files[path] = Spreadsheet.open(path)
  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)
  size = get_size(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 #{size}")
    if last_size <= size
      @logger.debug("#{path}: sincedb: seeking to #{last_size}")
      @pos[path] = last_size
    else
      @logger.debug("#{path}: last value size is greater than current value, starting over")
      @sincedb[inode] = {:size => size, :pos => 0}
    end
  elsif 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")
      @pos[path] = 0
      @sincedb[inode] = {:size => size, :pos => 0}
    else
      # seek to end
      @logger.debug("#{path}: initial create, no sincedb, seeking to end #{size}")
      @pos[path] = size
      @sincedb[inode] = {:size => size, :pos => size}
    end
  elsif event == :create
    @pos[path] = 0
    @sincedb[inode] = {:size => size, :pos => 0}
  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/xlstail.rb, line 119
def _read_file(path, &block)
  changed = false
  pos = 0

  worksheets = @files[path].worksheets

  worksheets.each_with_index do |worksheet, index_sheet|

    worksheet.each_with_index do |row, index_row|
      pos += 1

      if pos > @pos[path]
        changed = true

        sheet_name = worksheet.name.empty? ? "Sheet#{index_sheet+1}" : worksheet.name

        if pos == @size #end of file is reached
          data = {:row => row, :wsname => sheet_name, :eof => true}
        else
          data = {:row => row, :wsname => sheet_name, :eof => false}
        end

        yield(path, data, :log)

        @pos[path] = pos
        @sincedb[@statcache[path]][:pos] = pos
        _check_sincedb(false, path, &block)
      end
    end
  end
  _check_sincedb(true, path, &block) if changed
end
get_size(path) click to toggle source
# File lib/filewatch/ext/xlstail.rb, line 44
def get_size(path)
  workbook = Spreadsheet.open(path)
  pos = 0
  workbook.worksheets.each do |worksheet|
    pos += worksheet.rows.length
  end
  @size = pos
end