iodine 0.7.60 → 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 -21
- 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 -148
- 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_defer.c
DELETED
|
@@ -1,420 +0,0 @@
|
|
|
1
|
-
#include "iodine.h"
|
|
2
|
-
|
|
3
|
-
#include <ruby/thread.h>
|
|
4
|
-
|
|
5
|
-
#include <stdint.h>
|
|
6
|
-
// clang-format on
|
|
7
|
-
|
|
8
|
-
#define FIO_INCLUDE_LINKED_LIST
|
|
9
|
-
#include "fio.h"
|
|
10
|
-
|
|
11
|
-
#include <pthread.h>
|
|
12
|
-
|
|
13
|
-
static ID STATE_PRE_START;
|
|
14
|
-
static ID STATE_BEFORE_FORK;
|
|
15
|
-
static ID STATE_AFTER_FORK;
|
|
16
|
-
static ID STATE_ENTER_CHILD;
|
|
17
|
-
static ID STATE_ENTER_MASTER;
|
|
18
|
-
static ID STATE_ON_START;
|
|
19
|
-
static ID STATE_ON_PARENT_CRUSH;
|
|
20
|
-
static ID STATE_ON_CHILD_CRUSH;
|
|
21
|
-
static ID STATE_START_SHUTDOWN;
|
|
22
|
-
static ID STATE_ON_FINISH;
|
|
23
|
-
|
|
24
|
-
/* *****************************************************************************
|
|
25
|
-
IO flushing dedicated thread for protection against blocking code
|
|
26
|
-
***************************************************************************** */
|
|
27
|
-
|
|
28
|
-
static fio_lock_i sock_io_thread_flag = 0;
|
|
29
|
-
static pthread_t sock_io_pthread;
|
|
30
|
-
typedef struct {
|
|
31
|
-
size_t threads;
|
|
32
|
-
size_t processes;
|
|
33
|
-
} iodine_start_settings_s;
|
|
34
|
-
|
|
35
|
-
static void *iodine_io_thread(void *arg) {
|
|
36
|
-
(void)arg;
|
|
37
|
-
while (sock_io_thread_flag) {
|
|
38
|
-
if (fio_flush_all())
|
|
39
|
-
fio_throttle_thread(500000UL);
|
|
40
|
-
else
|
|
41
|
-
fio_throttle_thread(150000000UL);
|
|
42
|
-
}
|
|
43
|
-
return NULL;
|
|
44
|
-
}
|
|
45
|
-
static void iodine_start_io_thread(void *a_) {
|
|
46
|
-
if (!fio_trylock(&sock_io_thread_flag)) {
|
|
47
|
-
if (pthread_create(&sock_io_pthread, NULL, iodine_io_thread, NULL)) {
|
|
48
|
-
FIO_LOG_ERROR("Couldn't spawn IO thread.");
|
|
49
|
-
};
|
|
50
|
-
FIO_LOG_DEBUG("IO thread started.");
|
|
51
|
-
}
|
|
52
|
-
(void)a_;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
static void iodine_join_io_thread(void) {
|
|
56
|
-
if (fio_unlock(&sock_io_thread_flag) && sock_io_pthread) {
|
|
57
|
-
pthread_join(sock_io_pthread, NULL);
|
|
58
|
-
sock_io_pthread = (pthread_t)NULL;
|
|
59
|
-
FIO_LOG_DEBUG("IO thread stopped and joined.");
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/* *****************************************************************************
|
|
64
|
-
The Defer library overriding functions
|
|
65
|
-
***************************************************************************** */
|
|
66
|
-
|
|
67
|
-
/* used to create Ruby threads and pass them the information they need */
|
|
68
|
-
struct CreateThreadArgs {
|
|
69
|
-
void *(*thread_func)(void *);
|
|
70
|
-
void *arg;
|
|
71
|
-
fio_lock_i lock;
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
/* used for GVL signalling */
|
|
75
|
-
static void call_async_signal(void *pool) {
|
|
76
|
-
fio_stop();
|
|
77
|
-
(void)pool;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
static void *defer_thread_start(void *args_) {
|
|
81
|
-
struct CreateThreadArgs *args = args_;
|
|
82
|
-
IodineCaller.set_GVL(0);
|
|
83
|
-
args->thread_func(args->arg);
|
|
84
|
-
return NULL;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/* the thread's GVL release */
|
|
88
|
-
static VALUE defer_thread_inGVL(void *args_) {
|
|
89
|
-
struct CreateThreadArgs *old_args = args_;
|
|
90
|
-
struct CreateThreadArgs args = *old_args;
|
|
91
|
-
IodineCaller.set_GVL(1);
|
|
92
|
-
fio_unlock(&old_args->lock);
|
|
93
|
-
rb_thread_call_without_gvl(defer_thread_start, &args,
|
|
94
|
-
(void (*)(void *))call_async_signal, args.arg);
|
|
95
|
-
return Qnil;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/* Within the GVL, creates a Ruby thread using an API call */
|
|
99
|
-
static void *create_ruby_thread_gvl(void *args) {
|
|
100
|
-
return (void *)IodineStore.add(rb_thread_create(defer_thread_inGVL, args));
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
static void *fork_using_ruby(void *ignr) {
|
|
104
|
-
// stop IO thread, if running (shouldn't occur)
|
|
105
|
-
if (sock_io_pthread) {
|
|
106
|
-
iodine_join_io_thread();
|
|
107
|
-
}
|
|
108
|
-
// fork using Ruby
|
|
109
|
-
const VALUE ProcessClass = rb_const_get(rb_cObject, rb_intern2("Process", 7));
|
|
110
|
-
const VALUE rb_pid = IodineCaller.call(ProcessClass, rb_intern2("fork", 4));
|
|
111
|
-
intptr_t pid = 0;
|
|
112
|
-
if (rb_pid != Qnil) {
|
|
113
|
-
pid = NUM2INT(rb_pid);
|
|
114
|
-
} else {
|
|
115
|
-
pid = 0;
|
|
116
|
-
}
|
|
117
|
-
// manage post forking state for Iodine
|
|
118
|
-
IodineCaller.set_GVL(1); /* enforce GVL state in thread storage */
|
|
119
|
-
if (!pid) {
|
|
120
|
-
IodineStore.after_fork();
|
|
121
|
-
}
|
|
122
|
-
return (void *)pid;
|
|
123
|
-
(void)ignr;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
OVERRIDE THIS to replace the default pthread implementation.
|
|
128
|
-
*/
|
|
129
|
-
void *fio_thread_new(void *(*thread_func)(void *), void *arg) {
|
|
130
|
-
struct CreateThreadArgs data = (struct CreateThreadArgs){
|
|
131
|
-
.thread_func = thread_func,
|
|
132
|
-
.arg = arg,
|
|
133
|
-
.lock = FIO_LOCK_INIT,
|
|
134
|
-
};
|
|
135
|
-
fio_lock(&data.lock);
|
|
136
|
-
void *thr = IodineCaller.enterGVL(create_ruby_thread_gvl, &data);
|
|
137
|
-
if (!thr || thr == (void *)Qnil || thr == (void *)Qfalse) {
|
|
138
|
-
thr = NULL;
|
|
139
|
-
} else {
|
|
140
|
-
/* wait for thread to signal it's alive. */
|
|
141
|
-
fio_lock(&data.lock);
|
|
142
|
-
}
|
|
143
|
-
return thr;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
OVERRIDE THIS to replace the default pthread implementation.
|
|
148
|
-
*/
|
|
149
|
-
int fio_thread_join(void *thr) {
|
|
150
|
-
if (!thr || (VALUE)thr == Qfalse || (VALUE)thr == Qnil)
|
|
151
|
-
return -1;
|
|
152
|
-
IodineCaller.call((VALUE)thr, rb_intern("join"));
|
|
153
|
-
IodineStore.remove((VALUE)thr);
|
|
154
|
-
return 0;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// void defer_free_thread(void *thr) { (void)thr; }
|
|
158
|
-
void fio_thread_free(void *thr) { IodineStore.remove((VALUE)thr); }
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
OVERRIDE THIS to replace the default `fork` implementation or to inject hooks
|
|
162
|
-
into the forking function.
|
|
163
|
-
|
|
164
|
-
Behaves like the system's `fork`.
|
|
165
|
-
*/
|
|
166
|
-
int fio_fork(void) {
|
|
167
|
-
intptr_t pid = (intptr_t)IodineCaller.enterGVL(fork_using_ruby, NULL);
|
|
168
|
-
return (int)pid;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/* *****************************************************************************
|
|
172
|
-
Task performance
|
|
173
|
-
***************************************************************************** */
|
|
174
|
-
|
|
175
|
-
static ID call_id;
|
|
176
|
-
|
|
177
|
-
static void iodine_defer_performe_once(void *block, void *ignr) {
|
|
178
|
-
IodineCaller.call((VALUE)block, call_id);
|
|
179
|
-
IodineStore.remove((VALUE)block);
|
|
180
|
-
(void)ignr;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
static void iodine_defer_run_timer(void *block) {
|
|
184
|
-
/* TODO, update return value to allow timer cancellation */
|
|
185
|
-
IodineCaller.call((VALUE)block, call_id);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/* *****************************************************************************
|
|
189
|
-
Defer API
|
|
190
|
-
***************************************************************************** */
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Runs a block of code asyncronously (adds the code to the event queue).
|
|
194
|
-
*
|
|
195
|
-
* Always returns the block of code to executed (Proc object).
|
|
196
|
-
*
|
|
197
|
-
* Code will be executed only while Iodine is running (after {Iodine.start}).
|
|
198
|
-
*
|
|
199
|
-
* Code blocks that where scheduled to run before Iodine enters cluster mode
|
|
200
|
-
* will run on all child processes.
|
|
201
|
-
*/
|
|
202
|
-
static VALUE iodine_defer_run(VALUE self) {
|
|
203
|
-
rb_need_block();
|
|
204
|
-
VALUE block = IodineStore.add(rb_block_proc());
|
|
205
|
-
fio_defer(iodine_defer_performe_once, (void *)block, NULL);
|
|
206
|
-
return block;
|
|
207
|
-
(void)self;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
Runs the required block after the specified number of milliseconds have passed.
|
|
212
|
-
Time is counted only once Iodine started running (using {Iodine.start}).
|
|
213
|
-
|
|
214
|
-
Tasks scheduled before calling {Iodine.start} will run once for every process.
|
|
215
|
-
|
|
216
|
-
Always returns a copy of the block object.
|
|
217
|
-
*/
|
|
218
|
-
static VALUE iodine_defer_run_after(VALUE self, VALUE milliseconds) {
|
|
219
|
-
(void)(self);
|
|
220
|
-
if (milliseconds == Qnil) {
|
|
221
|
-
return iodine_defer_run(self);
|
|
222
|
-
}
|
|
223
|
-
if (TYPE(milliseconds) != T_FIXNUM) {
|
|
224
|
-
rb_raise(rb_eTypeError, "milliseconds must be a number");
|
|
225
|
-
return Qnil;
|
|
226
|
-
}
|
|
227
|
-
size_t milli = FIX2UINT(milliseconds);
|
|
228
|
-
if (milli == 0) {
|
|
229
|
-
return iodine_defer_run(self);
|
|
230
|
-
}
|
|
231
|
-
// requires a block to be passed
|
|
232
|
-
rb_need_block();
|
|
233
|
-
VALUE block = rb_block_proc();
|
|
234
|
-
if (block == Qnil)
|
|
235
|
-
return Qfalse;
|
|
236
|
-
IodineStore.add(block);
|
|
237
|
-
if (fio_run_every(milli, 1, iodine_defer_run_timer, (void *)block,
|
|
238
|
-
(void (*)(void *))IodineStore.remove) == -1) {
|
|
239
|
-
perror("ERROR: Iodine couldn't initialize timer");
|
|
240
|
-
return Qnil;
|
|
241
|
-
}
|
|
242
|
-
return block;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// clang-format off
|
|
246
|
-
/**
|
|
247
|
-
Runs the required block after the specified number of milliseconds have passed.
|
|
248
|
-
Time is counted only once Iodine started running (using {Iodine.start}).
|
|
249
|
-
|
|
250
|
-
Accepts:
|
|
251
|
-
|
|
252
|
-
| | |
|
|
253
|
-
|---|---|
|
|
254
|
-
| `:milliseconds` | the number of milliseconds between event repetitions.|
|
|
255
|
-
| `:repetitions` | the number of event repetitions. Defaults to 0 (never ending).|
|
|
256
|
-
| `:block` | (required) a block is required, as otherwise there is nothing to|
|
|
257
|
-
perform.
|
|
258
|
-
|
|
259
|
-
The event will repeat itself until the number of repetitions had been delpeted.
|
|
260
|
-
|
|
261
|
-
Always returns a copy of the block object.
|
|
262
|
-
*/
|
|
263
|
-
static VALUE iodine_defer_run_every(int argc, VALUE *argv, VALUE self) {
|
|
264
|
-
// clang-format on
|
|
265
|
-
(void)(self);
|
|
266
|
-
VALUE milliseconds, repetitions, block;
|
|
267
|
-
|
|
268
|
-
rb_scan_args(argc, argv, "11&", &milliseconds, &repetitions, &block);
|
|
269
|
-
|
|
270
|
-
if (TYPE(milliseconds) != T_FIXNUM) {
|
|
271
|
-
rb_raise(rb_eTypeError, "milliseconds must be a number.");
|
|
272
|
-
return Qnil;
|
|
273
|
-
}
|
|
274
|
-
if (repetitions != Qnil && TYPE(repetitions) != T_FIXNUM) {
|
|
275
|
-
rb_raise(rb_eTypeError, "repetitions must be a number or `nil`.");
|
|
276
|
-
return Qnil;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
size_t milli = FIX2UINT(milliseconds);
|
|
280
|
-
size_t repeat = (repetitions == Qnil) ? 0 : FIX2UINT(repetitions);
|
|
281
|
-
// requires a block to be passed
|
|
282
|
-
rb_need_block();
|
|
283
|
-
IodineStore.add(block);
|
|
284
|
-
if (fio_run_every(milli, repeat, iodine_defer_run_timer, (void *)block,
|
|
285
|
-
(void (*)(void *))IodineStore.remove) == -1) {
|
|
286
|
-
perror("ERROR: Iodine couldn't initialize timer");
|
|
287
|
-
return Qnil;
|
|
288
|
-
}
|
|
289
|
-
return block;
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
/* *****************************************************************************
|
|
293
|
-
Pre/Post `fork`
|
|
294
|
-
***************************************************************************** */
|
|
295
|
-
|
|
296
|
-
/* performs a Ruby state callback without clearing the Ruby object's memory */
|
|
297
|
-
static void iodine_perform_state_callback_persist(void *blk_) {
|
|
298
|
-
VALUE blk = (VALUE)blk_;
|
|
299
|
-
IodineCaller.call(blk, call_id);
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
// clang-format off
|
|
303
|
-
/**
|
|
304
|
-
Sets a block of code to run when Iodine's core state is updated.
|
|
305
|
-
|
|
306
|
-
@param [Symbol] event the state event for which the block should run (see list).
|
|
307
|
-
@since 0.7.9
|
|
308
|
-
|
|
309
|
-
The state event Symbol can be any of the following:
|
|
310
|
-
|
|
311
|
-
| | |
|
|
312
|
-
|---|---|
|
|
313
|
-
| `:pre_start` | the block will be called once before starting up the IO reactor. |
|
|
314
|
-
| `:before_fork` | the block will be called before each time the IO reactor forks a new worker. |
|
|
315
|
-
| `:after_fork` | the block will be called after each fork (both in parent and workers). |
|
|
316
|
-
| `:enter_child` | the block will be called by a worker process right after forking. |
|
|
317
|
-
| `:enter_master` | the block will be called by the master process after spawning a worker (after forking). |
|
|
318
|
-
| `:on_start` | the block will be called every time a *worker* proceess starts. In single process mode, the master process is also a worker. |
|
|
319
|
-
| `:on_parent_crush` | the block will be called by each worker the moment it detects the master process crashed. |
|
|
320
|
-
| `:on_child_crush` | the block will be called by the parent (master) after a worker process crashed. |
|
|
321
|
-
| `:start_shutdown` | the block will be called before starting the shutdown sequence. |
|
|
322
|
-
| `:on_finish` | the block will be called just before finishing up (both on chlid and parent processes). |
|
|
323
|
-
|
|
324
|
-
Code runs in both the parent and the child.
|
|
325
|
-
*/
|
|
326
|
-
static VALUE iodine_on_state(VALUE self, VALUE event) {
|
|
327
|
-
// clang-format on
|
|
328
|
-
rb_need_block();
|
|
329
|
-
Check_Type(event, T_SYMBOL);
|
|
330
|
-
VALUE block = rb_block_proc();
|
|
331
|
-
IodineStore.add(block);
|
|
332
|
-
ID state = rb_sym2id(event);
|
|
333
|
-
|
|
334
|
-
if (state == STATE_PRE_START) {
|
|
335
|
-
fio_state_callback_add(FIO_CALL_PRE_START,
|
|
336
|
-
iodine_perform_state_callback_persist,
|
|
337
|
-
(void *)block);
|
|
338
|
-
} else if (state == STATE_BEFORE_FORK) {
|
|
339
|
-
fio_state_callback_add(FIO_CALL_BEFORE_FORK,
|
|
340
|
-
iodine_perform_state_callback_persist,
|
|
341
|
-
(void *)block);
|
|
342
|
-
} else if (state == STATE_AFTER_FORK) {
|
|
343
|
-
fio_state_callback_add(FIO_CALL_AFTER_FORK,
|
|
344
|
-
iodine_perform_state_callback_persist,
|
|
345
|
-
(void *)block);
|
|
346
|
-
} else if (state == STATE_ENTER_CHILD) {
|
|
347
|
-
fio_state_callback_add(FIO_CALL_IN_CHILD,
|
|
348
|
-
iodine_perform_state_callback_persist,
|
|
349
|
-
(void *)block);
|
|
350
|
-
} else if (state == STATE_ENTER_MASTER) {
|
|
351
|
-
fio_state_callback_add(FIO_CALL_IN_MASTER,
|
|
352
|
-
iodine_perform_state_callback_persist,
|
|
353
|
-
(void *)block);
|
|
354
|
-
} else if (state == STATE_ON_START) {
|
|
355
|
-
fio_state_callback_add(FIO_CALL_ON_START,
|
|
356
|
-
iodine_perform_state_callback_persist,
|
|
357
|
-
(void *)block);
|
|
358
|
-
} else if (state == STATE_ON_PARENT_CRUSH) {
|
|
359
|
-
fio_state_callback_add(FIO_CALL_ON_PARENT_CRUSH,
|
|
360
|
-
iodine_perform_state_callback_persist,
|
|
361
|
-
(void *)block);
|
|
362
|
-
} else if (state == STATE_ON_CHILD_CRUSH) {
|
|
363
|
-
fio_state_callback_add(FIO_CALL_ON_CHILD_CRUSH,
|
|
364
|
-
iodine_perform_state_callback_persist,
|
|
365
|
-
(void *)block);
|
|
366
|
-
} else if (state == STATE_START_SHUTDOWN) {
|
|
367
|
-
fio_state_callback_add(FIO_CALL_ON_SHUTDOWN,
|
|
368
|
-
iodine_perform_state_callback_persist,
|
|
369
|
-
(void *)block);
|
|
370
|
-
} else if (state == STATE_ON_FINISH) {
|
|
371
|
-
fio_state_callback_add(FIO_CALL_ON_FINISH,
|
|
372
|
-
iodine_perform_state_callback_persist,
|
|
373
|
-
(void *)block);
|
|
374
|
-
} else {
|
|
375
|
-
IodineStore.remove(block);
|
|
376
|
-
rb_raise(rb_eTypeError, "unknown event in Iodine.on_state");
|
|
377
|
-
}
|
|
378
|
-
return block;
|
|
379
|
-
(void)self;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
/* Performs any cleanup before worker dies */
|
|
383
|
-
static void iodine_defer_on_finish(void *ignr) {
|
|
384
|
-
(void)ignr;
|
|
385
|
-
iodine_join_io_thread();
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
/* *****************************************************************************
|
|
389
|
-
Add defer API to Iodine
|
|
390
|
-
***************************************************************************** */
|
|
391
|
-
|
|
392
|
-
void iodine_defer_initialize(void) {
|
|
393
|
-
call_id = rb_intern2("call", 4);
|
|
394
|
-
rb_define_module_function(IodineModule, "run", iodine_defer_run, 0);
|
|
395
|
-
rb_define_module_function(IodineModule, "defer", iodine_defer_run, 0);
|
|
396
|
-
|
|
397
|
-
rb_define_module_function(IodineModule, "run_after", iodine_defer_run_after,
|
|
398
|
-
1);
|
|
399
|
-
rb_define_module_function(IodineModule, "run_every", iodine_defer_run_every,
|
|
400
|
-
-1);
|
|
401
|
-
rb_define_module_function(IodineModule, "on_state", iodine_on_state, 1);
|
|
402
|
-
|
|
403
|
-
STATE_PRE_START = rb_intern("pre_start");
|
|
404
|
-
STATE_BEFORE_FORK = rb_intern("before_fork");
|
|
405
|
-
STATE_AFTER_FORK = rb_intern("after_fork");
|
|
406
|
-
STATE_ENTER_CHILD = rb_intern("enter_child");
|
|
407
|
-
STATE_ENTER_MASTER = rb_intern("enter_master");
|
|
408
|
-
STATE_ON_START = rb_intern("on_start");
|
|
409
|
-
STATE_ON_PARENT_CRUSH = rb_intern("on_parent_crush");
|
|
410
|
-
STATE_ON_CHILD_CRUSH = rb_intern("on_child_crush");
|
|
411
|
-
STATE_START_SHUTDOWN = rb_intern("start_shutdown");
|
|
412
|
-
STATE_ON_FINISH = rb_intern("on_finish");
|
|
413
|
-
|
|
414
|
-
/* start the IO thread is workrs (only starts in root if root is worker) */
|
|
415
|
-
fio_state_callback_add(FIO_CALL_ON_START, iodine_start_io_thread, NULL);
|
|
416
|
-
/* stop the IO thread before exit */
|
|
417
|
-
fio_state_callback_add(FIO_CALL_ON_FINISH, iodine_defer_on_finish, NULL);
|
|
418
|
-
/* kill IO thread even after a non-graceful iodine shutdown (force-quit) */
|
|
419
|
-
fio_state_callback_add(FIO_CALL_AT_EXIT, iodine_defer_on_finish, NULL);
|
|
420
|
-
}
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
#ifndef H_RB_FIOBJ2RUBY_H
|
|
2
|
-
/*
|
|
3
|
-
Copyright: Boaz segev, 2016-2017
|
|
4
|
-
License: MIT
|
|
5
|
-
|
|
6
|
-
Feel free to copy, use and enjoy according to the license provided.
|
|
7
|
-
*/
|
|
8
|
-
#define H_RB_FIOBJ2RUBY_H
|
|
9
|
-
#include <fiobj.h>
|
|
10
|
-
#include <ruby.h>
|
|
11
|
-
|
|
12
|
-
#include "iodine_store.h"
|
|
13
|
-
|
|
14
|
-
typedef struct {
|
|
15
|
-
FIOBJ stack;
|
|
16
|
-
uintptr_t count;
|
|
17
|
-
VALUE rb;
|
|
18
|
-
uint8_t str2sym;
|
|
19
|
-
} fiobj2rb_s;
|
|
20
|
-
|
|
21
|
-
typedef struct {
|
|
22
|
-
uint8_t str2sym;
|
|
23
|
-
} fiobj2rb_settings_s;
|
|
24
|
-
|
|
25
|
-
static inline VALUE fiobj2rb(FIOBJ o, uint8_t str2sym) {
|
|
26
|
-
VALUE rb;
|
|
27
|
-
if (!o)
|
|
28
|
-
return Qnil;
|
|
29
|
-
switch (FIOBJ_TYPE(o)) {
|
|
30
|
-
case FIOBJ_T_NUMBER:
|
|
31
|
-
rb = LONG2FIX(fiobj_obj2num(o));
|
|
32
|
-
break;
|
|
33
|
-
case FIOBJ_T_TRUE:
|
|
34
|
-
rb = Qtrue;
|
|
35
|
-
break;
|
|
36
|
-
case FIOBJ_T_FALSE:
|
|
37
|
-
rb = Qfalse;
|
|
38
|
-
break;
|
|
39
|
-
case FIOBJ_T_FLOAT:
|
|
40
|
-
rb = rb_float_new(fiobj_obj2float(o));
|
|
41
|
-
break;
|
|
42
|
-
case FIOBJ_T_DATA: /* fallthrough */
|
|
43
|
-
case FIOBJ_T_UNKNOWN: /* fallthrough */
|
|
44
|
-
case FIOBJ_T_STRING: {
|
|
45
|
-
fio_str_info_s tmp = fiobj_obj2cstr(o);
|
|
46
|
-
if (str2sym) {
|
|
47
|
-
rb = rb_intern2(tmp.data, tmp.len);
|
|
48
|
-
rb = ID2SYM(rb);
|
|
49
|
-
} else {
|
|
50
|
-
rb = rb_str_new(tmp.data, tmp.len);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
} break;
|
|
54
|
-
case FIOBJ_T_ARRAY:
|
|
55
|
-
rb = rb_ary_new();
|
|
56
|
-
break;
|
|
57
|
-
case FIOBJ_T_HASH:
|
|
58
|
-
rb = rb_hash_new();
|
|
59
|
-
break;
|
|
60
|
-
case FIOBJ_T_NULL: /* fallthrough */
|
|
61
|
-
default:
|
|
62
|
-
rb = Qnil;
|
|
63
|
-
break;
|
|
64
|
-
};
|
|
65
|
-
return rb;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
static int fiobj2rb_task(FIOBJ o, void *data_) {
|
|
69
|
-
fiobj2rb_s *data = data_;
|
|
70
|
-
VALUE rb_tmp;
|
|
71
|
-
rb_tmp = fiobj2rb(o, 0);
|
|
72
|
-
IodineStore.add(rb_tmp);
|
|
73
|
-
if (data->rb) {
|
|
74
|
-
if (RB_TYPE_P(data->rb, T_HASH)) {
|
|
75
|
-
rb_hash_aset(data->rb, fiobj2rb(fiobj_hash_key_in_loop(), data->str2sym),
|
|
76
|
-
rb_tmp);
|
|
77
|
-
} else {
|
|
78
|
-
rb_ary_push(data->rb, rb_tmp);
|
|
79
|
-
}
|
|
80
|
-
--(data->count);
|
|
81
|
-
IodineStore.remove(rb_tmp);
|
|
82
|
-
} else {
|
|
83
|
-
data->rb = rb_tmp;
|
|
84
|
-
// IodineStore.add(rb_tmp);
|
|
85
|
-
}
|
|
86
|
-
if (FIOBJ_TYPE_IS(o, FIOBJ_T_ARRAY)) {
|
|
87
|
-
fiobj_ary_push(data->stack, (FIOBJ)data->count);
|
|
88
|
-
fiobj_ary_push(data->stack, (FIOBJ)data->rb);
|
|
89
|
-
data->count = fiobj_ary_count(o);
|
|
90
|
-
data->rb = rb_tmp;
|
|
91
|
-
} else if (FIOBJ_TYPE_IS(o, FIOBJ_T_HASH)) {
|
|
92
|
-
fiobj_ary_push(data->stack, (FIOBJ)data->count);
|
|
93
|
-
fiobj_ary_push(data->stack, (FIOBJ)data->rb);
|
|
94
|
-
data->count = fiobj_hash_count(o);
|
|
95
|
-
data->rb = rb_tmp;
|
|
96
|
-
}
|
|
97
|
-
while (data->count == 0 && fiobj_ary_count(data->stack)) {
|
|
98
|
-
data->rb = fiobj_ary_pop(data->stack);
|
|
99
|
-
data->count = fiobj_ary_pop(data->stack);
|
|
100
|
-
}
|
|
101
|
-
return 0;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
static inline VALUE fiobj2rb_deep(FIOBJ obj, uint8_t str2sym) {
|
|
105
|
-
fiobj2rb_s data = {.stack = fiobj_ary_new2(4), .str2sym = str2sym};
|
|
106
|
-
|
|
107
|
-
/* deep copy */
|
|
108
|
-
fiobj_each2(obj, fiobj2rb_task, &data);
|
|
109
|
-
/* cleanup (shouldn't happen, but what the hell)... */
|
|
110
|
-
while (fiobj_ary_pop(data.stack))
|
|
111
|
-
;
|
|
112
|
-
fiobj_free(data.stack);
|
|
113
|
-
// IodineStore.remove(data.rb); // don't remove data
|
|
114
|
-
return data.rb;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// require 'iodine'
|
|
118
|
-
// Iodine::JSON.parse "{\"1\":[1,2,3,4]}"
|
|
119
|
-
// Iodine::JSON.parse IO.binread("")
|
|
120
|
-
#endif /* H_RB_FIOBJ2RUBY_H */
|