polyphony 0.84 → 0.86
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -0
- data/Gemfile.lock +1 -1
- data/Rakefile +1 -1
- data/examples/core/multi_suspend.rb +39 -0
- data/examples/core/shutdown_all_children.rb +41 -0
- data/examples/io/gzip.rb +8 -0
- data/examples/io/splice_echo_server.rb +15 -0
- data/ext/polyphony/backend_io_uring.c +57 -31
- data/ext/polyphony/io_extensions.c +137 -26
- data/lib/polyphony/extensions/fiber.rb +3 -1
- data/lib/polyphony/extensions/io.rb +4 -0
- data/lib/polyphony/extensions/pipe.rb +4 -0
- data/lib/polyphony/extensions/socket.rb +4 -0
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +1 -1
- data/test/test_backend.rb +1 -1
- data/test/test_fiber.rb +5 -2
- data/test/test_signal.rb +3 -3
- data/vendor/liburing/.github/pull_request_template.md +86 -0
- data/vendor/liburing/.github/workflows/build.yml +85 -0
- data/vendor/liburing/.github/workflows/shellcheck.yml +20 -0
- data/vendor/liburing/.gitignore +149 -0
- data/vendor/liburing/COPYING +502 -0
- data/vendor/liburing/COPYING.GPL +339 -0
- data/vendor/liburing/LICENSE +7 -0
- data/vendor/liburing/Makefile +82 -0
- data/vendor/liburing/Makefile.common +5 -0
- data/vendor/liburing/Makefile.quiet +11 -0
- data/vendor/liburing/README +46 -0
- data/vendor/liburing/configure +486 -0
- data/vendor/liburing/debian/README.Debian +7 -0
- data/vendor/liburing/debian/changelog +27 -0
- data/vendor/liburing/debian/compat +1 -0
- data/vendor/liburing/debian/control +48 -0
- data/vendor/liburing/debian/copyright +49 -0
- data/vendor/liburing/debian/liburing-dev.install +4 -0
- data/vendor/liburing/debian/liburing-dev.manpages +6 -0
- data/vendor/liburing/debian/liburing1-udeb.install +1 -0
- data/vendor/liburing/debian/liburing1.install +1 -0
- data/vendor/liburing/debian/liburing1.symbols +32 -0
- data/vendor/liburing/debian/patches/series +1 -0
- data/vendor/liburing/debian/rules +81 -0
- data/vendor/liburing/debian/source/format +1 -0
- data/vendor/liburing/debian/source/local-options +2 -0
- data/vendor/liburing/debian/source/options +1 -0
- data/vendor/liburing/debian/watch +3 -0
- data/vendor/liburing/examples/Makefile +38 -0
- data/vendor/liburing/examples/io_uring-cp.c +282 -0
- data/vendor/liburing/examples/io_uring-test.c +112 -0
- data/vendor/liburing/examples/link-cp.c +193 -0
- data/vendor/liburing/examples/ucontext-cp.c +273 -0
- data/vendor/liburing/liburing.pc.in +12 -0
- data/vendor/liburing/liburing.spec +66 -0
- data/vendor/liburing/make-debs.sh +53 -0
- data/vendor/liburing/man/io_uring.7 +754 -0
- data/vendor/liburing/man/io_uring_cq_advance.3 +35 -0
- data/vendor/liburing/man/io_uring_cq_ready.3 +25 -0
- data/vendor/liburing/man/io_uring_cqe_get_data.3 +34 -0
- data/vendor/liburing/man/io_uring_cqe_seen.3 +32 -0
- data/vendor/liburing/man/io_uring_enter.2 +1483 -0
- data/vendor/liburing/man/io_uring_free_probe.3 +24 -0
- data/vendor/liburing/man/io_uring_get_probe.3 +29 -0
- data/vendor/liburing/man/io_uring_get_sqe.3 +38 -0
- data/vendor/liburing/man/io_uring_opcode_supported.3 +29 -0
- data/vendor/liburing/man/io_uring_prep_msg_ring.3 +58 -0
- data/vendor/liburing/man/io_uring_prep_read.3 +50 -0
- data/vendor/liburing/man/io_uring_prep_read_fixed.3 +54 -0
- data/vendor/liburing/man/io_uring_prep_readv.3 +51 -0
- data/vendor/liburing/man/io_uring_prep_readv2.3 +79 -0
- data/vendor/liburing/man/io_uring_prep_write.3 +50 -0
- data/vendor/liburing/man/io_uring_prep_write_fixed.3 +54 -0
- data/vendor/liburing/man/io_uring_prep_writev.3 +51 -0
- data/vendor/liburing/man/io_uring_prep_writev2.3 +78 -0
- data/vendor/liburing/man/io_uring_queue_exit.3 +27 -0
- data/vendor/liburing/man/io_uring_queue_init.3 +44 -0
- data/vendor/liburing/man/io_uring_register.2 +688 -0
- data/vendor/liburing/man/io_uring_register_buffers.3 +41 -0
- data/vendor/liburing/man/io_uring_register_files.3 +35 -0
- data/vendor/liburing/man/io_uring_setup.2 +534 -0
- data/vendor/liburing/man/io_uring_sq_ready.3 +25 -0
- data/vendor/liburing/man/io_uring_sq_space_left.3 +25 -0
- data/vendor/liburing/man/io_uring_sqe_set_data.3 +30 -0
- data/vendor/liburing/man/io_uring_sqe_set_flags.3 +60 -0
- data/vendor/liburing/man/io_uring_sqring_wait.3 +30 -0
- data/vendor/liburing/man/io_uring_submit.3 +29 -0
- data/vendor/liburing/man/io_uring_submit_and_wait.3 +34 -0
- data/vendor/liburing/man/io_uring_submit_and_wait_timeout.3 +49 -0
- data/vendor/liburing/man/io_uring_unregister_buffers.3 +26 -0
- data/vendor/liburing/man/io_uring_unregister_files.3 +26 -0
- data/vendor/liburing/man/io_uring_wait_cqe.3 +33 -0
- data/vendor/liburing/man/io_uring_wait_cqe_nr.3 +36 -0
- data/vendor/liburing/man/io_uring_wait_cqe_timeout.3 +39 -0
- data/vendor/liburing/man/io_uring_wait_cqes.3 +46 -0
- data/vendor/liburing/src/Makefile +89 -0
- data/vendor/liburing/src/arch/aarch64/syscall.h +95 -0
- data/vendor/liburing/src/arch/generic/lib.h +21 -0
- data/vendor/liburing/src/arch/generic/syscall.h +87 -0
- data/vendor/liburing/src/arch/syscall-defs.h +67 -0
- data/vendor/liburing/src/arch/x86/lib.h +32 -0
- data/vendor/liburing/src/arch/x86/syscall.h +160 -0
- data/vendor/liburing/src/include/liburing/barrier.h +81 -0
- data/vendor/liburing/src/include/liburing/io_uring.h +442 -0
- data/vendor/liburing/src/include/liburing.h +921 -0
- data/vendor/liburing/src/int_flags.h +8 -0
- data/vendor/liburing/src/lib.h +57 -0
- data/vendor/liburing/src/liburing.map +53 -0
- data/vendor/liburing/src/nolibc.c +48 -0
- data/vendor/liburing/src/queue.c +403 -0
- data/vendor/liburing/src/register.c +293 -0
- data/vendor/liburing/src/setup.c +332 -0
- data/vendor/liburing/src/syscall.c +47 -0
- data/vendor/liburing/src/syscall.h +103 -0
- data/vendor/liburing/test/232c93d07b74-test.c +306 -0
- data/vendor/liburing/test/35fa71a030ca-test.c +329 -0
- data/vendor/liburing/test/500f9fbadef8-test.c +89 -0
- data/vendor/liburing/test/7ad0e4b2f83c-test.c +93 -0
- data/vendor/liburing/test/8a9973408177-test.c +106 -0
- data/vendor/liburing/test/917257daa0fe-test.c +53 -0
- data/vendor/liburing/test/Makefile +244 -0
- data/vendor/liburing/test/a0908ae19763-test.c +58 -0
- data/vendor/liburing/test/a4c0b3decb33-test.c +180 -0
- data/vendor/liburing/test/accept-link.c +254 -0
- data/vendor/liburing/test/accept-reuse.c +164 -0
- data/vendor/liburing/test/accept-test.c +79 -0
- data/vendor/liburing/test/accept.c +477 -0
- data/vendor/liburing/test/across-fork.c +283 -0
- data/vendor/liburing/test/b19062a56726-test.c +53 -0
- data/vendor/liburing/test/b5837bd5311d-test.c +77 -0
- data/vendor/liburing/test/ce593a6c480a-test.c +136 -0
- data/vendor/liburing/test/close-opath.c +122 -0
- data/vendor/liburing/test/config +10 -0
- data/vendor/liburing/test/connect.c +398 -0
- data/vendor/liburing/test/cq-full.c +96 -0
- data/vendor/liburing/test/cq-overflow.c +294 -0
- data/vendor/liburing/test/cq-peek-batch.c +102 -0
- data/vendor/liburing/test/cq-ready.c +94 -0
- data/vendor/liburing/test/cq-size.c +64 -0
- data/vendor/liburing/test/d4ae271dfaae-test.c +96 -0
- data/vendor/liburing/test/d77a67ed5f27-test.c +65 -0
- data/vendor/liburing/test/defer.c +307 -0
- data/vendor/liburing/test/double-poll-crash.c +185 -0
- data/vendor/liburing/test/drop-submit.c +92 -0
- data/vendor/liburing/test/eeed8b54e0df-test.c +114 -0
- data/vendor/liburing/test/empty-eownerdead.c +45 -0
- data/vendor/liburing/test/eventfd-disable.c +151 -0
- data/vendor/liburing/test/eventfd-reg.c +76 -0
- data/vendor/liburing/test/eventfd-ring.c +97 -0
- data/vendor/liburing/test/eventfd.c +112 -0
- data/vendor/liburing/test/exec-target.c +6 -0
- data/vendor/liburing/test/exit-no-cleanup.c +117 -0
- data/vendor/liburing/test/fadvise.c +202 -0
- data/vendor/liburing/test/fallocate.c +249 -0
- data/vendor/liburing/test/fc2a85cb02ef-test.c +131 -0
- data/vendor/liburing/test/file-register.c +858 -0
- data/vendor/liburing/test/file-update.c +173 -0
- data/vendor/liburing/test/file-verify.c +629 -0
- data/vendor/liburing/test/files-exit-hang-poll.c +128 -0
- data/vendor/liburing/test/files-exit-hang-timeout.c +134 -0
- data/vendor/liburing/test/fixed-link.c +90 -0
- data/vendor/liburing/test/fpos.c +252 -0
- data/vendor/liburing/test/fsync.c +224 -0
- data/vendor/liburing/test/hardlink.c +136 -0
- data/vendor/liburing/test/helpers.c +135 -0
- data/vendor/liburing/test/helpers.h +67 -0
- data/vendor/liburing/test/io-cancel.c +550 -0
- data/vendor/liburing/test/io_uring_enter.c +296 -0
- data/vendor/liburing/test/io_uring_register.c +676 -0
- data/vendor/liburing/test/io_uring_setup.c +192 -0
- data/vendor/liburing/test/iopoll.c +372 -0
- data/vendor/liburing/test/lfs-openat-write.c +119 -0
- data/vendor/liburing/test/lfs-openat.c +275 -0
- data/vendor/liburing/test/link-timeout.c +1107 -0
- data/vendor/liburing/test/link.c +496 -0
- data/vendor/liburing/test/link_drain.c +229 -0
- data/vendor/liburing/test/madvise.c +195 -0
- data/vendor/liburing/test/mkdir.c +108 -0
- data/vendor/liburing/test/msg-ring.c +234 -0
- data/vendor/liburing/test/multicqes_drain.c +387 -0
- data/vendor/liburing/test/nop-all-sizes.c +99 -0
- data/vendor/liburing/test/nop.c +115 -0
- data/vendor/liburing/test/open-close.c +261 -0
- data/vendor/liburing/test/openat2.c +308 -0
- data/vendor/liburing/test/personality.c +204 -0
- data/vendor/liburing/test/pipe-eof.c +83 -0
- data/vendor/liburing/test/pipe-reuse.c +105 -0
- data/vendor/liburing/test/poll-cancel-ton.c +135 -0
- data/vendor/liburing/test/poll-cancel.c +228 -0
- data/vendor/liburing/test/poll-link.c +230 -0
- data/vendor/liburing/test/poll-many.c +208 -0
- data/vendor/liburing/test/poll-mshot-update.c +273 -0
- data/vendor/liburing/test/poll-ring.c +48 -0
- data/vendor/liburing/test/poll-v-poll.c +353 -0
- data/vendor/liburing/test/poll.c +109 -0
- data/vendor/liburing/test/pollfree.c +426 -0
- data/vendor/liburing/test/probe.c +135 -0
- data/vendor/liburing/test/read-write.c +876 -0
- data/vendor/liburing/test/register-restrictions.c +633 -0
- data/vendor/liburing/test/rename.c +135 -0
- data/vendor/liburing/test/ring-leak.c +173 -0
- data/vendor/liburing/test/ring-leak2.c +249 -0
- data/vendor/liburing/test/rsrc_tags.c +449 -0
- data/vendor/liburing/test/runtests-loop.sh +16 -0
- data/vendor/liburing/test/runtests.sh +170 -0
- data/vendor/liburing/test/rw_merge_test.c +97 -0
- data/vendor/liburing/test/self.c +91 -0
- data/vendor/liburing/test/send_recv.c +286 -0
- data/vendor/liburing/test/send_recvmsg.c +345 -0
- data/vendor/liburing/test/sendmsg_fs_cve.c +200 -0
- data/vendor/liburing/test/shared-wq.c +84 -0
- data/vendor/liburing/test/short-read.c +75 -0
- data/vendor/liburing/test/shutdown.c +165 -0
- data/vendor/liburing/test/sigfd-deadlock.c +74 -0
- data/vendor/liburing/test/skip-cqe.c +429 -0
- data/vendor/liburing/test/socket-rw-eagain.c +158 -0
- data/vendor/liburing/test/socket-rw-offset.c +157 -0
- data/vendor/liburing/test/socket-rw.c +145 -0
- data/vendor/liburing/test/splice.c +512 -0
- data/vendor/liburing/test/sq-full-cpp.cc +45 -0
- data/vendor/liburing/test/sq-full.c +45 -0
- data/vendor/liburing/test/sq-poll-dup.c +204 -0
- data/vendor/liburing/test/sq-poll-kthread.c +169 -0
- data/vendor/liburing/test/sq-poll-share.c +137 -0
- data/vendor/liburing/test/sq-space_left.c +159 -0
- data/vendor/liburing/test/sqpoll-cancel-hang.c +157 -0
- data/vendor/liburing/test/sqpoll-disable-exit.c +196 -0
- data/vendor/liburing/test/sqpoll-exit-hang.c +78 -0
- data/vendor/liburing/test/sqpoll-sleep.c +69 -0
- data/vendor/liburing/test/statx.c +172 -0
- data/vendor/liburing/test/stdout.c +232 -0
- data/vendor/liburing/test/submit-link-fail.c +154 -0
- data/vendor/liburing/test/submit-reuse.c +239 -0
- data/vendor/liburing/test/symlink.c +116 -0
- data/vendor/liburing/test/teardowns.c +58 -0
- data/vendor/liburing/test/thread-exit.c +143 -0
- data/vendor/liburing/test/timeout-new.c +252 -0
- data/vendor/liburing/test/timeout-overflow.c +204 -0
- data/vendor/liburing/test/timeout.c +1523 -0
- data/vendor/liburing/test/unlink.c +112 -0
- data/vendor/liburing/test/wakeup-hang.c +162 -0
- metadata +227 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b87dae4e2c17055e8206c820a4281774cdf3127195173948c97df4eb09a2bd13
|
|
4
|
+
data.tar.gz: 2e7bd958ec7435569423398069223eda41e9c2d89f580627bc22e9054276dd1c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 48f6489939da965463735c83acb4372263eb44b48b5a16da1e704a15e3af971a5d43abd7da5e44f2455b40d880413c6fa8159794e663176c83a11eddebdebc7d
|
|
7
|
+
data.tar.gz: 3ada5f9041041e91b6b2a7f31ec609352752317e87c51df090517c9e2b556d9ef69ef8842babd15f25b2257c4226431520ff15df505748cb38bb4a1d5a19063c
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## 0.86 2022-03-14
|
|
2
|
+
|
|
3
|
+
- Fix gemspec
|
|
4
|
+
|
|
5
|
+
## 0.85 2022-03-13
|
|
6
|
+
|
|
7
|
+
- Reduce write ops in `IO.gzip` (#77)
|
|
8
|
+
- Add support for read/write method detection for compression/decompression
|
|
9
|
+
methods (#77)
|
|
10
|
+
- Improve `Fiber#shutdown_all_children`
|
|
11
|
+
- Improve io_uring `wait_event` implementation (share single I/O poll across
|
|
12
|
+
multiple fibers)
|
|
13
|
+
- Fix io_uring `write` file offset
|
|
14
|
+
|
|
1
15
|
## 0.84 2022-03-11
|
|
2
16
|
|
|
3
17
|
- Implement `IO.tee` (#82)
|
data/Gemfile.lock
CHANGED
data/Rakefile
CHANGED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'bundler/setup'
|
|
4
|
+
require 'polyphony'
|
|
5
|
+
|
|
6
|
+
module ::Kernel
|
|
7
|
+
def trace(*args)
|
|
8
|
+
STDOUT.orig_write(format_trace(args))
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def format_trace(args)
|
|
12
|
+
if args.first.is_a?(String)
|
|
13
|
+
if args.size > 1
|
|
14
|
+
format("%s: %p\n", args.shift, args)
|
|
15
|
+
else
|
|
16
|
+
format("%s\n", args.first)
|
|
17
|
+
end
|
|
18
|
+
else
|
|
19
|
+
format("%p\n", args.size == 1 ? args.first : args)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def monotonic_clock
|
|
24
|
+
::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
count = 10000
|
|
29
|
+
|
|
30
|
+
count.times do
|
|
31
|
+
spin { Polyphony.backend_wait_event(true) }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
trace 'sleeping...'
|
|
35
|
+
sleep 1
|
|
36
|
+
|
|
37
|
+
trace 'shutting down children...'
|
|
38
|
+
Fiber.current.shutdown_all_children
|
|
39
|
+
trace 'done'
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'bundler/setup'
|
|
4
|
+
require 'polyphony'
|
|
5
|
+
|
|
6
|
+
module ::Kernel
|
|
7
|
+
def trace(*args)
|
|
8
|
+
STDOUT.orig_write(format_trace(args))
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def format_trace(args)
|
|
12
|
+
if args.first.is_a?(String)
|
|
13
|
+
if args.size > 1
|
|
14
|
+
format("%s: %p\n", args.shift, args)
|
|
15
|
+
else
|
|
16
|
+
format("%s\n", args.first)
|
|
17
|
+
end
|
|
18
|
+
else
|
|
19
|
+
format("%p\n", args.size == 1 ? args.first : args)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def monotonic_clock
|
|
24
|
+
::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
count = 10
|
|
29
|
+
|
|
30
|
+
f = spin do
|
|
31
|
+
count.times { spin { suspend } }
|
|
32
|
+
suspend
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
snooze
|
|
36
|
+
trace children_alive: f.children.size
|
|
37
|
+
|
|
38
|
+
trace 'shutting down children...'
|
|
39
|
+
f.shutdown_all_children
|
|
40
|
+
|
|
41
|
+
trace children_alive: f.children.size
|
data/examples/io/gzip.rb
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'bundler/setup'
|
|
4
|
+
require 'polyphony'
|
|
5
|
+
|
|
6
|
+
require 'polyphony'
|
|
7
|
+
|
|
8
|
+
def handle_echo_client(conn)
|
|
9
|
+
buffer = Polyphony.pipe
|
|
10
|
+
spin { buffer.splice_to_eof_from(conn) }
|
|
11
|
+
spin { conn.splice_to_eof_from(buffer) }
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
puts "Serving echo on port 1234..."
|
|
15
|
+
TCPServer.new('127.0.0.1', 1234).accept_loop { |c| handle_echo_client(c) }
|
|
@@ -41,8 +41,10 @@ typedef struct Backend_t {
|
|
|
41
41
|
op_context_store_t store;
|
|
42
42
|
unsigned int pending_sqes;
|
|
43
43
|
unsigned int prepared_limit;
|
|
44
|
-
int event_fd;
|
|
45
44
|
int ring_initialized;
|
|
45
|
+
|
|
46
|
+
int event_fd;
|
|
47
|
+
op_context_t *event_fd_ctx;
|
|
46
48
|
} Backend_t;
|
|
47
49
|
|
|
48
50
|
static void Backend_mark(void *ptr) {
|
|
@@ -83,6 +85,7 @@ static VALUE Backend_initialize(VALUE self) {
|
|
|
83
85
|
backend->pending_sqes = 0;
|
|
84
86
|
backend->ring_initialized = 0;
|
|
85
87
|
backend->event_fd = -1;
|
|
88
|
+
backend->event_fd_ctx = NULL;
|
|
86
89
|
|
|
87
90
|
context_store_initialize(&backend->store);
|
|
88
91
|
|
|
@@ -183,13 +186,21 @@ done:
|
|
|
183
186
|
return;
|
|
184
187
|
}
|
|
185
188
|
|
|
189
|
+
inline void io_uring_backend_immediate_submit(Backend_t *backend) {
|
|
190
|
+
backend->pending_sqes = 0;
|
|
191
|
+
io_uring_submit(&backend->ring);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
inline void io_uring_backend_defer_submit(Backend_t *backend) {
|
|
195
|
+
backend->pending_sqes += 1;
|
|
196
|
+
if (backend->pending_sqes >= backend->prepared_limit)
|
|
197
|
+
io_uring_backend_immediate_submit(backend);
|
|
198
|
+
}
|
|
199
|
+
|
|
186
200
|
void io_uring_backend_poll(Backend_t *backend) {
|
|
187
201
|
poll_context_t poll_ctx;
|
|
188
202
|
poll_ctx.ring = &backend->ring;
|
|
189
|
-
if (backend->pending_sqes)
|
|
190
|
-
backend->pending_sqes = 0;
|
|
191
|
-
io_uring_submit(&backend->ring);
|
|
192
|
-
}
|
|
203
|
+
if (backend->pending_sqes) io_uring_backend_immediate_submit(backend);
|
|
193
204
|
|
|
194
205
|
wait_cqe:
|
|
195
206
|
backend->base.currently_polling = 1;
|
|
@@ -211,10 +222,7 @@ inline VALUE Backend_poll(VALUE self, VALUE blocking) {
|
|
|
211
222
|
|
|
212
223
|
backend->base.poll_count++;
|
|
213
224
|
|
|
214
|
-
if (!is_blocking && backend->pending_sqes)
|
|
215
|
-
backend->pending_sqes = 0;
|
|
216
|
-
io_uring_submit(&backend->ring);
|
|
217
|
-
}
|
|
225
|
+
if (!is_blocking && backend->pending_sqes) io_uring_backend_immediate_submit(backend);
|
|
218
226
|
|
|
219
227
|
COND_TRACE(&backend->base, 2, SYM_enter_poll, rb_fiber_current());
|
|
220
228
|
|
|
@@ -263,8 +271,7 @@ VALUE Backend_wakeup(VALUE self) {
|
|
|
263
271
|
// NOP which would cause the io_uring_enter syscall to return
|
|
264
272
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
|
265
273
|
io_uring_prep_nop(sqe);
|
|
266
|
-
backend
|
|
267
|
-
io_uring_submit(&backend->ring);
|
|
274
|
+
io_uring_backend_immediate_submit(backend);
|
|
268
275
|
|
|
269
276
|
return Qtrue;
|
|
270
277
|
}
|
|
@@ -272,14 +279,6 @@ VALUE Backend_wakeup(VALUE self) {
|
|
|
272
279
|
return Qnil;
|
|
273
280
|
}
|
|
274
281
|
|
|
275
|
-
inline void io_uring_backend_defer_submit(Backend_t *backend) {
|
|
276
|
-
backend->pending_sqes += 1;
|
|
277
|
-
if (backend->pending_sqes >= backend->prepared_limit) {
|
|
278
|
-
backend->pending_sqes = 0;
|
|
279
|
-
io_uring_submit(&backend->ring);
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
282
|
int io_uring_backend_defer_submit_and_await(
|
|
284
283
|
Backend_t *backend,
|
|
285
284
|
struct io_uring_sqe *sqe,
|
|
@@ -305,8 +304,7 @@ int io_uring_backend_defer_submit_and_await(
|
|
|
305
304
|
ctx->result = -ECANCELED;
|
|
306
305
|
sqe = io_uring_get_sqe(&backend->ring);
|
|
307
306
|
io_uring_prep_cancel(sqe, (__u64)ctx, 0);
|
|
308
|
-
backend
|
|
309
|
-
io_uring_submit(&backend->ring);
|
|
307
|
+
io_uring_backend_immediate_submit(backend);
|
|
310
308
|
}
|
|
311
309
|
|
|
312
310
|
if (value_ptr) (*value_ptr) = switchpoint_result;
|
|
@@ -552,7 +550,7 @@ VALUE Backend_write(VALUE self, VALUE io, VALUE str) {
|
|
|
552
550
|
int result;
|
|
553
551
|
int completed;
|
|
554
552
|
|
|
555
|
-
io_uring_prep_write(sqe, fd, buffer.ptr, left,
|
|
553
|
+
io_uring_prep_write(sqe, fd, buffer.ptr, left, -1);
|
|
556
554
|
|
|
557
555
|
result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
|
558
556
|
completed = context_store_release(&backend->store, ctx);
|
|
@@ -1161,8 +1159,7 @@ VALUE Backend_timeout_ensure(VALUE arg) {
|
|
|
1161
1159
|
// op was not completed, so we need to cancel it
|
|
1162
1160
|
sqe = io_uring_get_sqe(&timeout_ctx->backend->ring);
|
|
1163
1161
|
io_uring_prep_cancel(sqe, (__u64)timeout_ctx->ctx, 0);
|
|
1164
|
-
timeout_ctx->backend
|
|
1165
|
-
io_uring_submit(&timeout_ctx->backend->ring);
|
|
1162
|
+
io_uring_backend_immediate_submit(timeout_ctx->backend);
|
|
1166
1163
|
}
|
|
1167
1164
|
context_store_release(&timeout_ctx->backend->store, timeout_ctx->ctx);
|
|
1168
1165
|
return Qnil;
|
|
@@ -1237,6 +1234,13 @@ VALUE Backend_waitpid(VALUE self, VALUE pid) {
|
|
|
1237
1234
|
return rb_ary_new_from_args(2, INT2NUM(ret), INT2NUM(WEXITSTATUS(status)));
|
|
1238
1235
|
}
|
|
1239
1236
|
|
|
1237
|
+
/*
|
|
1238
|
+
Blocks a fiber indefinitely. This is accomplished by using an eventfd that will
|
|
1239
|
+
never be signalled. The eventfd is needed so we could do a blocking polling for
|
|
1240
|
+
completions even when no other I/O operations are pending.
|
|
1241
|
+
|
|
1242
|
+
The eventfd is refcounted in order to allow multiple fibers to be blocked.
|
|
1243
|
+
*/
|
|
1240
1244
|
VALUE Backend_wait_event(VALUE self, VALUE raise) {
|
|
1241
1245
|
Backend_t *backend;
|
|
1242
1246
|
VALUE resume_value;
|
|
@@ -1251,7 +1255,32 @@ VALUE Backend_wait_event(VALUE self, VALUE raise) {
|
|
|
1251
1255
|
}
|
|
1252
1256
|
}
|
|
1253
1257
|
|
|
1254
|
-
|
|
1258
|
+
if (!backend->event_fd_ctx) {
|
|
1259
|
+
struct io_uring_sqe *sqe;
|
|
1260
|
+
|
|
1261
|
+
backend->event_fd_ctx = context_store_acquire(&backend->store, OP_POLL);
|
|
1262
|
+
sqe = io_uring_get_sqe(&backend->ring);
|
|
1263
|
+
io_uring_prep_poll_add(sqe, backend->event_fd, POLLIN);
|
|
1264
|
+
backend->base.op_count++;
|
|
1265
|
+
io_uring_sqe_set_data(sqe, backend->event_fd_ctx);
|
|
1266
|
+
io_uring_backend_defer_submit(backend);
|
|
1267
|
+
}
|
|
1268
|
+
else
|
|
1269
|
+
backend->event_fd_ctx->ref_count += 1;
|
|
1270
|
+
|
|
1271
|
+
resume_value = backend_await((struct Backend_base *)backend);
|
|
1272
|
+
context_store_release(&backend->store, backend->event_fd_ctx);
|
|
1273
|
+
|
|
1274
|
+
if (backend->event_fd_ctx->ref_count == 1) {
|
|
1275
|
+
|
|
1276
|
+
// last fiber to use the eventfd, so we cancel the ongoing poll
|
|
1277
|
+
struct io_uring_sqe *sqe;
|
|
1278
|
+
sqe = io_uring_get_sqe(&backend->ring);
|
|
1279
|
+
io_uring_prep_cancel(sqe, (__u64)backend->event_fd_ctx, 0);
|
|
1280
|
+
io_uring_backend_immediate_submit(backend);
|
|
1281
|
+
backend->event_fd_ctx = NULL;
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1255
1284
|
if (RTEST(raise)) RAISE_IF_EXCEPTION(resume_value);
|
|
1256
1285
|
RB_GC_GUARD(resume_value);
|
|
1257
1286
|
return resume_value;
|
|
@@ -1354,8 +1383,7 @@ VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
|
|
|
1354
1383
|
ctx->result = -ECANCELED;
|
|
1355
1384
|
sqe = io_uring_get_sqe(&backend->ring);
|
|
1356
1385
|
io_uring_prep_cancel(sqe, (__u64)ctx, 0);
|
|
1357
|
-
backend
|
|
1358
|
-
io_uring_submit(&backend->ring);
|
|
1386
|
+
io_uring_backend_immediate_submit(backend);
|
|
1359
1387
|
}
|
|
1360
1388
|
else {
|
|
1361
1389
|
ctx->ref_count = 1;
|
|
@@ -1385,8 +1413,7 @@ VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
|
|
|
1385
1413
|
ctx->result = -ECANCELED;
|
|
1386
1414
|
sqe = io_uring_get_sqe(&backend->ring);
|
|
1387
1415
|
io_uring_prep_cancel(sqe, (__u64)ctx, 0);
|
|
1388
|
-
backend
|
|
1389
|
-
io_uring_submit(&backend->ring);
|
|
1416
|
+
io_uring_backend_immediate_submit(backend);
|
|
1390
1417
|
RAISE_IF_EXCEPTION(resume_value);
|
|
1391
1418
|
return resume_value;
|
|
1392
1419
|
}
|
|
@@ -1452,8 +1479,7 @@ static inline void splice_chunks_cancel(Backend_t *backend, op_context_t *ctx) {
|
|
|
1452
1479
|
ctx->result = -ECANCELED;
|
|
1453
1480
|
sqe = io_uring_get_sqe(&backend->ring);
|
|
1454
1481
|
io_uring_prep_cancel(sqe, (__u64)ctx, 0);
|
|
1455
|
-
backend
|
|
1456
|
-
io_uring_submit(&backend->ring);
|
|
1482
|
+
io_uring_backend_immediate_submit(backend);
|
|
1457
1483
|
}
|
|
1458
1484
|
|
|
1459
1485
|
static inline int splice_chunks_await_ops(
|
|
@@ -13,24 +13,68 @@
|
|
|
13
13
|
|
|
14
14
|
ID ID_at;
|
|
15
15
|
ID ID_read_method;
|
|
16
|
+
ID ID_readpartial;
|
|
16
17
|
ID ID_to_i;
|
|
17
18
|
ID ID_write_method;
|
|
19
|
+
ID ID_write;
|
|
18
20
|
|
|
21
|
+
VALUE SYM_backend_read;
|
|
22
|
+
VALUE SYM_backend_recv;
|
|
23
|
+
VALUE SYM_backend_send;
|
|
24
|
+
VALUE SYM_backend_write;
|
|
25
|
+
VALUE SYM_call;
|
|
26
|
+
VALUE SYM_comment;
|
|
19
27
|
VALUE SYM_mtime;
|
|
20
28
|
VALUE SYM_orig_name;
|
|
21
|
-
VALUE
|
|
29
|
+
VALUE SYM_readpartial;
|
|
22
30
|
|
|
23
31
|
enum read_method {
|
|
24
32
|
RM_BACKEND_READ,
|
|
25
|
-
RM_BACKEND_RECV
|
|
33
|
+
RM_BACKEND_RECV,
|
|
34
|
+
RM_READPARTIAL,
|
|
35
|
+
RM_CALL
|
|
26
36
|
};
|
|
27
37
|
|
|
28
38
|
enum write_method {
|
|
29
39
|
WM_BACKEND_WRITE,
|
|
30
|
-
WM_BACKEND_SEND
|
|
40
|
+
WM_BACKEND_SEND,
|
|
41
|
+
WM_WRITE,
|
|
42
|
+
WM_CALL
|
|
31
43
|
};
|
|
32
44
|
|
|
33
|
-
|
|
45
|
+
static enum read_method detect_read_method(VALUE io) {
|
|
46
|
+
if (rb_respond_to(io, ID_read_method)) {
|
|
47
|
+
VALUE method = rb_funcall(io, ID_read_method, 0);
|
|
48
|
+
if (method == SYM_readpartial) return RM_READPARTIAL;
|
|
49
|
+
if (method == SYM_backend_read) return RM_BACKEND_READ;
|
|
50
|
+
if (method == SYM_backend_recv) return RM_BACKEND_RECV;
|
|
51
|
+
if (method == SYM_call) return RM_CALL;
|
|
52
|
+
|
|
53
|
+
rb_raise(rb_eRuntimeError, "Given io instance uses unsupported read method");
|
|
54
|
+
}
|
|
55
|
+
else if (rb_respond_to(io, ID_call))
|
|
56
|
+
return RM_CALL;
|
|
57
|
+
else
|
|
58
|
+
rb_raise(rb_eRuntimeError, "Given io instance should be a callable or respond to #__read_method__");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
static enum write_method detect_write_method(VALUE io) {
|
|
62
|
+
if (rb_respond_to(io, ID_write_method)) {
|
|
63
|
+
VALUE method = rb_funcall(io, ID_write_method, 0);
|
|
64
|
+
if (method == SYM_readpartial) return WM_WRITE;
|
|
65
|
+
if (method == SYM_backend_write) return WM_BACKEND_WRITE;
|
|
66
|
+
if (method == SYM_backend_send) return WM_BACKEND_SEND;
|
|
67
|
+
if (method == SYM_call) return WM_CALL;
|
|
68
|
+
|
|
69
|
+
rb_raise(rb_eRuntimeError, "Given io instance uses unsupported write method");
|
|
70
|
+
}
|
|
71
|
+
else if (rb_respond_to(io, ID_call))
|
|
72
|
+
return WM_CALL;
|
|
73
|
+
else
|
|
74
|
+
rb_raise(rb_eRuntimeError, "Given io instance should be a callable or respond to #__write_method__");
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
#define PRINT_BUFFER(prefix, ptr, len) { \
|
|
34
78
|
printf("%s buffer (%d): ", prefix, (int)len); \
|
|
35
79
|
for (int i = 0; i < len; i++) printf("%02X ", ptr[i]); \
|
|
36
80
|
printf("\n"); \
|
|
@@ -40,6 +84,7 @@ enum write_method {
|
|
|
40
84
|
#define MAX_WRITE_STR_LEN 16384
|
|
41
85
|
#define DEFAULT_LEVEL 9
|
|
42
86
|
#define DEFAULT_MEM_LEVEL 8
|
|
87
|
+
#define GZIP_FOOTER_LEN 8
|
|
43
88
|
|
|
44
89
|
/* from zutil.h */
|
|
45
90
|
#define OS_MSDOS 0x00
|
|
@@ -63,14 +108,64 @@ enum write_method {
|
|
|
63
108
|
#define OS_CODE OS_UNIX
|
|
64
109
|
#endif
|
|
65
110
|
|
|
111
|
+
|
|
66
112
|
static inline int read_to_raw_buffer(VALUE backend, VALUE io, enum read_method method, struct raw_buffer *buffer) {
|
|
67
|
-
|
|
68
|
-
|
|
113
|
+
switch (method) {
|
|
114
|
+
case RM_BACKEND_READ: {
|
|
115
|
+
VALUE len = Backend_read(backend, io, PTR2FIX(buffer), Qnil, Qfalse, INT2FIX(0));
|
|
116
|
+
return (len == Qnil) ? 0 : FIX2INT(len);
|
|
117
|
+
}
|
|
118
|
+
case RM_BACKEND_RECV: {
|
|
119
|
+
VALUE len = Backend_recv(backend, io, PTR2FIX(buffer), Qnil, INT2FIX(0));
|
|
120
|
+
return (len == Qnil) ? 0 : FIX2INT(len);
|
|
121
|
+
}
|
|
122
|
+
case RM_READPARTIAL: {
|
|
123
|
+
VALUE str = rb_funcall(io, ID_readpartial, 1, INT2FIX(buffer->len));
|
|
124
|
+
int len = RSTRING_LEN(str);
|
|
125
|
+
if (len) memcpy(buffer->ptr, RSTRING_PTR(str), len);
|
|
126
|
+
RB_GC_GUARD(str);
|
|
127
|
+
return len;
|
|
128
|
+
}
|
|
129
|
+
case RM_CALL: {
|
|
130
|
+
VALUE str = rb_funcall(io, ID_call, INT2FIX(buffer->len));
|
|
131
|
+
if (TYPE(str) != T_STRING)
|
|
132
|
+
rb_raise(rb_eRuntimeError, "io#call must return a string");
|
|
133
|
+
int len = RSTRING_LEN(str);
|
|
134
|
+
if (len > buffer->len) len = buffer->len;
|
|
135
|
+
if (len) memcpy(buffer->ptr, RSTRING_PTR(str), len);
|
|
136
|
+
RB_GC_GUARD(str);
|
|
137
|
+
return len;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
69
140
|
}
|
|
70
141
|
|
|
71
142
|
static inline int write_from_raw_buffer(VALUE backend, VALUE io, enum write_method method, struct raw_buffer *buffer) {
|
|
72
|
-
|
|
73
|
-
|
|
143
|
+
switch (method) {
|
|
144
|
+
case WM_BACKEND_WRITE: {
|
|
145
|
+
VALUE len = Backend_write(backend, io, PTR2FIX(buffer));
|
|
146
|
+
return FIX2INT(len);
|
|
147
|
+
}
|
|
148
|
+
case WM_BACKEND_SEND: {
|
|
149
|
+
VALUE len = Backend_send(backend, io, PTR2FIX(buffer), INT2FIX(0));
|
|
150
|
+
return FIX2INT(len);
|
|
151
|
+
}
|
|
152
|
+
case WM_WRITE: {
|
|
153
|
+
VALUE str = rb_str_new(0, buffer->len);
|
|
154
|
+
memcpy(RSTRING_PTR(str), buffer->ptr, buffer->len);
|
|
155
|
+
rb_str_modify_expand(str, buffer->len);
|
|
156
|
+
rb_funcall(io, ID_write, 1, str);
|
|
157
|
+
RB_GC_GUARD(str);
|
|
158
|
+
return buffer->len;
|
|
159
|
+
}
|
|
160
|
+
case WM_CALL: {
|
|
161
|
+
VALUE str = rb_str_new(0, buffer->len);
|
|
162
|
+
memcpy(RSTRING_PTR(str), buffer->ptr, buffer->len);
|
|
163
|
+
rb_str_modify_expand(str, buffer->len);
|
|
164
|
+
rb_funcall(io, ID_call, 1, str);
|
|
165
|
+
RB_GC_GUARD(str);
|
|
166
|
+
return buffer->len;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
74
169
|
}
|
|
75
170
|
|
|
76
171
|
static inline int write_c_string_from_str(VALUE str, struct raw_buffer *buffer) {
|
|
@@ -165,12 +260,12 @@ int gzip_prepare_header(struct gzip_header_ctx *ctx, char *buffer, int maxlen) {
|
|
|
165
260
|
}
|
|
166
261
|
|
|
167
262
|
int gzip_prepare_footer(unsigned long crc32, unsigned long total_in, char *buffer, int maxlen) {
|
|
168
|
-
assert(maxlen >=
|
|
263
|
+
assert(maxlen >= GZIP_FOOTER_LEN);
|
|
169
264
|
|
|
170
265
|
gzfile_set32(crc32, buffer);
|
|
171
266
|
gzfile_set32(total_in, buffer + 4);
|
|
172
267
|
|
|
173
|
-
return
|
|
268
|
+
return GZIP_FOOTER_LEN;
|
|
174
269
|
}
|
|
175
270
|
|
|
176
271
|
enum stream_mode {
|
|
@@ -183,7 +278,11 @@ struct z_stream_ctx {
|
|
|
183
278
|
VALUE src;
|
|
184
279
|
VALUE dest;
|
|
185
280
|
|
|
281
|
+
enum read_method src_read_method;
|
|
282
|
+
enum write_method dest_write_method;
|
|
283
|
+
|
|
186
284
|
enum stream_mode mode;
|
|
285
|
+
int f_gzip_footer; // should a gzip footer be generated
|
|
187
286
|
z_stream strm;
|
|
188
287
|
|
|
189
288
|
unsigned char in[CHUNK];
|
|
@@ -216,11 +315,11 @@ void gzip_read_header(struct z_stream_ctx *ctx, struct gzip_header_ctx *header_c
|
|
|
216
315
|
int flags;
|
|
217
316
|
|
|
218
317
|
while (ctx->in_total < 10) {
|
|
219
|
-
int read = read_to_raw_buffer(ctx->backend, ctx->src,
|
|
318
|
+
int read = read_to_raw_buffer(ctx->backend, ctx->src, ctx->src_read_method, &in_buffer);
|
|
220
319
|
if (read == 0) goto error;
|
|
221
320
|
ctx->in_total += read;
|
|
222
321
|
}
|
|
223
|
-
//
|
|
322
|
+
// PRINT_BUFFER("read gzip header", ctx->in, ctx->in_total);
|
|
224
323
|
if (ctx->in[0] != GZ_MAGIC1) goto error;
|
|
225
324
|
if (ctx->in[1] != GZ_MAGIC2) goto error;
|
|
226
325
|
if (ctx->in[2] != GZ_METHOD_DEFLATE) goto error;
|
|
@@ -245,9 +344,6 @@ error:
|
|
|
245
344
|
rb_raise(rb_eRuntimeError, "Invalid gzip header");
|
|
246
345
|
}
|
|
247
346
|
|
|
248
|
-
// void gzip_read_footer(struct z_stream_ctx *ctx, struct gzip_footer_ctx *footer_ctx) {
|
|
249
|
-
// }
|
|
250
|
-
|
|
251
347
|
static inline int z_stream_write_out(struct z_stream_ctx *ctx, zlib_func fun, int eof) {
|
|
252
348
|
int ret;
|
|
253
349
|
int written;
|
|
@@ -260,8 +356,14 @@ static inline int z_stream_write_out(struct z_stream_ctx *ctx, zlib_func fun, in
|
|
|
260
356
|
written = avail_out_pre - ctx->strm.avail_out;
|
|
261
357
|
out_buffer.ptr = ctx->out;
|
|
262
358
|
out_buffer.len = ctx->out_pos + written;
|
|
359
|
+
|
|
360
|
+
if (eof && ctx->f_gzip_footer && (CHUNK - out_buffer.len >= GZIP_FOOTER_LEN)) {
|
|
361
|
+
gzip_prepare_footer(ctx->crc32, ctx->in_total, out_buffer.ptr + out_buffer.len, 8);
|
|
362
|
+
out_buffer.len += GZIP_FOOTER_LEN;
|
|
363
|
+
}
|
|
364
|
+
|
|
263
365
|
if (out_buffer.len) {
|
|
264
|
-
ret = write_from_raw_buffer(ctx->backend, ctx->dest,
|
|
366
|
+
ret = write_from_raw_buffer(ctx->backend, ctx->dest, ctx->dest_write_method, &out_buffer);
|
|
265
367
|
if (ctx->mode == SM_INFLATE)
|
|
266
368
|
ctx->crc32 = crc32(ctx->crc32, out_buffer.ptr + ctx->out_pos, written);
|
|
267
369
|
ctx->out_total += ret - ctx->out_pos;
|
|
@@ -271,7 +373,7 @@ static inline int z_stream_write_out(struct z_stream_ctx *ctx, zlib_func fun, in
|
|
|
271
373
|
}
|
|
272
374
|
|
|
273
375
|
void z_stream_io_loop(struct z_stream_ctx *ctx) {
|
|
274
|
-
zlib_func fun = (ctx->mode == SM_DEFLATE) ? deflate : inflate;
|
|
376
|
+
zlib_func fun = (ctx->mode == SM_DEFLATE) ? deflate : inflate;
|
|
275
377
|
|
|
276
378
|
if (ctx->in_total > ctx->in_pos) {
|
|
277
379
|
// In bytes already read for parsing gzip header, so we need to process the
|
|
@@ -289,7 +391,7 @@ void z_stream_io_loop(struct z_stream_ctx *ctx) {
|
|
|
289
391
|
while (1) {
|
|
290
392
|
struct raw_buffer in_buffer = {ctx->in, CHUNK};
|
|
291
393
|
ctx->strm.next_in = ctx->in;
|
|
292
|
-
int read_len = ctx->strm.avail_in = read_to_raw_buffer(ctx->backend, ctx->src,
|
|
394
|
+
int read_len = ctx->strm.avail_in = read_to_raw_buffer(ctx->backend, ctx->src, ctx->src_read_method, &in_buffer);
|
|
293
395
|
if (!read_len) break;
|
|
294
396
|
int eof = read_len < CHUNK;
|
|
295
397
|
|
|
@@ -297,7 +399,7 @@ void z_stream_io_loop(struct z_stream_ctx *ctx) {
|
|
|
297
399
|
ctx->crc32 = crc32(ctx->crc32, ctx->in, read_len);
|
|
298
400
|
ctx->in_total += read_len;
|
|
299
401
|
|
|
300
|
-
//
|
|
402
|
+
// PRINT_BUFFER("read stream", ctx->in, read_len);
|
|
301
403
|
|
|
302
404
|
while (1) {
|
|
303
405
|
// z_stream_write_out returns strm.avail_out. If there's still room in the
|
|
@@ -318,7 +420,10 @@ static inline void setup_ctx(struct z_stream_ctx *ctx, enum stream_mode mode, VA
|
|
|
318
420
|
ctx->backend = BACKEND();
|
|
319
421
|
ctx->src = src;
|
|
320
422
|
ctx->dest = dest;
|
|
423
|
+
ctx->src_read_method = detect_read_method(src);
|
|
424
|
+
ctx->dest_write_method = detect_write_method(dest);
|
|
321
425
|
ctx->mode = mode;
|
|
426
|
+
ctx->f_gzip_footer = 0;
|
|
322
427
|
ctx->strm.zalloc = Z_NULL;
|
|
323
428
|
ctx->strm.zfree = Z_NULL;
|
|
324
429
|
ctx->strm.opaque = Z_NULL;
|
|
@@ -349,14 +454,12 @@ VALUE IO_gzip(int argc, VALUE *argv, VALUE self) {
|
|
|
349
454
|
int ret;
|
|
350
455
|
|
|
351
456
|
setup_ctx(&ctx, SM_DEFLATE, src, dest);
|
|
457
|
+
ctx.f_gzip_footer = 1; // write gzip footer
|
|
352
458
|
ctx.out_pos = gzip_prepare_header(&header_ctx, ctx.out, sizeof(ctx.out));
|
|
353
459
|
|
|
354
460
|
ret = deflateInit2(&ctx.strm, level, Z_DEFLATED, -MAX_WBITS, DEFAULT_MEM_LEVEL, Z_DEFAULT_STRATEGY);
|
|
355
461
|
if (ret != Z_OK) return INT2FIX(ret);
|
|
356
462
|
z_stream_io_loop(&ctx);
|
|
357
|
-
int footer_len = gzip_prepare_footer(ctx.crc32, ctx.in_total, ctx.out, sizeof(ctx.out));
|
|
358
|
-
struct raw_buffer footer_buffer = {ctx.out, footer_len};
|
|
359
|
-
write_from_raw_buffer(ctx.backend, dest, WM_BACKEND_WRITE, &footer_buffer);
|
|
360
463
|
deflateEnd(&ctx.strm);
|
|
361
464
|
|
|
362
465
|
return INT2FIX(ctx.out_total);
|
|
@@ -431,10 +534,18 @@ void Init_IOExtensions() {
|
|
|
431
534
|
|
|
432
535
|
ID_at = rb_intern("at");
|
|
433
536
|
ID_read_method = rb_intern("__read_method__");
|
|
537
|
+
ID_readpartial = rb_intern("readpartial");
|
|
434
538
|
ID_to_i = rb_intern("to_i");
|
|
435
539
|
ID_write_method = rb_intern("__write_method__");
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
540
|
+
ID_write = rb_intern("write");
|
|
541
|
+
|
|
542
|
+
SYM_backend_read = ID2SYM(rb_intern("backend_read"));
|
|
543
|
+
SYM_backend_recv = ID2SYM(rb_intern("backend_recv"));
|
|
544
|
+
SYM_backend_send = ID2SYM(rb_intern("backend_send"));
|
|
545
|
+
SYM_backend_write = ID2SYM(rb_intern("backend_write"));
|
|
546
|
+
SYM_call = ID2SYM(rb_intern("call"));
|
|
547
|
+
SYM_comment = ID2SYM(rb_intern("comment"));
|
|
548
|
+
SYM_mtime = ID2SYM(rb_intern("mtime"));
|
|
549
|
+
SYM_orig_name = ID2SYM(rb_intern("orig_name"));
|
|
550
|
+
SYM_readpartial = ID2SYM(rb_intern("readpartial"));
|
|
440
551
|
}
|
|
@@ -390,12 +390,14 @@ module Polyphony
|
|
|
390
390
|
def shutdown_all_children(graceful = false)
|
|
391
391
|
return self unless @children
|
|
392
392
|
|
|
393
|
+
pending = []
|
|
393
394
|
@children.keys.each do |c|
|
|
394
395
|
next if c.dead?
|
|
395
396
|
|
|
396
397
|
c.terminate(graceful)
|
|
397
|
-
c
|
|
398
|
+
pending << c
|
|
398
399
|
end
|
|
400
|
+
Fiber.await(*pending)
|
|
399
401
|
self
|
|
400
402
|
end
|
|
401
403
|
|