kgio 2.9.3 → 2.10.0
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/.document +0 -1
- data/GIT-VERSION-GEN +1 -1
- data/HACKING +9 -11
- data/README +4 -3
- data/TODO +1 -0
- data/ext/kgio/accept.c +0 -7
- data/ext/kgio/extconf.rb +1 -0
- data/ext/kgio/kgio.h +0 -12
- data/ext/kgio/kgio_ext.c +0 -1
- data/ext/kgio/poll.c +13 -1
- data/ext/kgio/read.c +0 -8
- data/ext/kgio/write.c +0 -4
- data/ext/kgio/writev.c +1 -4
- data/lib/kgio.rb +10 -0
- data/test/test_autopush.rb +3 -157
- metadata +5 -7
- data/ext/kgio/autopush.c +0 -247
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5533173b595411c7f3c68c9aa925e18e76444660
|
4
|
+
data.tar.gz: 743fdc287fcbab34e689a6e4f272f7110bb3d7aa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 88ec86a25c45bc5a288d5f85e445a3d2cfda9611d99aec077a982e86ae0399095b98fc5cb0154896a2d6e6931b05ed7431e6d1d23e23b1758b51796dfed810bc
|
7
|
+
data.tar.gz: e736aec41387787b030ae419a0650dd529c2bf000a97cd38c7bbafe6a096a56a4ec7d5a40367d3cbb6f30c96748481cdd72d4201e4a1c87dd5c408aa7a1c581b
|
data/.document
CHANGED
data/GIT-VERSION-GEN
CHANGED
data/HACKING
CHANGED
@@ -9,20 +9,19 @@ Please wrap documentation at 72 characters-per-line or less (long URLs
|
|
9
9
|
are exempt) so it is comfortably readable from terminals.
|
10
10
|
|
11
11
|
When referencing mailing list posts, use
|
12
|
-
"http://
|
13
|
-
remains searchable even if
|
12
|
+
"http://bogomips.org/kgio-public/$MESSAGE_ID/" if possible since the
|
13
|
+
Message-ID remains searchable even if the archive becomes unavailable.
|
14
14
|
|
15
15
|
=== Code Compatibility
|
16
16
|
|
17
|
-
We target Ruby 1.
|
18
|
-
respective C APIs.
|
17
|
+
We target mainline Ruby 1.9.3 and later.
|
19
18
|
|
20
19
|
All of our C code should be compatible with all reasonably modern Unices
|
21
20
|
and should run on compilers supported by the versions of Ruby we target.
|
22
21
|
|
23
|
-
We will NEVER
|
22
|
+
We will NEVER support non-Free platforms under any circumstances.
|
24
23
|
|
25
|
-
Our C code follows
|
24
|
+
Our C code follows Linux kernel coding style (hard tabs, tabs are always 8
|
26
25
|
characters wide) and NOT the indentation style of Matz Ruby.
|
27
26
|
|
28
27
|
== Contributing
|
@@ -51,7 +50,7 @@ don't email the git mailing list or maintainer with kgio patches :)
|
|
51
50
|
|
52
51
|
It is easy to install the contents of your git working directory:
|
53
52
|
|
54
|
-
Via RubyGems
|
53
|
+
Via RubyGems:
|
55
54
|
|
56
55
|
gmake install-gem
|
57
56
|
|
@@ -64,10 +63,9 @@ installation done without RubyGems, however.
|
|
64
63
|
|
65
64
|
=== Tests
|
66
65
|
|
67
|
-
We use GNU make to run tests in parallel.
|
68
|
-
|
69
|
-
|
70
|
-
"gmake".
|
66
|
+
We use GNU make to run tests in parallel for historical reasons. Users
|
67
|
+
of GNU-based systems (such as GNU/Linux) usually have GNU make installed
|
68
|
+
as "make" instead of "gmake".
|
71
69
|
|
72
70
|
Running the entire test suite with 4 tests in parallel:
|
73
71
|
|
data/README
CHANGED
@@ -2,15 +2,16 @@
|
|
2
2
|
|
3
3
|
kgio provides non-blocking I/O methods for Ruby without raising
|
4
4
|
exceptions on EAGAIN and EINPROGRESS. It is intended for use with the
|
5
|
-
|
6
|
-
|
5
|
+
unicorn Rack server, but may be used by other applications (that run on
|
6
|
+
Unix-like platforms).
|
7
7
|
|
8
8
|
== Features
|
9
9
|
|
10
10
|
* Can avoid expensive exceptions on common EAGAIN/EINPROGRESS errors,
|
11
11
|
returning :wait_readable or :wait_writable instead.
|
12
12
|
These exceptions got more expensive to hit under Ruby 1.9.2
|
13
|
-
(but were fixed in Ruby 1.9.3 and later to 1.9.1 performance levels
|
13
|
+
(but were fixed in Ruby 1.9.3 and later to 1.9.1 performance levels,
|
14
|
+
which were still bad)
|
14
15
|
|
15
16
|
* Returns the unwritten portion of the string on partial writes,
|
16
17
|
making it ideal for buffering unwritten data.
|
data/TODO
CHANGED
data/ext/kgio/accept.c
CHANGED
@@ -160,12 +160,6 @@ static VALUE in_addr_set(VALUE io, struct sockaddr_storage *addr, socklen_t len)
|
|
160
160
|
return rb_ivar_set(io, iv_kgio_addr, host);
|
161
161
|
}
|
162
162
|
|
163
|
-
#if defined(__linux__)
|
164
|
-
# define post_accept kgio_autopush_accept
|
165
|
-
#else
|
166
|
-
# define post_accept(a,b) for(;0;)
|
167
|
-
#endif
|
168
|
-
|
169
163
|
static VALUE
|
170
164
|
my_accept(struct accept_args *a, int force_nonblock)
|
171
165
|
{
|
@@ -211,7 +205,6 @@ retry:
|
|
211
205
|
}
|
212
206
|
}
|
213
207
|
client_io = sock_for_fd(a->accepted_class, client_fd);
|
214
|
-
post_accept(a->accept_io, client_io);
|
215
208
|
|
216
209
|
if (a->addr)
|
217
210
|
in_addr_set(client_io,
|
data/ext/kgio/extconf.rb
CHANGED
@@ -51,6 +51,7 @@ have_func('rb_thread_call_without_gvl', %w{ruby/thread.h})
|
|
51
51
|
have_func('rb_thread_blocking_region')
|
52
52
|
have_func('rb_thread_io_blocking_region')
|
53
53
|
have_func('rb_str_set_len')
|
54
|
+
have_func("rb_hash_clear", "ruby.h") # Ruby 2.0+
|
54
55
|
have_func('rb_time_interval')
|
55
56
|
have_func('rb_wait_for_single_fd')
|
56
57
|
have_func('rb_str_subseq')
|
data/ext/kgio/kgio.h
CHANGED
@@ -29,14 +29,9 @@ void init_kgio_write(void);
|
|
29
29
|
void init_kgio_writev(void);
|
30
30
|
void init_kgio_accept(void);
|
31
31
|
void init_kgio_connect(void);
|
32
|
-
void init_kgio_autopush(void);
|
33
32
|
void init_kgio_poll(void);
|
34
33
|
void init_kgio_tryopen(void);
|
35
34
|
|
36
|
-
void kgio_autopush_accept(VALUE, VALUE);
|
37
|
-
void kgio_autopush_recv(VALUE);
|
38
|
-
void kgio_autopush_send(VALUE);
|
39
|
-
|
40
35
|
VALUE kgio_call_wait_writable(VALUE io);
|
41
36
|
VALUE kgio_call_wait_readable(VALUE io);
|
42
37
|
#if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL) && defined(HAVE_RUBY_THREAD_H)
|
@@ -90,13 +85,6 @@ NORETURN(void kgio_rd_sys_fail(const char *));
|
|
90
85
|
# define USE_MSG_DONTWAIT
|
91
86
|
# endif
|
92
87
|
|
93
|
-
#ifdef USE_MSG_DONTWAIT
|
94
|
-
/* we don't need these variants, we call kgio_autopush_send/recv directly */
|
95
|
-
static inline void kgio_autopush_write(VALUE io) { }
|
96
|
-
#else
|
97
|
-
static inline void kgio_autopush_write(VALUE io) { kgio_autopush_send(io); }
|
98
|
-
#endif
|
99
|
-
|
100
88
|
/* prefer rb_str_subseq because we don't use negative offsets */
|
101
89
|
#ifndef HAVE_RB_STR_SUBSEQ
|
102
90
|
#define MY_STR_SUBSEQ(str,beg,len) rb_str_substr((str),(beg),(len))
|
data/ext/kgio/kgio_ext.c
CHANGED
data/ext/kgio/poll.c
CHANGED
@@ -12,8 +12,18 @@
|
|
12
12
|
#endif
|
13
13
|
|
14
14
|
static VALUE sym_wait_readable, sym_wait_writable;
|
15
|
+
|
16
|
+
#ifdef HAVE_RB_HASH_CLEAR /* Ruby >= 2.0 */
|
17
|
+
# define my_hash_clear(h) (void)rb_hash_clear(h)
|
18
|
+
#else /* !HAVE_RB_HASH_CLEAR - Ruby <= 1.9.3 */
|
15
19
|
static ID id_clear;
|
16
20
|
|
21
|
+
static void my_hash_clear(VALUE h)
|
22
|
+
{
|
23
|
+
rb_funcall(h, id_clear, 0);
|
24
|
+
}
|
25
|
+
#endif /* HAVE_RB_HASH_CLEAR */
|
26
|
+
|
17
27
|
struct poll_args {
|
18
28
|
struct pollfd *fds;
|
19
29
|
nfds_t nfds;
|
@@ -126,7 +136,7 @@ static VALUE poll_result(int nr, struct poll_args *a)
|
|
126
136
|
int rc;
|
127
137
|
|
128
138
|
if ((nfds_t)nr != a->nfds)
|
129
|
-
|
139
|
+
my_hash_clear(a->ios);
|
130
140
|
for (; nr > 0; fds++) {
|
131
141
|
if (fds->revents == 0)
|
132
142
|
continue;
|
@@ -218,7 +228,9 @@ void init_kgio_poll(void)
|
|
218
228
|
|
219
229
|
sym_wait_readable = ID2SYM(rb_intern("wait_readable"));
|
220
230
|
sym_wait_writable = ID2SYM(rb_intern("wait_writable"));
|
231
|
+
#ifndef HAVE_RB_HASH_CLEAR
|
221
232
|
id_clear = rb_intern("clear");
|
233
|
+
#endif
|
222
234
|
|
223
235
|
#define c(x) rb_define_const(mKgio,#x,INT2NUM((int)x))
|
224
236
|
|
data/ext/kgio/read.c
CHANGED
@@ -7,13 +7,8 @@ static VALUE sym_wait_readable;
|
|
7
7
|
|
8
8
|
#ifdef USE_MSG_DONTWAIT
|
9
9
|
static const int peek_flags = MSG_DONTWAIT|MSG_PEEK;
|
10
|
-
|
11
|
-
/* we don't need these variants, we call kgio_autopush_recv directly */
|
12
|
-
static inline void kgio_autopush_read(VALUE io) { }
|
13
|
-
|
14
10
|
#else
|
15
11
|
static const int peek_flags = MSG_PEEK;
|
16
|
-
static inline void kgio_autopush_read(VALUE io) { kgio_autopush_recv(io); }
|
17
12
|
#endif
|
18
13
|
|
19
14
|
struct rd_args {
|
@@ -85,7 +80,6 @@ static VALUE my_read(int io_wait, int argc, VALUE *argv, VALUE io)
|
|
85
80
|
long n;
|
86
81
|
|
87
82
|
prepare_read(&a, argc, argv, io);
|
88
|
-
kgio_autopush_read(io);
|
89
83
|
|
90
84
|
if (a.len > 0) {
|
91
85
|
set_nonblocking(a.fd);
|
@@ -158,7 +152,6 @@ static VALUE my_recv(int io_wait, int argc, VALUE *argv, VALUE io)
|
|
158
152
|
long n;
|
159
153
|
|
160
154
|
prepare_read(&a, argc, argv, io);
|
161
|
-
kgio_autopush_recv(io);
|
162
155
|
|
163
156
|
if (a.len > 0) {
|
164
157
|
retry:
|
@@ -212,7 +205,6 @@ static VALUE my_peek(int io_wait, int argc, VALUE *argv, VALUE io)
|
|
212
205
|
long n;
|
213
206
|
|
214
207
|
prepare_read(&a, argc, argv, io);
|
215
|
-
kgio_autopush_recv(io);
|
216
208
|
|
217
209
|
if (a.len > 0) {
|
218
210
|
if (peek_flags == MSG_PEEK)
|
data/ext/kgio/write.c
CHANGED
@@ -72,8 +72,6 @@ retry:
|
|
72
72
|
n = (long)write(a.fd, a.ptr, a.len);
|
73
73
|
if (write_check(&a, n, "write", io_wait) != 0)
|
74
74
|
goto retry;
|
75
|
-
if (TYPE(a.buf) != T_SYMBOL)
|
76
|
-
kgio_autopush_write(io);
|
77
75
|
return a.buf;
|
78
76
|
}
|
79
77
|
|
@@ -126,8 +124,6 @@ retry:
|
|
126
124
|
n = (long)send(a.fd, a.ptr, a.len, MSG_DONTWAIT);
|
127
125
|
if (write_check(&a, n, "send", io_wait) != 0)
|
128
126
|
goto retry;
|
129
|
-
if (TYPE(a.buf) != T_SYMBOL)
|
130
|
-
kgio_autopush_send(io);
|
131
127
|
return a.buf;
|
132
128
|
}
|
133
129
|
|
data/ext/kgio/writev.c
CHANGED
@@ -90,8 +90,7 @@ static ssize_t custom_writev(int fd, const struct iovec *vec, int iov_cnt, size_
|
|
90
90
|
|
91
91
|
result = write(fd, buf, total_len);
|
92
92
|
|
93
|
-
/*
|
94
|
-
* but lets save it anyway */
|
93
|
+
/* free() may alter errno */
|
95
94
|
i = errno;
|
96
95
|
free(buf);
|
97
96
|
errno = i;
|
@@ -250,8 +249,6 @@ static VALUE my_writev(VALUE io, VALUE ary, int io_wait)
|
|
250
249
|
} while (writev_check(&a, n, "writev", io_wait) != 0);
|
251
250
|
rb_str_resize(a.vec_buf, 0);
|
252
251
|
|
253
|
-
if (TYPE(a.buf) != T_SYMBOL)
|
254
|
-
kgio_autopush_write(io);
|
255
252
|
return a.buf;
|
256
253
|
}
|
257
254
|
|
data/lib/kgio.rb
CHANGED
@@ -16,6 +16,16 @@ module Kgio
|
|
16
16
|
# PipeMethods#kgio_trywrite and SocketMethods#kgio_trywrite will return
|
17
17
|
# :wait_writable when waiting for a read is required.
|
18
18
|
WaitWritable = :wait_writable
|
19
|
+
|
20
|
+
# autopush is no-op nowadays
|
21
|
+
@autopush = false
|
22
|
+
|
23
|
+
class << self
|
24
|
+
attr_accessor :autopush # :nodoc:
|
25
|
+
def autopush? # :nodoc:
|
26
|
+
!!@autopush
|
27
|
+
end
|
28
|
+
end
|
19
29
|
end
|
20
30
|
|
21
31
|
require 'kgio_ext'
|
data/test/test_autopush.rb
CHANGED
@@ -1,165 +1,11 @@
|
|
1
|
-
require 'tempfile'
|
2
1
|
require 'test/unit'
|
3
|
-
begin
|
4
|
-
$-w = false
|
5
|
-
RUBY_PLATFORM =~ /linux/ and require 'strace'
|
6
|
-
rescue LoadError
|
7
|
-
end
|
8
|
-
$-w = true
|
9
2
|
require 'kgio'
|
10
3
|
|
11
4
|
class TestAutopush < Test::Unit::TestCase
|
12
|
-
|
13
|
-
TCP_NOPUSH = 4
|
14
|
-
|
15
|
-
def setup
|
16
|
-
Kgio.autopush = false
|
17
|
-
assert_equal false, Kgio.autopush?
|
18
|
-
|
19
|
-
@host = ENV["TEST_HOST"] || '127.0.0.1'
|
20
|
-
@srv = Kgio::TCPServer.new(@host, 0)
|
21
|
-
RUBY_PLATFORM =~ /linux/ and
|
22
|
-
@srv.setsockopt(Socket::IPPROTO_TCP, TCP_CORK, 1)
|
23
|
-
RUBY_PLATFORM =~ /freebsd/ and
|
24
|
-
@srv.setsockopt(Socket::IPPROTO_TCP, TCP_NOPUSH, 1)
|
25
|
-
@port = @srv.addr[1]
|
26
|
-
end
|
27
|
-
|
28
|
-
def test_autopush_accessors
|
29
|
-
Kgio.autopush = true
|
30
|
-
opt = RUBY_PLATFORM =~ /freebsd/ ? TCP_NOPUSH : TCP_CORK
|
31
|
-
s = Kgio::TCPSocket.new(@host, @port)
|
32
|
-
assert_equal 0, s.getsockopt(Socket::IPPROTO_TCP, opt).unpack('i')[0]
|
33
|
-
assert ! s.kgio_autopush?
|
34
|
-
s.kgio_autopush = true
|
35
|
-
assert s.kgio_autopush?
|
36
|
-
s.kgio_write 'asdf'
|
37
|
-
assert_equal :wait_readable, s.kgio_tryread(1)
|
38
|
-
assert s.kgio_autopush?
|
39
|
-
val = s.getsockopt(Socket::IPPROTO_TCP, opt).unpack('i')[0]
|
40
|
-
assert_operator val, :>, 0, "#{opt}=#{val} (#{RUBY_PLATFORM})"
|
41
|
-
end
|
42
|
-
|
43
|
-
def test_autopush_true_unix
|
44
|
-
Kgio.autopush = true
|
45
|
-
tmp = Tempfile.new('kgio_unix')
|
46
|
-
@path = tmp.path
|
47
|
-
tmp.close!
|
48
|
-
@srv = Kgio::UNIXServer.new(@path)
|
49
|
-
@rd = Kgio::UNIXSocket.new(@path)
|
50
|
-
t0 = nil
|
51
|
-
if defined?(Strace)
|
52
|
-
io, err = Strace.me { @wr = @srv.kgio_accept }
|
53
|
-
assert_nil err
|
54
|
-
rc = nil
|
55
|
-
io, err = Strace.me {
|
56
|
-
t0 = Time.now
|
57
|
-
@wr.kgio_write "HI\n"
|
58
|
-
rc = @wr.kgio_tryread 666
|
59
|
-
}
|
60
|
-
assert_nil err
|
61
|
-
lines = io.readlines
|
62
|
-
assert lines.grep(/TCP_CORK/).empty?, lines.inspect
|
63
|
-
else
|
64
|
-
@wr = @srv.kgio_accept
|
65
|
-
t0 = Time.now
|
66
|
-
@wr.kgio_write "HI\n"
|
67
|
-
rc = @wr.kgio_tryread 666
|
68
|
-
end
|
69
|
-
assert_equal "HI\n", @rd.kgio_read(3)
|
70
|
-
diff = Time.now - t0
|
71
|
-
assert(diff < 0.200, "nopush on UNIX sockets? diff=#{diff} > 200ms")
|
72
|
-
assert_equal :wait_readable, rc
|
73
|
-
ensure
|
74
|
-
File.unlink(@path) rescue nil
|
75
|
-
end
|
76
|
-
|
77
|
-
def test_autopush_false
|
78
|
-
Kgio.autopush = nil
|
79
|
-
assert_equal false, Kgio.autopush?
|
80
|
-
|
81
|
-
@wr = Kgio::TCPSocket.new(@host, @port)
|
82
|
-
if defined?(Strace)
|
83
|
-
io, err = Strace.me { @rd = @srv.kgio_accept }
|
84
|
-
assert_nil err
|
85
|
-
lines = io.readlines
|
86
|
-
assert lines.grep(/TCP_CORK/).empty?, lines.inspect
|
87
|
-
assert_equal 1, @rd.getsockopt(Socket::SOL_TCP, TCP_CORK).unpack("i")[0]
|
88
|
-
else
|
89
|
-
@rd = @srv.kgio_accept
|
90
|
-
end
|
91
|
-
|
92
|
-
rbuf = "..."
|
93
|
-
t0 = Time.now
|
94
|
-
@rd.kgio_write "HI\n"
|
95
|
-
@wr.kgio_read(3, rbuf)
|
96
|
-
diff = Time.now - t0
|
97
|
-
assert(diff >= 0.190, "nopush broken? diff=#{diff} > 200ms")
|
98
|
-
assert_equal "HI\n", rbuf
|
99
|
-
end
|
100
|
-
|
101
|
-
def test_autopush_true
|
5
|
+
def test_compatibility
|
102
6
|
Kgio.autopush = true
|
103
7
|
assert_equal true, Kgio.autopush?
|
104
|
-
@wr = Kgio::TCPSocket.new(@host, @port)
|
105
|
-
|
106
|
-
if defined?(Strace)
|
107
|
-
io, err = Strace.me { @rd = @srv.kgio_accept }
|
108
|
-
assert_nil err
|
109
|
-
lines = io.readlines
|
110
|
-
assert_equal 1, lines.grep(/TCP_CORK/).size, lines.inspect
|
111
|
-
assert_equal 1, @rd.getsockopt(Socket::SOL_TCP, TCP_CORK).unpack("i")[0]
|
112
|
-
else
|
113
|
-
@rd = @srv.kgio_accept
|
114
|
-
end
|
115
|
-
|
116
|
-
@wr.write "HI\n"
|
117
|
-
rbuf = ""
|
118
|
-
if defined?(Strace)
|
119
|
-
io, err = Strace.me { @rd.kgio_read(3, rbuf) }
|
120
|
-
assert_nil err
|
121
|
-
lines = io.readlines
|
122
|
-
assert lines.grep(/TCP_CORK/).empty?, lines.inspect
|
123
|
-
assert_equal "HI\n", rbuf
|
124
|
-
else
|
125
|
-
assert_equal "HI\n", @rd.kgio_read(3, rbuf)
|
126
|
-
end
|
127
|
-
|
128
|
-
t0 = Time.now
|
129
|
-
@rd.kgio_write "HI2U2\n"
|
130
|
-
@rd.kgio_write "HOW\n"
|
131
|
-
rc = false
|
132
|
-
|
133
|
-
if defined?(Strace)
|
134
|
-
io, err = Strace.me { rc = @rd.kgio_tryread(666) }
|
135
|
-
else
|
136
|
-
rc = @rd.kgio_tryread(666)
|
137
|
-
end
|
138
|
-
|
139
|
-
@wr.readpartial(666, rbuf)
|
140
|
-
rbuf == "HI2U2\nHOW\n" or warn "rbuf=#{rbuf.inspect} looking bad?"
|
141
|
-
diff = Time.now - t0
|
142
|
-
assert(diff < 0.200, "time diff=#{diff} >= 200ms")
|
143
|
-
assert_equal :wait_readable, rc
|
144
|
-
if defined?(Strace)
|
145
|
-
assert_nil err
|
146
|
-
lines = io.readlines
|
147
|
-
assert_equal 2, lines.grep(/TCP_CORK/).size, lines.inspect
|
148
|
-
end
|
149
|
-
@wr.close
|
150
|
-
@rd.close
|
151
|
-
|
152
|
-
@wr = Kgio::TCPSocket.new(@host, @port)
|
153
|
-
if defined?(Strace)
|
154
|
-
io, err = Strace.me { @rd = @srv.kgio_accept }
|
155
|
-
assert_nil err
|
156
|
-
lines = io.readlines
|
157
|
-
assert lines.grep(/TCP_CORK/).empty?,"optimization fail: #{lines.inspect}"
|
158
|
-
assert_equal 1, @rd.getsockopt(Socket::SOL_TCP, TCP_CORK).unpack("i")[0]
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
def teardown
|
163
8
|
Kgio.autopush = false
|
9
|
+
assert_equal false, Kgio.autopush?
|
164
10
|
end
|
165
|
-
end
|
11
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kgio
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- kgio hackers
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-09-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: olddoc
|
@@ -41,8 +41,8 @@ dependencies:
|
|
41
41
|
description: |-
|
42
42
|
kgio provides non-blocking I/O methods for Ruby without raising
|
43
43
|
exceptions on EAGAIN and EINPROGRESS. It is intended for use with the
|
44
|
-
|
45
|
-
|
44
|
+
unicorn Rack server, but may be used by other applications (that run on
|
45
|
+
Unix-like platforms).
|
46
46
|
email: kgio-public@bogomips.org
|
47
47
|
executables: []
|
48
48
|
extensions:
|
@@ -57,7 +57,6 @@ extra_rdoc_files:
|
|
57
57
|
- HACKING
|
58
58
|
- lib/kgio.rb
|
59
59
|
- ext/kgio/accept.c
|
60
|
-
- ext/kgio/autopush.c
|
61
60
|
- ext/kgio/connect.c
|
62
61
|
- ext/kgio/kgio_ext.c
|
63
62
|
- ext/kgio/poll.c
|
@@ -83,7 +82,6 @@ files:
|
|
83
82
|
- archive/slrnpull.conf
|
84
83
|
- ext/kgio/accept.c
|
85
84
|
- ext/kgio/ancient_ruby.h
|
86
|
-
- ext/kgio/autopush.c
|
87
85
|
- ext/kgio/blocking_io_region.h
|
88
86
|
- ext/kgio/broken_system_compat.h
|
89
87
|
- ext/kgio/connect.c
|
@@ -154,7 +152,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
154
152
|
version: '0'
|
155
153
|
requirements: []
|
156
154
|
rubyforge_project:
|
157
|
-
rubygems_version: 2.
|
155
|
+
rubygems_version: 2.5.0
|
158
156
|
signing_key:
|
159
157
|
specification_version: 4
|
160
158
|
summary: kinder, gentler I/O for Ruby
|
data/ext/kgio/autopush.c
DELETED
@@ -1,247 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
* We use a very basic strategy to use TCP_CORK semantics optimally
|
3
|
-
* in most TCP servers: On corked sockets, we will uncork on recv()
|
4
|
-
* if there was a previous send(). Otherwise we do not fiddle
|
5
|
-
* with TCP_CORK at all.
|
6
|
-
*
|
7
|
-
* Under Linux, we can rely on TCP_CORK being inherited in an
|
8
|
-
* accept()-ed client socket so we can avoid syscalls for each
|
9
|
-
* accept()-ed client if we know the accept() socket corks.
|
10
|
-
*
|
11
|
-
* This module does NOTHING for client TCP sockets, we only deal
|
12
|
-
* with accept()-ed sockets right now.
|
13
|
-
*/
|
14
|
-
|
15
|
-
#include "kgio.h"
|
16
|
-
#include "my_fileno.h"
|
17
|
-
#include <netinet/tcp.h>
|
18
|
-
|
19
|
-
/*
|
20
|
-
* As of FreeBSD 4.5, TCP_NOPUSH == TCP_CORK
|
21
|
-
* ref: http://dotat.at/writing/nopush.html
|
22
|
-
* We won't care for older FreeBSD since nobody runs Ruby on them...
|
23
|
-
*/
|
24
|
-
#ifdef TCP_CORK
|
25
|
-
# define KGIO_NOPUSH TCP_CORK
|
26
|
-
#elif defined(TCP_NOPUSH)
|
27
|
-
# define KGIO_NOPUSH TCP_NOPUSH
|
28
|
-
#endif
|
29
|
-
|
30
|
-
#ifdef KGIO_NOPUSH
|
31
|
-
static ID id_autopush_state;
|
32
|
-
static int enabled = 1;
|
33
|
-
|
34
|
-
enum autopush_state {
|
35
|
-
AUTOPUSH_STATE_ACCEPTOR_IGNORE = -1,
|
36
|
-
AUTOPUSH_STATE_IGNORE = 0,
|
37
|
-
AUTOPUSH_STATE_WRITER = 1,
|
38
|
-
AUTOPUSH_STATE_WRITTEN = 2,
|
39
|
-
AUTOPUSH_STATE_ACCEPTOR = 3
|
40
|
-
};
|
41
|
-
|
42
|
-
#if defined(R_CAST) && \
|
43
|
-
defined(HAVE_TYPE_STRUCT_RFILE) && \
|
44
|
-
defined(HAVE_TYPE_STRUCT_ROBJECT) && \
|
45
|
-
((SIZEOF_STRUCT_RFILE + SIZEOF_INT) <= (SIZEOF_STRUCT_ROBJECT))
|
46
|
-
|
47
|
-
struct AutopushSocket {
|
48
|
-
struct RFile rfile;
|
49
|
-
enum autopush_state autopush_state;
|
50
|
-
};
|
51
|
-
|
52
|
-
static enum autopush_state state_get(VALUE io)
|
53
|
-
{
|
54
|
-
return ((struct AutopushSocket *)(io))->autopush_state;
|
55
|
-
}
|
56
|
-
|
57
|
-
static void state_set(VALUE io, enum autopush_state state)
|
58
|
-
{
|
59
|
-
((struct AutopushSocket *)(io))->autopush_state = state;
|
60
|
-
}
|
61
|
-
#else
|
62
|
-
static enum autopush_state state_get(VALUE io)
|
63
|
-
{
|
64
|
-
VALUE val;
|
65
|
-
|
66
|
-
if (rb_ivar_defined(io, id_autopush_state) == Qfalse)
|
67
|
-
return AUTOPUSH_STATE_IGNORE;
|
68
|
-
val = rb_ivar_get(io, id_autopush_state);
|
69
|
-
|
70
|
-
return (enum autopush_state)NUM2INT(val);
|
71
|
-
}
|
72
|
-
|
73
|
-
static void state_set(VALUE io, enum autopush_state state)
|
74
|
-
{
|
75
|
-
rb_ivar_set(io, id_autopush_state, INT2NUM(state));
|
76
|
-
}
|
77
|
-
#endif /* IVAR fallback */
|
78
|
-
|
79
|
-
static enum autopush_state detect_acceptor_state(VALUE io);
|
80
|
-
static void push_pending_data(VALUE io);
|
81
|
-
|
82
|
-
/*
|
83
|
-
* call-seq:
|
84
|
-
* Kgio.autopush? -> true or false
|
85
|
-
*
|
86
|
-
* Returns whether or not autopush is enabled.
|
87
|
-
*
|
88
|
-
* Only available on systems with TCP_CORK (Linux) or
|
89
|
-
* TCP_NOPUSH (FreeBSD, and maybe other *BSDs).
|
90
|
-
*/
|
91
|
-
static VALUE s_get_autopush(VALUE self)
|
92
|
-
{
|
93
|
-
return enabled ? Qtrue : Qfalse;
|
94
|
-
}
|
95
|
-
|
96
|
-
/*
|
97
|
-
* call-seq:
|
98
|
-
* Kgio.autopush = true
|
99
|
-
* Kgio.autopush = false
|
100
|
-
*
|
101
|
-
* Enables or disables autopush for sockets created with kgio_accept
|
102
|
-
* and kgio_tryaccept methods. Autopush relies on TCP_CORK/TCP_NOPUSH
|
103
|
-
* being enabled on the listen socket.
|
104
|
-
*
|
105
|
-
* Only available on systems with TCP_CORK (Linux) or
|
106
|
-
* TCP_NOPUSH (FreeBSD, and maybe other *BSDs).
|
107
|
-
*/
|
108
|
-
static VALUE s_set_autopush(VALUE self, VALUE val)
|
109
|
-
{
|
110
|
-
enabled = RTEST(val);
|
111
|
-
|
112
|
-
return val;
|
113
|
-
}
|
114
|
-
|
115
|
-
/*
|
116
|
-
* call-seq:
|
117
|
-
*
|
118
|
-
* io.kgio_autopush? -> true or false
|
119
|
-
*
|
120
|
-
* Returns the current autopush state of the Kgio::SocketMethods-enabled
|
121
|
-
* socket.
|
122
|
-
*
|
123
|
-
* Only available on systems with TCP_CORK (Linux) or
|
124
|
-
* TCP_NOPUSH (FreeBSD, and maybe other *BSDs).
|
125
|
-
*/
|
126
|
-
static VALUE autopush_get(VALUE io)
|
127
|
-
{
|
128
|
-
return state_get(io) <= 0 ? Qfalse : Qtrue;
|
129
|
-
}
|
130
|
-
|
131
|
-
/*
|
132
|
-
* call-seq:
|
133
|
-
*
|
134
|
-
* io.kgio_autopush = true
|
135
|
-
* io.kgio_autopush = false
|
136
|
-
*
|
137
|
-
* Enables or disables autopush on any given Kgio::SocketMethods-capable
|
138
|
-
* IO object. This does NOT enable or disable TCP_NOPUSH/TCP_CORK right
|
139
|
-
* away, that must be done with IO.setsockopt
|
140
|
-
*
|
141
|
-
* Only available on systems with TCP_CORK (Linux) or
|
142
|
-
* TCP_NOPUSH (FreeBSD, and maybe other *BSDs).
|
143
|
-
*/
|
144
|
-
static VALUE autopush_set(VALUE io, VALUE vbool)
|
145
|
-
{
|
146
|
-
if (RTEST(vbool))
|
147
|
-
state_set(io, AUTOPUSH_STATE_WRITER);
|
148
|
-
else
|
149
|
-
state_set(io, AUTOPUSH_STATE_IGNORE);
|
150
|
-
return vbool;
|
151
|
-
}
|
152
|
-
|
153
|
-
void init_kgio_autopush(void)
|
154
|
-
{
|
155
|
-
VALUE mKgio = rb_define_module("Kgio");
|
156
|
-
VALUE tmp;
|
157
|
-
|
158
|
-
rb_define_singleton_method(mKgio, "autopush?", s_get_autopush, 0);
|
159
|
-
rb_define_singleton_method(mKgio, "autopush=", s_set_autopush, 1);
|
160
|
-
|
161
|
-
tmp = rb_define_module_under(mKgio, "SocketMethods");
|
162
|
-
rb_define_method(tmp, "kgio_autopush=", autopush_set, 1);
|
163
|
-
rb_define_method(tmp, "kgio_autopush?", autopush_get, 0);
|
164
|
-
|
165
|
-
id_autopush_state = rb_intern("@kgio_autopush_state");
|
166
|
-
}
|
167
|
-
|
168
|
-
/*
|
169
|
-
* called after a successful write, just mark that we've put something
|
170
|
-
* in the skb and will need to uncork on the next write.
|
171
|
-
*/
|
172
|
-
void kgio_autopush_send(VALUE io)
|
173
|
-
{
|
174
|
-
if (state_get(io) == AUTOPUSH_STATE_WRITER)
|
175
|
-
state_set(io, AUTOPUSH_STATE_WRITTEN);
|
176
|
-
}
|
177
|
-
|
178
|
-
/* called on successful accept() */
|
179
|
-
void kgio_autopush_accept(VALUE accept_io, VALUE client_io)
|
180
|
-
{
|
181
|
-
enum autopush_state acceptor_state;
|
182
|
-
|
183
|
-
if (!enabled)
|
184
|
-
return;
|
185
|
-
acceptor_state = state_get(accept_io);
|
186
|
-
if (acceptor_state == AUTOPUSH_STATE_IGNORE)
|
187
|
-
acceptor_state = detect_acceptor_state(accept_io);
|
188
|
-
if (acceptor_state == AUTOPUSH_STATE_ACCEPTOR)
|
189
|
-
state_set(client_io, AUTOPUSH_STATE_WRITER);
|
190
|
-
else
|
191
|
-
state_set(client_io, AUTOPUSH_STATE_IGNORE);
|
192
|
-
}
|
193
|
-
|
194
|
-
void kgio_autopush_recv(VALUE io)
|
195
|
-
{
|
196
|
-
if (enabled && (state_get(io) == AUTOPUSH_STATE_WRITTEN)) {
|
197
|
-
push_pending_data(io);
|
198
|
-
state_set(io, AUTOPUSH_STATE_WRITER);
|
199
|
-
}
|
200
|
-
}
|
201
|
-
|
202
|
-
static enum autopush_state detect_acceptor_state(VALUE io)
|
203
|
-
{
|
204
|
-
int corked = 0;
|
205
|
-
int fd = my_fileno(io);
|
206
|
-
socklen_t optlen = sizeof(int);
|
207
|
-
enum autopush_state state;
|
208
|
-
|
209
|
-
if (getsockopt(fd, IPPROTO_TCP, KGIO_NOPUSH, &corked, &optlen) != 0) {
|
210
|
-
if (errno != EOPNOTSUPP)
|
211
|
-
rb_sys_fail("getsockopt(TCP_CORK/TCP_NOPUSH)");
|
212
|
-
errno = 0;
|
213
|
-
state = AUTOPUSH_STATE_ACCEPTOR_IGNORE;
|
214
|
-
} else if (corked) {
|
215
|
-
state = AUTOPUSH_STATE_ACCEPTOR;
|
216
|
-
} else {
|
217
|
-
state = AUTOPUSH_STATE_ACCEPTOR_IGNORE;
|
218
|
-
}
|
219
|
-
state_set(io, state);
|
220
|
-
|
221
|
-
return state;
|
222
|
-
}
|
223
|
-
|
224
|
-
/*
|
225
|
-
* checks to see if we've written anything since the last recv()
|
226
|
-
* If we have, uncork the socket and immediately recork it.
|
227
|
-
*/
|
228
|
-
static void push_pending_data(VALUE io)
|
229
|
-
{
|
230
|
-
int optval = 0;
|
231
|
-
const socklen_t optlen = sizeof(int);
|
232
|
-
const int fd = my_fileno(io);
|
233
|
-
|
234
|
-
if (setsockopt(fd, IPPROTO_TCP, KGIO_NOPUSH, &optval, optlen) != 0)
|
235
|
-
rb_sys_fail("setsockopt(TCP_CORK/TCP_NOPUSH, 0)");
|
236
|
-
/* immediately recork */
|
237
|
-
optval = 1;
|
238
|
-
if (setsockopt(fd, IPPROTO_TCP, KGIO_NOPUSH, &optval, optlen) != 0)
|
239
|
-
rb_sys_fail("setsockopt(TCP_CORK/TCP_NOPUSH, 1)");
|
240
|
-
}
|
241
|
-
#else /* !KGIO_NOPUSH */
|
242
|
-
void kgio_autopush_recv(VALUE io){}
|
243
|
-
void kgio_autopush_send(VALUE io){}
|
244
|
-
void init_kgio_autopush(void)
|
245
|
-
{
|
246
|
-
}
|
247
|
-
#endif /* ! KGIO_NOPUSH */
|