iodine 0.7.59 → 0.8.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/.clang-format +15 -0
- data/.rspec +1 -0
- data/.yardopts +1 -3
- data/CHANGELOG.md +132 -12
- data/Gemfile +5 -7
- data/LICENSE.txt +1 -1
- data/README.md +147 -671
- data/Rakefile +9 -16
- data/examples/chatroom.nru +9 -0
- data/examples/client +74 -0
- data/examples/config-hello.nru +9 -0
- data/examples/config-hello.ru +11 -0
- data/examples/config-hijack.ru +13 -0
- data/examples/config-shootout.ru +43 -0
- data/examples/config.nru +120 -0
- data/examples/config.rb +37 -0
- data/examples/config.ru +42 -53
- data/examples/fake +24 -0
- data/examples/hello_neorack +137 -0
- data/examples/routes.nru +29 -0
- data/examples/routes.ru +42 -0
- data/exe/iodine +218 -258
- data/ext/iodine/extconf.rb +27 -100
- data/ext/iodine/fio-stl.h +128336 -0
- data/ext/iodine/fio-stl.md +26396 -0
- data/ext/iodine/iodine.c +213 -1393
- data/ext/iodine/iodine.h +250 -55
- data/ext/iodine/iodine_arg_helper.h +329 -0
- data/ext/iodine/iodine_caller.h +234 -25
- data/ext/iodine/iodine_cli.h +434 -0
- data/ext/iodine/iodine_compression.h +312 -0
- data/ext/iodine/iodine_connection.h +3484 -34
- data/ext/iodine/iodine_core.h +363 -0
- data/ext/iodine/iodine_crypto.h +1441 -0
- data/ext/iodine/iodine_defer.h +225 -4
- data/ext/iodine/iodine_json.h +738 -4
- data/ext/iodine/iodine_listener.h +263 -0
- data/ext/iodine/iodine_log.h +297 -0
- data/ext/iodine/iodine_minimap.h +543 -0
- data/ext/iodine/iodine_mustache.h +461 -4
- data/ext/iodine/iodine_pubsub_eng.h +729 -0
- data/ext/iodine/iodine_pubsub_history.h +547 -0
- data/ext/iodine/iodine_pubsub_msg.h +228 -0
- data/ext/iodine/iodine_redis.h +322 -0
- data/ext/iodine/iodine_store.h +418 -16
- data/ext/iodine/iodine_threads.h +279 -0
- data/ext/iodine/iodine_tls.h +515 -6
- data/ext/iodine/iodine_utils.h +923 -0
- data/iodine.gemspec +37 -42
- data/lib/iodine/benchmark.rb +1690 -0
- data/lib/iodine/documentation.rb +3085 -0
- data/lib/iodine/version.rb +17 -1
- data/lib/iodine.rb +54 -255
- data/logo.svg +36 -0
- data/mustache.md +55 -0
- data/sig/iodine.rbs +4 -0
- metadata +58 -184
- data/.github/ISSUE_TEMPLATE/bug_report.md +0 -40
- data/.github/workflows/ruby.yml +0 -42
- data/.gitignore +0 -20
- data/LIMITS.md +0 -41
- data/SPEC-PubSub-Draft.md +0 -159
- data/SPEC-WebSocket-Draft.md +0 -239
- data/bin/console +0 -22
- data/bin/info.md +0 -353
- data/bin/mustache_bench.rb +0 -100
- data/bin/poc/Gemfile.lock +0 -23
- data/bin/poc/README.md +0 -37
- data/bin/poc/config.ru +0 -66
- data/bin/poc/gemfile +0 -1
- data/bin/poc/www/index.html +0 -57
- data/examples/async_task.ru +0 -92
- data/examples/bates/README.md +0 -3
- data/examples/bates/config.ru +0 -342
- data/examples/bates/david+bold.pdf +0 -0
- data/examples/bates/public/drop-pdf.png +0 -0
- data/examples/bates/public/index.html +0 -600
- data/examples/echo.ru +0 -59
- data/examples/etag.ru +0 -16
- data/examples/hello.ru +0 -29
- data/examples/pubsub_engine.ru +0 -81
- data/examples/rack3.ru +0 -12
- data/examples/redis.ru +0 -70
- data/examples/shootout.ru +0 -73
- data/examples/sub-protocols.ru +0 -90
- data/examples/tcp_client.rb +0 -66
- data/examples/x-sendfile.ru +0 -14
- data/ext/iodine/fio.c +0 -11995
- data/ext/iodine/fio.h +0 -6371
- data/ext/iodine/fio_cli.c +0 -431
- data/ext/iodine/fio_cli.h +0 -189
- data/ext/iodine/fio_json_parser.h +0 -688
- data/ext/iodine/fio_siphash.c +0 -157
- data/ext/iodine/fio_siphash.h +0 -37
- data/ext/iodine/fio_tls.h +0 -129
- data/ext/iodine/fio_tls_missing.c +0 -649
- data/ext/iodine/fio_tls_openssl.c +0 -1106
- data/ext/iodine/fio_tmpfile.h +0 -50
- data/ext/iodine/fiobj.h +0 -44
- data/ext/iodine/fiobj4fio.h +0 -21
- data/ext/iodine/fiobj_ary.c +0 -333
- data/ext/iodine/fiobj_ary.h +0 -139
- data/ext/iodine/fiobj_data.c +0 -1187
- data/ext/iodine/fiobj_data.h +0 -167
- data/ext/iodine/fiobj_hash.c +0 -409
- data/ext/iodine/fiobj_hash.h +0 -176
- data/ext/iodine/fiobj_json.c +0 -622
- data/ext/iodine/fiobj_json.h +0 -68
- data/ext/iodine/fiobj_mem.h +0 -71
- data/ext/iodine/fiobj_mustache.c +0 -317
- data/ext/iodine/fiobj_mustache.h +0 -62
- data/ext/iodine/fiobj_numbers.c +0 -344
- data/ext/iodine/fiobj_numbers.h +0 -127
- data/ext/iodine/fiobj_str.c +0 -433
- data/ext/iodine/fiobj_str.h +0 -172
- data/ext/iodine/fiobject.c +0 -620
- data/ext/iodine/fiobject.h +0 -655
- data/ext/iodine/hpack.h +0 -1923
- data/ext/iodine/http.c +0 -2743
- data/ext/iodine/http.h +0 -1002
- data/ext/iodine/http1.c +0 -910
- data/ext/iodine/http1.h +0 -29
- data/ext/iodine/http1_parser.h +0 -878
- data/ext/iodine/http_internal.c +0 -1279
- data/ext/iodine/http_internal.h +0 -237
- data/ext/iodine/http_mime_parser.h +0 -350
- data/ext/iodine/iodine_caller.c +0 -230
- data/ext/iodine/iodine_connection.c +0 -941
- data/ext/iodine/iodine_defer.c +0 -420
- data/ext/iodine/iodine_fiobj2rb.h +0 -120
- data/ext/iodine/iodine_helpers.c +0 -282
- data/ext/iodine/iodine_helpers.h +0 -12
- data/ext/iodine/iodine_http.c +0 -1181
- data/ext/iodine/iodine_http.h +0 -23
- data/ext/iodine/iodine_json.c +0 -302
- data/ext/iodine/iodine_mustache.c +0 -567
- data/ext/iodine/iodine_pubsub.c +0 -580
- data/ext/iodine/iodine_pubsub.h +0 -26
- data/ext/iodine/iodine_rack_io.c +0 -273
- data/ext/iodine/iodine_rack_io.h +0 -20
- data/ext/iodine/iodine_store.c +0 -146
- data/ext/iodine/iodine_tcp.c +0 -346
- data/ext/iodine/iodine_tcp.h +0 -13
- data/ext/iodine/iodine_tls.c +0 -261
- data/ext/iodine/mustache_parser.h +0 -1546
- data/ext/iodine/redis_engine.c +0 -957
- data/ext/iodine/redis_engine.h +0 -79
- data/ext/iodine/resp_parser.h +0 -317
- data/ext/iodine/websocket_parser.h +0 -506
- data/ext/iodine/websockets.c +0 -743
- data/ext/iodine/websockets.h +0 -185
- data/lib/iodine/connection.rb +0 -61
- data/lib/iodine/json.rb +0 -42
- data/lib/iodine/mustache.rb +0 -113
- data/lib/iodine/pubsub.rb +0 -55
- data/lib/iodine/rack_utils.rb +0 -43
- data/lib/iodine/tls.rb +0 -16
- data/lib/rack/handler/iodine.rb +0 -33
- data/logo.png +0 -0
data/ext/iodine/iodine_rack_io.c
DELETED
|
@@ -1,273 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright: Boaz segev, 2016-2017
|
|
3
|
-
License: MIT
|
|
4
|
-
|
|
5
|
-
Feel free to copy, use and enjoy according to the license provided.
|
|
6
|
-
*/
|
|
7
|
-
#include "iodine_rack_io.h"
|
|
8
|
-
|
|
9
|
-
#include "iodine.h"
|
|
10
|
-
|
|
11
|
-
#include <ruby/encoding.h>
|
|
12
|
-
#include <ruby/io.h>
|
|
13
|
-
#include <unistd.h>
|
|
14
|
-
|
|
15
|
-
#ifndef _GNU_SOURCE
|
|
16
|
-
#define _GNU_SOURCE
|
|
17
|
-
#endif
|
|
18
|
-
|
|
19
|
-
/* IodineRackIO manages a minimal interface to act as an IO wrapper according to
|
|
20
|
-
these Rack specifications:
|
|
21
|
-
|
|
22
|
-
The input stream is an IO-like object which contains the raw HTTP POST data.
|
|
23
|
-
When applicable, its external encoding must be “ASCII-8BIT” and it must be
|
|
24
|
-
opened in binary mode, for Ruby 1.9 compatibility. The input stream must respond
|
|
25
|
-
to gets, each, read and rewind.
|
|
26
|
-
|
|
27
|
-
gets must be called without arguments and return a string, or nil on EOF.
|
|
28
|
-
|
|
29
|
-
read behaves like IO#read. Its signature is read([length, [buffer]]). If given,
|
|
30
|
-
length must be a non-negative Integer (>= 0) or nil, and buffer must be a String
|
|
31
|
-
and may not be nil. If length is given and not nil, then this method reads at
|
|
32
|
-
most length bytes from the input stream. If length is not given or nil, then
|
|
33
|
-
this method reads all data until EOF. When EOF is reached, this method returns
|
|
34
|
-
nil if length is given and not nil, or “” if length is not given or is nil. If
|
|
35
|
-
buffer is given, then the read data will be placed into buffer instead of a
|
|
36
|
-
newly created String object.
|
|
37
|
-
|
|
38
|
-
each must be called without arguments and only yield Strings.
|
|
39
|
-
|
|
40
|
-
rewind must be called without arguments. It rewinds the input stream back to the
|
|
41
|
-
beginning. It must not raise Errno::ESPIPE: that is, it may not be a pipe or a
|
|
42
|
-
socket. Therefore, handler developers must buffer the input data into some
|
|
43
|
-
rewindable object if the underlying input stream is not rewindable.
|
|
44
|
-
|
|
45
|
-
close must never be called on the input stream.
|
|
46
|
-
|
|
47
|
-
*/
|
|
48
|
-
|
|
49
|
-
/* *****************************************************************************
|
|
50
|
-
Core data / helpers
|
|
51
|
-
*/
|
|
52
|
-
|
|
53
|
-
static VALUE rRackIO;
|
|
54
|
-
|
|
55
|
-
static ID env_id;
|
|
56
|
-
static ID io_id;
|
|
57
|
-
|
|
58
|
-
static VALUE R_INPUT; /* rack.input */
|
|
59
|
-
static VALUE hijack_func_sym;
|
|
60
|
-
static VALUE TCPSOCKET_CLASS;
|
|
61
|
-
static ID for_fd_id;
|
|
62
|
-
static ID iodine_fd_var_id;
|
|
63
|
-
static ID iodine_new_func_id;
|
|
64
|
-
#ifdef __MINGW32__
|
|
65
|
-
static ID iodine_osffd_id;
|
|
66
|
-
#endif
|
|
67
|
-
static rb_encoding *IodineUTF8Encoding;
|
|
68
|
-
static rb_encoding *IodineBinaryEncoding;
|
|
69
|
-
|
|
70
|
-
#define set_handle(object, handle) \
|
|
71
|
-
rb_ivar_set((object), iodine_fd_var_id, ULL2NUM((uintptr_t)handle))
|
|
72
|
-
|
|
73
|
-
inline static http_s *get_handle(VALUE obj) {
|
|
74
|
-
VALUE i = rb_ivar_get(obj, iodine_fd_var_id);
|
|
75
|
-
return (http_s *)NUM2ULL(i);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/* *****************************************************************************
|
|
79
|
-
IO API
|
|
80
|
-
*/
|
|
81
|
-
|
|
82
|
-
static inline FIOBJ get_data(VALUE self) {
|
|
83
|
-
VALUE i = rb_ivar_get(self, io_id);
|
|
84
|
-
return (FIOBJ)NUM2ULL(i);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
static VALUE rio_rewind(VALUE self) {
|
|
88
|
-
FIOBJ io = get_data(self);
|
|
89
|
-
if (!FIOBJ_TYPE_IS(io, FIOBJ_T_DATA))
|
|
90
|
-
return Qnil;
|
|
91
|
-
fiobj_data_seek(io, 0);
|
|
92
|
-
return INT2NUM(0);
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
Gets returns a line. this is okay for small lines,
|
|
96
|
-
but shouldn't really be used.
|
|
97
|
-
|
|
98
|
-
Limited to ~ 1Mb of a line length.
|
|
99
|
-
*/
|
|
100
|
-
static VALUE rio_gets(VALUE self) {
|
|
101
|
-
FIOBJ io = get_data(self);
|
|
102
|
-
if (!FIOBJ_TYPE_IS(io, FIOBJ_T_DATA))
|
|
103
|
-
return Qnil;
|
|
104
|
-
fio_str_info_s line = fiobj_data_gets(io);
|
|
105
|
-
if (line.len) {
|
|
106
|
-
VALUE buffer = rb_str_new(line.data, line.len);
|
|
107
|
-
// make sure the buffer is binary encoded.
|
|
108
|
-
rb_enc_associate(buffer, IodineBinaryEncoding);
|
|
109
|
-
return buffer;
|
|
110
|
-
}
|
|
111
|
-
return Qnil;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Reads data from the IO, according to the Rack specifications for `#read`.
|
|
115
|
-
static VALUE rio_read(int argc, VALUE *argv, VALUE self) {
|
|
116
|
-
FIOBJ io = get_data(self);
|
|
117
|
-
VALUE buffer = Qnil;
|
|
118
|
-
uint8_t ret_nil = 0;
|
|
119
|
-
ssize_t len = 0;
|
|
120
|
-
if (!FIOBJ_TYPE_IS(io, FIOBJ_T_DATA)) {
|
|
121
|
-
return (argc > 0 && argv[0] != Qnil) ? Qnil : rb_str_buf_new(0);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// get the buffer object if given
|
|
125
|
-
if (argc == 2) {
|
|
126
|
-
Check_Type(argv[1], T_STRING);
|
|
127
|
-
buffer = argv[1];
|
|
128
|
-
}
|
|
129
|
-
// get the length object, if given
|
|
130
|
-
if (argc > 0 && argv[0] != Qnil) {
|
|
131
|
-
Check_Type(argv[0], T_FIXNUM);
|
|
132
|
-
len = FIX2LONG(argv[0]);
|
|
133
|
-
if (len < 0)
|
|
134
|
-
rb_raise(rb_eRangeError, "length should be bigger then 0.");
|
|
135
|
-
if (len == 0)
|
|
136
|
-
return rb_str_buf_new(0);
|
|
137
|
-
ret_nil = 1;
|
|
138
|
-
}
|
|
139
|
-
// return if we're at the EOF.
|
|
140
|
-
fio_str_info_s buf = fiobj_data_read(io, len);
|
|
141
|
-
if (buf.len) {
|
|
142
|
-
// create the buffer if we don't have one.
|
|
143
|
-
if (buffer == Qnil) {
|
|
144
|
-
// make sure the buffer is binary encoded.
|
|
145
|
-
buffer = rb_enc_str_new(buf.data, buf.len, IodineBinaryEncoding);
|
|
146
|
-
} else {
|
|
147
|
-
// make sure the buffer is binary encoded.
|
|
148
|
-
rb_enc_associate(buffer, IodineBinaryEncoding);
|
|
149
|
-
if (rb_str_capacity(buffer) < (size_t)buf.len)
|
|
150
|
-
rb_str_resize(buffer, buf.len);
|
|
151
|
-
memcpy(RSTRING_PTR(buffer), buf.data, buf.len);
|
|
152
|
-
rb_str_set_len(buffer, buf.len);
|
|
153
|
-
}
|
|
154
|
-
return buffer;
|
|
155
|
-
}
|
|
156
|
-
return ret_nil ? Qnil : rb_str_buf_new(0);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// Does nothing - this is controlled by the server.
|
|
160
|
-
static VALUE rio_close(VALUE self) {
|
|
161
|
-
// FIOBJ io = get_data(self);
|
|
162
|
-
// fiobj_free(io); // we don't call fiobj_dup, do we?
|
|
163
|
-
rb_ivar_set(self, io_id, INT2NUM(0));
|
|
164
|
-
(void)self;
|
|
165
|
-
return Qnil;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// Passes each line of the input to the block. This should be avoided.
|
|
169
|
-
static VALUE rio_each(VALUE self) {
|
|
170
|
-
rb_need_block();
|
|
171
|
-
rio_rewind(self);
|
|
172
|
-
VALUE str = Qnil;
|
|
173
|
-
while ((str = rio_gets(self)) != Qnil) {
|
|
174
|
-
rb_yield(str);
|
|
175
|
-
}
|
|
176
|
-
return self;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/* *****************************************************************************
|
|
180
|
-
Hijacking
|
|
181
|
-
*/
|
|
182
|
-
|
|
183
|
-
// defined by iodine_http
|
|
184
|
-
extern VALUE IODINE_R_HIJACK; // for Rack: rack.hijack
|
|
185
|
-
extern VALUE IODINE_R_HIJACK_CB; // for Rack: rack.hijack
|
|
186
|
-
extern VALUE IODINE_R_HIJACK_IO; // for Rack: rack.hijack_io
|
|
187
|
-
|
|
188
|
-
static VALUE rio_get_io(int argc, VALUE *argv, VALUE self) {
|
|
189
|
-
if (TCPSOCKET_CLASS == Qnil)
|
|
190
|
-
return Qfalse;
|
|
191
|
-
VALUE env = rb_ivar_get(self, env_id);
|
|
192
|
-
http_s *h = get_handle(self);
|
|
193
|
-
if (h == NULL) {
|
|
194
|
-
/* we're repeating ourselves, aren't we? */
|
|
195
|
-
VALUE io = rb_hash_aref(env, IODINE_R_HIJACK_IO);
|
|
196
|
-
return io;
|
|
197
|
-
}
|
|
198
|
-
// mark update
|
|
199
|
-
set_handle(self, NULL);
|
|
200
|
-
// hijack the IO object
|
|
201
|
-
intptr_t uuid = http_hijack(h, NULL);
|
|
202
|
-
#ifdef __MINGW32__
|
|
203
|
-
int osffd = fio_osffd4fd(fio_uuid2fd(uuid));
|
|
204
|
-
if (osffd == -1)
|
|
205
|
-
return Qfalse;
|
|
206
|
-
VALUE fd = INT2FIX(osffd);
|
|
207
|
-
#else
|
|
208
|
-
VALUE fd = INT2FIX(fio_uuid2fd(uuid));
|
|
209
|
-
#endif
|
|
210
|
-
// VALUE new_io = how the fuck do we create a new IO from the fd?
|
|
211
|
-
VALUE new_io = IodineCaller.call2(TCPSOCKET_CLASS, for_fd_id, 1,
|
|
212
|
-
&fd); // TCPSocket.for_fd(fd) ... cool...
|
|
213
|
-
rb_hash_aset(env, IODINE_R_HIJACK_IO, new_io);
|
|
214
|
-
if (argc)
|
|
215
|
-
rb_hash_aset(env, IODINE_R_HIJACK_CB, *argv);
|
|
216
|
-
return new_io;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
/* *****************************************************************************
|
|
220
|
-
C land API
|
|
221
|
-
*/
|
|
222
|
-
|
|
223
|
-
// new object
|
|
224
|
-
static VALUE new_rack_io(http_s *h, VALUE env) {
|
|
225
|
-
VALUE rack_io = rb_funcall2(rRackIO, iodine_new_func_id, 0, NULL);
|
|
226
|
-
rb_ivar_set(rack_io, io_id, ULL2NUM(h->body));
|
|
227
|
-
set_handle(rack_io, h);
|
|
228
|
-
rb_ivar_set(rack_io, env_id, env);
|
|
229
|
-
rb_hash_aset(env, IODINE_R_INPUT, rack_io);
|
|
230
|
-
rb_hash_aset(env, IODINE_R_HIJACK, rb_obj_method(rack_io, hijack_func_sym));
|
|
231
|
-
return rack_io;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
static void close_rack_io(VALUE rack_io) {
|
|
235
|
-
// rio_close(rack_io);
|
|
236
|
-
rb_ivar_set(rack_io, io_id, INT2NUM(0));
|
|
237
|
-
set_handle(rack_io, NULL); /* this disables hijacking. */
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
// initialize library
|
|
241
|
-
static void init_rack_io(void) {
|
|
242
|
-
IodineUTF8Encoding = rb_enc_find("UTF-8");
|
|
243
|
-
IodineBinaryEncoding = rb_enc_find("binary");
|
|
244
|
-
rRackIO = rb_define_class_under(IodineBaseModule, "RackIO", rb_cObject);
|
|
245
|
-
|
|
246
|
-
io_id = rb_intern("rack_io");
|
|
247
|
-
env_id = rb_intern("env");
|
|
248
|
-
for_fd_id = rb_intern("for_fd");
|
|
249
|
-
iodine_fd_var_id = rb_intern("fd");
|
|
250
|
-
iodine_new_func_id = rb_intern("new");
|
|
251
|
-
#ifdef __MINGW32__
|
|
252
|
-
iodine_osffd_id = rb_intern("osffd");
|
|
253
|
-
#endif
|
|
254
|
-
hijack_func_sym = ID2SYM(rb_intern("_hijack"));
|
|
255
|
-
|
|
256
|
-
TCPSOCKET_CLASS = rb_const_get(rb_cObject, rb_intern("TCPSocket"));
|
|
257
|
-
// IO methods
|
|
258
|
-
|
|
259
|
-
rb_define_method(rRackIO, "rewind", rio_rewind, 0);
|
|
260
|
-
rb_define_method(rRackIO, "gets", rio_gets, 0);
|
|
261
|
-
rb_define_method(rRackIO, "read", rio_read, -1);
|
|
262
|
-
rb_define_method(rRackIO, "close", rio_close, 0);
|
|
263
|
-
rb_define_method(rRackIO, "each", rio_each, 0);
|
|
264
|
-
rb_define_method(rRackIO, "_hijack", rio_get_io, -1);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
////////////////////////////////////////////////////////////////////////////
|
|
268
|
-
// the API interface
|
|
269
|
-
struct IodineRackIO IodineRackIO = {
|
|
270
|
-
.create = new_rack_io,
|
|
271
|
-
.close = close_rack_io,
|
|
272
|
-
.init = init_rack_io,
|
|
273
|
-
};
|
data/ext/iodine/iodine_rack_io.h
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright: Boaz segev, 2016-2017
|
|
3
|
-
License: MIT
|
|
4
|
-
|
|
5
|
-
Feel free to copy, use and enjoy according to the license provided.
|
|
6
|
-
*/
|
|
7
|
-
#ifndef RUBY_RACK_IO_H
|
|
8
|
-
#define RUBY_RACK_IO_H
|
|
9
|
-
|
|
10
|
-
#include <ruby.h>
|
|
11
|
-
|
|
12
|
-
#include "http.h"
|
|
13
|
-
|
|
14
|
-
extern struct IodineRackIO {
|
|
15
|
-
VALUE (*create)(http_s *h, VALUE env);
|
|
16
|
-
void (*close)(VALUE rack_io);
|
|
17
|
-
void (*init)(void);
|
|
18
|
-
} IodineRackIO;
|
|
19
|
-
|
|
20
|
-
#endif /* RUBY_RACK_IO_H */
|
data/ext/iodine/iodine_store.c
DELETED
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
#include "iodine_store.h"
|
|
2
|
-
|
|
3
|
-
#include <inttypes.h>
|
|
4
|
-
#include <stdint.h>
|
|
5
|
-
|
|
6
|
-
#include "iodine.h"
|
|
7
|
-
|
|
8
|
-
#define FIO_SET_NAME fio_store
|
|
9
|
-
#define FIO_SET_OBJ_TYPE uintptr_t
|
|
10
|
-
#include <fio.h>
|
|
11
|
-
|
|
12
|
-
static fio_lock_i iodine_storage_lock = FIO_LOCK_INIT;
|
|
13
|
-
static fio_store_s iodine_storage = FIO_SET_INIT;
|
|
14
|
-
static size_t iodine_storage_count_max = 0;
|
|
15
|
-
|
|
16
|
-
#ifndef IODINE_DEBUG
|
|
17
|
-
#define IODINE_DEBUG 0
|
|
18
|
-
#endif
|
|
19
|
-
|
|
20
|
-
/* *****************************************************************************
|
|
21
|
-
API
|
|
22
|
-
***************************************************************************** */
|
|
23
|
-
|
|
24
|
-
/** Adds an object to the storage (or increases it's reference count). */
|
|
25
|
-
static VALUE storage_add(VALUE obj) {
|
|
26
|
-
if (!obj || obj == Qnil || obj == Qtrue || obj == Qfalse) return obj;
|
|
27
|
-
uintptr_t old = 0;
|
|
28
|
-
fio_lock(&iodine_storage_lock);
|
|
29
|
-
fio_store_overwrite(&iodine_storage, obj, 1, &old);
|
|
30
|
-
if (old) fio_store_overwrite(&iodine_storage, obj, old + 1, NULL);
|
|
31
|
-
if (iodine_storage_count_max < fio_store_count(&iodine_storage))
|
|
32
|
-
iodine_storage_count_max = fio_store_count(&iodine_storage);
|
|
33
|
-
fio_unlock(&iodine_storage_lock);
|
|
34
|
-
return obj;
|
|
35
|
-
}
|
|
36
|
-
/** Removes an object from the storage (or decreases it's reference count). */
|
|
37
|
-
static VALUE storage_remove(VALUE obj) {
|
|
38
|
-
if (!obj || obj == Qnil || obj == Qtrue || obj == Qfalse ||
|
|
39
|
-
iodine_storage.count == 0)
|
|
40
|
-
return obj;
|
|
41
|
-
fio_lock(&iodine_storage_lock);
|
|
42
|
-
uintptr_t old = 0;
|
|
43
|
-
fio_store_remove(&iodine_storage, obj, 0, &old);
|
|
44
|
-
if (old > 1) fio_store_overwrite(&iodine_storage, obj, old - 1, NULL);
|
|
45
|
-
fio_unlock(&iodine_storage_lock);
|
|
46
|
-
return obj;
|
|
47
|
-
}
|
|
48
|
-
/** Should be called after forking to reset locks */
|
|
49
|
-
static void storage_after_fork(void) { iodine_storage_lock = FIO_LOCK_INIT; }
|
|
50
|
-
|
|
51
|
-
/** Prints debugging information to the console. */
|
|
52
|
-
static void storage_print(void) {
|
|
53
|
-
FIO_LOG_DEBUG("Ruby <=> C Memory storage stats (pid: %d):\n", getpid());
|
|
54
|
-
fio_lock(&iodine_storage_lock);
|
|
55
|
-
uintptr_t index = 0;
|
|
56
|
-
FIO_SET_FOR_LOOP(&iodine_storage, pos) {
|
|
57
|
-
if (pos->obj) {
|
|
58
|
-
fprintf(stderr,
|
|
59
|
-
"[%" PRIuPTR "] => %" PRIuPTR " X obj %p type %d\n",
|
|
60
|
-
index++,
|
|
61
|
-
pos->obj,
|
|
62
|
-
(void *)pos->hash,
|
|
63
|
-
TYPE(pos->hash));
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
fprintf(stderr, "Total of %" PRIuPTR " objects protected form GC\n", index);
|
|
67
|
-
fprintf(stderr,
|
|
68
|
-
"Storage uses %" PRIuPTR " Hash bins for %" PRIuPTR
|
|
69
|
-
" objects\n"
|
|
70
|
-
"The largest collection was %zu objects.\n",
|
|
71
|
-
iodine_storage.capa,
|
|
72
|
-
iodine_storage.count,
|
|
73
|
-
iodine_storage_count_max);
|
|
74
|
-
fio_unlock(&iodine_storage_lock);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Used for debugging purposes (when testing iodine for Ruby object "leaks").
|
|
79
|
-
*/
|
|
80
|
-
static VALUE storage_print_rb(VALUE self) {
|
|
81
|
-
storage_print();
|
|
82
|
-
return Qnil;
|
|
83
|
-
(void)self;
|
|
84
|
-
}
|
|
85
|
-
/* *****************************************************************************
|
|
86
|
-
GC protection
|
|
87
|
-
***************************************************************************** */
|
|
88
|
-
|
|
89
|
-
/* a callback for the GC (marking active objects) */
|
|
90
|
-
static void storage_mark(void *ignore) {
|
|
91
|
-
(void)ignore;
|
|
92
|
-
if (FIO_LOG_LEVEL >= FIO_LOG_LEVEL_DEBUG) storage_print();
|
|
93
|
-
fio_lock(&iodine_storage_lock);
|
|
94
|
-
// fio_store_compact(&iodine_storage);
|
|
95
|
-
FIO_SET_FOR_LOOP(&iodine_storage, pos) {
|
|
96
|
-
if (pos->obj) {
|
|
97
|
-
rb_gc_mark((VALUE)pos->hash);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
fio_unlock(&iodine_storage_lock);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/* clear the registry (end of lifetime) */
|
|
104
|
-
static void storage_clear(void *ignore) {
|
|
105
|
-
(void)ignore;
|
|
106
|
-
FIO_LOG_DEBUG("Ruby<=>C Storage cleared.\n");
|
|
107
|
-
fio_lock(&iodine_storage_lock);
|
|
108
|
-
fio_store_free(&iodine_storage);
|
|
109
|
-
iodine_storage = (fio_store_s)FIO_SET_INIT;
|
|
110
|
-
fio_unlock(&iodine_storage_lock);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/*
|
|
114
|
-
the data-type used to identify the registry
|
|
115
|
-
this sets the callbacks.
|
|
116
|
-
*/
|
|
117
|
-
static const struct rb_data_type_struct storage_type_struct = {
|
|
118
|
-
.wrap_struct_name = "RubyReferencesIn_C_Land",
|
|
119
|
-
.function.dfree = (void (*)(void *))storage_clear,
|
|
120
|
-
.function.dmark = (void (*)(void *))storage_mark,
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
/* *****************************************************************************
|
|
124
|
-
Initialization
|
|
125
|
-
***************************************************************************** */
|
|
126
|
-
|
|
127
|
-
struct IodineStorage_s IodineStore = {
|
|
128
|
-
.add = storage_add,
|
|
129
|
-
.remove = storage_remove,
|
|
130
|
-
.after_fork = storage_after_fork,
|
|
131
|
-
.print = storage_print,
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
/** Initializes the storage unit for first use. */
|
|
135
|
-
void iodine_storage_init(void) {
|
|
136
|
-
fio_store_capa_require(&iodine_storage, 512);
|
|
137
|
-
VALUE tmp = rb_define_module_under(rb_cObject, "IodineObjectStorage");
|
|
138
|
-
VALUE storage_obj =
|
|
139
|
-
TypedData_Wrap_Struct(tmp, &storage_type_struct, &iodine_storage);
|
|
140
|
-
// rb_global_variable(&iodine_storage_obj);
|
|
141
|
-
rb_ivar_set(IodineModule, rb_intern2("storage", 7), storage_obj);
|
|
142
|
-
rb_define_module_function(IodineBaseModule,
|
|
143
|
-
"db_print_protected_objects",
|
|
144
|
-
storage_print_rb,
|
|
145
|
-
0);
|
|
146
|
-
}
|