class Evesync::Watcher::File

Watches the files and directories, defined in configuration attribute watch

TODO:

* Test on various cases, make it work properly
* Find out all possible occasions

Public Class Methods

new(queue) click to toggle source
# File lib/evesync/watcher/file.rb, line 20
def initialize(queue)
  @queue = queue
  @watches = Config[:evemond]['watch']
  @period = Config[:evemond]['watch_interval'].to_i
  @inotify = INotify::Notifier.new
  @events = {}
  @wfiles = []
  @wdirs = []
  initialize_watcher
end

Public Instance Methods

start() click to toggle source
# File lib/evesync/watcher/file.rb, line 31
def start
  @inotify_thr = Thread.new { @inotify.run }
  @main_thr = Thread.new do
    loop do
      sleep @period
      send_events
    end
  end
end
stop() click to toggle source
# File lib/evesync/watcher/file.rb, line 41
def stop
  @inotify.stop
  @inotify_thr.exit
  @main_thr.exit
end

Private Instance Methods

guess_event(events) click to toggle source
# File lib/evesync/watcher/file.rb, line 144
def guess_event(events)
  return events.first if events.length == 1

  return :modify if events.include?(:create) && events.include?(:modify)

  return :delete if events.include?(:delete) && (!events.include? :create)

  # TODO: find out more logic
  events.last
end
h_directory(filename, events) click to toggle source
# File lib/evesync/watcher/file.rb, line 129
def h_directory(filename, events)
  if ::File.file? filename
    watch_file(filename)
    @watches << filename unless @watches.include? filename
  elsif ::File.directory? filename
    watch_directory(filename)
  end

  # Better pass a file
  @events[filename] = [] unless @events[filename]

  @events[filename] += events
  Log.debug("Watcher File added events for directory #{filename}")
end
h_file(filename, events) click to toggle source

Handlers of inotify changes

# File lib/evesync/watcher/file.rb, line 122
def h_file(filename, events)
  @events[filename] = [] unless @events[filename]

  @events[filename] += events
  Log.debug("Watcher File added events for file #{filename}")
end
initialize_watcher() click to toggle source
# File lib/evesync/watcher/file.rb, line 71
def initialize_watcher
  @watches.each do |filename|
    unless ::File.exist? filename
      Log.error("Watcher File: '#{filename}' absent on system")
    end

    # TODO: ignore /dev and /sys, /proc directories
    if ::File.file? filename
      watch_file filename
    elsif ::File.directory? filename
      watch_directory filename
    else
      # Seems to be a drive or
      Log.warn("Watcher File: watching '#{filename}' is not implemented yet")
    end
  end
end
send_events() click to toggle source

Send all events from the methods-handlers

# File lib/evesync/watcher/file.rb, line 50
def send_events
  @events.each do |file, events|
    event = guess_event(events)
    mode = case event
           when :delete then nil
           else ::File::Stat.new(file).mode
           end

    msg = IPC::Data::File.new(
      name: file,
      mode: mode,
      action: event,
      touched_at: NTP.time.to_s
    )
    @queue.push msg
    Log.debug("Watcher File guessed event #{event} " \
              "from #{events} on #{file}")
  end
  @events = {}
end
watch_directory(dirname) click to toggle source
# File lib/evesync/watcher/file.rb, line 107
def watch_directory(dirname)
  @inotify.watch(dirname, :create, :delete, :moved_to, :moved_from) do |e|
    Log.debug("Watcher File: DIRECTORY #{e.absolute_name}")
    h_directory(e.absolute_name, e.flags)
  end
end
watch_directory_for_file(dirname) click to toggle source
# File lib/evesync/watcher/file.rb, line 114
def watch_directory_for_file(dirname)
  @inotify.watch(dirname, :create, :moved_to) do |e|
    watch_file(e.absolute_name) if @wfiles.include? e.absolute_name
  end
end
watch_file(filename) click to toggle source
# File lib/evesync/watcher/file.rb, line 89
def watch_file(filename)
  # add file modify watch
  Log.debug("Watcher File watching #{filename}")

  @inotify.watch(filename, :modify) do |e|
    Log.debug("Watcher File: MODIFIED #{e.absolute_name}")
    h_file(e.absolute_name, [:modify]) # the only flag we need
  end

  # Waiting for file to disappear and created again
  @wfiles << filename unless @wfiles.include?(filename)
  dirname = ::File.dirname(filename)
  unless @wdirs.include?(dirname)
    watch_directory_for_file(dirname)
    @wdirs << dirname
  end
end