iodine 0.4.19 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of iodine might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.travis.yml +1 -2
- data/CHANGELOG.md +22 -0
- data/LIMITS.md +19 -9
- data/README.md +92 -77
- data/SPEC-PubSub-Draft.md +113 -0
- data/SPEC-Websocket-Draft.md +127 -143
- data/bin/http-hello +0 -1
- data/bin/raw-rbhttp +1 -1
- data/bin/raw_broadcast +8 -10
- data/bin/updated api +2 -2
- data/bin/ws-broadcast +2 -4
- data/bin/ws-echo +2 -2
- data/examples/config.ru +13 -13
- data/examples/echo.ru +5 -6
- data/examples/hello.ru +2 -3
- data/examples/info.md +316 -0
- data/examples/pubsub_engine.ru +81 -0
- data/examples/redis.ru +9 -9
- data/examples/shootout.ru +45 -11
- data/ext/iodine/defer.c +194 -297
- data/ext/iodine/defer.h +61 -53
- data/ext/iodine/evio.c +0 -260
- data/ext/iodine/evio.h +50 -22
- data/ext/iodine/evio_callbacks.c +26 -0
- data/ext/iodine/evio_epoll.c +251 -0
- data/ext/iodine/evio_kqueue.c +193 -0
- data/ext/iodine/extconf.rb +1 -1
- data/ext/iodine/facil.c +1420 -542
- data/ext/iodine/facil.h +151 -64
- data/ext/iodine/fio_ary.h +418 -0
- data/ext/iodine/{base64.c → fio_base64.c} +33 -24
- data/ext/iodine/{base64.h → fio_base64.h} +6 -7
- data/ext/iodine/{fio_cli_helper.c → fio_cli.c} +77 -58
- data/ext/iodine/{fio_cli_helper.h → fio_cli.h} +9 -4
- data/ext/iodine/fio_hashmap.h +759 -0
- data/ext/iodine/fio_json_parser.h +651 -0
- data/ext/iodine/fio_llist.h +257 -0
- data/ext/iodine/fio_mem.c +672 -0
- data/ext/iodine/fio_mem.h +140 -0
- data/ext/iodine/fio_random.c +248 -0
- data/ext/iodine/{random.h → fio_random.h} +11 -14
- data/ext/iodine/{sha1.c → fio_sha1.c} +28 -24
- data/ext/iodine/{sha1.h → fio_sha1.h} +38 -16
- data/ext/iodine/{sha2.c → fio_sha2.c} +66 -49
- data/ext/iodine/{sha2.h → fio_sha2.h} +57 -26
- data/ext/iodine/{fiobj_internal.c → fio_siphash.c} +9 -90
- data/ext/iodine/fio_siphash.h +18 -0
- data/ext/iodine/fio_tmpfile.h +38 -0
- data/ext/iodine/fiobj.h +24 -7
- data/ext/iodine/fiobj4sock.h +23 -0
- data/ext/iodine/fiobj_ary.c +143 -226
- data/ext/iodine/fiobj_ary.h +17 -16
- data/ext/iodine/fiobj_data.c +1160 -0
- data/ext/iodine/fiobj_data.h +164 -0
- data/ext/iodine/fiobj_hash.c +298 -406
- data/ext/iodine/fiobj_hash.h +101 -54
- data/ext/iodine/fiobj_json.c +478 -601
- data/ext/iodine/fiobj_json.h +34 -9
- data/ext/iodine/fiobj_numbers.c +383 -51
- data/ext/iodine/fiobj_numbers.h +87 -11
- data/ext/iodine/fiobj_str.c +423 -184
- data/ext/iodine/fiobj_str.h +81 -32
- data/ext/iodine/fiobject.c +273 -522
- data/ext/iodine/fiobject.h +477 -112
- data/ext/iodine/http.c +2243 -83
- data/ext/iodine/http.h +842 -121
- data/ext/iodine/http1.c +810 -385
- data/ext/iodine/http1.h +16 -39
- data/ext/iodine/http1_parser.c +146 -74
- data/ext/iodine/http1_parser.h +15 -4
- data/ext/iodine/http_internal.c +1258 -0
- data/ext/iodine/http_internal.h +226 -0
- data/ext/iodine/http_mime_parser.h +341 -0
- data/ext/iodine/iodine.c +86 -68
- data/ext/iodine/iodine.h +26 -11
- data/ext/iodine/iodine_helpers.c +8 -7
- data/ext/iodine/iodine_http.c +487 -324
- data/ext/iodine/iodine_json.c +304 -0
- data/ext/iodine/iodine_json.h +6 -0
- data/ext/iodine/iodine_protocol.c +107 -45
- data/ext/iodine/iodine_pubsub.c +526 -225
- data/ext/iodine/iodine_pubsub.h +10 -0
- data/ext/iodine/iodine_websockets.c +268 -510
- data/ext/iodine/iodine_websockets.h +2 -4
- data/ext/iodine/pubsub.c +726 -432
- data/ext/iodine/pubsub.h +85 -103
- data/ext/iodine/rb-call.c +4 -4
- data/ext/iodine/rb-defer.c +46 -22
- data/ext/iodine/rb-fiobj2rb.h +117 -0
- data/ext/iodine/rb-rack-io.c +73 -238
- data/ext/iodine/rb-rack-io.h +2 -2
- data/ext/iodine/rb-registry.c +35 -93
- data/ext/iodine/rb-registry.h +1 -0
- data/ext/iodine/redis_engine.c +742 -304
- data/ext/iodine/redis_engine.h +42 -39
- data/ext/iodine/resp_parser.h +311 -0
- data/ext/iodine/sock.c +627 -490
- data/ext/iodine/sock.h +345 -297
- data/ext/iodine/spnlock.inc +15 -4
- data/ext/iodine/websocket_parser.h +16 -20
- data/ext/iodine/websockets.c +188 -257
- data/ext/iodine/websockets.h +24 -133
- data/lib/iodine.rb +52 -7
- data/lib/iodine/cli.rb +6 -24
- data/lib/iodine/json.rb +40 -0
- data/lib/iodine/version.rb +1 -1
- data/lib/iodine/websocket.rb +5 -3
- data/lib/rack/handler/iodine.rb +58 -13
- metadata +38 -48
- data/bin/ws-shootout +0 -107
- data/examples/broadcast.ru +0 -56
- data/ext/iodine/bscrypt-common.h +0 -116
- data/ext/iodine/bscrypt.h +0 -49
- data/ext/iodine/fio2resp.c +0 -60
- data/ext/iodine/fio2resp.h +0 -51
- data/ext/iodine/fio_dict.c +0 -446
- data/ext/iodine/fio_dict.h +0 -99
- data/ext/iodine/fio_hash_table.h +0 -370
- data/ext/iodine/fio_list.h +0 -111
- data/ext/iodine/fiobj_internal.h +0 -280
- data/ext/iodine/fiobj_primitives.c +0 -131
- data/ext/iodine/fiobj_primitives.h +0 -55
- data/ext/iodine/fiobj_sym.c +0 -135
- data/ext/iodine/fiobj_sym.h +0 -60
- data/ext/iodine/hex.c +0 -124
- data/ext/iodine/hex.h +0 -70
- data/ext/iodine/http1_request.c +0 -81
- data/ext/iodine/http1_request.h +0 -58
- data/ext/iodine/http1_response.c +0 -417
- data/ext/iodine/http1_response.h +0 -95
- data/ext/iodine/http_request.c +0 -111
- data/ext/iodine/http_request.h +0 -102
- data/ext/iodine/http_response.c +0 -1703
- data/ext/iodine/http_response.h +0 -250
- data/ext/iodine/misc.c +0 -182
- data/ext/iodine/misc.h +0 -74
- data/ext/iodine/random.c +0 -208
- data/ext/iodine/redis_connection.c +0 -278
- data/ext/iodine/redis_connection.h +0 -86
- data/ext/iodine/resp.c +0 -842
- data/ext/iodine/resp.h +0 -261
- data/ext/iodine/siphash.c +0 -154
- data/ext/iodine/siphash.h +0 -22
- data/ext/iodine/xor-crypt.c +0 -193
- data/ext/iodine/xor-crypt.h +0 -107
data/ext/iodine/rb-rack-io.c
CHANGED
@@ -51,198 +51,64 @@ close must never be called on the input stream.
|
|
51
51
|
Core data / helpers
|
52
52
|
*/
|
53
53
|
|
54
|
-
static VALUE
|
55
|
-
static VALUE rRackFileIO;
|
54
|
+
static VALUE rRackIO;
|
56
55
|
|
57
|
-
static ID pos_id;
|
58
|
-
static ID end_id;
|
59
56
|
static ID env_id;
|
60
57
|
static ID io_id;
|
61
58
|
|
62
59
|
static VALUE TCPSOCKET_CLASS;
|
63
60
|
static ID for_fd_id;
|
64
61
|
|
65
|
-
#define
|
66
|
-
rb_ivar_set((object), iodine_fd_var_id,
|
62
|
+
#define set_handle(object, handle) \
|
63
|
+
rb_ivar_set((object), iodine_fd_var_id, ULL2NUM((uintptr_t)handle))
|
67
64
|
|
68
|
-
inline static
|
65
|
+
inline static http_s *get_handle(VALUE obj) {
|
69
66
|
VALUE i = rb_ivar_get(obj, iodine_fd_var_id);
|
70
|
-
return (
|
71
|
-
}
|
72
|
-
|
73
|
-
#define set_pos(object, pos) rb_ivar_set((object), pos_id, ULONG2NUM(pos))
|
74
|
-
|
75
|
-
inline static size_t get_pos(VALUE obj) {
|
76
|
-
VALUE i = rb_ivar_get(obj, pos_id);
|
77
|
-
return (size_t)FIX2ULONG(i);
|
78
|
-
}
|
79
|
-
|
80
|
-
inline static size_t get_end(VALUE obj) {
|
81
|
-
VALUE i = rb_ivar_get(obj, end_id);
|
82
|
-
return (size_t)FIX2ULONG(i);
|
67
|
+
return (http_s *)FIX2ULONG(i);
|
83
68
|
}
|
84
69
|
|
85
70
|
/* *****************************************************************************
|
86
|
-
|
71
|
+
IO API
|
87
72
|
*/
|
88
73
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
return (char *)FIX2ULONG(i);
|
93
|
-
}
|
94
|
-
|
95
|
-
/**
|
96
|
-
Gets returns a line. this is okay for small lines,
|
97
|
-
but shouldn't really be used.
|
98
|
-
|
99
|
-
Limited to ~ 1Mb of a line length.
|
100
|
-
*/
|
101
|
-
static VALUE strio_gets(VALUE self) {
|
102
|
-
char *str = get_str(self);
|
103
|
-
size_t pos = get_pos(self);
|
104
|
-
size_t end = get_end(self);
|
105
|
-
if (str == NULL || pos == end)
|
106
|
-
return Qnil;
|
107
|
-
size_t pos_e = pos;
|
108
|
-
|
109
|
-
while ((pos_e < end) && str[pos_e] != '\n')
|
110
|
-
pos_e++;
|
111
|
-
set_pos(self, pos_e + 1);
|
112
|
-
return rb_enc_str_new(str + pos, pos_e - pos, IodineBinaryEncoding);
|
113
|
-
}
|
114
|
-
|
115
|
-
// Reads data from the IO, according to the Rack specifications for `#read`.
|
116
|
-
static VALUE strio_read(int argc, VALUE *argv, VALUE self) {
|
117
|
-
char *str = get_str(self);
|
118
|
-
size_t pos = get_pos(self);
|
119
|
-
size_t end = get_end(self);
|
120
|
-
VALUE buffer = Qnil;
|
121
|
-
char ret_nil = 0;
|
122
|
-
ssize_t len = 0;
|
123
|
-
// get the buffer object if given
|
124
|
-
if (argc == 2) {
|
125
|
-
Check_Type(argv[1], T_STRING);
|
126
|
-
buffer = argv[1];
|
127
|
-
}
|
128
|
-
// get the length object, if given
|
129
|
-
if (argc > 0 && argv[0] != Qnil) {
|
130
|
-
Check_Type(argv[0], T_FIXNUM);
|
131
|
-
len = FIX2LONG(argv[0]);
|
132
|
-
if (len < 0)
|
133
|
-
rb_raise(rb_eRangeError, "length should be bigger then 0.");
|
134
|
-
ret_nil = 1;
|
135
|
-
}
|
136
|
-
// return if we're at the EOF.
|
137
|
-
if (str == NULL)
|
138
|
-
goto no_data;
|
139
|
-
// calculate length if it wasn't specified.
|
140
|
-
if (len == 0) {
|
141
|
-
// make sure we're not reading more then we have (string buffer)
|
142
|
-
len = end - pos;
|
143
|
-
// set position for future reads
|
144
|
-
set_pos(self, end);
|
145
|
-
if (len == 0)
|
146
|
-
goto no_data;
|
147
|
-
} else {
|
148
|
-
// set position for future reads
|
149
|
-
set_pos(self, pos + len);
|
150
|
-
}
|
151
|
-
if (len + pos > end)
|
152
|
-
len = end - pos;
|
153
|
-
// create the buffer if we don't have one.
|
154
|
-
if (buffer == Qnil) {
|
155
|
-
buffer = rb_str_buf_new(len);
|
156
|
-
// make sure the buffer is binary encoded.
|
157
|
-
rb_enc_associate(buffer, IodineBinaryEncoding);
|
158
|
-
} else {
|
159
|
-
// make sure the buffer is binary encoded.
|
160
|
-
rb_enc_associate(buffer, IodineBinaryEncoding);
|
161
|
-
if (rb_str_capacity(buffer) < (size_t)len)
|
162
|
-
rb_str_resize(buffer, len);
|
163
|
-
}
|
164
|
-
// read the data.
|
165
|
-
memcpy(RSTRING_PTR(buffer), str + pos, len);
|
166
|
-
rb_str_set_len(buffer, len);
|
167
|
-
return buffer;
|
168
|
-
no_data:
|
169
|
-
if (ret_nil)
|
170
|
-
return Qnil;
|
171
|
-
else
|
172
|
-
return rb_str_buf_new(0);
|
173
|
-
}
|
174
|
-
|
175
|
-
// Does nothing - this is controlled by the server.
|
176
|
-
static VALUE strio_close(VALUE self) {
|
177
|
-
(void)self;
|
178
|
-
return Qnil;
|
74
|
+
static inline FIOBJ get_data(VALUE self) {
|
75
|
+
VALUE i = rb_ivar_get(self, io_id);
|
76
|
+
return (FIOBJ)FIX2ULONG(i);
|
179
77
|
}
|
180
78
|
|
181
|
-
// Rewinds the IO, so that it is read from the begining.
|
182
79
|
static VALUE rio_rewind(VALUE self) {
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
static VALUE strio_each(VALUE self) {
|
189
|
-
rb_need_block();
|
190
|
-
rio_rewind(self);
|
191
|
-
VALUE str = Qnil;
|
192
|
-
while ((str = strio_gets(self)) != Qnil) {
|
193
|
-
rb_yield(str);
|
194
|
-
}
|
195
|
-
return self;
|
196
|
-
}
|
197
|
-
|
198
|
-
/* *****************************************************************************
|
199
|
-
TempFileIO API
|
200
|
-
*/
|
201
|
-
|
202
|
-
// a macro helper to get the server pointer embeded in an object
|
203
|
-
inline static int get_tmpfile(VALUE obj) {
|
204
|
-
VALUE i = rb_ivar_get(obj, io_id);
|
205
|
-
return (int)FIX2INT(i);
|
80
|
+
FIOBJ io = get_data(self);
|
81
|
+
if (!FIOBJ_TYPE_IS(io, FIOBJ_T_DATA))
|
82
|
+
return Qnil;
|
83
|
+
fiobj_data_seek(io, 0);
|
84
|
+
return INT2NUM(0);
|
206
85
|
}
|
207
|
-
|
208
86
|
/**
|
209
87
|
Gets returns a line. this is okay for small lines,
|
210
88
|
but shouldn't really be used.
|
211
89
|
|
212
90
|
Limited to ~ 1Mb of a line length.
|
213
91
|
*/
|
214
|
-
static VALUE
|
215
|
-
|
216
|
-
|
217
|
-
size_t end = get_end(self);
|
218
|
-
if (pos == end)
|
92
|
+
static VALUE rio_gets(VALUE self) {
|
93
|
+
FIOBJ io = get_data(self);
|
94
|
+
if (!FIOBJ_TYPE_IS(io, FIOBJ_T_DATA))
|
219
95
|
return Qnil;
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
VALUE buffer;
|
224
|
-
|
225
|
-
do {
|
226
|
-
ret = pread(fd, &c, 1, pos_e);
|
227
|
-
} while (ret > 0 && c != '\n' && (++pos_e < end));
|
228
|
-
set_pos(self, pos_e + 1);
|
229
|
-
if (pos > pos_e) {
|
230
|
-
buffer = rb_str_buf_new(pos_e - pos);
|
96
|
+
fio_cstr_s line = fiobj_data_gets(io);
|
97
|
+
if (line.len) {
|
98
|
+
VALUE buffer = rb_str_new(line.data, line.len);
|
231
99
|
// make sure the buffer is binary encoded.
|
232
100
|
rb_enc_associate(buffer, IodineBinaryEncoding);
|
233
|
-
if (pread(fd, RSTRING_PTR(buffer), pos_e - pos, pos) < 0)
|
234
|
-
return Qnil;
|
235
|
-
rb_str_set_len(buffer, pos_e - pos);
|
236
101
|
return buffer;
|
237
102
|
}
|
238
103
|
return Qnil;
|
239
104
|
}
|
240
105
|
|
241
106
|
// Reads data from the IO, according to the Rack specifications for `#read`.
|
242
|
-
static VALUE
|
243
|
-
|
244
|
-
|
245
|
-
|
107
|
+
static VALUE rio_read(int argc, VALUE *argv, VALUE self) {
|
108
|
+
FIOBJ io = get_data(self);
|
109
|
+
if (!FIOBJ_TYPE_IS(io, FIOBJ_T_DATA))
|
110
|
+
return Qnil;
|
111
|
+
|
246
112
|
VALUE buffer = Qnil;
|
247
113
|
char ret_nil = 0;
|
248
114
|
ssize_t len = 0;
|
@@ -257,43 +123,27 @@ static VALUE tfio_read(int argc, VALUE *argv, VALUE self) {
|
|
257
123
|
len = FIX2LONG(argv[0]);
|
258
124
|
if (len < 0)
|
259
125
|
rb_raise(rb_eRangeError, "length should be bigger then 0.");
|
126
|
+
if (len == 0)
|
127
|
+
return rb_str_buf_new(0);
|
260
128
|
ret_nil = 1;
|
261
129
|
}
|
262
130
|
// return if we're at the EOF.
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
if (len + pos > end)
|
279
|
-
len = end - pos;
|
280
|
-
// create the buffer if we don't have one.
|
281
|
-
if (buffer == Qnil) {
|
282
|
-
buffer = rb_str_buf_new(len);
|
283
|
-
// make sure the buffer is binary encoded.
|
284
|
-
rb_enc_associate(buffer, IodineBinaryEncoding);
|
285
|
-
} else {
|
286
|
-
// make sure the buffer is binary encoded.
|
287
|
-
rb_enc_associate(buffer, IodineBinaryEncoding);
|
288
|
-
if (rb_str_capacity(buffer) < (size_t)len)
|
289
|
-
rb_str_resize(buffer, len);
|
131
|
+
fio_cstr_s buf = fiobj_data_read(io, len);
|
132
|
+
if (buf.len) {
|
133
|
+
// create the buffer if we don't have one.
|
134
|
+
if (buffer == Qnil) {
|
135
|
+
// make sure the buffer is binary encoded.
|
136
|
+
buffer = rb_enc_str_new(buf.data, buf.len, IodineBinaryEncoding);
|
137
|
+
} else {
|
138
|
+
// make sure the buffer is binary encoded.
|
139
|
+
rb_enc_associate(buffer, IodineBinaryEncoding);
|
140
|
+
if (rb_str_capacity(buffer) < (size_t)buf.len)
|
141
|
+
rb_str_resize(buffer, buf.len);
|
142
|
+
memcpy(RSTRING_PTR(buffer), buf.data, buf.len);
|
143
|
+
rb_str_set_len(buffer, buf.len);
|
144
|
+
}
|
145
|
+
return buffer;
|
290
146
|
}
|
291
|
-
// read the data.
|
292
|
-
if (pread(fd, RSTRING_PTR(buffer), len, pos) <= 0)
|
293
|
-
goto no_data;
|
294
|
-
rb_str_set_len(buffer, len);
|
295
|
-
return buffer;
|
296
|
-
no_data:
|
297
147
|
if (ret_nil)
|
298
148
|
return Qnil;
|
299
149
|
else
|
@@ -301,17 +151,20 @@ no_data:
|
|
301
151
|
}
|
302
152
|
|
303
153
|
// Does nothing - this is controlled by the server.
|
304
|
-
static VALUE
|
154
|
+
static VALUE rio_close(VALUE self) {
|
155
|
+
FIOBJ io = get_data(self);
|
156
|
+
fiobj_free(io);
|
157
|
+
rb_ivar_set(self, io_id, INT2NUM(0));
|
305
158
|
(void)self;
|
306
159
|
return Qnil;
|
307
160
|
}
|
308
161
|
|
309
162
|
// Passes each line of the input to the block. This should be avoided.
|
310
|
-
static VALUE
|
163
|
+
static VALUE rio_each(VALUE self) {
|
311
164
|
rb_need_block();
|
312
165
|
rio_rewind(self);
|
313
166
|
VALUE str = Qnil;
|
314
|
-
while ((str =
|
167
|
+
while ((str = rio_gets(self)) != Qnil) {
|
315
168
|
rb_yield(str);
|
316
169
|
}
|
317
170
|
return self;
|
@@ -329,17 +182,21 @@ extern VALUE IODINE_R_HIJACK_IO; // for Rack: rack.hijack_io
|
|
329
182
|
static VALUE rio_get_io(int argc, VALUE *argv, VALUE self) {
|
330
183
|
if (TCPSOCKET_CLASS == Qnil)
|
331
184
|
return Qfalse;
|
332
|
-
intptr_t fduuid = get_uuid(self);
|
333
|
-
// hijack the IO object
|
334
|
-
VALUE fd = INT2FIX(sock_uuid2fd(fduuid));
|
335
185
|
VALUE env = rb_ivar_get(self, env_id);
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
186
|
+
http_s *h = get_handle(self);
|
187
|
+
if (h == NULL) {
|
188
|
+
/* we're repeating ourselves, aren't we? */
|
189
|
+
VALUE io = rb_hash_aref(env, IODINE_R_HIJACK_IO);
|
190
|
+
return io;
|
191
|
+
}
|
192
|
+
// mark update
|
193
|
+
set_handle(self, NULL);
|
194
|
+
// hijack the IO object
|
195
|
+
intptr_t uuid = http_hijack(h, NULL);
|
196
|
+
VALUE fd = INT2FIX(sock_uuid2fd(uuid));
|
340
197
|
// VALUE new_io = how the fuck do we create a new IO from the fd?
|
341
|
-
new_io = RubyCaller.call2(TCPSOCKET_CLASS, for_fd_id, 1,
|
342
|
-
|
198
|
+
VALUE new_io = RubyCaller.call2(TCPSOCKET_CLASS, for_fd_id, 1,
|
199
|
+
&fd); // TCPSocket.for_fd(fd) ... cool...
|
343
200
|
rb_hash_aset(env, IODINE_R_HIJACK_IO, new_io);
|
344
201
|
if (argc)
|
345
202
|
rb_hash_aset(env, IODINE_R_HIJACK_CB, *argv);
|
@@ -351,53 +208,31 @@ C land API
|
|
351
208
|
*/
|
352
209
|
|
353
210
|
// new object
|
354
|
-
static VALUE new_rack_io(
|
355
|
-
VALUE rack_io;
|
356
|
-
|
357
|
-
|
358
|
-
rb_ivar_set(rack_io, io_id, ULONG2NUM(request->body_file));
|
359
|
-
lseek(request->body_file, 0, SEEK_SET);
|
360
|
-
} else {
|
361
|
-
rack_io = rb_funcall2(rRackStrIO, iodine_new_func_id, 0, NULL);
|
362
|
-
rb_ivar_set(rack_io, io_id, ULONG2NUM(((intptr_t)request->body_str)));
|
363
|
-
// fprintf(stderr, "rack body IO (%lu, %p):%.*s\n", request->content_length,
|
364
|
-
// request->body_str, (int)request->content_length,
|
365
|
-
// request->body_str);
|
366
|
-
}
|
367
|
-
set_uuid(rack_io, request);
|
368
|
-
set_pos(rack_io, 0);
|
369
|
-
rb_ivar_set(rack_io, end_id, ULONG2NUM(request->content_length));
|
211
|
+
static VALUE new_rack_io(http_s *h, VALUE env) {
|
212
|
+
VALUE rack_io = rb_funcall2(rRackIO, iodine_new_func_id, 0, NULL);
|
213
|
+
rb_ivar_set(rack_io, io_id, ULL2NUM(h->body));
|
214
|
+
set_handle(rack_io, h);
|
370
215
|
rb_ivar_set(rack_io, env_id, env);
|
371
|
-
|
372
216
|
return rack_io;
|
373
217
|
}
|
374
218
|
|
375
219
|
// initialize library
|
376
220
|
static void init_rack_io(void) {
|
377
|
-
|
378
|
-
rRackFileIO = rb_define_class_under(IodineBase, "RackTmpFileIO", rb_cObject);
|
221
|
+
rRackIO = rb_define_class_under(IodineBase, "RackIO", rb_cObject);
|
379
222
|
|
380
|
-
pos_id = rb_intern("pos");
|
381
|
-
end_id = rb_intern("io_end");
|
382
223
|
io_id = rb_intern("rack_io");
|
383
224
|
env_id = rb_intern("env");
|
384
225
|
for_fd_id = rb_intern("for_fd");
|
385
226
|
|
386
227
|
TCPSOCKET_CLASS = rb_const_get(rb_cObject, rb_intern("TCPSocket"));
|
387
228
|
// IO methods
|
388
|
-
|
389
|
-
rb_define_method(
|
390
|
-
rb_define_method(
|
391
|
-
rb_define_method(
|
392
|
-
rb_define_method(
|
393
|
-
rb_define_method(
|
394
|
-
|
395
|
-
rb_define_method(rRackFileIO, "rewind", rio_rewind, 0);
|
396
|
-
rb_define_method(rRackFileIO, "gets", tfio_gets, 0);
|
397
|
-
rb_define_method(rRackFileIO, "read", tfio_read, -1);
|
398
|
-
rb_define_method(rRackFileIO, "close", tfio_close, 0);
|
399
|
-
rb_define_method(rRackFileIO, "each", tfio_each, 0);
|
400
|
-
rb_define_method(rRackFileIO, "_hijack", rio_get_io, -1);
|
229
|
+
|
230
|
+
rb_define_method(rRackIO, "rewind", rio_rewind, 0);
|
231
|
+
rb_define_method(rRackIO, "gets", rio_gets, 0);
|
232
|
+
rb_define_method(rRackIO, "read", rio_read, -1);
|
233
|
+
rb_define_method(rRackIO, "close", rio_close, 0);
|
234
|
+
rb_define_method(rRackIO, "each", rio_each, 0);
|
235
|
+
rb_define_method(rRackIO, "_hijack", rio_get_io, -1);
|
401
236
|
}
|
402
237
|
|
403
238
|
////////////////////////////////////////////////////////////////////////////
|
data/ext/iodine/rb-rack-io.h
CHANGED
@@ -9,10 +9,10 @@ Feel free to copy, use and enjoy according to the license provided.
|
|
9
9
|
|
10
10
|
#include <ruby.h>
|
11
11
|
|
12
|
-
#include "
|
12
|
+
#include "http.h"
|
13
13
|
|
14
14
|
extern struct IodineRackIO {
|
15
|
-
VALUE (*create)(
|
15
|
+
VALUE (*create)(http_s *h, VALUE env);
|
16
16
|
void (*init)(void);
|
17
17
|
} IodineRackIO;
|
18
18
|
|
data/ext/iodine/rb-registry.c
CHANGED
@@ -9,81 +9,38 @@ Feel free to copy, use and enjoy according to the license provided.
|
|
9
9
|
|
10
10
|
#include "spnlock.inc"
|
11
11
|
|
12
|
-
#
|
13
|
-
#include
|
12
|
+
#define FIO_OVERRIDE_MALLOC 1
|
13
|
+
#include "fio_mem.h"
|
14
14
|
|
15
|
-
|
16
|
-
#
|
17
|
-
#define REGISTRY_POOL_SIZE 1024
|
18
|
-
#endif
|
15
|
+
#include "fio_hashmap.h"
|
16
|
+
#include <signal.h>
|
19
17
|
|
20
18
|
#ifndef RUBY_REG_DBG
|
21
19
|
#define RUBY_REG_DBG 0
|
22
20
|
#endif
|
23
21
|
|
24
|
-
typedef struct {
|
25
|
-
union {
|
26
|
-
fio_list_s pool;
|
27
|
-
fio_ht_node_s node;
|
28
|
-
};
|
29
|
-
VALUE obj;
|
30
|
-
volatile uint64_t ref;
|
31
|
-
} obj_s;
|
32
|
-
|
33
22
|
// the registry state keeper
|
34
23
|
static struct {
|
35
|
-
|
36
|
-
fio_list_s pool;
|
37
|
-
fio_ht_s store;
|
24
|
+
fio_hash_s store;
|
38
25
|
VALUE owner;
|
39
26
|
spn_lock_i lock;
|
40
|
-
} registry = {.
|
41
|
-
.store = FIO_HASH_TABLE_STATIC(registry.store),
|
42
|
-
.owner = 0,
|
43
|
-
.lock = SPN_LOCK_INIT};
|
27
|
+
} registry = {.store = {.capa = 0}, .owner = 0, .lock = SPN_LOCK_INIT};
|
44
28
|
|
45
29
|
#define try_lock_registry() spn_trylock(®istry.lock)
|
46
30
|
#define unlock_registry() spn_unlock(®istry.lock)
|
47
31
|
#define lock_registry() spn_lock(®istry.lock)
|
48
32
|
|
49
|
-
inline static void free_node(obj_s *to_free) {
|
50
|
-
if (to_free >= registry.pool_mem &&
|
51
|
-
(intptr_t)to_free <= (intptr_t)(®istry.pool))
|
52
|
-
fio_list_push(obj_s, pool, registry.pool, to_free);
|
53
|
-
else
|
54
|
-
free(to_free);
|
55
|
-
}
|
56
|
-
|
57
33
|
/** adds an object to the registry or increases it's reference count. */
|
58
34
|
static VALUE register_object(VALUE ruby_obj) {
|
59
35
|
if (!ruby_obj || ruby_obj == Qnil || ruby_obj == Qfalse)
|
60
36
|
return 0;
|
61
37
|
lock_registry();
|
62
|
-
|
63
|
-
if (obj) {
|
64
|
-
obj = fio_node2obj(obj_s, node, obj);
|
38
|
+
uintptr_t count = (uintptr_t)fio_hash_find(®istry.store, ruby_obj);
|
65
39
|
#if RUBY_REG_DBG == 1
|
66
|
-
|
67
|
-
|
40
|
+
fprintf(stderr, "Ruby Registry: register %p ref: %" PRIu64 " + 1\n",
|
41
|
+
(void *)ruby_obj, (uint64_t)count);
|
68
42
|
#endif
|
69
|
-
|
70
|
-
}
|
71
|
-
#if RUBY_REG_DBG == 1
|
72
|
-
fprintf(stderr, "Ruby Registry: register %p\n", (void *)ruby_obj);
|
73
|
-
#endif
|
74
|
-
obj = fio_list_pop(obj_s, pool, registry.pool);
|
75
|
-
if (!obj)
|
76
|
-
obj = malloc(sizeof(obj_s));
|
77
|
-
if (!obj) {
|
78
|
-
perror("No Memory!");
|
79
|
-
kill(0, SIGINT);
|
80
|
-
exit(1);
|
81
|
-
}
|
82
|
-
*obj = (obj_s){.obj = ruby_obj};
|
83
|
-
fio_ht_add(®istry.store, &obj->node, (uint64_t)ruby_obj);
|
84
|
-
exists:
|
85
|
-
spn_add(&obj->ref, 1);
|
86
|
-
|
43
|
+
fio_hash_insert(®istry.store, (uint64_t)ruby_obj, (void *)(count + 1));
|
87
44
|
unlock_registry();
|
88
45
|
return ruby_obj;
|
89
46
|
}
|
@@ -93,30 +50,15 @@ static void unregister_object(VALUE ruby_obj) {
|
|
93
50
|
if (!ruby_obj || ruby_obj == Qnil)
|
94
51
|
return;
|
95
52
|
lock_registry();
|
96
|
-
|
97
|
-
if (!obj) {
|
53
|
+
uintptr_t count = (uintptr_t)fio_hash_find(®istry.store, ruby_obj);
|
98
54
|
#if RUBY_REG_DBG == 1
|
99
|
-
|
100
|
-
|
55
|
+
fprintf(stderr, "Ruby Registry: unregister %p ref: %" PRIu64 " - 1\n",
|
56
|
+
(void *)ruby_obj, (uint64_t)count);
|
101
57
|
#endif
|
102
|
-
|
58
|
+
if (count) {
|
59
|
+
fio_hash_insert(®istry.store, (uint64_t)ruby_obj, (void *)(count - 1));
|
103
60
|
}
|
104
|
-
obj = fio_node2obj(obj_s, node, obj);
|
105
|
-
if (spn_sub(&obj->ref, 1)) {
|
106
|
-
unlock_registry();
|
107
|
-
#if RUBY_REG_DBG == 1
|
108
|
-
fprintf(stderr, "Ruby Registry: unregistered %p ref: %" PRIu64 " \n",
|
109
|
-
(void *)ruby_obj, obj->ref);
|
110
|
-
#endif
|
111
|
-
return;
|
112
|
-
}
|
113
|
-
fio_ht_remove(&obj->node);
|
114
|
-
free_node(obj);
|
115
|
-
finish:
|
116
61
|
unlock_registry();
|
117
|
-
#if RUBY_REG_DBG == 1
|
118
|
-
fprintf(stderr, "Ruby Registry: unregistered %p\n", (void *)ruby_obj);
|
119
|
-
#endif
|
120
62
|
}
|
121
63
|
|
122
64
|
/* a callback for the GC (marking active objects) */
|
@@ -126,8 +68,12 @@ static void registry_mark(void *ignore) {
|
|
126
68
|
Registry.print();
|
127
69
|
#endif
|
128
70
|
lock_registry();
|
129
|
-
|
130
|
-
|
71
|
+
fio_hash_compact(®istry.store);
|
72
|
+
FIO_HASH_FOR_LOOP(®istry.store, pos) {
|
73
|
+
if (pos->obj) {
|
74
|
+
rb_gc_mark((VALUE)pos->key);
|
75
|
+
}
|
76
|
+
}
|
131
77
|
unlock_registry();
|
132
78
|
}
|
133
79
|
|
@@ -138,13 +84,9 @@ static void registry_clear(void *ignore) {
|
|
138
84
|
fprintf(stderr, "Ruby Registry: Clear!!!\n");
|
139
85
|
#endif
|
140
86
|
lock_registry();
|
141
|
-
|
142
|
-
fio_ht_for_each(obj_s, node, obj, registry.store) {
|
143
|
-
fio_ht_remove(&obj->node);
|
144
|
-
rb_gc_mark(obj->obj);
|
145
|
-
}
|
87
|
+
fio_hash_free(®istry.store);
|
146
88
|
registry.owner = 0;
|
147
|
-
|
89
|
+
registry.store = (fio_hash_s){.capa = 0};
|
148
90
|
unlock_registry();
|
149
91
|
}
|
150
92
|
|
@@ -172,29 +114,28 @@ static void init(VALUE owner) {
|
|
172
114
|
VALUE r_registry =
|
173
115
|
TypedData_Wrap_Struct(rReferences, &my_registry_type_struct, ®istry);
|
174
116
|
rb_ivar_set(owner, rb_intern("registry"), r_registry);
|
175
|
-
// initialize memory pool
|
176
|
-
for (size_t i = 0; i < REGISTRY_POOL_SIZE; i++) {
|
177
|
-
fio_list_push(obj_s, pool, registry.pool, ®istry.pool_mem[i]);
|
178
|
-
}
|
179
117
|
finish:
|
180
118
|
unlock_registry();
|
181
119
|
}
|
182
120
|
|
121
|
+
static void registry_on_fork(void) { unlock_registry(); }
|
122
|
+
|
183
123
|
/* print data, for testing */
|
184
124
|
static void print(void) {
|
185
125
|
lock_registry();
|
186
126
|
fprintf(stderr, "Registry owner is %lu\n", registry.owner);
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
127
|
+
uintptr_t index = 0;
|
128
|
+
FIO_HASH_FOR_LOOP(®istry.store, pos) {
|
129
|
+
if (pos->obj) {
|
130
|
+
fprintf(stderr, "[%" PRIuPTR " ] => %" PRIuPTR " X obj %p type %d\n",
|
131
|
+
index++, (uintptr_t)pos->obj, (void *)pos->key, TYPE(pos->key));
|
132
|
+
}
|
192
133
|
}
|
193
|
-
fprintf(stderr, "Total of %"
|
134
|
+
fprintf(stderr, "Total of %" PRIuPTR " registered objects being marked\n",
|
194
135
|
index);
|
195
136
|
fprintf(stderr,
|
196
|
-
"Registry uses %"
|
197
|
-
registry.store.
|
137
|
+
"Registry uses %" PRIuPTR " Hash bins for %" PRIuPTR " objects\n",
|
138
|
+
registry.store.capa, registry.store.count);
|
198
139
|
unlock_registry();
|
199
140
|
}
|
200
141
|
|
@@ -205,4 +146,5 @@ struct ___RegistryClass___ Registry = {
|
|
205
146
|
.remove = unregister_object,
|
206
147
|
.add = register_object,
|
207
148
|
.print = print,
|
149
|
+
.on_fork = registry_on_fork,
|
208
150
|
};
|