iodine 0.3.6 → 0.4.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/CHANGELOG.md +46 -0
- data/LIMITS.md +25 -0
- data/README.md +39 -80
- data/SPEC-Websocket-Draft.md +129 -4
- data/bin/echo +2 -2
- data/bin/http-hello +1 -0
- data/bin/updated api +113 -0
- data/bin/ws-echo +0 -1
- data/examples/broadcast.ru +56 -0
- data/examples/echo.ru +57 -0
- data/examples/hello.ru +30 -0
- data/examples/redis.ru +69 -0
- data/examples/shootout.ru +53 -0
- data/exe/iodine +2 -80
- data/ext/iodine/defer.c +11 -5
- data/ext/iodine/empty.h +26 -0
- data/ext/iodine/evio.h +1 -1
- data/ext/iodine/facil.c +103 -61
- data/ext/iodine/facil.h +20 -12
- data/ext/iodine/fio_dict.c +446 -0
- data/ext/iodine/fio_dict.h +90 -0
- data/ext/iodine/fio_hash_table.h +370 -0
- data/ext/iodine/fio_list.h +30 -3
- data/ext/iodine/http.c +169 -37
- data/ext/iodine/http.h +33 -10
- data/ext/iodine/http1.c +78 -42
- data/ext/iodine/http_request.c +6 -0
- data/ext/iodine/http_request.h +3 -0
- data/ext/iodine/http_response.c +43 -11
- data/ext/iodine/iodine.c +380 -0
- data/ext/iodine/iodine.h +62 -0
- data/ext/iodine/iodine_helpers.c +235 -0
- data/ext/iodine/iodine_helpers.h +13 -0
- data/ext/iodine/iodine_http.c +409 -241
- data/ext/iodine/iodine_http.h +7 -14
- data/ext/iodine/iodine_protocol.c +626 -0
- data/ext/iodine/iodine_protocol.h +13 -0
- data/ext/iodine/iodine_pubsub.c +646 -0
- data/ext/iodine/iodine_pubsub.h +27 -0
- data/ext/iodine/iodine_websockets.c +796 -0
- data/ext/iodine/iodine_websockets.h +19 -0
- data/ext/iodine/pubsub.c +544 -0
- data/ext/iodine/pubsub.h +215 -0
- data/ext/iodine/random.c +4 -4
- data/ext/iodine/rb-call.c +1 -5
- data/ext/iodine/rb-defer.c +3 -20
- data/ext/iodine/rb-rack-io.c +22 -22
- data/ext/iodine/rb-rack-io.h +3 -4
- data/ext/iodine/rb-registry.c +111 -118
- data/ext/iodine/redis_connection.c +277 -0
- data/ext/iodine/redis_connection.h +77 -0
- data/ext/iodine/redis_engine.c +398 -0
- data/ext/iodine/redis_engine.h +68 -0
- data/ext/iodine/resp.c +842 -0
- data/ext/iodine/resp.h +253 -0
- data/ext/iodine/sock.c +26 -12
- data/ext/iodine/sock.h +14 -3
- data/ext/iodine/spnlock.inc +19 -2
- data/ext/iodine/websockets.c +299 -11
- data/ext/iodine/websockets.h +159 -6
- data/lib/iodine.rb +104 -1
- data/lib/iodine/cli.rb +106 -0
- data/lib/iodine/monkeypatch.rb +40 -0
- data/lib/iodine/pubsub.rb +70 -0
- data/lib/iodine/version.rb +1 -1
- data/lib/iodine/websocket.rb +12 -0
- data/lib/rack/handler/iodine.rb +33 -7
- metadata +35 -7
- data/ext/iodine/iodine_core.c +0 -760
- data/ext/iodine/iodine_core.h +0 -79
- data/ext/iodine/iodine_websocket.c +0 -551
- data/ext/iodine/iodine_websocket.h +0 -22
- data/lib/iodine/http.rb +0 -4
data/ext/iodine/defer.c
CHANGED
@@ -121,8 +121,8 @@ restart:
|
|
121
121
|
spn_unlock(&deferred.lock);
|
122
122
|
task.func(task.arg1, task.arg2);
|
123
123
|
goto restart;
|
124
|
-
}
|
125
|
-
|
124
|
+
}
|
125
|
+
spn_unlock(&deferred.lock);
|
126
126
|
}
|
127
127
|
|
128
128
|
/** returns true if there are deferred functions waiting for execution. */
|
@@ -186,15 +186,17 @@ struct defer_pool {
|
|
186
186
|
void *threads[];
|
187
187
|
};
|
188
188
|
|
189
|
-
static void *defer_worker_thread(void *
|
189
|
+
static void *defer_worker_thread(void *pool_) {
|
190
|
+
volatile pool_pt pool = pool_;
|
190
191
|
signal(SIGPIPE, SIG_IGN);
|
191
|
-
size_t throttle = (
|
192
|
+
size_t throttle = (pool->count) * DEFER_THROTTLE;
|
192
193
|
if (!throttle || throttle > 1572864UL)
|
193
194
|
throttle = 1572864UL;
|
195
|
+
defer_perform();
|
194
196
|
do {
|
195
197
|
throttle_thread(throttle);
|
196
198
|
defer_perform();
|
197
|
-
} while (
|
199
|
+
} while (pool->flag);
|
198
200
|
return NULL;
|
199
201
|
}
|
200
202
|
|
@@ -285,6 +287,8 @@ int defer_perform_in_fork(unsigned int process_count,
|
|
285
287
|
if (forked_pool)
|
286
288
|
return -1; /* we're already running inside an active `fork` */
|
287
289
|
|
290
|
+
static struct defer_pool pool_placeholder = {.count = 1, .flag = 1};
|
291
|
+
|
288
292
|
struct sigaction act, old, old_term, old_pipe;
|
289
293
|
pid_t *pids = NULL;
|
290
294
|
int ret = 0;
|
@@ -318,6 +322,7 @@ int defer_perform_in_fork(unsigned int process_count,
|
|
318
322
|
for (pids_count = 0; pids_count < process_count; pids_count++) {
|
319
323
|
if (!(pids[pids_count] = fork())) {
|
320
324
|
defer_fork_pid_id = pids_count + 1;
|
325
|
+
forked_pool = &pool_placeholder;
|
321
326
|
forked_pool = defer_pool_start(thread_count);
|
322
327
|
defer_pool_wait(forked_pool);
|
323
328
|
defer_perform();
|
@@ -330,6 +335,7 @@ int defer_perform_in_fork(unsigned int process_count,
|
|
330
335
|
}
|
331
336
|
}
|
332
337
|
pids_count++;
|
338
|
+
forked_pool = &pool_placeholder;
|
333
339
|
forked_pool = defer_pool_start(thread_count);
|
334
340
|
defer_pool_wait(forked_pool);
|
335
341
|
forked_pool = NULL;
|
data/ext/iodine/empty.h
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
/*
|
2
|
+
Copyright: Boaz segev, 2016-2017
|
3
|
+
License: MIT except for any non-public-domain algorithms (none that I'm aware
|
4
|
+
of), which might be subject to their own licenses.
|
5
|
+
|
6
|
+
Feel free to copy, use and enjoy in accordance with to the license(s).
|
7
|
+
*/
|
8
|
+
#ifndef BSCRYPT_EMPTY_H
|
9
|
+
#define BSCRYPT_EMPTY_H
|
10
|
+
#include "bscrypt-common.h"
|
11
|
+
/* *****************************************************************************
|
12
|
+
C++ extern
|
13
|
+
*/
|
14
|
+
#if defined(__cplusplus)
|
15
|
+
extern "C" {
|
16
|
+
#endif
|
17
|
+
|
18
|
+
/* *****************************************************************************
|
19
|
+
C++ extern finish
|
20
|
+
*/
|
21
|
+
#if defined(__cplusplus)
|
22
|
+
}
|
23
|
+
#endif
|
24
|
+
|
25
|
+
/* ****************************************************************************/
|
26
|
+
#endif /* include guard */
|
data/ext/iodine/evio.h
CHANGED
@@ -47,7 +47,7 @@ Returns -1 on error, otherwise returns a unique value representing the `epoll`
|
|
47
47
|
or `kqueue` object. The returned value can be safely ignored.
|
48
48
|
|
49
49
|
NOTE: Once an `epoll` / `kqueue` object was opened, `fork` should be avoided,
|
50
|
-
since ALL the events will be shared among the forked
|
50
|
+
since ALL the events will be shared among the forked processes (while not ALL
|
51
51
|
the file descriptors are expected to be shared).
|
52
52
|
*/
|
53
53
|
intptr_t evio_create(void);
|
data/ext/iodine/facil.c
CHANGED
@@ -83,15 +83,14 @@ inline static void protocol_unlock(protocol_s *pr,
|
|
83
83
|
/* *****************************************************************************
|
84
84
|
Deferred event handlers
|
85
85
|
***************************************************************************** */
|
86
|
-
static void deferred_on_close(void *
|
87
|
-
protocol_s *pr =
|
86
|
+
static void deferred_on_close(void *uuid_, void *pr_) {
|
87
|
+
protocol_s *pr = pr_;
|
88
88
|
if (pr->rsv)
|
89
89
|
goto postpone;
|
90
|
-
pr->on_close(pr);
|
90
|
+
pr->on_close((intptr_t)uuid_, pr);
|
91
91
|
return;
|
92
92
|
postpone:
|
93
|
-
defer(deferred_on_close,
|
94
|
-
(void)arg2;
|
93
|
+
defer(deferred_on_close, uuid_, pr_);
|
95
94
|
}
|
96
95
|
|
97
96
|
static void deferred_on_ready(void *arg, void *arg2) {
|
@@ -181,7 +180,7 @@ void sock_on_close(intptr_t uuid) {
|
|
181
180
|
clear_connection_data_unsafe(uuid, NULL);
|
182
181
|
spn_unlock(&uuid_data(uuid).lock);
|
183
182
|
if (old_protocol)
|
184
|
-
defer(deferred_on_close,
|
183
|
+
defer(deferred_on_close, (void *)uuid, old_protocol);
|
185
184
|
}
|
186
185
|
|
187
186
|
void sock_touch(intptr_t uuid) {
|
@@ -235,14 +234,22 @@ finish:
|
|
235
234
|
}
|
236
235
|
|
237
236
|
/* *****************************************************************************
|
238
|
-
Mock Protocol and
|
237
|
+
Mock Protocol Callbacks and Service Funcions
|
239
238
|
***************************************************************************** */
|
240
239
|
static void mock_on_ev(intptr_t uuid, protocol_s *protocol) {
|
241
240
|
(void)uuid;
|
242
241
|
(void)protocol;
|
243
242
|
}
|
244
243
|
|
245
|
-
static void mock_on_close(protocol_s *protocol) {
|
244
|
+
static void mock_on_close(intptr_t uuid, protocol_s *protocol) {
|
245
|
+
(void)(protocol);
|
246
|
+
(void)(uuid);
|
247
|
+
}
|
248
|
+
|
249
|
+
static void mock_on_finish(intptr_t uuid, void *udata) {
|
250
|
+
(void)(udata);
|
251
|
+
(void)(uuid);
|
252
|
+
}
|
246
253
|
|
247
254
|
static void mock_ping(intptr_t uuid, protocol_s *protocol) {
|
248
255
|
(void)(protocol);
|
@@ -250,6 +257,24 @@ static void mock_ping(intptr_t uuid, protocol_s *protocol) {
|
|
250
257
|
}
|
251
258
|
static void mock_idle(void) {}
|
252
259
|
|
260
|
+
/* Support for the default pub/sub cluster engine */
|
261
|
+
#pragma weak pubsub_cluster_init
|
262
|
+
void pubsub_cluster_init(void) {}
|
263
|
+
|
264
|
+
/*
|
265
|
+
* Support for the (removed) file caching service.
|
266
|
+
*
|
267
|
+
* It's possible to re-add the service from the `unused` folder.
|
268
|
+
*/
|
269
|
+
#pragma weak fio_cfd_clear
|
270
|
+
void fio_cfd_clear(void) {}
|
271
|
+
|
272
|
+
/* perform initialization for external services. */
|
273
|
+
static void facil_external_init(void) { pubsub_cluster_init(); }
|
274
|
+
|
275
|
+
/* perform cleanup for external services. */
|
276
|
+
static void facil_external_cleanup(void) { fio_cfd_clear(); }
|
277
|
+
|
253
278
|
/* *****************************************************************************
|
254
279
|
The listenning protocol
|
255
280
|
***************************************************************************** */
|
@@ -264,9 +289,10 @@ struct ListenerProtocol {
|
|
264
289
|
void *udata;
|
265
290
|
void *rw_udata;
|
266
291
|
sock_rw_hook_s *(*set_rw_hooks)(intptr_t uuid, void *udata);
|
267
|
-
void (*
|
268
|
-
void (*
|
269
|
-
|
292
|
+
void (*on_finish_rw)(intptr_t uuid, void *rw_udata);
|
293
|
+
void (*on_start)(intptr_t uuid, void *udata);
|
294
|
+
void (*on_finish)(intptr_t uuid, void *udata);
|
295
|
+
char port[16];
|
270
296
|
};
|
271
297
|
|
272
298
|
static sock_rw_hook_s *listener_set_rw_hooks(intptr_t uuid, void *udata) {
|
@@ -318,21 +344,16 @@ static void listener_on_data(intptr_t uuid, protocol_s *plistener) {
|
|
318
344
|
}
|
319
345
|
defer(listener_deferred_on_open, (void *)new_client, (void *)uuid);
|
320
346
|
defer(deferred_on_data, (void *)uuid, NULL);
|
321
|
-
// // Was, without `deferred_on_data`
|
322
|
-
// struct ListenerProtocol *listener = (void *)plistener;
|
323
|
-
// protocol_s *pr = listener->on_open(new_client, listener->udata);
|
324
|
-
// facil_attach(new_client, pr);
|
325
|
-
// if (!pr)
|
326
|
-
// sock_close(new_client);
|
327
347
|
return;
|
328
348
|
(void)plistener;
|
329
349
|
}
|
330
350
|
|
331
351
|
static void free_listenner(void *li) { free(li); }
|
332
352
|
|
333
|
-
static void listener_on_close(protocol_s *plistener) {
|
353
|
+
static void listener_on_close(intptr_t uuid, protocol_s *plistener) {
|
334
354
|
struct ListenerProtocol *listener = (void *)plistener;
|
335
|
-
listener->on_finish(listener->udata);
|
355
|
+
listener->on_finish(uuid, listener->udata);
|
356
|
+
listener->on_finish_rw(uuid, listener->rw_udata);
|
336
357
|
if (FACIL_PRINT_STATE)
|
337
358
|
fprintf(stderr, "* (%d) Stopped listening on port %s\n", getpid(),
|
338
359
|
listener->port);
|
@@ -342,9 +363,11 @@ static void listener_on_close(protocol_s *plistener) {
|
|
342
363
|
static inline struct ListenerProtocol *
|
343
364
|
listener_alloc(struct facil_listen_args settings) {
|
344
365
|
if (!settings.on_start)
|
345
|
-
settings.on_start =
|
366
|
+
settings.on_start = mock_on_finish;
|
346
367
|
if (!settings.on_finish)
|
347
|
-
settings.on_finish = (void (*)(void *))mock_on_close;
|
368
|
+
settings.on_finish = (void (*)(intptr_t, void *))mock_on_close;
|
369
|
+
if (!settings.on_finish_rw)
|
370
|
+
settings.on_finish_rw = mock_on_finish;
|
348
371
|
if (!settings.set_rw_hooks)
|
349
372
|
settings.set_rw_hooks = listener_set_rw_hooks;
|
350
373
|
struct ListenerProtocol *listener = malloc(sizeof(*listener));
|
@@ -358,10 +381,12 @@ listener_alloc(struct facil_listen_args settings) {
|
|
358
381
|
.udata = settings.udata,
|
359
382
|
.on_start = settings.on_start,
|
360
383
|
.on_finish = settings.on_finish,
|
384
|
+
.on_finish_rw = settings.on_finish_rw,
|
361
385
|
.set_rw_hooks = settings.set_rw_hooks,
|
362
386
|
.rw_udata = settings.rw_udata,
|
363
|
-
.port = settings.port,
|
364
387
|
};
|
388
|
+
size_t tmp = strlen(settings.port);
|
389
|
+
memcpy(listener->port, settings.port, tmp + 1);
|
365
390
|
return listener;
|
366
391
|
}
|
367
392
|
return NULL;
|
@@ -378,7 +403,7 @@ inline static void listener_on_start(size_t fd) {
|
|
378
403
|
// call the on_init callback
|
379
404
|
struct ListenerProtocol *listener =
|
380
405
|
(struct ListenerProtocol *)uuid_data(uuid).protocol;
|
381
|
-
listener->on_start(listener->udata);
|
406
|
+
listener->on_start(uuid, listener->udata);
|
382
407
|
}
|
383
408
|
|
384
409
|
/**
|
@@ -417,10 +442,11 @@ static const char *connector_protocol_name = "connect protocol __internal__";
|
|
417
442
|
struct ConnectProtocol {
|
418
443
|
protocol_s protocol;
|
419
444
|
protocol_s *(*on_connect)(intptr_t uuid, void *udata);
|
420
|
-
void (*on_fail)(void *udata);
|
445
|
+
void (*on_fail)(intptr_t uuid, void *udata);
|
421
446
|
sock_rw_hook_s *(*set_rw_hooks)(intptr_t uuid, void *udata);
|
422
447
|
void *udata;
|
423
448
|
void *rw_udata;
|
449
|
+
intptr_t uuid;
|
424
450
|
int opened;
|
425
451
|
};
|
426
452
|
|
@@ -447,22 +473,23 @@ static void connector_on_data(intptr_t uuid, protocol_s *connector) {
|
|
447
473
|
defer(deferred_on_data, (void *)uuid, NULL);
|
448
474
|
}
|
449
475
|
|
450
|
-
static void connector_on_close(protocol_s *pconnector) {
|
476
|
+
static void connector_on_close(intptr_t uuid, protocol_s *pconnector) {
|
451
477
|
struct ConnectProtocol *connector = (void *)pconnector;
|
452
478
|
if (connector->opened == 0 && connector->on_fail)
|
453
|
-
connector->on_fail(connector->udata);
|
479
|
+
connector->on_fail(connector->uuid, connector->udata);
|
454
480
|
free(connector);
|
481
|
+
(void)uuid;
|
455
482
|
}
|
456
483
|
|
457
484
|
#undef facil_connect
|
458
485
|
intptr_t facil_connect(struct facil_connect_args opt) {
|
459
486
|
if (!opt.address || !opt.port || !opt.on_connect)
|
460
|
-
|
487
|
+
goto error;
|
461
488
|
if (!opt.set_rw_hooks)
|
462
489
|
opt.set_rw_hooks = listener_set_rw_hooks;
|
463
|
-
if (!facil_data->last_cycle)
|
464
|
-
time(&facil_data->last_cycle);
|
465
490
|
struct ConnectProtocol *connector = malloc(sizeof(*connector));
|
491
|
+
if (!connector)
|
492
|
+
goto error;
|
466
493
|
*connector = (struct ConnectProtocol){
|
467
494
|
.on_connect = opt.on_connect,
|
468
495
|
.on_fail = opt.on_fail,
|
@@ -475,16 +502,18 @@ intptr_t facil_connect(struct facil_connect_args opt) {
|
|
475
502
|
.rw_udata = opt.rw_udata,
|
476
503
|
.opened = 0,
|
477
504
|
};
|
478
|
-
|
479
|
-
return -1;
|
480
|
-
intptr_t uuid = sock_connect(opt.address, opt.port);
|
505
|
+
intptr_t uuid = connector->uuid = sock_connect(opt.address, opt.port);
|
481
506
|
if (uuid == -1)
|
482
|
-
|
507
|
+
goto error;
|
483
508
|
if (facil_attach(uuid, &connector->protocol) == -1) {
|
484
509
|
sock_close(uuid);
|
485
510
|
return -1;
|
486
511
|
}
|
487
512
|
return uuid;
|
513
|
+
error:
|
514
|
+
if (opt.on_fail)
|
515
|
+
opt.on_fail(uuid, opt.udata);
|
516
|
+
return -1;
|
488
517
|
}
|
489
518
|
|
490
519
|
/* *****************************************************************************
|
@@ -519,9 +548,10 @@ static void timer_on_data(intptr_t uuid, protocol_s *protocol) {
|
|
519
548
|
sock_force_close(uuid);
|
520
549
|
}
|
521
550
|
|
522
|
-
static void timer_on_close(protocol_s *protocol) {
|
551
|
+
static void timer_on_close(intptr_t uuid, protocol_s *protocol) {
|
523
552
|
prot2timer(protocol).on_finish(prot2timer(protocol).arg);
|
524
553
|
free(protocol);
|
554
|
+
(void)uuid;
|
525
555
|
}
|
526
556
|
|
527
557
|
static inline timer_protocol_s *timer_alloc(void (*task)(void *), void *arg,
|
@@ -606,15 +636,11 @@ static struct {
|
|
606
636
|
.handlers.prev = &facil_cluster_data.handlers,
|
607
637
|
.lock = SPN_LOCK_INIT};
|
608
638
|
|
609
|
-
/* internal support for the default pub/sub cluster engin */
|
610
|
-
#pragma weak pubsub_cluster_init
|
611
|
-
void pubsub_cluster_init(void) {}
|
612
|
-
|
613
639
|
/* message handler */
|
614
640
|
typedef struct {
|
615
641
|
fio_list_s list;
|
616
642
|
void (*on_message)(void *data, uint32_t len);
|
617
|
-
|
643
|
+
int32_t msg_type;
|
618
644
|
} fio_cluster_handler;
|
619
645
|
|
620
646
|
/* message sending and protocol. */
|
@@ -623,7 +649,7 @@ struct facil_cluster_msg_packet {
|
|
623
649
|
spn_lock_i lock;
|
624
650
|
struct facil_cluster_msg {
|
625
651
|
uint32_t len;
|
626
|
-
|
652
|
+
int32_t msg_type;
|
627
653
|
} payload;
|
628
654
|
uint8_t data[];
|
629
655
|
};
|
@@ -653,7 +679,7 @@ static void facil_cluster_handle_msg(struct facil_cluster_msg *msg) {
|
|
653
679
|
static char *facil_cluster_protocol_id = "facil_io_internal_cluster_protocol";
|
654
680
|
|
655
681
|
/* cluster protocol on_close callback */
|
656
|
-
static void facil_cluster_on_close(protocol_s *pr_) {
|
682
|
+
static void facil_cluster_on_close(intptr_t uuid, protocol_s *pr_) {
|
657
683
|
struct facil_cluster_protocol *pr = (struct facil_cluster_protocol *)pr_;
|
658
684
|
if (pr->msg)
|
659
685
|
free(pr->msg);
|
@@ -663,6 +689,7 @@ static void facil_cluster_on_close(protocol_s *pr_) {
|
|
663
689
|
fprintf(stderr, "ERROR: facil cluster member (%d) closed prematurely.\n",
|
664
690
|
defer_fork_pid());
|
665
691
|
#endif
|
692
|
+
(void)uuid;
|
666
693
|
}
|
667
694
|
|
668
695
|
/* cluster protocol on_data callback */
|
@@ -758,7 +785,6 @@ static void facil_cluster_init(uint16_t count) {
|
|
758
785
|
facil_attach(facil_cluster_data.pipes[i].in, &stub_protocol);
|
759
786
|
facil_attach(facil_cluster_data.pipes[i].out, &stub_protocol);
|
760
787
|
}
|
761
|
-
pubsub_cluster_init();
|
762
788
|
defer(facil_cluster_register, NULL, NULL);
|
763
789
|
return;
|
764
790
|
error:
|
@@ -782,7 +808,7 @@ static void facil_cluster_destroy(void) {
|
|
782
808
|
facil_cluster_data.pipes = NULL;
|
783
809
|
}
|
784
810
|
|
785
|
-
void facil_cluster_set_handler(
|
811
|
+
void facil_cluster_set_handler(int32_t msg_type,
|
786
812
|
void (*on_message)(void *data, uint32_t len)) {
|
787
813
|
fio_cluster_handler *hnd;
|
788
814
|
spn_lock(&facil_cluster_data.lock);
|
@@ -810,7 +836,7 @@ static void facil_msg_free(void *msg_) {
|
|
810
836
|
}
|
811
837
|
free(msg);
|
812
838
|
}
|
813
|
-
int facil_cluster_send(
|
839
|
+
int facil_cluster_send(int32_t msg_type, void *data, uint32_t len) {
|
814
840
|
if (!defer_fork_is_active()) {
|
815
841
|
#ifdef DEBUG
|
816
842
|
fprintf(stderr,
|
@@ -893,18 +919,24 @@ static void facil_cycle(void *arg, void *ignr) {
|
|
893
919
|
(void)ignr;
|
894
920
|
static int idle = 0;
|
895
921
|
time(&facil_data->last_cycle);
|
896
|
-
int events
|
897
|
-
if (
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
922
|
+
int events;
|
923
|
+
if (defer_has_queue()) {
|
924
|
+
events = evio_review(0);
|
925
|
+
if (events < 0)
|
926
|
+
goto error;
|
927
|
+
if (events > 0)
|
928
|
+
idle = 1;
|
929
|
+
} else {
|
930
|
+
events = evio_review(512);
|
931
|
+
if (events < 0)
|
932
|
+
goto error;
|
933
|
+
if (events > 0) {
|
934
|
+
idle = 1;
|
935
|
+
} else if (idle) {
|
936
|
+
((struct facil_run_args *)arg)->on_idle();
|
937
|
+
idle = 0;
|
938
|
+
}
|
906
939
|
}
|
907
|
-
finish:
|
908
940
|
if (!defer_fork_is_active())
|
909
941
|
return;
|
910
942
|
if (facil_data->need_review) {
|
@@ -932,6 +964,7 @@ static void facil_init_run(void *arg, void *arg2) {
|
|
932
964
|
}
|
933
965
|
}
|
934
966
|
facil_data->need_review = 1;
|
967
|
+
facil_external_init();
|
935
968
|
defer(facil_cycle, arg, NULL);
|
936
969
|
}
|
937
970
|
|
@@ -950,6 +983,7 @@ static void facil_cleanup(void *arg) {
|
|
950
983
|
defer_perform();
|
951
984
|
evio_close();
|
952
985
|
facil_cluster_destroy();
|
986
|
+
facil_external_cleanup();
|
953
987
|
}
|
954
988
|
|
955
989
|
#undef facil_run
|
@@ -1013,18 +1047,19 @@ int facil_attach(intptr_t uuid, protocol_s *protocol) {
|
|
1013
1047
|
protocol->on_shutdown = mock_on_ev;
|
1014
1048
|
protocol->rsv = 0;
|
1015
1049
|
}
|
1050
|
+
spn_lock(&uuid_data(uuid).lock);
|
1016
1051
|
if (!sock_isvalid(uuid)) {
|
1052
|
+
spn_unlock(&uuid_data(uuid).lock);
|
1017
1053
|
if (protocol)
|
1018
|
-
defer(deferred_on_close,
|
1054
|
+
defer(deferred_on_close, (void *)uuid, protocol);
|
1019
1055
|
return -1;
|
1020
1056
|
}
|
1021
|
-
spn_lock(&uuid_data(uuid).lock);
|
1022
1057
|
protocol_s *old_protocol = uuid_data(uuid).protocol;
|
1023
1058
|
uuid_data(uuid).protocol = protocol;
|
1024
1059
|
uuid_data(uuid).active = facil_data->last_cycle;
|
1025
1060
|
spn_unlock(&uuid_data(uuid).lock);
|
1026
1061
|
if (old_protocol)
|
1027
|
-
defer(deferred_on_close,
|
1062
|
+
defer(deferred_on_close, (void *)uuid, old_protocol);
|
1028
1063
|
if (evio_isactive())
|
1029
1064
|
evio_add(sock_uuid2fd(uuid), (void *)uuid);
|
1030
1065
|
return 0;
|
@@ -1048,11 +1083,13 @@ Misc helpers
|
|
1048
1083
|
/**
|
1049
1084
|
Returns the last time the server reviewed any pending IO events.
|
1050
1085
|
*/
|
1051
|
-
time_t facil_last_tick(void) {
|
1086
|
+
time_t facil_last_tick(void) {
|
1087
|
+
return facil_data ? facil_data->last_cycle : time(NULL);
|
1088
|
+
}
|
1052
1089
|
|
1053
1090
|
/**
|
1054
|
-
* This function allows out-of-task access to a connection's `protocol_s`
|
1055
|
-
* by attempting to lock it.
|
1091
|
+
* This function allows out-of-task access to a connection's `protocol_s`
|
1092
|
+
* object by attempting to lock it.
|
1056
1093
|
*/
|
1057
1094
|
protocol_s *facil_protocol_try_lock(intptr_t uuid,
|
1058
1095
|
enum facil_protocol_lock_e type) {
|
@@ -1118,12 +1155,17 @@ static void perform_single_task(void *v_uuid, void *v_task) {
|
|
1118
1155
|
protocol_s *pr = protocol_try_lock(sock_uuid2fd(v_uuid), task->task_type);
|
1119
1156
|
if (!pr)
|
1120
1157
|
goto defer;
|
1158
|
+
if (pr->service == connector_protocol_name) {
|
1159
|
+
protocol_unlock(pr, task->task_type);
|
1160
|
+
goto defer;
|
1161
|
+
}
|
1121
1162
|
task->func((intptr_t)v_uuid, pr, task->arg);
|
1122
1163
|
protocol_unlock(pr, task->task_type);
|
1123
1164
|
free_facil_task(task);
|
1124
1165
|
return;
|
1125
1166
|
fallback:
|
1126
1167
|
task->on_done((intptr_t)v_uuid, task->arg);
|
1168
|
+
free_facil_task(task);
|
1127
1169
|
return;
|
1128
1170
|
defer:
|
1129
1171
|
defer(perform_single_task, v_uuid, v_task);
|