From d8ac22a13f092731bf29a0399f31f3074764c95d Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Fri, 20 Dec 2019 01:39:16 +0000 Subject: watchable: use fiddle for inotify support We have String#unpack at our disposal for working with "struct inotify_event", so use it instead of depending on an extension which requires a compiler and development headers to install. --- lib/dtas/watchable.rb | 115 +++++++++++++++++++++++++------------------------- 1 file changed, 58 insertions(+), 57 deletions(-) (limited to 'lib/dtas/watchable.rb') diff --git a/lib/dtas/watchable.rb b/lib/dtas/watchable.rb index d0f37af..2502b7c 100644 --- a/lib/dtas/watchable.rb +++ b/lib/dtas/watchable.rb @@ -1,71 +1,72 @@ # Copyright (C) 2013-2019 all contributors # License: GPL-3.0+ # frozen_string_literal: true +require_relative '../dtas' +require_relative 'nonblock' begin -require 'sleepy_penguin' + module DTAS::Watchable # :nodoc: + module InotifyCommon # :nodoc: + FLAGS = 8 | 128 # IN_CLOSE_WRITE | IN_MOVED_TO -# used to restart DTAS::Source::SplitFX processing in dtas-player -# if the YAML file is edited -module DTAS::Watchable # :nodoc: - class InotifyReadableIter < SleepyPenguin::Inotify # :nodoc: - def self.new - super(:CLOEXEC) - end - - FLAGS = CLOSE_WRITE | MOVED_TO - - def readable_iter - or_call = false - while event = take(true) # drain the buffer - w = @watches[event.wd] or next - if (event.mask & FLAGS) != 0 && w[event.name] - or_call = true + def readable_iter + or_call = false + while event = take(true) # drain the buffer + w = @watches[event.wd] or next + if (event.mask & FLAGS) != 0 && w[event.name] + or_call = true + end + end + if or_call + @on_readable.call + :delete + else + :wait_readable end end - if or_call - @on_readable.call - :delete - else - :wait_readable - end - end - # we must watch the directory, since - def watch_files(paths, blk) - @watches = {} # wd -> { basename -> true } - @on_readable = blk - @dir2wd = {} - Array(paths).each do |path| - watchdir, watchbase = File.split(File.expand_path(path)) - begin - wd = @dir2wd[watchdir] ||= add_watch(watchdir, FLAGS) - m = @watches[wd] ||= {} - m[watchbase] = true - rescue SystemCallError => e - warn "#{watchdir.dump}: #{e.message} (#{e.class})" + # we must watch the directory, since + def watch_files(paths, blk) + @watches = {} # wd -> { basename -> true } + @on_readable = blk + @dir2wd = {} + Array(paths).each do |path| + watchdir, watchbase = File.split(File.expand_path(path)) + begin + wd = @dir2wd[watchdir] ||= add_watch(watchdir, FLAGS) + m = @watches[wd] ||= {} + m[watchbase] = true + rescue SystemCallError => e + warn "#{watchdir.dump}: #{e.message} (#{e.class})" + end end end - end - end + end # module InotifyCommon - def watch_begin(blk) - @ino = InotifyReadableIter.new - @ino.watch_files(@watch_extra << @infile, blk) - @ino - end + begin + require_relative 'watchable/inotify' + rescue LoadError + # TODO: support kevent + require_relative 'watchable/fiddle_ino' + end - def watch_extra(paths) - @ino.watch_extra(paths) - end + def watch_begin(blk) + @ino = DTAS::Watchable::InotifyReadableIter.new + @ino.watch_files(@watch_extra << @infile, blk) + @ino + end - # Closing the inotify descriptor (instead of using inotify_rm_watch) - # is cleaner because it avoids EINVAL on race conditions in case - # a directory is deleted: https://lkml.org/lkml/2007/7/9/3 - def watch_end(srv) - srv.wait_ctl(@ino, :delete) - @ino = @ino.close - end -end + def watch_extra(paths) + @ino.watch_extra(paths) + end -rescue LoadError -end + # Closing the inotify descriptor (instead of using inotify_rm_watch) + # is cleaner because it avoids EINVAL on race conditions in case + # a directory is deleted: https://lkml.org/lkml/2007/7/9/3 + def watch_end(srv) + srv.wait_ctl(@ino, :delete) + @ino = @ino.close + end + end # module DTAS::Watchable +rescue LoadError, StandardError => e + warn "#{e.message} (#{e.class})" +end # begin -- cgit v1.2.3-24-ge0c7