rage-iodine 5.5.0 → 6.0.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 +8 -0
- data/Gemfile +2 -1
- data/ext/iodine/fio.c +126 -15
- data/ext/iodine/fio.h +25 -4
- 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/ext/iodine/scheduler.c +76 -20
- 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: 1595ec4d4f155fbc845b37ad096018a2a4bfa4f884c0ef96b7112d268fe86e89
|
|
4
|
+
data.tar.gz: 3185d0901b132a329509238b5188dcd29de1d4145a018adda6b3f9f215e008cf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4bbaa335fcd6202ac41a6449a5d8a38302c786b69348b66af733520e83c27bf4529c8a0e90dc7db5f19f8755aadfaf0c71edeb07fea904664b2cbf573da573f0
|
|
7
|
+
data.tar.gz: 991187eeb695f2128f83859e1025d62d580a1e41fc672822aaf7c8e5130edf15c83721e263a30799311766627fbd132393b50987486d137004f7ae439d11d0b8
|
data/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,14 @@ Please notice that this change log contains changes for upcoming releases as wel
|
|
|
6
6
|
|
|
7
7
|
## Changes:
|
|
8
8
|
|
|
9
|
+
#### Change log v.6.0.0 (2026-09-06)
|
|
10
|
+
|
|
11
|
+
**Update**: Update scheduler `read`/`write` hooks
|
|
12
|
+
|
|
13
|
+
#### Change log v.5.6.0 (2026-09-06)
|
|
14
|
+
|
|
15
|
+
**Update**: TCP Socket Listen: Accept Queue
|
|
16
|
+
|
|
9
17
|
#### Change log v.5.5.0 (2026-07-06)
|
|
10
18
|
|
|
11
19
|
**Update**: Update `pre_start` callbacks to fail the server launch in case of errors
|
data/Gemfile
CHANGED
data/ext/iodine/fio.c
CHANGED
|
@@ -3687,12 +3687,12 @@ retry_int:
|
|
|
3687
3687
|
}
|
|
3688
3688
|
|
|
3689
3689
|
/**
|
|
3690
|
-
*
|
|
3691
|
-
* socker on error.
|
|
3690
|
+
* Performs a single read operation using the connection's read hook.
|
|
3692
3691
|
*
|
|
3693
|
-
* The
|
|
3692
|
+
* The return value and errno match the underlying read operation. The socket
|
|
3693
|
+
* isn't closed on error.
|
|
3694
3694
|
*/
|
|
3695
|
-
ssize_t
|
|
3695
|
+
ssize_t fio_read_once(intptr_t uuid, void *buffer, size_t count) {
|
|
3696
3696
|
if (!uuid_is_valid(uuid) || !uuid_data(uuid).open) {
|
|
3697
3697
|
errno = EBADF;
|
|
3698
3698
|
return -1;
|
|
@@ -3704,22 +3704,36 @@ ssize_t fio_read_unsafe(intptr_t uuid, void *buffer, size_t count) {
|
|
|
3704
3704
|
uuid_data(uuid).rw_hooks->read;
|
|
3705
3705
|
void *udata = uuid_data(uuid).rw_udata;
|
|
3706
3706
|
fio_unlock(&uuid_data(uuid).sock_lock);
|
|
3707
|
-
|
|
3708
|
-
ssize_t ret;
|
|
3709
|
-
retry_int:
|
|
3710
|
-
ret = rw_read(uuid, udata, buffer, count);
|
|
3707
|
+
ssize_t ret = rw_read(uuid, udata, buffer, count);
|
|
3711
3708
|
if (ret > 0) {
|
|
3712
3709
|
fio_touch(uuid);
|
|
3713
|
-
return ret;
|
|
3714
3710
|
}
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3711
|
+
return ret;
|
|
3712
|
+
}
|
|
3713
|
+
|
|
3714
|
+
/**
|
|
3715
|
+
* Performs a single write operation using the connection's write hook.
|
|
3716
|
+
*
|
|
3717
|
+
* The return value and errno match the underlying write operation. The socket
|
|
3718
|
+
* isn't closed on error and no data is queued for the reactor.
|
|
3719
|
+
*/
|
|
3720
|
+
ssize_t fio_write_once(intptr_t uuid, const void *buffer, size_t count) {
|
|
3721
|
+
if (!uuid_is_valid(uuid) || !uuid_data(uuid).open) {
|
|
3722
|
+
errno = EBADF;
|
|
3723
|
+
return -1;
|
|
3724
|
+
}
|
|
3725
|
+
if (count == 0)
|
|
3720
3726
|
return 0;
|
|
3727
|
+
fio_lock(&uuid_data(uuid).sock_lock);
|
|
3728
|
+
ssize_t (*rw_write)(intptr_t, void *, const void *, size_t) =
|
|
3729
|
+
uuid_data(uuid).rw_hooks->write;
|
|
3730
|
+
void *udata = uuid_data(uuid).rw_udata;
|
|
3731
|
+
fio_unlock(&uuid_data(uuid).sock_lock);
|
|
3732
|
+
ssize_t ret = rw_write(uuid, udata, buffer, count);
|
|
3733
|
+
if (ret > 0) {
|
|
3734
|
+
fio_touch(uuid);
|
|
3721
3735
|
}
|
|
3722
|
-
return
|
|
3736
|
+
return ret;
|
|
3723
3737
|
}
|
|
3724
3738
|
|
|
3725
3739
|
/**
|
|
@@ -4532,10 +4546,22 @@ Initialize the library
|
|
|
4532
4546
|
|
|
4533
4547
|
static void fio_pubsub_on_fork(void);
|
|
4534
4548
|
|
|
4549
|
+
#if defined(__linux__)
|
|
4550
|
+
/* accept-queue tracking lock for the listener registry (defined alongside
|
|
4551
|
+
* fio_accept_queue_listeners in the listener section below); declared here
|
|
4552
|
+
* so fio_on_fork can reset it across children. */
|
|
4553
|
+
static fio_lock_i fio_accept_queue_lock;
|
|
4554
|
+
#endif
|
|
4555
|
+
|
|
4535
4556
|
/* Called within a child process after it starts. */
|
|
4536
4557
|
static void fio_on_fork(void) {
|
|
4537
4558
|
fio_timer_lock = FIO_LOCK_INIT;
|
|
4538
4559
|
fio_data->lock = FIO_LOCK_INIT;
|
|
4560
|
+
#if defined(__linux__)
|
|
4561
|
+
/* a forked child may inherit the accept-queue lock while a parent thread
|
|
4562
|
+
* held it mid-walk; that thread won't exist in the child, so reset it. */
|
|
4563
|
+
fio_accept_queue_lock = FIO_LOCK_INIT;
|
|
4564
|
+
#endif
|
|
4539
4565
|
fio_defer_on_fork();
|
|
4540
4566
|
fio_malloc_after_fork();
|
|
4541
4567
|
fio_poll_init();
|
|
@@ -5571,6 +5597,14 @@ The listening protocol (use the facil.io API to make a socket and attach it)
|
|
|
5571
5597
|
typedef struct {
|
|
5572
5598
|
fio_protocol_s pr;
|
|
5573
5599
|
intptr_t uuid;
|
|
5600
|
+
#if defined(__linux__)
|
|
5601
|
+
/**
|
|
5602
|
+
* Listener node adding this listener into to fio_accept_queue_listeners,
|
|
5603
|
+
* so Iodine::Perf.queued_connections can find its socket's fd and read its
|
|
5604
|
+
* kernel length accept-queue(AcceptQ):backlog where (backlog <= somaxconn) (TCP_INFO).
|
|
5605
|
+
*/
|
|
5606
|
+
fio_ls_embd_s listener_node;
|
|
5607
|
+
#endif
|
|
5574
5608
|
void *udata;
|
|
5575
5609
|
void (*on_open)(intptr_t uuid, void *udata);
|
|
5576
5610
|
void (*on_start)(intptr_t uuid, void *udata);
|
|
@@ -5582,8 +5616,20 @@ typedef struct {
|
|
|
5582
5616
|
void *tls;
|
|
5583
5617
|
} fio_listen_protocol_s;
|
|
5584
5618
|
|
|
5619
|
+
#if defined(__linux__)
|
|
5620
|
+
/* tracks iodine's listening sockets for the accept-queue backlog query.
|
|
5621
|
+
* guarded against concurrent teardown (reactor thread, no GVL) */
|
|
5622
|
+
static fio_ls_embd_s fio_accept_queue_listeners = FIO_LS_INIT(fio_accept_queue_listeners);
|
|
5623
|
+
static fio_lock_i fio_accept_queue_lock = FIO_LOCK_INIT;
|
|
5624
|
+
#endif
|
|
5625
|
+
|
|
5585
5626
|
static void fio_listen_cleanup_task(void *pr_) {
|
|
5586
5627
|
fio_listen_protocol_s *pr = pr_;
|
|
5628
|
+
#if defined(__linux__)
|
|
5629
|
+
fio_lock(&fio_accept_queue_lock);
|
|
5630
|
+
fio_ls_embd_remove(&pr->listener_node);
|
|
5631
|
+
fio_unlock(&fio_accept_queue_lock);
|
|
5632
|
+
#endif
|
|
5587
5633
|
#ifndef __MINGW32__
|
|
5588
5634
|
if (pr->tls)
|
|
5589
5635
|
fio_tls_destroy(pr->tls);
|
|
@@ -5733,6 +5779,12 @@ intptr_t fio_listen FIO_IGNORE_MACRO(struct fio_listen_args args) {
|
|
|
5733
5779
|
if (port_len)
|
|
5734
5780
|
memcpy(pr->port, args.port, port_len + 1);
|
|
5735
5781
|
|
|
5782
|
+
#if defined(__linux__)
|
|
5783
|
+
fio_lock(&fio_accept_queue_lock);
|
|
5784
|
+
fio_ls_embd_push(&fio_accept_queue_listeners, &pr->listener_node);
|
|
5785
|
+
fio_unlock(&fio_accept_queue_lock);
|
|
5786
|
+
#endif
|
|
5787
|
+
|
|
5736
5788
|
if (fio_is_running()) {
|
|
5737
5789
|
fio_attach(pr->uuid, &pr->pr);
|
|
5738
5790
|
} else {
|
|
@@ -5753,6 +5805,65 @@ error:
|
|
|
5753
5805
|
return -1;
|
|
5754
5806
|
}
|
|
5755
5807
|
|
|
5808
|
+
/* -------------------------------------------------------------------------
|
|
5809
|
+
* Kernel accept-queue(AcceptQ) which is Queue length: backlog, where backlog <= somaxconn
|
|
5810
|
+
* "backlog are established connections waiting for accept()" = sk_ack_backlog.
|
|
5811
|
+
* Returns the sum of the accept-queues of all iodine listening sockets, or 0.
|
|
5812
|
+
* ---------------------------------------------------------------------- */
|
|
5813
|
+
#if defined(__linux__)
|
|
5814
|
+
intptr_t fio_queued_connections(void) {
|
|
5815
|
+
intptr_t backlog = 0;
|
|
5816
|
+
|
|
5817
|
+
fio_lock(&fio_accept_queue_lock);
|
|
5818
|
+
/**
|
|
5819
|
+
* Walk every registered listener and sum its kernel accept-queue depth/length.
|
|
5820
|
+
* The list always begins with a permanent head node (fio_accept_queue_listeners)
|
|
5821
|
+
* that works like a fixed bookmark: it holds no listener of its own, real nodes
|
|
5822
|
+
* are chained after it, and the last node links back to it, forming a circle
|
|
5823
|
+
* i.e a circular linked list also it's a doubly linked list.
|
|
5824
|
+
*
|
|
5825
|
+
* So the loop:
|
|
5826
|
+
* - starts at `.next`, i.e. the FIRST REAL node starting at the head
|
|
5827
|
+
* itself would be wrong, since it owns no listener and converting it
|
|
5828
|
+
* with FIO_LS_EMBD_OBJ would produce a bogus pointer;
|
|
5829
|
+
* - stops when it arrives back at the head, meaning every real node
|
|
5830
|
+
* has been visited;
|
|
5831
|
+
* - runs zero times on an empty list, because a lone head simply
|
|
5832
|
+
* points at itself.
|
|
5833
|
+
*/
|
|
5834
|
+
for (fio_ls_embd_s *pos = fio_accept_queue_listeners.next; pos != &fio_accept_queue_listeners; pos = pos->next) {
|
|
5835
|
+
fio_listen_protocol_s *pr = FIO_LS_EMBD_OBJ(fio_listen_protocol_s, listener_node, pos);
|
|
5836
|
+
struct tcp_info info;
|
|
5837
|
+
socklen_t tlen = sizeof(info);
|
|
5838
|
+
int fd = fio_uuid2fd(pr->uuid);
|
|
5839
|
+
|
|
5840
|
+
fio_lock(&fd_data(fd).protocol_lock);
|
|
5841
|
+
|
|
5842
|
+
/* Skip sockets that were closed or reused before we could query them.
|
|
5843
|
+
* Callers must run this after listeners are attached (e.g. from within
|
|
5844
|
+
* Iodine.run / a background thread), so the listener's protocol slot is
|
|
5845
|
+
* populated and the checks below are meaningful. */
|
|
5846
|
+
if (!uuid_is_valid(pr->uuid) || fd_data(fd).protocol != &pr->pr) {
|
|
5847
|
+
fio_unlock(&fd_data(fd).protocol_lock);
|
|
5848
|
+
continue;
|
|
5849
|
+
}
|
|
5850
|
+
|
|
5851
|
+
int ok = !getsockopt(fd, IPPROTO_TCP, TCP_INFO, &info, &tlen);
|
|
5852
|
+
|
|
5853
|
+
fio_unlock(&fd_data(fd).protocol_lock);
|
|
5854
|
+
|
|
5855
|
+
if (!ok) {
|
|
5856
|
+
continue;
|
|
5857
|
+
}
|
|
5858
|
+
|
|
5859
|
+
backlog += (intptr_t)info.tcpi_unacked;
|
|
5860
|
+
}
|
|
5861
|
+
fio_unlock(&fio_accept_queue_lock);
|
|
5862
|
+
|
|
5863
|
+
return backlog;
|
|
5864
|
+
}
|
|
5865
|
+
#endif
|
|
5866
|
+
|
|
5756
5867
|
/* *****************************************************************************
|
|
5757
5868
|
Section Start Marker
|
|
5758
5869
|
|
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
|
*
|
|
@@ -1185,12 +1198,20 @@ size_t fio_local_addr(char *dest, size_t limit);
|
|
|
1185
1198
|
ssize_t fio_read(intptr_t uuid, void *buffer, size_t count);
|
|
1186
1199
|
|
|
1187
1200
|
/**
|
|
1188
|
-
*
|
|
1189
|
-
*
|
|
1201
|
+
* Performs a single read operation using the connection's read hook.
|
|
1202
|
+
*
|
|
1203
|
+
* The return value and errno match the underlying read operation. The socket
|
|
1204
|
+
* isn't closed on error.
|
|
1205
|
+
*/
|
|
1206
|
+
ssize_t fio_read_once(intptr_t uuid, void *buffer, size_t count);
|
|
1207
|
+
|
|
1208
|
+
/**
|
|
1209
|
+
* Performs a single write operation using the connection's write hook.
|
|
1190
1210
|
*
|
|
1191
|
-
* The
|
|
1211
|
+
* The return value and errno match the underlying write operation. The socket
|
|
1212
|
+
* isn't closed on error and no data is queued for the reactor.
|
|
1192
1213
|
*/
|
|
1193
|
-
ssize_t
|
|
1214
|
+
ssize_t fio_write_once(intptr_t uuid, const void *buffer, size_t count);
|
|
1194
1215
|
|
|
1195
1216
|
/** The following structure is used for `fio_write2_fn` function arguments. */
|
|
1196
1217
|
typedef struct {
|
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/ext/iodine/scheduler.c
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
#include "iodine.h"
|
|
2
2
|
#include "iodine_store.h"
|
|
3
3
|
#include "ruby.h"
|
|
4
|
+
#include "ruby/fiber/scheduler.h"
|
|
5
|
+
#include "ruby/io/buffer.h"
|
|
4
6
|
|
|
5
7
|
#include <errno.h>
|
|
6
8
|
#include <stddef.h>
|
|
@@ -10,7 +12,7 @@
|
|
|
10
12
|
|
|
11
13
|
#include "fio.h"
|
|
12
14
|
|
|
13
|
-
#define IO_MAX_READ
|
|
15
|
+
#define IO_MAX_READ 65536
|
|
14
16
|
|
|
15
17
|
static ID call_id;
|
|
16
18
|
static uint8_t ATTACH_ON_READ_READY_CALLBACK;
|
|
@@ -151,51 +153,104 @@ static VALUE iodine_scheduler_attach(VALUE self, VALUE r_fd, VALUE r_waittype, V
|
|
|
151
153
|
(void)self;
|
|
152
154
|
}
|
|
153
155
|
|
|
154
|
-
static VALUE
|
|
156
|
+
static VALUE iodine_scheduler_write_async(VALUE self, VALUE r_fd, VALUE r_buffer, VALUE r_length, VALUE r_offset) {
|
|
155
157
|
Check_Type(r_fd, T_FIXNUM);
|
|
156
158
|
int fd = FIX2INT(r_fd);
|
|
157
159
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
+
const void *buffer;
|
|
161
|
+
size_t buffer_length;
|
|
162
|
+
rb_io_buffer_get_bytes_for_reading(r_buffer, &buffer, &buffer_length);
|
|
160
163
|
|
|
161
164
|
Check_Type(r_length, T_FIXNUM);
|
|
162
|
-
|
|
165
|
+
size_t length = NUM2SIZET(r_length);
|
|
163
166
|
|
|
164
167
|
Check_Type(r_offset, T_FIXNUM);
|
|
165
|
-
|
|
168
|
+
size_t offset = NUM2SIZET(r_offset);
|
|
169
|
+
|
|
170
|
+
if (offset > buffer_length || length > buffer_length - offset) {
|
|
171
|
+
return rb_fiber_scheduler_io_result(-1, EINVAL);
|
|
172
|
+
}
|
|
173
|
+
if (!length) {
|
|
174
|
+
return r_length;
|
|
175
|
+
}
|
|
166
176
|
|
|
167
177
|
void *cpy = fio_malloc(length);
|
|
168
|
-
memcpy(cpy, buffer, length);
|
|
169
|
-
fio_write2(fio_fd2uuid(fd), .data.buffer = cpy, .length = length, .
|
|
178
|
+
memcpy(cpy, (const char *)buffer + offset, length);
|
|
179
|
+
fio_write2(fio_fd2uuid(fd), .data.buffer = cpy, .length = length, .after.dealloc = fio_free);
|
|
170
180
|
|
|
171
181
|
return r_length;
|
|
172
182
|
|
|
173
183
|
(void)self;
|
|
174
184
|
}
|
|
175
185
|
|
|
176
|
-
static VALUE
|
|
186
|
+
static VALUE iodine_scheduler_write(VALUE self, VALUE r_fd, VALUE r_buffer, VALUE r_length, VALUE r_offset) {
|
|
177
187
|
Check_Type(r_fd, T_FIXNUM);
|
|
178
188
|
int fd = FIX2INT(r_fd);
|
|
179
189
|
|
|
190
|
+
const void *buffer;
|
|
191
|
+
size_t buffer_length;
|
|
192
|
+
rb_io_buffer_get_bytes_for_reading(r_buffer, &buffer, &buffer_length);
|
|
193
|
+
|
|
180
194
|
Check_Type(r_length, T_FIXNUM);
|
|
181
|
-
|
|
195
|
+
size_t length = NUM2SIZET(r_length);
|
|
182
196
|
|
|
183
|
-
|
|
184
|
-
|
|
197
|
+
Check_Type(r_offset, T_FIXNUM);
|
|
198
|
+
size_t offset = NUM2SIZET(r_offset);
|
|
199
|
+
|
|
200
|
+
if (offset > buffer_length || length > buffer_length - offset) {
|
|
201
|
+
return rb_fiber_scheduler_io_result(-1, EINVAL);
|
|
202
|
+
}
|
|
203
|
+
if (!length) {
|
|
204
|
+
return rb_fiber_scheduler_io_result(0, 0);
|
|
185
205
|
}
|
|
186
206
|
|
|
187
|
-
|
|
188
|
-
|
|
207
|
+
ssize_t result = fio_write_once(fio_fd2uuid(fd), (const char *)buffer + offset, length);
|
|
208
|
+
int error = result < 0 ? errno : 0;
|
|
209
|
+
return rb_fiber_scheduler_io_result(result, error);
|
|
210
|
+
|
|
211
|
+
(void)self;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
static VALUE iodine_scheduler_read(VALUE self, VALUE r_fd, VALUE r_buffer, VALUE r_length, VALUE r_offset) {
|
|
215
|
+
Check_Type(r_fd, T_FIXNUM);
|
|
216
|
+
int fd = FIX2INT(r_fd);
|
|
217
|
+
|
|
218
|
+
void *buffer;
|
|
219
|
+
size_t buffer_length;
|
|
220
|
+
rb_io_buffer_get_bytes_for_writing(r_buffer, &buffer, &buffer_length);
|
|
221
|
+
|
|
222
|
+
Check_Type(r_length, T_FIXNUM);
|
|
223
|
+
size_t length = NUM2SIZET(r_length);
|
|
224
|
+
|
|
225
|
+
Check_Type(r_offset, T_FIXNUM);
|
|
226
|
+
size_t offset = NUM2SIZET(r_offset);
|
|
227
|
+
|
|
228
|
+
if (offset > buffer_length || length > buffer_length - offset) {
|
|
229
|
+
return rb_fiber_scheduler_io_result(-1, EINVAL);
|
|
230
|
+
}
|
|
189
231
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
232
|
+
#if RUBY_FIBER_SCHEDULER_VERSION >= 4
|
|
233
|
+
if (length > IO_MAX_READ) {
|
|
234
|
+
length = IO_MAX_READ;
|
|
235
|
+
}
|
|
236
|
+
#else
|
|
237
|
+
if (length == 0) {
|
|
238
|
+
length = buffer_length - offset;
|
|
239
|
+
if (length > IO_MAX_READ) {
|
|
240
|
+
length = IO_MAX_READ;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
#endif
|
|
244
|
+
|
|
245
|
+
if (!length) {
|
|
246
|
+
return rb_fiber_scheduler_io_result(0, 0);
|
|
193
247
|
}
|
|
194
248
|
|
|
195
|
-
|
|
249
|
+
ssize_t result = fio_read_once(fio_fd2uuid(fd), (char *)buffer + offset, length);
|
|
250
|
+
int error = result < 0 ? errno : 0;
|
|
251
|
+
return rb_fiber_scheduler_io_result(result, error);
|
|
196
252
|
|
|
197
253
|
(void)self;
|
|
198
|
-
(void)r_offset;
|
|
199
254
|
}
|
|
200
255
|
|
|
201
256
|
static VALUE iodine_scheduler_close(VALUE self) {
|
|
@@ -219,8 +274,9 @@ void iodine_scheduler_initialize(void) {
|
|
|
219
274
|
VALUE SchedulerModule = rb_define_module_under(IodineModule, "Scheduler");
|
|
220
275
|
|
|
221
276
|
rb_define_module_function(SchedulerModule, "attach", iodine_scheduler_attach, 3);
|
|
277
|
+
rb_define_module_function(SchedulerModule, "write_async", iodine_scheduler_write_async, 4);
|
|
222
278
|
rb_define_module_function(SchedulerModule, "write", iodine_scheduler_write, 4);
|
|
223
|
-
rb_define_module_function(SchedulerModule, "read", iodine_scheduler_read,
|
|
279
|
+
rb_define_module_function(SchedulerModule, "read", iodine_scheduler_read, 4);
|
|
224
280
|
rb_define_module_function(SchedulerModule, "close", iodine_scheduler_close, 0);
|
|
225
281
|
|
|
226
282
|
VALUE cIO = rb_const_get(rb_cObject, rb_intern2("IO", 2));
|
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:
|
|
4
|
+
version: 6.0.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
|