kgio 2.4.2 → 2.5.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.
- data/.document +1 -0
- data/GIT-VERSION-GEN +1 -1
- data/HACKING +1 -1
- data/ISSUES +2 -2
- data/README +4 -7
- data/ext/kgio/accept.c +2 -0
- data/ext/kgio/ancient_ruby.h +2 -1
- data/ext/kgio/autopush.c +1 -4
- data/ext/kgio/connect.c +0 -1
- data/ext/kgio/extconf.rb +6 -0
- data/ext/kgio/kgio.h +1 -2
- data/ext/kgio/kgio_ext.c +1 -0
- data/ext/kgio/poll.c +1 -0
- data/ext/kgio/read_write.c +6 -3
- data/ext/kgio/set_file_path.h +26 -0
- data/ext/kgio/tryopen.c +181 -0
- data/ext/kgio/wait.c +69 -29
- data/pkg.mk +5 -1
- data/test/test_default_wait.rb +24 -0
- data/test/test_tryopen.rb +81 -0
- metadata +10 -5
data/.document
CHANGED
data/GIT-VERSION-GEN
CHANGED
data/HACKING
CHANGED
@@ -29,7 +29,7 @@ characters wide) and NOT the indentation style of Matz Ruby.
|
|
29
29
|
|
30
30
|
Contributions are welcome in the form of patches, pull requests, code
|
31
31
|
review, testing, documentation, user support or any other feedback. The
|
32
|
-
{kgio mailing list}[mailto:kgio@librelist.
|
32
|
+
{kgio mailing list}[mailto:kgio@librelist.org] is the
|
33
33
|
central coordination point for all user and developer feedback and bug
|
34
34
|
reports.
|
35
35
|
|
data/ISSUES
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
= Issues
|
2
2
|
|
3
|
-
The kgio {mailing list}[mailto:kgio@librelist.
|
3
|
+
The kgio {mailing list}[mailto:kgio@librelist.org] is the best
|
4
4
|
place to report bugs, submit patches and/or obtain support after you
|
5
5
|
have searched the mailing list archives and
|
6
6
|
{documentation}[http://bogomips.org/kgio].
|
@@ -25,7 +25,7 @@ guidelines for patch submission.
|
|
25
25
|
== Mailing List Info
|
26
26
|
|
27
27
|
* subscribe: send a message to the mailing list
|
28
|
-
* post: mailto:kgio@librelist.
|
28
|
+
* post: mailto:kgio@librelist.org
|
29
29
|
* private: mailto:kgio@bogomips.org
|
30
30
|
|
31
31
|
== Mailing List Archives (coming soon)
|
data/README
CHANGED
@@ -3,7 +3,7 @@
|
|
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
5
|
Unicorn and Rainbows! Rack servers, but may be used by other
|
6
|
-
applications.
|
6
|
+
applications (that run on Unix-like platforms).
|
7
7
|
|
8
8
|
== Features
|
9
9
|
|
@@ -30,11 +30,8 @@ applications.
|
|
30
30
|
|
31
31
|
== Install
|
32
32
|
|
33
|
-
The library consists of a C extension so you'll need a
|
34
|
-
and Ruby development libraries/headers.
|
35
|
-
|
36
|
-
You may download the tarball from the Rainbows! project page on Rubyforge
|
37
|
-
and run setup.rb after unpacking it:
|
33
|
+
The library consists of a C extension so you'll need a Unix-like system
|
34
|
+
with a C compiler and Ruby development libraries/headers.
|
38
35
|
|
39
36
|
http://rubyforge.org/frs/?group_id=8977
|
40
37
|
|
@@ -61,7 +58,7 @@ from git.
|
|
61
58
|
|
62
59
|
All feedback (bug reports, user/development dicussion, patches, pull
|
63
60
|
requests) go to the mailing list/newsgroup. See the ISSUES document for
|
64
|
-
information on the {kgio mailing list}[mailto:kgio@librelist.
|
61
|
+
information on the {kgio mailing list}[mailto:kgio@librelist.org]
|
65
62
|
|
66
63
|
For the latest on kgio releases, you may check our NEWS page (and
|
67
64
|
subscribe to our Atom feed).
|
data/ext/kgio/accept.c
CHANGED
data/ext/kgio/ancient_ruby.h
CHANGED
@@ -2,11 +2,12 @@
|
|
2
2
|
#define MISSING_ANCIENT_RUBY_H
|
3
3
|
|
4
4
|
#ifndef HAVE_RB_STR_SET_LEN
|
5
|
-
static void
|
5
|
+
static void my_str_set_len(VALUE str, long len)
|
6
6
|
{
|
7
7
|
RSTRING(str)->len = len;
|
8
8
|
RSTRING(str)->ptr[len] = '\0';
|
9
9
|
}
|
10
|
+
#define rb_str_set_len(str,len) my_str_set_len((str),(len))
|
10
11
|
#endif /* ! HAVE_RB_STR_SET_LEN */
|
11
12
|
|
12
13
|
#ifndef RSTRING_PTR
|
data/ext/kgio/autopush.c
CHANGED
@@ -13,6 +13,7 @@
|
|
13
13
|
*/
|
14
14
|
|
15
15
|
#include "kgio.h"
|
16
|
+
#include "my_fileno.h"
|
16
17
|
#include <netinet/tcp.h>
|
17
18
|
|
18
19
|
/*
|
@@ -142,10 +143,6 @@ static VALUE autopush_get(VALUE io)
|
|
142
143
|
*/
|
143
144
|
static VALUE autopush_set(VALUE io, VALUE vbool)
|
144
145
|
{
|
145
|
-
int fd = my_fileno(io);
|
146
|
-
int val;
|
147
|
-
socklen_t len = sizeof(val);
|
148
|
-
|
149
146
|
if (RTEST(vbool))
|
150
147
|
state_set(io, AUTOPUSH_STATE_WRITER);
|
151
148
|
else
|
data/ext/kgio/connect.c
CHANGED
data/ext/kgio/extconf.rb
CHANGED
@@ -21,16 +21,20 @@ have_func("getnameinfo", %w(sys/types.h sys/socket.h netdb.h)) or
|
|
21
21
|
have_type("struct sockaddr_storage", %w(sys/types.h sys/socket.h)) or
|
22
22
|
abort "struct sockaddr_storage required"
|
23
23
|
have_func('accept4', %w(sys/socket.h))
|
24
|
+
have_header("sys/select.h")
|
25
|
+
|
24
26
|
if have_header('ruby/io.h')
|
25
27
|
rubyio = %w(ruby.h ruby/io.h)
|
26
28
|
have_struct_member("rb_io_t", "fd", rubyio)
|
27
29
|
have_struct_member("rb_io_t", "mode", rubyio)
|
30
|
+
have_struct_member("rb_io_t", "pathv", rubyio)
|
28
31
|
else
|
29
32
|
rubyio = %w(ruby.h rubyio.h)
|
30
33
|
rb_io_t = have_type("OpenFile", rubyio) ? "OpenFile" : "rb_io_t"
|
31
34
|
have_struct_member(rb_io_t, "f", rubyio)
|
32
35
|
have_struct_member(rb_io_t, "f2", rubyio)
|
33
36
|
have_struct_member(rb_io_t, "mode", rubyio)
|
37
|
+
have_struct_member(rb_io_t, "path", rubyio)
|
34
38
|
have_func('rb_fdopen')
|
35
39
|
end
|
36
40
|
have_type("struct RFile", rubyio) and check_sizeof("struct RFile", rubyio)
|
@@ -40,5 +44,7 @@ have_func('rb_io_ascii8bit_binmode')
|
|
40
44
|
have_func('rb_thread_blocking_region')
|
41
45
|
have_func('rb_thread_io_blocking_region')
|
42
46
|
have_func('rb_str_set_len')
|
47
|
+
have_func('rb_time_interval')
|
48
|
+
have_func('rb_wait_for_single_fd')
|
43
49
|
|
44
50
|
create_makefile('kgio_ext')
|
data/ext/kgio/kgio.h
CHANGED
@@ -19,8 +19,6 @@
|
|
19
19
|
#include <netdb.h>
|
20
20
|
|
21
21
|
#include "ancient_ruby.h"
|
22
|
-
#include "nonblock.h"
|
23
|
-
#include "my_fileno.h"
|
24
22
|
|
25
23
|
struct io_args {
|
26
24
|
VALUE io;
|
@@ -36,6 +34,7 @@ void init_kgio_accept(void);
|
|
36
34
|
void init_kgio_connect(void);
|
37
35
|
void init_kgio_autopush(void);
|
38
36
|
void init_kgio_poll(void);
|
37
|
+
void init_kgio_tryopen(void);
|
39
38
|
|
40
39
|
void kgio_autopush_accept(VALUE, VALUE);
|
41
40
|
void kgio_autopush_recv(VALUE);
|
data/ext/kgio/kgio_ext.c
CHANGED
data/ext/kgio/poll.c
CHANGED
data/ext/kgio/read_write.c
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
#include "kgio.h"
|
2
|
+
#include "my_fileno.h"
|
3
|
+
#include "nonblock.h"
|
2
4
|
static VALUE sym_wait_readable, sym_wait_writable;
|
3
5
|
static VALUE eErrno_EPIPE, eErrno_ECONNRESET;
|
4
6
|
static ID id_set_backtrace;
|
@@ -518,9 +520,10 @@ void init_kgio_read_write(void)
|
|
518
520
|
rb_define_method(mSocketMethods, "kgio_peek", kgio_peek, -1);
|
519
521
|
|
520
522
|
/*
|
521
|
-
* Returns the client
|
522
|
-
*
|
523
|
-
* Kgio::LOCALHOST constant
|
523
|
+
* Returns the client IP address of the socket as a string
|
524
|
+
* (e.g. "127.0.0.1" or "::1").
|
525
|
+
* This is always the value of the Kgio::LOCALHOST constant
|
526
|
+
* for UNIX domain sockets.
|
524
527
|
*/
|
525
528
|
rb_define_attr(mSocketMethods, "kgio_addr", 1, 1);
|
526
529
|
id_set_backtrace = rb_intern("set_backtrace");
|
@@ -0,0 +1,26 @@
|
|
1
|
+
#if defined(HAVE_RB_IO_T) && \
|
2
|
+
defined(HAVE_TYPE_STRUCT_RFILE) && \
|
3
|
+
defined(HAVE_ST_PATHV)
|
4
|
+
/* MRI 1.9 */
|
5
|
+
static void set_file_path(VALUE io, VALUE path)
|
6
|
+
{
|
7
|
+
rb_io_t *fptr = RFILE(io)->fptr;
|
8
|
+
fptr->pathv = rb_str_new4(path);
|
9
|
+
}
|
10
|
+
#elif defined(HAVE_TYPE_OPENFILE) && \
|
11
|
+
defined(HAVE_TYPE_STRUCT_RFILE) && \
|
12
|
+
defined(HAVE_ST_PATH)
|
13
|
+
/* MRI 1.8 */
|
14
|
+
#include "util.h"
|
15
|
+
static void set_file_path(VALUE io, VALUE path)
|
16
|
+
{
|
17
|
+
OpenFile *fptr = RFILE(io)->fptr;
|
18
|
+
fptr->path = ruby_strdup(RSTRING_PTR(path));
|
19
|
+
}
|
20
|
+
#else
|
21
|
+
/* Rubinius */
|
22
|
+
static void set_file_path(VALUE io, VALUE path)
|
23
|
+
{
|
24
|
+
rb_iv_set(io, "@path", rb_str_new4(path));
|
25
|
+
}
|
26
|
+
#endif
|
data/ext/kgio/tryopen.c
ADDED
@@ -0,0 +1,181 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#ifdef HAVE_RUBY_IO_H
|
3
|
+
# include <ruby/io.h>
|
4
|
+
#else
|
5
|
+
# include <rubyio.h>
|
6
|
+
#endif
|
7
|
+
|
8
|
+
#ifdef HAVE_RUBY_ST_H
|
9
|
+
# include <ruby/st.h>
|
10
|
+
#else
|
11
|
+
# include <st.h>
|
12
|
+
#endif
|
13
|
+
|
14
|
+
#include <sys/types.h>
|
15
|
+
#include <sys/stat.h>
|
16
|
+
#include <fcntl.h>
|
17
|
+
#include "set_file_path.h"
|
18
|
+
|
19
|
+
static ID id_for_fd, id_to_path, id_path;
|
20
|
+
static st_table *errno2sym;
|
21
|
+
|
22
|
+
struct open_args {
|
23
|
+
const char *pathname;
|
24
|
+
int flags;
|
25
|
+
mode_t mode;
|
26
|
+
};
|
27
|
+
|
28
|
+
static VALUE nogvl_open(void *ptr)
|
29
|
+
{
|
30
|
+
struct open_args *o = ptr;
|
31
|
+
|
32
|
+
return (VALUE)open(o->pathname, o->flags, o->mode);
|
33
|
+
}
|
34
|
+
|
35
|
+
#ifndef HAVE_RB_THREAD_BLOCKING_REGION
|
36
|
+
# define RUBY_UBF_IO ((void *)(-1))
|
37
|
+
# include "rubysig.h"
|
38
|
+
typedef void rb_unblock_function_t(void *);
|
39
|
+
typedef VALUE rb_blocking_function_t(void *);
|
40
|
+
static VALUE rb_thread_blocking_region(
|
41
|
+
rb_blocking_function_t *fn, void *data1,
|
42
|
+
rb_unblock_function_t *ubf, void *data2)
|
43
|
+
{
|
44
|
+
VALUE rv;
|
45
|
+
|
46
|
+
TRAP_BEG; /* for FIFO */
|
47
|
+
rv = fn(data1);
|
48
|
+
TRAP_END;
|
49
|
+
|
50
|
+
return rv;
|
51
|
+
}
|
52
|
+
#endif /* ! HAVE_RB_THREAD_BLOCKING_REGION */
|
53
|
+
|
54
|
+
/*
|
55
|
+
* call-seq:
|
56
|
+
*
|
57
|
+
* Kgio::File.tryopen(filename, [, mode [, perm]]) -> Kgio::File or Symbol
|
58
|
+
*
|
59
|
+
* Returns a Kgio::File object on a successful open. +filename+ is a
|
60
|
+
* path to any file on the filesystem. If specified, +mode+ is a bitmask
|
61
|
+
* of flags (see IO.sysopen) and +perm+ should be an octal number.
|
62
|
+
*
|
63
|
+
* This does not raise errors for most failures, but installs returns a
|
64
|
+
* Ruby symbol for the constant in the Errno::* namespace.
|
65
|
+
*
|
66
|
+
* Common error symbols are:
|
67
|
+
*
|
68
|
+
* - :ENOENT
|
69
|
+
* - :EACCES
|
70
|
+
*
|
71
|
+
* See your open(2) manpage for more information on open(2) errors.
|
72
|
+
*/
|
73
|
+
static VALUE s_tryopen(int argc, VALUE *argv, VALUE klass)
|
74
|
+
{
|
75
|
+
int fd;
|
76
|
+
VALUE pathname, flags, mode;
|
77
|
+
struct open_args o;
|
78
|
+
int retried = 0;
|
79
|
+
VALUE rv;
|
80
|
+
|
81
|
+
rb_scan_args(argc, argv, "12", &pathname, &flags, &mode);
|
82
|
+
if (rb_respond_to(pathname, id_to_path))
|
83
|
+
pathname = rb_funcall(pathname, id_to_path, 0);
|
84
|
+
o.pathname = StringValueCStr(pathname);
|
85
|
+
|
86
|
+
switch (TYPE(flags)) {
|
87
|
+
case T_NIL: o.flags = O_RDONLY; break;
|
88
|
+
case T_FIXNUM: o.flags = FIX2INT(flags); break;
|
89
|
+
case T_BIGNUM: o.flags = NUM2INT(flags); break;
|
90
|
+
default: rb_raise(rb_eArgError, "flags must be an Integer");
|
91
|
+
}
|
92
|
+
switch (TYPE(mode)) {
|
93
|
+
case T_NIL: o.mode = 0666; break;
|
94
|
+
case T_FIXNUM: o.mode = FIX2INT(mode); break;
|
95
|
+
case T_BIGNUM: o.mode = NUM2INT(mode); break;
|
96
|
+
default: rb_raise(rb_eArgError, "mode must be an Integer");
|
97
|
+
}
|
98
|
+
|
99
|
+
retry:
|
100
|
+
fd = (int)rb_thread_blocking_region(nogvl_open, &o, RUBY_UBF_IO, 0);
|
101
|
+
if (fd == -1) {
|
102
|
+
if (errno == EMFILE || errno == ENFILE || errno == ENOMEM) {
|
103
|
+
rb_gc();
|
104
|
+
if (retried)
|
105
|
+
rb_sys_fail(o.pathname);
|
106
|
+
retried = 1;
|
107
|
+
goto retry;
|
108
|
+
}
|
109
|
+
if (fd == -1) {
|
110
|
+
int saved_errno = errno;
|
111
|
+
|
112
|
+
if (!st_lookup(errno2sym, (st_data_t)errno, &rv)) {
|
113
|
+
errno = saved_errno;
|
114
|
+
rb_sys_fail(o.pathname);
|
115
|
+
}
|
116
|
+
return rv;
|
117
|
+
}
|
118
|
+
}
|
119
|
+
rv = rb_funcall(klass, id_for_fd, 1, INT2FIX(fd));
|
120
|
+
set_file_path(rv, pathname);
|
121
|
+
return rv;
|
122
|
+
}
|
123
|
+
|
124
|
+
void init_kgio_tryopen(void)
|
125
|
+
{
|
126
|
+
VALUE mKgio = rb_define_module("Kgio");
|
127
|
+
VALUE mPipeMethods = rb_const_get(mKgio, rb_intern("PipeMethods"));
|
128
|
+
VALUE cFile;
|
129
|
+
VALUE tmp;
|
130
|
+
VALUE *ptr;
|
131
|
+
long len;
|
132
|
+
|
133
|
+
id_path = rb_intern("path");
|
134
|
+
id_for_fd = rb_intern("for_fd");
|
135
|
+
id_to_path = rb_intern("to_path");
|
136
|
+
|
137
|
+
/*
|
138
|
+
* Document-class: Kgio::File
|
139
|
+
*
|
140
|
+
* This subclass of the core File class adds the "tryopen" singleton
|
141
|
+
* method for opening files. A single "tryopen" and check for the
|
142
|
+
* return value may be used to avoid unnecessary stat(2) syscalls
|
143
|
+
* or File.open exceptions when checking for the existence of a file
|
144
|
+
* and opening it.
|
145
|
+
*/
|
146
|
+
cFile = rb_define_class_under(mKgio, "File", rb_cFile);
|
147
|
+
rb_define_singleton_method(cFile, "tryopen", s_tryopen, -1);
|
148
|
+
rb_include_module(cFile, mPipeMethods);
|
149
|
+
|
150
|
+
if (!rb_funcall(cFile, rb_intern("method_defined?"), 1,
|
151
|
+
ID2SYM(id_to_path)))
|
152
|
+
rb_define_alias(cFile, "to_path", "path");
|
153
|
+
|
154
|
+
errno2sym = st_init_numtable();
|
155
|
+
tmp = rb_funcall(rb_mErrno, rb_intern("constants"), 0);
|
156
|
+
ptr = RARRAY_PTR(tmp);
|
157
|
+
len = RARRAY_LEN(tmp);
|
158
|
+
for (; --len >= 0; ptr++) {
|
159
|
+
VALUE error;
|
160
|
+
ID const_id;
|
161
|
+
|
162
|
+
switch (TYPE(*ptr)) {
|
163
|
+
case T_SYMBOL: const_id = SYM2ID(*ptr); break;
|
164
|
+
case T_STRING: const_id = rb_intern(RSTRING_PTR(*ptr)); break;
|
165
|
+
default: rb_bug("constant not a symbol or string");
|
166
|
+
}
|
167
|
+
|
168
|
+
error = rb_const_get(rb_mErrno, const_id);
|
169
|
+
if ((TYPE(error) != T_CLASS) ||
|
170
|
+
!rb_const_defined(error, rb_intern("Errno")))
|
171
|
+
continue;
|
172
|
+
|
173
|
+
error = rb_const_get(error, rb_intern("Errno"));
|
174
|
+
switch (TYPE(error)) {
|
175
|
+
case T_FIXNUM:
|
176
|
+
case T_BIGNUM:
|
177
|
+
st_insert(errno2sym, (st_data_t)NUM2INT(error),
|
178
|
+
ID2SYM(const_id));
|
179
|
+
}
|
180
|
+
}
|
181
|
+
}
|
data/ext/kgio/wait.c
CHANGED
@@ -1,53 +1,93 @@
|
|
1
1
|
#include "kgio.h"
|
2
|
-
|
2
|
+
#include "my_fileno.h"
|
3
3
|
static ID id_wait_rd, id_wait_wr;
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
#if defined(HAVE_RB_TIME_INTERVAL) && defined(HAVE_RB_WAIT_FOR_SINGLE_FD)
|
6
|
+
static int kgio_timedwait(VALUE self, VALUE timeout, int write_p)
|
7
|
+
{
|
8
|
+
struct timeval tv = rb_time_interval(timeout);
|
9
|
+
int events = write_p ? RB_WAITFD_OUT : RB_WAITFD_IN;
|
10
|
+
|
11
|
+
return rb_wait_for_single_fd(my_fileno(self), events, &tv);
|
12
|
+
}
|
13
|
+
#else /* ! (HAVE_RB_TIME_INTERVAL && HAVE_RB_WAIT_FOR_SINGLE_FD) */
|
14
|
+
static int kgio_timedwait(VALUE self, VALUE timeout, int write_p)
|
15
|
+
{
|
16
|
+
VALUE argv[4];
|
17
|
+
VALUE set = rb_ary_new3(1, self);
|
11
18
|
|
19
|
+
argv[0] = write_p ? Qnil : set;
|
20
|
+
argv[1] = write_p ? set : Qnil;
|
21
|
+
argv[2] = Qnil;
|
22
|
+
argv[3] = timeout;
|
23
|
+
|
24
|
+
set = rb_funcall2(rb_cIO, rb_intern("select"), 4, argv);
|
25
|
+
return NIL_P(set) ? 0 : 1;
|
26
|
+
}
|
27
|
+
#endif /* ! (HAVE_RB_TIME_INTERVAL && HAVE_RB_WAIT_FOR_SINGLE_FD) */
|
28
|
+
|
29
|
+
static int kgio_wait(int argc, VALUE *argv, VALUE self, int write_p)
|
30
|
+
{
|
31
|
+
int fd;
|
32
|
+
VALUE timeout;
|
33
|
+
|
34
|
+
if (rb_scan_args(argc, argv, "01", &timeout) == 1 && !NIL_P(timeout))
|
35
|
+
return kgio_timedwait(self, timeout, write_p);
|
36
|
+
|
37
|
+
fd = my_fileno(self);
|
38
|
+
errno = EAGAIN;
|
39
|
+
write_p ? rb_io_wait_writable(fd) : rb_io_wait_readable(fd);
|
40
|
+
return 1;
|
41
|
+
}
|
12
42
|
|
13
43
|
/*
|
14
|
-
*
|
15
|
-
*
|
16
|
-
*
|
44
|
+
* call-seq:
|
45
|
+
*
|
46
|
+
* io.kgio_wait_readable -> IO
|
47
|
+
* io.kgio_wait_readable(timeout) -> IO or nil
|
48
|
+
*
|
49
|
+
* Blocks the running Thread indefinitely until the IO object is readable
|
50
|
+
* or if +timeout+ expires. If +timeout+ is specified and expires, +nil+
|
51
|
+
* is returned.
|
52
|
+
*
|
53
|
+
* This method is automatically called (without timeout argument) by default
|
54
|
+
* whenever kgio_read needs to block on input.
|
17
55
|
*
|
18
56
|
* Users of alternative threading/fiber libraries are
|
19
57
|
* encouraged to override this method in their subclasses or modules to
|
20
58
|
* work with their threading/blocking methods.
|
21
59
|
*/
|
22
|
-
static VALUE kgio_wait_readable(VALUE self)
|
60
|
+
static VALUE kgio_wait_readable(int argc, VALUE *argv, VALUE self)
|
23
61
|
{
|
24
|
-
int
|
25
|
-
|
26
|
-
errno = EAGAIN;
|
27
|
-
if (!rb_io_wait_readable(fd))
|
28
|
-
rb_sys_fail("kgio_wait_readable");
|
62
|
+
int r = kgio_wait(argc, argv, self, 0);
|
29
63
|
|
30
|
-
|
64
|
+
if (r < 0) rb_sys_fail("kgio_wait_readable");
|
65
|
+
return r == 0 ? Qnil : self;
|
31
66
|
}
|
32
67
|
|
33
68
|
/*
|
34
|
-
*
|
35
|
-
*
|
36
|
-
*
|
69
|
+
* call-seq:
|
70
|
+
*
|
71
|
+
* io.kgio_wait_writeable -> IO
|
72
|
+
* io.kgio_wait_writable(timeout) -> IO or nil
|
73
|
+
*
|
74
|
+
* Blocks the running Thread indefinitely until the IO object is writable
|
75
|
+
* or if +timeout+ expires. If +timeout+ is specified and expires, +nil+
|
76
|
+
* is returned.
|
77
|
+
*
|
78
|
+
* This method is automatically called (without timeout argument) by default
|
79
|
+
* whenever kgio_write needs to block on output.
|
37
80
|
*
|
38
81
|
* Users of alternative threading/fiber libraries are
|
39
82
|
* encouraged to override this method in their subclasses or modules to
|
40
83
|
* work with their threading/blocking methods.
|
41
84
|
*/
|
42
|
-
static VALUE kgio_wait_writable(VALUE self)
|
85
|
+
static VALUE kgio_wait_writable(int argc, VALUE *argv, VALUE self)
|
43
86
|
{
|
44
|
-
int
|
45
|
-
|
46
|
-
errno = EAGAIN;
|
47
|
-
if (!rb_io_wait_writable(fd))
|
48
|
-
rb_sys_fail("kgio_wait_writable");
|
87
|
+
int r = kgio_wait(argc, argv, self, 1);
|
49
88
|
|
50
|
-
|
89
|
+
if (r < 0) rb_sys_fail("kgio_wait_writable");
|
90
|
+
return r == 0 ? Qnil : self;
|
51
91
|
}
|
52
92
|
|
53
93
|
VALUE kgio_call_wait_writable(VALUE io)
|
@@ -80,7 +120,7 @@ void init_kgio_wait(void)
|
|
80
120
|
id_wait_wr = rb_intern("kgio_wait_writable");
|
81
121
|
|
82
122
|
rb_define_method(mWaiters, "kgio_wait_readable",
|
83
|
-
kgio_wait_readable,
|
123
|
+
kgio_wait_readable, -1);
|
84
124
|
rb_define_method(mWaiters, "kgio_wait_writable",
|
85
|
-
kgio_wait_writable,
|
125
|
+
kgio_wait_writable, -1);
|
86
126
|
}
|
data/pkg.mk
CHANGED
@@ -69,7 +69,7 @@ doc:: .document .wrongdoc.yml $(pkg_extra)
|
|
69
69
|
$(RM) -r doc
|
70
70
|
$(WRONGDOC) all
|
71
71
|
install -m644 COPYING doc/COPYING
|
72
|
-
install -m644 $(shell grep '^[A-Z]' .document) doc/
|
72
|
+
install -m644 $(shell LC_ALL=C grep '^[A-Z]' .document) doc/
|
73
73
|
|
74
74
|
ifneq ($(VERSION),)
|
75
75
|
pkggem := pkg/$(rfpackage)-$(VERSION).gem
|
@@ -167,5 +167,9 @@ doc_gz: docs = $(shell find doc -type f ! -regex '^.*\.\(gif\|jpg\|png\|gz\)$$')
|
|
167
167
|
doc_gz:
|
168
168
|
for i in $(docs); do \
|
169
169
|
gzip --rsyncable -9 < $$i > $$i.gz; touch -r $$i $$i.gz; done
|
170
|
+
check-warnings:
|
171
|
+
@(for i in $$(git ls-files '*.rb'| grep -v '^setup\.rb$$'); \
|
172
|
+
do $(RUBY) -d -W2 -c $$i; done) | grep -v '^Syntax OK$$' || :
|
170
173
|
|
171
174
|
.PHONY: all .FORCE-GIT-VERSION-FILE doc test $(test_units) manifest
|
175
|
+
.PHONY: check-warnings
|
data/test/test_default_wait.rb
CHANGED
@@ -18,4 +18,28 @@ class TestDefaultWait < Test::Unit::TestCase
|
|
18
18
|
b.syswrite('.')
|
19
19
|
assert_equal a, a.kgio_wait_readable
|
20
20
|
end
|
21
|
+
|
22
|
+
def test_wait_readable_timed
|
23
|
+
a, b = Kgio::Pipe.new
|
24
|
+
t0 = Time.now
|
25
|
+
assert_nil a.kgio_wait_readable(1.1)
|
26
|
+
diff = Time.now - t0
|
27
|
+
assert_in_delta diff, 1.1, 0.05
|
28
|
+
|
29
|
+
b.kgio_write '.'
|
30
|
+
assert_equal a, a.kgio_wait_readable(1.1)
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_wait_writable_timed
|
34
|
+
a, b = Kgio::Pipe.new
|
35
|
+
buf = "*" * 65536
|
36
|
+
true until Symbol === b.kgio_trywrite(buf)
|
37
|
+
t0 = Time.now
|
38
|
+
assert_nil b.kgio_wait_writable(1.1)
|
39
|
+
diff = Time.now - t0
|
40
|
+
assert_in_delta diff, 1.1, 0.05
|
41
|
+
|
42
|
+
a.kgio_read(16384)
|
43
|
+
assert_equal b, b.kgio_wait_writable(1.1)
|
44
|
+
end
|
21
45
|
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
require 'test/unit'
|
3
|
+
$-w = true
|
4
|
+
require 'kgio'
|
5
|
+
|
6
|
+
class TestTryopen < Test::Unit::TestCase
|
7
|
+
|
8
|
+
def test_tryopen_success
|
9
|
+
tmp = Kgio::File.tryopen(__FILE__)
|
10
|
+
assert_kind_of File, tmp
|
11
|
+
assert_equal File.read(__FILE__), tmp.read
|
12
|
+
assert_equal __FILE__, tmp.path
|
13
|
+
assert_equal __FILE__, tmp.to_path
|
14
|
+
assert_nothing_raised { tmp.close }
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_tryopen_ENOENT
|
18
|
+
tmp = Tempfile.new "tryopen"
|
19
|
+
path = tmp.path
|
20
|
+
tmp.close!
|
21
|
+
tmp = Kgio::File.tryopen(path)
|
22
|
+
assert_equal :ENOENT, tmp
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_tryopen_EPERM
|
26
|
+
tmp = Tempfile.new "tryopen"
|
27
|
+
File.chmod 0000, tmp.path
|
28
|
+
tmp = Kgio::File.tryopen(tmp.path)
|
29
|
+
assert_equal :EACCES, tmp
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_tryopen_readwrite
|
33
|
+
tmp = Tempfile.new "tryopen"
|
34
|
+
file = Kgio::File.tryopen(tmp.path, IO::RDWR)
|
35
|
+
file.syswrite "FOO"
|
36
|
+
assert_equal "FOO", tmp.sysread(3)
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_tryopen_try_readwrite
|
40
|
+
tmp = Tempfile.new "tryopen"
|
41
|
+
file = Kgio::File.tryopen(tmp.path, IO::RDWR)
|
42
|
+
assert_nil file.kgio_trywrite("FOO")
|
43
|
+
file.rewind
|
44
|
+
assert_equal "FOO", file.kgio_tryread(3)
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_tryopen_mode
|
48
|
+
tmp = Tempfile.new "tryopen"
|
49
|
+
path = tmp.path
|
50
|
+
tmp.close!
|
51
|
+
file = Kgio::File.tryopen(path, IO::RDWR|IO::CREAT, 0000)
|
52
|
+
assert_equal 0100000, File.stat(path).mode
|
53
|
+
ensure
|
54
|
+
File.unlink path
|
55
|
+
end
|
56
|
+
|
57
|
+
require "benchmark"
|
58
|
+
def test_benchmark
|
59
|
+
nr = 1000000
|
60
|
+
tmp = Tempfile.new('tryopen')
|
61
|
+
file = tmp.path
|
62
|
+
Benchmark.bmbm do |x|
|
63
|
+
x.report("tryopen (OK)") do
|
64
|
+
nr.times { Kgio::File.tryopen(file).close }
|
65
|
+
end
|
66
|
+
x.report("open (OK)") do
|
67
|
+
nr.times { File.readable?(file) && File.open(file).close }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
tmp.close!
|
71
|
+
assert_equal :ENOENT, Kgio::File.tryopen(file)
|
72
|
+
Benchmark.bmbm do |x|
|
73
|
+
x.report("tryopen (ENOENT)") do
|
74
|
+
nr.times { Kgio::File.tryopen(file) }
|
75
|
+
end
|
76
|
+
x.report("open (ENOENT)") do
|
77
|
+
nr.times { File.readable?(file) && File.open(file) }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end if ENV["BENCHMARK"]
|
81
|
+
end
|
metadata
CHANGED
@@ -5,9 +5,9 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 2
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 2.
|
8
|
+
- 5
|
9
|
+
- 0
|
10
|
+
version: 2.5.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- kgio hackers
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-06-
|
18
|
+
date: 2011-06-20 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: wrongdoc
|
@@ -51,7 +51,7 @@ description: |-
|
|
51
51
|
kgio provides non-blocking I/O methods for Ruby without raising
|
52
52
|
exceptions on EAGAIN and EINPROGRESS. It is intended for use with the
|
53
53
|
Unicorn and Rainbows! Rack servers, but may be used by other
|
54
|
-
applications.
|
54
|
+
applications (that run on Unix-like platforms).
|
55
55
|
email: kgio@librelist.org
|
56
56
|
executables: []
|
57
57
|
|
@@ -74,6 +74,7 @@ extra_rdoc_files:
|
|
74
74
|
- ext/kgio/poll.c
|
75
75
|
- ext/kgio/read_write.c
|
76
76
|
- ext/kgio/wait.c
|
77
|
+
- ext/kgio/tryopen.c
|
77
78
|
files:
|
78
79
|
- .document
|
79
80
|
- .gitignore
|
@@ -106,7 +107,9 @@ files:
|
|
106
107
|
- ext/kgio/nonblock.h
|
107
108
|
- ext/kgio/poll.c
|
108
109
|
- ext/kgio/read_write.c
|
110
|
+
- ext/kgio/set_file_path.h
|
109
111
|
- ext/kgio/sock_for_fd.h
|
112
|
+
- ext/kgio/tryopen.c
|
110
113
|
- ext/kgio/wait.c
|
111
114
|
- kgio.gemspec
|
112
115
|
- lib/kgio.rb
|
@@ -132,6 +135,7 @@ files:
|
|
132
135
|
- test/test_tcp_connect.rb
|
133
136
|
- test/test_tcp_server.rb
|
134
137
|
- test/test_tcp_server_read_client_write.rb
|
138
|
+
- test/test_tryopen.rb
|
135
139
|
- test/test_unix_client_read_server_write.rb
|
136
140
|
- test/test_unix_connect.rb
|
137
141
|
- test/test_unix_server.rb
|
@@ -189,6 +193,7 @@ test_files:
|
|
189
193
|
- test/test_connect_fd_leak.rb
|
190
194
|
- test/test_singleton_read_write.rb
|
191
195
|
- test/test_kgio_addr.rb
|
196
|
+
- test/test_tryopen.rb
|
192
197
|
- test/test_tcp6_client_read_server_write.rb
|
193
198
|
- test/test_tcp_server_read_client_write.rb
|
194
199
|
- test/test_unix_client_read_server_write.rb
|