From: Eric Wong <e@80x24.org> To: dtas-all@nongnu.org Subject: [PATCH 4/5] watchable: use fiddle for inotify support Date: Sun, 1 Dec 2019 01:26:52 +0000 Message-ID: <20191201012653.21967-5-e@80x24.org> (raw) In-Reply-To: <20191201012653.21967-1-e@80x24.org> 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 | 85 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 77 insertions(+), 8 deletions(-) diff --git a/lib/dtas/watchable.rb b/lib/dtas/watchable.rb index d0f37af..4047a42 100644 --- a/lib/dtas/watchable.rb +++ b/lib/dtas/watchable.rb @@ -1,22 +1,80 @@ # Copyright (C) 2013-2019 all contributors <dtas-all@nongnu.org> # License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt> # frozen_string_literal: true +require_relative '../dtas' +require_relative 'nonblock' + begin -require 'sleepy_penguin' +require 'fiddle' # 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) + class InotifyReadableIter # :nodoc: + + Inotify_init = Fiddle::Function.new(DTAS.libc['inotify_init1'], + [ Fiddle::TYPE_INT ], + Fiddle::TYPE_INT) + + Inotify_add_watch = Fiddle::Function.new(DTAS.libc['inotify_add_watch'], + [ Fiddle::TYPE_INT, Fiddle::TYPE_VOIDP, Fiddle::TYPE_INT ], + Fiddle::TYPE_INT) + + # IO.select compatibility + attr_reader :to_io #:nodoc: + + def initialize # :nodoc: + fd = Inotify_init.call(02000000 | 04000) # CLOEXEC | NONBLOCK + raise "inotify_init failed: #{Fiddle.last_error}" if fd < 0 + @to_io = DTAS::Nonblock.for_fd(fd) + @buf = ''.b + @q = [] end - FLAGS = CLOSE_WRITE | MOVED_TO + # struct inotify_event { + # int wd; /* Watch descriptor */ + # uint32_t mask; /* Mask describing event */ + # uint32_t cookie; /* Unique cookie associating related + # events (for rename(2)) */ + # uint32_t len; /* Size of name field */ + # char name[]; /* Optional null-terminated name */ + InotifyEvent = Struct.new(:wd, :mask, :cookie, :len, :name) # :nodoc: + + def take # :nodoc: + event = @q.pop and return event + case rv = @to_io.read_nonblock(16384, @buf, exception: false) + when :wait_readable, nil + return + else + until rv.empty? + hdr = rv.slice!(0,16) + name = nil + wd, mask, cookie, len = res = hdr.unpack('iIII') + wd && mask && cookie && len or + raise "bogus inotify_event #{res.inspect} hdr=#{hdr.inspect}" + if len > 0 + name = rv.slice!(0, len) + name.size == len or raise "short name #{name.inspect} != #{len}" + name.sub!(/\0+\z/, '') or + raise "missing: `\\0', inotify_event.name=#{name.inspect}" + name = DTAS.dedupe_str(name) + end + ie = InotifyEvent.new(wd, mask, cookie, len, name) + if event + @q << ie + else + event = ie + end + end # /until rv.empty? + return event + end while true + end + + FLAGS = 8 | 128 # CLOSE_WRITE | MOVED_TO def readable_iter or_call = false - while event = take(true) # drain the buffer + while event = take # drain the buffer w = @watches[event.wd] or next if (event.mask & FLAGS) != 0 && w[event.name] or_call = true @@ -30,6 +88,16 @@ def readable_iter end end + def add_watch(watchdir) + wd = Inotify_add_watch.call(@to_io.fileno, watchdir, FLAGS) + raise "inotify_add_watch failed: #{Fiddle.last_error}" if wd < 0 + wd + end + + def close + @to_io = @to_io.close if @to_io + end + # we must watch the directory, since def watch_files(paths, blk) @watches = {} # wd -> { basename -> true } @@ -38,7 +106,7 @@ def watch_files(paths, blk) Array(paths).each do |path| watchdir, watchbase = File.split(File.expand_path(path)) begin - wd = @dir2wd[watchdir] ||= add_watch(watchdir, FLAGS) + wd = @dir2wd[watchdir] ||= add_watch(watchdir) m = @watches[wd] ||= {} m[watchbase] = true rescue SystemCallError => e @@ -67,5 +135,6 @@ def watch_end(srv) end end -rescue LoadError +rescue LoadError, Fiddle::DLError => e + warn "#{e.message} (#{e.class})" end
next prev parent reply other threads:[~2019-12-01 1:27 UTC|newest] Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top 2019-12-01 1:26 [PATCH 0/5] use fiddle for Linux-specific APIs Eric Wong 2019-12-01 1:26 ` [PATCH 1/5] pipe: avoid loading sleepy_penguin Eric Wong 2019-12-01 1:26 ` [PATCH 2/5] use fiddle-based eventfd implementation Eric Wong 2019-12-01 1:26 ` [PATCH 3/5] buffer: replace sleepy_penguin with fiddle Eric Wong 2019-12-01 1:26 ` Eric Wong [this message] 2019-12-01 1:26 ` [PATCH 5/5] doc: remove "sleepy_penguin" references Eric Wong 2019-12-13 18:16 ` [PATCH 0/5] use fiddle for Linux-specific APIs Eric Wong 2019-12-15 20:39 ` fiddle vs sleepy_penguin vs Perl syscall() bench scripts Eric Wong
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style List information: https://80x24.org/dtas/README * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20191201012653.21967-5-e@80x24.org \ --to=e@80x24.org \ --cc=dtas-all@nongnu.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
everything related to duct tape audio suite (dtas) This inbox may be cloned and mirrored by anyone: git clone --mirror https://80x24.org/dtas-all git clone --mirror http://ou63pmih66umazou.onion/dtas-all # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V1 dtas-all dtas-all/ https://80x24.org/dtas-all \ dtas-all@nongnu.org public-inbox-index dtas-all Example config snippet for mirrors. Newsgroups are available over NNTP: nntp://news.public-inbox.org/inbox.comp.audio.dtas nntp://ou63pmih66umazou.onion/inbox.comp.audio.dtas note: .onion URLs require Tor: https://www.torproject.org/ code repositories for the project(s) associated with this inbox: ../../dtas.git AGPL code for this site: git clone http://ou63pmih66umazou.onion/public-inbox.git