From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: AS22989 209.51.188.0/24 X-Spam-Status: No, score=-3.5 required=3.0 tests=AWL,BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED, SPF_HELO_NONE,SPF_PASS shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dcvr.yhbt.net (Postfix) with ESMTPS id AD35E1F463 for ; Sun, 1 Dec 2019 01:27:11 +0000 (UTC) Received: from localhost ([::1]:39822 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ibE10-0004Or-Ox for e@80x24.org; Sat, 30 Nov 2019 20:27:10 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:59314) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ibE0x-0004N3-Th for dtas-all@nongnu.org; Sat, 30 Nov 2019 20:27:09 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ibE0w-0006TU-CG for dtas-all@nongnu.org; Sat, 30 Nov 2019 20:27:07 -0500 Received: from dcvr.yhbt.net ([64.71.152.64]:48390) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ibE0w-0006T9-4h for dtas-all@nongnu.org; Sat, 30 Nov 2019 20:27:06 -0500 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id E8ECD1F46C for ; Sun, 1 Dec 2019 01:26:53 +0000 (UTC) From: Eric Wong To: dtas-all@nongnu.org Subject: [PATCH 3/5] buffer: replace sleepy_penguin with fiddle Date: Sun, 1 Dec 2019 01:26:51 +0000 Message-Id: <20191201012653.21967-4-e@80x24.org> In-Reply-To: <20191201012653.21967-1-e@80x24.org> References: <20191201012653.21967-1-e@80x24.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 64.71.152.64 X-BeenThere: dtas-all@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: duct tape audio suite List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dtas-all-bounces+e=80x24.org@nongnu.org Sender: "dtas-all" Fiddle exists on all Ruby 1.9.2+ installations and seems alright. Since splice is a Linux-only API, we don't need to worry about the values of constants changing (and they're architecture-independent). --- lib/dtas/buffer.rb | 7 +- .../buffer/{splice.rb =3D> fiddle_splice.rb} | 75 +++++++++++++++---- lib/dtas/buffer/read_write.rb | 4 +- test/test_buffer.rb | 10 +-- 4 files changed, 69 insertions(+), 27 deletions(-) rename lib/dtas/buffer/{splice.rb =3D> fiddle_splice.rb} (68%) diff --git a/lib/dtas/buffer.rb b/lib/dtas/buffer.rb index 39070d7..2bc44ba 100644 --- a/lib/dtas/buffer.rb +++ b/lib/dtas/buffer.rb @@ -8,11 +8,8 @@ class DTAS::Buffer # :nodoc: begin raise LoadError, "no splice with _DTAS_POSIX" if ENV["_DTAS_POSIX"] - require 'sleepy_penguin' # splice is only in Linux for now... - SleepyPenguin.respond_to?(:splice) or - raise LoadError, 'sleepy_penguin 3.5+ required for splice', [] - require_relative 'buffer/splice' - include DTAS::Buffer::Splice + require_relative 'buffer/fiddle_splice' # splice is only in Linux fo= r now... + include DTAS::Buffer::FiddleSplice rescue LoadError require_relative 'buffer/read_write' include DTAS::Buffer::ReadWrite diff --git a/lib/dtas/buffer/splice.rb b/lib/dtas/buffer/fiddle_splice.rb similarity index 68% rename from lib/dtas/buffer/splice.rb rename to lib/dtas/buffer/fiddle_splice.rb index 2e86d0a..543b3e0 100644 --- a/lib/dtas/buffer/splice.rb +++ b/lib/dtas/buffer/fiddle_splice.rb @@ -2,16 +2,64 @@ # License: GPL-3.0+ # frozen_string_literal: true require 'io/nonblock' -require 'sleepy_penguin' +require 'fiddle' # require_relative caller should expect LoadError require_relative '../../dtas' require_relative '../pipe' =20 -# Used by -player on Linux systems with the "sleepy_penguin" RubyGem ins= talled -module DTAS::Buffer::Splice # :nodoc: +# Used by -player on Linux systems with the "splice" syscall +module DTAS::Buffer::FiddleSplice # :nodoc: MAX_AT_ONCE =3D 4096 # page size in Linux MAX_AT_ONCE_1 =3D 65536 - F_MOVE =3D SleepyPenguin::F_MOVE - F_NONBLOCK =3D SleepyPenguin::F_NONBLOCK + F_MOVE =3D 1 + F_NONBLOCK =3D 2 + + Splice =3D Fiddle::Function.new(DTAS.libc['splice'], [ + Fiddle::TYPE_INT, # int fd_in, + Fiddle::TYPE_VOIDP, # loff_t *off_in + Fiddle::TYPE_INT, # int fd_out + Fiddle::TYPE_VOIDP, # loff_t *off_out + Fiddle::TYPE_SIZE_T, # size_t len + Fiddle::TYPE_INT, # unsigned int flags + ], + Fiddle::TYPE_SSIZE_T) # ssize_t + + Tee =3D Fiddle::Function.new(DTAS.libc['tee'], [ + Fiddle::TYPE_INT, # int fd_in, + Fiddle::TYPE_INT, # int fd_out + Fiddle::TYPE_SIZE_T, # size_t len + Fiddle::TYPE_INT, # unsigned int flags + ], + Fiddle::TYPE_SSIZE_T) # ssize_t + + def _syserr(s, func) + raise "BUG: we should not encounter EOF on #{func}" if s =3D=3D 0 + case errno =3D Fiddle.last_error + when Errno::EAGAIN::Errno + return :EAGAIN + when Errno::EPIPE::Errno + raise Errno::EPIPE.exception + when Errno::EINTR::Errno + return nil + else + raise SystemCallError, "#{func} error: #{errno}" + end + end + + def splice(src, dst, len, flags) + begin + s =3D Splice.call(src.fileno, nil, dst.fileno, nil, len, flags) + return s if s > 0 + sym =3D _syserr(s, 'splice') and return sym + end while true + end + + def tee(src, dst, len, flags =3D 0) + begin + s =3D Tee.call(src.fileno, dst.fileno, len, flags) + return s if s > 0 + sym =3D _syserr(s, 'tee') and return sym + end while true + end =20 def buffer_size @to_io.pipe_size @@ -25,14 +73,13 @@ def buffer_size=3D(bytes) =20 # be sure to only call this with nil when all writers to @wr are done def discard(bytes) - SleepyPenguin.splice(@to_io, DTAS.null, bytes) + splice(@to_io, DTAS.null, bytes, 0) end =20 def broadcast_one(targets, limit =3D nil) # single output is always non-blocking limit ||=3D MAX_AT_ONCE_1 - s =3D SleepyPenguin.splice(@to_io, targets[0], limit, F_MOVE|F_NONBL= OCK, - exception: false) + s =3D splice(@to_io, targets[0], limit, F_MOVE|F_NONBLOCK) if Symbol =3D=3D=3D s targets # our one and only target blocked on write else @@ -48,7 +95,7 @@ def broadcast_one(targets, limit =3D nil) def __tee_in_full(src, dst, bytes) rv =3D 0 while bytes > 0 - s =3D SleepyPenguin.tee(src, dst, bytes) + s =3D tee(src, dst, bytes) bytes -=3D s rv +=3D s end @@ -58,7 +105,7 @@ def __tee_in_full(src, dst, bytes) def __splice_in_full(src, dst, bytes, flags) rv =3D 0 while bytes > 0 - s =3D SleepyPenguin.splice(src, dst, bytes, flags) + s =3D splice(src, dst, bytes, flags) rv +=3D s bytes -=3D s end @@ -71,9 +118,8 @@ def __broadcast_tee(blocked, targets, chunk_size) targets.delete_if do |dst| begin t =3D (dst.nonblock? || most_teed =3D=3D 0) ? - SleepyPenguin.tee(@to_io, dst, chunk_size, F_NONBLOCK, - exception: false) : - __tee_in_full(@to_io, dst, chunk_size) + tee(@to_io, dst, chunk_size, F_NONBLOCK) : + __tee_in_full(@to_io, dst, chunk_size) if Integer =3D=3D=3D t if t > most_teed chunk_size =3D t if most_teed =3D=3D 0 @@ -120,8 +166,7 @@ def broadcast_inf(targets, limit =3D nil) begin targets << last if last.nonblock? || most_teed =3D=3D 0 - s =3D SleepyPenguin.splice(@to_io, last, bytes, F_MOVE|F_NONBLOC= K, - exception: false) + s =3D splice(@to_io, last, bytes, F_MOVE|F_NONBLOCK) if Symbol =3D=3D=3D s blocked << last =20 diff --git a/lib/dtas/buffer/read_write.rb b/lib/dtas/buffer/read_write.r= b index 04856c7..e2001b6 100644 --- a/lib/dtas/buffer/read_write.rb +++ b/lib/dtas/buffer/read_write.rb @@ -6,8 +6,8 @@ require_relative '../pipe' require_relative '../nonblock' =20 -# compatibility code for systems lacking "splice" support via the -# "sleepy_penguin" 3.5+ RubyGem. Used only by -player +# compatibility code for non-Linux systems lacking "splice" support. +# Used only by -player module DTAS::Buffer::ReadWrite # :nodoc: MAX_AT_ONCE =3D 512 # min PIPE_BUF value in POSIX attr_accessor :buffer_size diff --git a/test/test_buffer.rb b/test/test_buffer.rb index 8f5d8b5..1773ca3 100644 --- a/test/test_buffer.rb +++ b/test/test_buffer.rb @@ -49,14 +49,14 @@ def test_set_buffer_size buf =3D new_buffer buf.buffer_size =3D @@max_size assert_equal @@max_size, buf.buffer_size - end if defined?(SleepyPenguin::F_GETPIPE_SZ) + end if defined?(DTAS::Pipe::F_GETPIPE_SZ) =20 def test_buffer_size buf =3D new_buffer assert_operator buf.buffer_size, :>, 128 buf.buffer_size =3D @@max_size assert_equal @@max_size, buf.buffer_size - end if defined?(SleepyPenguin::F_GETPIPE_SZ) + end if defined?(DTAS::Pipe::F_GETPIPE_SZ) =20 def test_broadcast_1 buf =3D new_buffer @@ -108,7 +108,7 @@ def test_broadcast assert_equal "HELLO", a[0].read(5) assert_equal "HELLO", b[0].read(5) =20 - return unless defined?(SleepyPenguin::F_GETPIPE_SZ) + return unless defined?(DTAS::Pipe::F_GETPIPE_SZ) =20 b[1].nonblock =3D true b[1].write('*' * pipe_size(b[1])) @@ -167,7 +167,7 @@ def test_broadcast_all_full buf.wr.write "HELLO" assert_equal tmp, buf.broadcast(tmp) assert_equal [a[1], b[1]], tmp - end if defined?(SleepyPenguin::F_GETPIPE_SZ) + end if defined?(DTAS::Pipe::F_GETPIPE_SZ) =20 def test_serialize buf =3D new_buffer @@ -206,6 +206,6 @@ def test_load_size end =20 def pipe_size(io) - io.fcntl(SleepyPenguin::F_GETPIPE_SZ) + io.fcntl(DTAS::Pipe::F_GETPIPE_SZ) end end