kgio 2.4.2 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|