rage-iodine 5.5.0 → 5.6.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/CHANGELOG.md +4 -0
- data/Gemfile +2 -1
- data/ext/iodine/fio.c +97 -0
- data/ext/iodine/fio.h +13 -0
- data/ext/iodine/iodine.c +3 -0
- data/ext/iodine/iodine.h +1 -0
- data/ext/iodine/iodine_defer.c +1 -0
- data/ext/iodine/iodine_perf.c +28 -0
- data/ext/iodine/iodine_perf.h +6 -0
- data/lib/iodine/version.rb +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7ffa46cab7e0fb7fc7550dd142f42b0850287fee60cc0d72b7f52757f52720f7
|
|
4
|
+
data.tar.gz: c51b8ad9e316c21ed06e6803dcfb5af7bf70fc3eee84a0fd179b2730d2572473
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fa99ee4e7abb10b55b6f14aeeaef6bf03e85cf8aff9b33a66f7b4f64097c5ef824e0c3de6663caf00f5404b2d08b663debb60c796a0a44490138a96ac92a832c
|
|
7
|
+
data.tar.gz: ca2a4ac6f633955b202dccf09661cb7799ae92e16078ef3776c1648e18e2b1ab620f470f4b99b3c75b7d0e8f9b064fad180fd5c9b32ab6ae0ddd60c9d601b58d
|
data/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,10 @@ Please notice that this change log contains changes for upcoming releases as wel
|
|
|
6
6
|
|
|
7
7
|
## Changes:
|
|
8
8
|
|
|
9
|
+
#### Change log v.5.6.0 (2026-09-06)
|
|
10
|
+
|
|
11
|
+
**Update**: TCP Socket Listen: Accept Queue
|
|
12
|
+
|
|
9
13
|
#### Change log v.5.5.0 (2026-07-06)
|
|
10
14
|
|
|
11
15
|
**Update**: Update `pre_start` callbacks to fail the server launch in case of errors
|
data/Gemfile
CHANGED
data/ext/iodine/fio.c
CHANGED
|
@@ -4532,10 +4532,22 @@ Initialize the library
|
|
|
4532
4532
|
|
|
4533
4533
|
static void fio_pubsub_on_fork(void);
|
|
4534
4534
|
|
|
4535
|
+
#if defined(__linux__)
|
|
4536
|
+
/* accept-queue tracking lock for the listener registry (defined alongside
|
|
4537
|
+
* fio_accept_queue_listeners in the listener section below); declared here
|
|
4538
|
+
* so fio_on_fork can reset it across children. */
|
|
4539
|
+
static fio_lock_i fio_accept_queue_lock;
|
|
4540
|
+
#endif
|
|
4541
|
+
|
|
4535
4542
|
/* Called within a child process after it starts. */
|
|
4536
4543
|
static void fio_on_fork(void) {
|
|
4537
4544
|
fio_timer_lock = FIO_LOCK_INIT;
|
|
4538
4545
|
fio_data->lock = FIO_LOCK_INIT;
|
|
4546
|
+
#if defined(__linux__)
|
|
4547
|
+
/* a forked child may inherit the accept-queue lock while a parent thread
|
|
4548
|
+
* held it mid-walk; that thread won't exist in the child, so reset it. */
|
|
4549
|
+
fio_accept_queue_lock = FIO_LOCK_INIT;
|
|
4550
|
+
#endif
|
|
4539
4551
|
fio_defer_on_fork();
|
|
4540
4552
|
fio_malloc_after_fork();
|
|
4541
4553
|
fio_poll_init();
|
|
@@ -5571,6 +5583,14 @@ The listening protocol (use the facil.io API to make a socket and attach it)
|
|
|
5571
5583
|
typedef struct {
|
|
5572
5584
|
fio_protocol_s pr;
|
|
5573
5585
|
intptr_t uuid;
|
|
5586
|
+
#if defined(__linux__)
|
|
5587
|
+
/**
|
|
5588
|
+
* Listener node adding this listener into to fio_accept_queue_listeners,
|
|
5589
|
+
* so Iodine::Perf.queued_connections can find its socket's fd and read its
|
|
5590
|
+
* kernel length accept-queue(AcceptQ):backlog where (backlog <= somaxconn) (TCP_INFO).
|
|
5591
|
+
*/
|
|
5592
|
+
fio_ls_embd_s listener_node;
|
|
5593
|
+
#endif
|
|
5574
5594
|
void *udata;
|
|
5575
5595
|
void (*on_open)(intptr_t uuid, void *udata);
|
|
5576
5596
|
void (*on_start)(intptr_t uuid, void *udata);
|
|
@@ -5582,8 +5602,20 @@ typedef struct {
|
|
|
5582
5602
|
void *tls;
|
|
5583
5603
|
} fio_listen_protocol_s;
|
|
5584
5604
|
|
|
5605
|
+
#if defined(__linux__)
|
|
5606
|
+
/* tracks iodine's listening sockets for the accept-queue backlog query.
|
|
5607
|
+
* guarded against concurrent teardown (reactor thread, no GVL) */
|
|
5608
|
+
static fio_ls_embd_s fio_accept_queue_listeners = FIO_LS_INIT(fio_accept_queue_listeners);
|
|
5609
|
+
static fio_lock_i fio_accept_queue_lock = FIO_LOCK_INIT;
|
|
5610
|
+
#endif
|
|
5611
|
+
|
|
5585
5612
|
static void fio_listen_cleanup_task(void *pr_) {
|
|
5586
5613
|
fio_listen_protocol_s *pr = pr_;
|
|
5614
|
+
#if defined(__linux__)
|
|
5615
|
+
fio_lock(&fio_accept_queue_lock);
|
|
5616
|
+
fio_ls_embd_remove(&pr->listener_node);
|
|
5617
|
+
fio_unlock(&fio_accept_queue_lock);
|
|
5618
|
+
#endif
|
|
5587
5619
|
#ifndef __MINGW32__
|
|
5588
5620
|
if (pr->tls)
|
|
5589
5621
|
fio_tls_destroy(pr->tls);
|
|
@@ -5733,6 +5765,12 @@ intptr_t fio_listen FIO_IGNORE_MACRO(struct fio_listen_args args) {
|
|
|
5733
5765
|
if (port_len)
|
|
5734
5766
|
memcpy(pr->port, args.port, port_len + 1);
|
|
5735
5767
|
|
|
5768
|
+
#if defined(__linux__)
|
|
5769
|
+
fio_lock(&fio_accept_queue_lock);
|
|
5770
|
+
fio_ls_embd_push(&fio_accept_queue_listeners, &pr->listener_node);
|
|
5771
|
+
fio_unlock(&fio_accept_queue_lock);
|
|
5772
|
+
#endif
|
|
5773
|
+
|
|
5736
5774
|
if (fio_is_running()) {
|
|
5737
5775
|
fio_attach(pr->uuid, &pr->pr);
|
|
5738
5776
|
} else {
|
|
@@ -5753,6 +5791,65 @@ error:
|
|
|
5753
5791
|
return -1;
|
|
5754
5792
|
}
|
|
5755
5793
|
|
|
5794
|
+
/* -------------------------------------------------------------------------
|
|
5795
|
+
* Kernel accept-queue(AcceptQ) which is Queue length: backlog, where backlog <= somaxconn
|
|
5796
|
+
* "backlog are established connections waiting for accept()" = sk_ack_backlog.
|
|
5797
|
+
* Returns the sum of the accept-queues of all iodine listening sockets, or 0.
|
|
5798
|
+
* ---------------------------------------------------------------------- */
|
|
5799
|
+
#if defined(__linux__)
|
|
5800
|
+
intptr_t fio_queued_connections(void) {
|
|
5801
|
+
intptr_t backlog = 0;
|
|
5802
|
+
|
|
5803
|
+
fio_lock(&fio_accept_queue_lock);
|
|
5804
|
+
/**
|
|
5805
|
+
* Walk every registered listener and sum its kernel accept-queue depth/length.
|
|
5806
|
+
* The list always begins with a permanent head node (fio_accept_queue_listeners)
|
|
5807
|
+
* that works like a fixed bookmark: it holds no listener of its own, real nodes
|
|
5808
|
+
* are chained after it, and the last node links back to it, forming a circle
|
|
5809
|
+
* i.e a circular linked list also it's a doubly linked list.
|
|
5810
|
+
*
|
|
5811
|
+
* So the loop:
|
|
5812
|
+
* - starts at `.next`, i.e. the FIRST REAL node starting at the head
|
|
5813
|
+
* itself would be wrong, since it owns no listener and converting it
|
|
5814
|
+
* with FIO_LS_EMBD_OBJ would produce a bogus pointer;
|
|
5815
|
+
* - stops when it arrives back at the head, meaning every real node
|
|
5816
|
+
* has been visited;
|
|
5817
|
+
* - runs zero times on an empty list, because a lone head simply
|
|
5818
|
+
* points at itself.
|
|
5819
|
+
*/
|
|
5820
|
+
for (fio_ls_embd_s *pos = fio_accept_queue_listeners.next; pos != &fio_accept_queue_listeners; pos = pos->next) {
|
|
5821
|
+
fio_listen_protocol_s *pr = FIO_LS_EMBD_OBJ(fio_listen_protocol_s, listener_node, pos);
|
|
5822
|
+
struct tcp_info info;
|
|
5823
|
+
socklen_t tlen = sizeof(info);
|
|
5824
|
+
int fd = fio_uuid2fd(pr->uuid);
|
|
5825
|
+
|
|
5826
|
+
fio_lock(&fd_data(fd).protocol_lock);
|
|
5827
|
+
|
|
5828
|
+
/* Skip sockets that were closed or reused before we could query them.
|
|
5829
|
+
* Callers must run this after listeners are attached (e.g. from within
|
|
5830
|
+
* Iodine.run / a background thread), so the listener's protocol slot is
|
|
5831
|
+
* populated and the checks below are meaningful. */
|
|
5832
|
+
if (!uuid_is_valid(pr->uuid) || fd_data(fd).protocol != &pr->pr) {
|
|
5833
|
+
fio_unlock(&fd_data(fd).protocol_lock);
|
|
5834
|
+
continue;
|
|
5835
|
+
}
|
|
5836
|
+
|
|
5837
|
+
int ok = !getsockopt(fd, IPPROTO_TCP, TCP_INFO, &info, &tlen);
|
|
5838
|
+
|
|
5839
|
+
fio_unlock(&fd_data(fd).protocol_lock);
|
|
5840
|
+
|
|
5841
|
+
if (!ok) {
|
|
5842
|
+
continue;
|
|
5843
|
+
}
|
|
5844
|
+
|
|
5845
|
+
backlog += (intptr_t)info.tcpi_unacked;
|
|
5846
|
+
}
|
|
5847
|
+
fio_unlock(&fio_accept_queue_lock);
|
|
5848
|
+
|
|
5849
|
+
return backlog;
|
|
5850
|
+
}
|
|
5851
|
+
#endif
|
|
5852
|
+
|
|
5756
5853
|
/* *****************************************************************************
|
|
5757
5854
|
Section Start Marker
|
|
5758
5855
|
|
data/ext/iodine/fio.h
CHANGED
|
@@ -1111,6 +1111,19 @@ intptr_t fio_socket(const char *address, const char *port, uint8_t is_server);
|
|
|
1111
1111
|
*/
|
|
1112
1112
|
intptr_t fio_accept(intptr_t srv_uuid);
|
|
1113
1113
|
|
|
1114
|
+
/**
|
|
1115
|
+
* Returns the number of established connections currently parked in the
|
|
1116
|
+
* kernel's accept queue(s) (sk_ack_backlog) of all iodine listening sockets.
|
|
1117
|
+
*
|
|
1118
|
+
* The query goes straight to the kernel via getsockopt(TCP_INFO).
|
|
1119
|
+
*
|
|
1120
|
+
* Returns the total accept queue length across all iodine listeners, or 0
|
|
1121
|
+
* when there are no listeners.
|
|
1122
|
+
*/
|
|
1123
|
+
#if defined(__linux__)
|
|
1124
|
+
intptr_t fio_queued_connections(void);
|
|
1125
|
+
#endif /* linux only */
|
|
1126
|
+
|
|
1114
1127
|
/**
|
|
1115
1128
|
* Returns 1 if the uuid refers to a valid and open, socket.
|
|
1116
1129
|
*
|
data/ext/iodine/iodine.c
CHANGED
|
@@ -1401,6 +1401,9 @@ void Init_iodine_ext(void) {
|
|
|
1401
1401
|
// initialize concurrency related methods
|
|
1402
1402
|
iodine_defer_initialize();
|
|
1403
1403
|
|
|
1404
|
+
// initialize performance metrics
|
|
1405
|
+
iodine_perf_initialize();
|
|
1406
|
+
|
|
1404
1407
|
// initialize the connection class
|
|
1405
1408
|
iodine_connection_init();
|
|
1406
1409
|
|
data/ext/iodine/iodine.h
CHANGED
data/ext/iodine/iodine_defer.c
CHANGED
|
@@ -415,6 +415,7 @@ static void iodine_defer_on_finish(void *ignr) {
|
|
|
415
415
|
iodine_join_io_thread();
|
|
416
416
|
}
|
|
417
417
|
|
|
418
|
+
|
|
418
419
|
/* *****************************************************************************
|
|
419
420
|
Add defer API to Iodine
|
|
420
421
|
***************************************************************************** */
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#include "iodine.h"
|
|
2
|
+
|
|
3
|
+
/* *****************************************************************************
|
|
4
|
+
Performance metrics
|
|
5
|
+
***************************************************************************** */
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Iodine::Perf.queued_connections
|
|
9
|
+
*
|
|
10
|
+
* Returns the total number of established connections currently parked in
|
|
11
|
+
* the kernel's accept queue(s) (sk_ack_backlog) for all iodine listening
|
|
12
|
+
* sockets. Returns 0 when there are no listeners and nil on non-Linux systems.
|
|
13
|
+
*/
|
|
14
|
+
static VALUE iodine_perf_queued_connections(VALUE self) {
|
|
15
|
+
(void)self;
|
|
16
|
+
#if defined(__linux__)
|
|
17
|
+
intptr_t backlog = fio_queued_connections();
|
|
18
|
+
return INT2NUM((long)backlog);
|
|
19
|
+
#else
|
|
20
|
+
return Qnil;
|
|
21
|
+
#endif
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
void iodine_perf_initialize(void) {
|
|
25
|
+
VALUE IodinePerfModule = rb_define_module_under(IodineModule, "Perf");
|
|
26
|
+
rb_define_module_function(IodinePerfModule, "queued_connections",
|
|
27
|
+
iodine_perf_queued_connections, 0);
|
|
28
|
+
}
|
data/lib/iodine/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rage-iodine
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 5.
|
|
4
|
+
version: 5.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Boaz Segev
|
|
@@ -217,6 +217,8 @@ files:
|
|
|
217
217
|
- ext/iodine/iodine_json.h
|
|
218
218
|
- ext/iodine/iodine_mustache.c
|
|
219
219
|
- ext/iodine/iodine_mustache.h
|
|
220
|
+
- ext/iodine/iodine_perf.c
|
|
221
|
+
- ext/iodine/iodine_perf.h
|
|
220
222
|
- ext/iodine/iodine_pubsub.c
|
|
221
223
|
- ext/iodine/iodine_pubsub.h
|
|
222
224
|
- ext/iodine/iodine_rack_io.c
|