uringmachine 0.32.0 → 0.33.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 +5 -0
- data/TODO.md +40 -22
- data/docs/um_api.md +4 -9
- data/ext/um/um.c +21 -76
- data/ext/um/um.h +3 -22
- data/ext/um/um_class.c +11 -65
- data/ext/um/um_io.c +0 -1
- data/ext/um/um_op.c +0 -1
- data/ext/um/um_utils.c +0 -86
- data/lib/uringmachine/version.rb +1 -1
- data/test/test_io.rb +34 -34
- data/test/test_um.rb +10 -88
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b6b62f0845e3bc8044bb1a21481d44c231d07a0fa191a92c7d4916ca6005a076
|
|
4
|
+
data.tar.gz: 7d2533a8c3c7c1fcc5d03c183a39a7fb789a2f05510cfbdce5bc08d9744969f3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a3d7b2d5ae670304d8540fd6684c3e2a8548c491866cbd3a2ddf1fb65034517f55b6faa41da4f7a8965d243cd86ae965c3ad3e6cb2d5026097ac36cdf4911d8b
|
|
7
|
+
data.tar.gz: 800d1c0fe51d8399aefd799efe3338e060c15a6a072b86b33078696f2920f84e59d138e97dd4518eb71d2a00f7ac7c5dc8860caef3d24a645486946291a09dba
|
data/CHANGELOG.md
CHANGED
data/TODO.md
CHANGED
|
@@ -1,28 +1,13 @@
|
|
|
1
|
-
- Rename Connection to IO
|
|
2
|
-
|
|
3
|
-
```ruby
|
|
4
|
-
io = machine.io(fd)
|
|
5
|
-
l = io.read_line(4)
|
|
6
|
-
io.write('foo')
|
|
7
|
-
```
|
|
8
|
-
|
|
9
|
-
- Add `IO#fd`/`IO#target` method
|
|
10
|
-
|
|
11
|
-
- Add `UM#inspect` (show size, modes)
|
|
12
|
-
- Add `UM::IO#inspect` (show target, mode, pending bytes)
|
|
13
|
-
|
|
14
|
-
## Reimplement multishot read/recv using buffer pool
|
|
15
|
-
|
|
16
|
-
- remove `#setup_buffer_ring` method
|
|
17
|
-
- use buffer pool, just like UM::Connection
|
|
18
|
-
|
|
19
1
|
## immediate
|
|
20
2
|
|
|
3
|
+
- Add `IO#http_xxx` methods
|
|
4
|
+
- `#http_read_request_headers()`
|
|
5
|
+
- `#http_read_body(content_length)` (-1 means chunked TE)
|
|
6
|
+
|
|
21
7
|
- Add tests for support for Set in `machine#await`
|
|
22
8
|
- Add tests for support for Set, Array in `machine#join`
|
|
23
9
|
- Add `UM#read_file` for reading entire file
|
|
24
10
|
- Add `UM#write_file` for writing entire file
|
|
25
|
-
- Rename stream methods: `:fd`, `:socket`, `:ssl`
|
|
26
11
|
|
|
27
12
|
## Balancing I/O with the runqueue
|
|
28
13
|
|
|
@@ -48,7 +33,7 @@
|
|
|
48
33
|
- debounce
|
|
49
34
|
|
|
50
35
|
```ruby
|
|
51
|
-
debouncer = machine.debounce { }
|
|
36
|
+
debouncer = machine.debounce { ... }
|
|
52
37
|
```
|
|
53
38
|
|
|
54
39
|
- happy eyeballs algo for TCP connect
|
|
@@ -104,8 +89,6 @@
|
|
|
104
89
|
When doing a `call`, we need to provide a mailbox for the response. can this be
|
|
105
90
|
automatic?
|
|
106
91
|
|
|
107
|
-
##
|
|
108
|
-
|
|
109
92
|
## Syntax / pattern for launching/supervising multiple operations
|
|
110
93
|
|
|
111
94
|
Select (see above):
|
|
@@ -125,3 +108,38 @@ machine.shift_select(*queues) #=> [result, queue]
|
|
|
125
108
|
# ['1.1.1.1:80', '2.2.2.2:80']
|
|
126
109
|
tcp_connect_he(*addrs)
|
|
127
110
|
```
|
|
111
|
+
|
|
112
|
+
## Character scanning in UM::IO
|
|
113
|
+
|
|
114
|
+
```c
|
|
115
|
+
// bitmaps for character types can be generated with a bit of Ruby:
|
|
116
|
+
//
|
|
117
|
+
// def t(r); (0..255).map { [it].pack('c') =~ r ? 1 : 0 }; end
|
|
118
|
+
// def tn(r); (0..255).map { [it].pack('c') =~ r ? 0 : 1 }; end
|
|
119
|
+
// def u64(bits); bits.reverse.join.to_i(2); end
|
|
120
|
+
// def p(a); a.each_slice(64).map { u64(it) }; end
|
|
121
|
+
|
|
122
|
+
// usage:
|
|
123
|
+
//
|
|
124
|
+
// p(t(/[a-zA-Z0-9]/)).map { format('%016X', it) }
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
// /[a-zA-Z0-9]/
|
|
128
|
+
uint64_t alpha_numeric[] = [
|
|
129
|
+
0x000000000000FFC0,
|
|
130
|
+
0x7FFFFFE07FFFFFE0,
|
|
131
|
+
0x0000000000000000,
|
|
132
|
+
0x0000000000000000
|
|
133
|
+
];
|
|
134
|
+
|
|
135
|
+
// HTTP method: /[a-zA-Z]/ (3-12 characters)
|
|
136
|
+
// header-key: /[a-zA-Z\-]/ ()
|
|
137
|
+
// path: /^($/
|
|
138
|
+
|
|
139
|
+
// check if character is in bitmap
|
|
140
|
+
inline int test_char(char c, uint64 *bitmap) {
|
|
141
|
+
return bitmap[c / 64] & (1UL << (c % 64));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
```
|
data/docs/um_api.md
CHANGED
|
@@ -43,26 +43,21 @@
|
|
|
43
43
|
- `pop(queue)` - removes and returns a value off the end of the given queue.
|
|
44
44
|
- `prep_timeout(interval)` - returns a timeout AsyncOp with the given interval.
|
|
45
45
|
- `push(queue, value)` - adds the given value to the end of the given queue.
|
|
46
|
-
- `read_each(fd
|
|
47
|
-
|
|
48
|
-
block.
|
|
46
|
+
- `read_each(fd) { |data| ... }` - reads repeatedly from the given fd, yielding
|
|
47
|
+
each chunk of data to the given block.
|
|
49
48
|
- `read(fd, buffer[, maxlen[, buffer_offset[, file_offset]]])` - reads from the
|
|
50
49
|
given fd int o the given buffer (String or IO::Buffer).
|
|
51
|
-
- `recv_each(fd,
|
|
52
|
-
|
|
50
|
+
- `recv_each(fd, flags)` - receives repeatedly from the given fd with the given
|
|
51
|
+
flags.
|
|
53
52
|
- `recv(fd, buffer, maxlen, flags)` - receives from the given fd into the given
|
|
54
53
|
buffer.
|
|
55
54
|
- `schedule(fiber, value)` - adds the given fiber to the runqueue with the given
|
|
56
55
|
resume value.
|
|
57
56
|
- `select(rfds, wfds, efds)` - selects ready fds from the given readable,
|
|
58
57
|
writable and exeptable fds.
|
|
59
|
-
- `send_bundle(fd, bgid, *strings)` - sends a bundle of buffers to the given fd
|
|
60
|
-
using the given buffer group id.
|
|
61
58
|
- `send(fd, buffer, len, flags)` - sends to the given fd from the given buffer.
|
|
62
59
|
- `sendv(fd, *buffers)` - sends multiple buffers to the given fd.
|
|
63
60
|
- `setsockopt(fd, level, opt, value)` - sets a socket option.
|
|
64
|
-
- `setup_buffer_ring(size, count)` - sets up a buffer ring and returns the
|
|
65
|
-
buffer group id.
|
|
66
61
|
- `shift(queue)` - removes and returns a value from the head of given queue.
|
|
67
62
|
- `shutdown_async(fd, how)` - shuts down the given socket fd without blocking.
|
|
68
63
|
- `shutdown(fd, how)` - shuts down the given socket fd.
|
data/ext/um/um.c
CHANGED
|
@@ -49,12 +49,6 @@ inline void um_teardown(struct um *machine) {
|
|
|
49
49
|
if (machine->sidecar_mode) um_sidecar_teardown(machine);
|
|
50
50
|
if (machine->sidecar_signal) free(machine->sidecar_signal);
|
|
51
51
|
|
|
52
|
-
for (unsigned i = 0; i < machine->buffer_ring_count; i++) {
|
|
53
|
-
struct buf_ring_descriptor *desc = machine->buffer_rings + i;
|
|
54
|
-
io_uring_free_buf_ring(&machine->ring, desc->br, desc->buf_count, i);
|
|
55
|
-
free(desc->buf_base);
|
|
56
|
-
}
|
|
57
|
-
machine->buffer_ring_count = 0;
|
|
58
52
|
io_uring_queue_exit(&machine->ring);
|
|
59
53
|
machine->ring_initialized = 0;
|
|
60
54
|
|
|
@@ -523,7 +517,6 @@ struct op_ctx {
|
|
|
523
517
|
struct um *machine;
|
|
524
518
|
struct um_op *op;
|
|
525
519
|
int fd;
|
|
526
|
-
int bgid;
|
|
527
520
|
|
|
528
521
|
struct um_queue *queue;
|
|
529
522
|
void *read_buf;
|
|
@@ -870,25 +863,6 @@ VALUE um_sendv(struct um *machine, int fd, int argc, VALUE *argv) {
|
|
|
870
863
|
return ret;
|
|
871
864
|
}
|
|
872
865
|
|
|
873
|
-
VALUE um_send_bundle(struct um *machine, int fd, int bgid, VALUE strings) {
|
|
874
|
-
um_add_strings_to_buffer_ring(machine, bgid, strings);
|
|
875
|
-
struct um_op *op = um_op_acquire(machine);
|
|
876
|
-
um_prep_op(machine, op, OP_SEND_BUNDLE, 2, 0);
|
|
877
|
-
struct io_uring_sqe *sqe = um_get_sqe(machine, op);
|
|
878
|
-
io_uring_prep_send_bundle(sqe, fd, 0, MSG_NOSIGNAL | MSG_WAITALL);
|
|
879
|
-
sqe->flags |= IOSQE_BUFFER_SELECT;
|
|
880
|
-
sqe->buf_group = bgid;
|
|
881
|
-
|
|
882
|
-
VALUE ret = um_yield(machine);
|
|
883
|
-
|
|
884
|
-
if (likely(um_verify_op_completion(machine, op, true))) ret = INT2NUM(op->result.res);
|
|
885
|
-
um_op_release(machine, op);
|
|
886
|
-
|
|
887
|
-
RAISE_IF_EXCEPTION(ret);
|
|
888
|
-
RB_GC_GUARD(ret);
|
|
889
|
-
return ret;
|
|
890
|
-
}
|
|
891
|
-
|
|
892
866
|
VALUE um_recv(struct um *machine, int fd, VALUE buffer, size_t maxlen, int flags) {
|
|
893
867
|
void *ptr = um_prepare_read_buffer(buffer, maxlen, 0);
|
|
894
868
|
struct um_op *op = um_op_acquire(machine);
|
|
@@ -1461,72 +1435,44 @@ VALUE um_accept_into_queue(struct um *machine, int fd, VALUE queue) {
|
|
|
1461
1435
|
return rb_ensure(accept_into_queue_start, (VALUE)&ctx, multishot_complete, (VALUE)&ctx);
|
|
1462
1436
|
}
|
|
1463
1437
|
|
|
1464
|
-
int um_read_each_singleshot_loop(struct op_ctx *ctx) {
|
|
1465
|
-
struct buf_ring_descriptor *desc = ctx->machine->buffer_rings + ctx->bgid;
|
|
1466
|
-
ctx->read_maxlen = desc->buf_size;
|
|
1467
|
-
ctx->read_buf = malloc(desc->buf_size);
|
|
1468
|
-
int total = 0;
|
|
1469
|
-
|
|
1470
|
-
while (1) {
|
|
1471
|
-
um_prep_op(ctx->machine, ctx->op, OP_READ, 2, 0);
|
|
1472
|
-
struct io_uring_sqe *sqe = um_get_sqe(ctx->machine, ctx->op);
|
|
1473
|
-
io_uring_prep_read(sqe, ctx->fd, ctx->read_buf, ctx->read_maxlen, -1);
|
|
1474
|
-
|
|
1475
|
-
VALUE ret = um_yield(ctx->machine);
|
|
1476
|
-
|
|
1477
|
-
if (likely(um_verify_op_completion(ctx->machine, ctx->op, true))) {
|
|
1478
|
-
VALUE buf = rb_str_new(ctx->read_buf, ctx->op->result.res);
|
|
1479
|
-
total += ctx->op->result.res;
|
|
1480
|
-
rb_yield(buf);
|
|
1481
|
-
RB_GC_GUARD(buf);
|
|
1482
|
-
}
|
|
1483
|
-
else {
|
|
1484
|
-
RAISE_IF_EXCEPTION(ret);
|
|
1485
|
-
return 0;
|
|
1486
|
-
}
|
|
1487
|
-
RB_GC_GUARD(ret);
|
|
1488
|
-
}
|
|
1489
|
-
return 0;
|
|
1490
|
-
}
|
|
1491
|
-
|
|
1492
1438
|
// // returns true if more results are expected
|
|
1493
|
-
int read_recv_each_multishot_process_result(struct op_ctx *ctx, struct um_op_result *result, int *total) {
|
|
1439
|
+
inline int read_recv_each_multishot_process_result(struct op_ctx *ctx, struct um_op_result *result, int *total) {
|
|
1494
1440
|
if (result->res == 0)
|
|
1495
1441
|
return false;
|
|
1496
1442
|
|
|
1497
1443
|
*total += result->res;
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
// if the F_MORE flag is absent, then switch to single shot mode.
|
|
1505
|
-
if (unlikely(!(result->flags & IORING_CQE_F_MORE))) {
|
|
1506
|
-
*total += um_read_each_singleshot_loop(ctx);
|
|
1507
|
-
return false;
|
|
1444
|
+
if (likely(result->segment)) {
|
|
1445
|
+
VALUE buf = rb_str_new(result->segment->ptr, result->segment->len);
|
|
1446
|
+
um_segment_checkin(ctx->machine, result->segment);
|
|
1447
|
+
result->segment = NULL;
|
|
1448
|
+
rb_yield(buf);
|
|
1449
|
+
RB_GC_GUARD(buf);
|
|
1508
1450
|
}
|
|
1509
1451
|
|
|
1510
1452
|
return true;
|
|
1511
1453
|
}
|
|
1512
1454
|
|
|
1513
|
-
void read_recv_each_prep(struct io_uring_sqe *sqe, struct op_ctx *ctx) {
|
|
1455
|
+
static inline void read_recv_each_prep(struct io_uring_sqe *sqe, struct op_ctx *ctx) {
|
|
1456
|
+
bp_ensure_commit_level(ctx->machine);
|
|
1457
|
+
ctx->op->bp_commit_level = ctx->machine->bp_commit_level;
|
|
1458
|
+
|
|
1514
1459
|
switch (ctx->op->kind) {
|
|
1515
1460
|
case OP_READ_MULTISHOT:
|
|
1516
|
-
io_uring_prep_read_multishot(sqe, ctx->fd, 0, -1,
|
|
1461
|
+
io_uring_prep_read_multishot(sqe, ctx->fd, 0, -1, BP_BGID);
|
|
1517
1462
|
return;
|
|
1518
1463
|
case OP_RECV_MULTISHOT:
|
|
1519
1464
|
io_uring_prep_recv_multishot(sqe, ctx->fd, NULL, 0, 0);
|
|
1520
|
-
sqe->buf_group =
|
|
1465
|
+
sqe->buf_group = BP_BGID;
|
|
1521
1466
|
sqe->flags |= IOSQE_BUFFER_SELECT;
|
|
1522
1467
|
return;
|
|
1523
1468
|
default:
|
|
1524
|
-
|
|
1469
|
+
um_raise_internal_error("Invalid multishot op");
|
|
1525
1470
|
}
|
|
1526
1471
|
}
|
|
1527
1472
|
|
|
1528
1473
|
VALUE read_recv_each_start(VALUE arg) {
|
|
1529
1474
|
struct op_ctx *ctx = (struct op_ctx *)arg;
|
|
1475
|
+
|
|
1530
1476
|
struct io_uring_sqe *sqe = um_get_sqe(ctx->machine, ctx->op);
|
|
1531
1477
|
read_recv_each_prep(sqe, ctx);
|
|
1532
1478
|
int total = 0;
|
|
@@ -1558,19 +1504,19 @@ VALUE read_recv_each_start(VALUE arg) {
|
|
|
1558
1504
|
return Qnil;
|
|
1559
1505
|
}
|
|
1560
1506
|
|
|
1561
|
-
VALUE um_read_each(struct um *machine, int fd
|
|
1507
|
+
VALUE um_read_each(struct um *machine, int fd) {
|
|
1562
1508
|
struct um_op *op = um_op_acquire(machine);
|
|
1563
|
-
um_prep_op(machine, op, OP_READ_MULTISHOT, 2, OP_F_MULTISHOT);
|
|
1509
|
+
um_prep_op(machine, op, OP_READ_MULTISHOT, 2, OP_F_MULTISHOT | OP_F_BUFFER_POOL);
|
|
1564
1510
|
|
|
1565
|
-
struct op_ctx ctx = { .machine = machine, .op = op, .fd = fd, .
|
|
1511
|
+
struct op_ctx ctx = { .machine = machine, .op = op, .fd = fd, .read_buf = NULL };
|
|
1566
1512
|
return rb_ensure(read_recv_each_start, (VALUE)&ctx, multishot_complete, (VALUE)&ctx);
|
|
1567
1513
|
}
|
|
1568
1514
|
|
|
1569
|
-
VALUE um_recv_each(struct um *machine, int fd, int
|
|
1515
|
+
VALUE um_recv_each(struct um *machine, int fd, int flags) {
|
|
1570
1516
|
struct um_op *op = um_op_acquire(machine);
|
|
1571
|
-
um_prep_op(machine, op, OP_RECV_MULTISHOT, 2, OP_F_MULTISHOT);
|
|
1517
|
+
um_prep_op(machine, op, OP_RECV_MULTISHOT, 2, OP_F_MULTISHOT | OP_F_BUFFER_POOL);
|
|
1572
1518
|
|
|
1573
|
-
struct op_ctx ctx = { .machine = machine, .op = op, .fd = fd, .
|
|
1519
|
+
struct op_ctx ctx = { .machine = machine, .op = op, .fd = fd, .read_buf = NULL, .flags = flags };
|
|
1574
1520
|
return rb_ensure(read_recv_each_start, (VALUE)&ctx, multishot_complete, (VALUE)&ctx);
|
|
1575
1521
|
}
|
|
1576
1522
|
|
|
@@ -1623,7 +1569,6 @@ extern VALUE SYM_ops_free;
|
|
|
1623
1569
|
extern VALUE SYM_ops_transient;
|
|
1624
1570
|
extern VALUE SYM_time_total_cpu;
|
|
1625
1571
|
extern VALUE SYM_time_total_wait;
|
|
1626
|
-
extern VALUE SYM_buffer_groups;
|
|
1627
1572
|
extern VALUE SYM_buffers_allocated;
|
|
1628
1573
|
extern VALUE SYM_buffers_free;
|
|
1629
1574
|
extern VALUE SYM_segments_free;
|
data/ext/um/um.h
CHANGED
|
@@ -56,7 +56,6 @@ enum um_op_kind {
|
|
|
56
56
|
OP_RECV,
|
|
57
57
|
OP_RECVMSG,
|
|
58
58
|
OP_SEND,
|
|
59
|
-
OP_SEND_BUNDLE,
|
|
60
59
|
OP_SENDMSG,
|
|
61
60
|
OP_SENDV,
|
|
62
61
|
OP_SOCKET,
|
|
@@ -168,15 +167,6 @@ struct um_op {
|
|
|
168
167
|
};
|
|
169
168
|
};
|
|
170
169
|
|
|
171
|
-
struct buf_ring_descriptor {
|
|
172
|
-
struct io_uring_buf_ring *br;
|
|
173
|
-
size_t br_size;
|
|
174
|
-
unsigned buf_count;
|
|
175
|
-
unsigned buf_size;
|
|
176
|
-
unsigned buf_mask;
|
|
177
|
-
void *buf_base;
|
|
178
|
-
};
|
|
179
|
-
|
|
180
170
|
struct um_metrics {
|
|
181
171
|
ulong total_ops; // total ops submitted
|
|
182
172
|
ulong total_switches; // total fiber switches
|
|
@@ -199,8 +189,6 @@ struct um_metrics {
|
|
|
199
189
|
double time_first_cpu; // last seen time stamp
|
|
200
190
|
};
|
|
201
191
|
|
|
202
|
-
#define BUFFER_RING_MAX_COUNT 10
|
|
203
|
-
|
|
204
192
|
struct um {
|
|
205
193
|
VALUE self;
|
|
206
194
|
|
|
@@ -216,13 +204,9 @@ struct um {
|
|
|
216
204
|
pthread_t sidecar_thread;
|
|
217
205
|
uint32_t *sidecar_signal;
|
|
218
206
|
|
|
219
|
-
uint buffer_ring_count; // number of registered buffer rings
|
|
220
|
-
|
|
221
207
|
uint size; // size of SQ
|
|
222
208
|
uint sqpoll_mode; // SQPOLL mode enabled
|
|
223
209
|
|
|
224
|
-
struct buf_ring_descriptor buffer_rings[BUFFER_RING_MAX_COUNT];
|
|
225
|
-
|
|
226
210
|
struct um_op *transient_head; // list of pending transient ops
|
|
227
211
|
VALUE pending_fibers; // set containing pending fibers
|
|
228
212
|
|
|
@@ -351,9 +335,7 @@ void um_raise_on_error_result(int result);
|
|
|
351
335
|
int um_get_buffer_bytes_for_writing(VALUE buffer, const void **base, size_t *size, int raise_on_bad_buffer);
|
|
352
336
|
void * um_prepare_read_buffer(VALUE buffer, ssize_t len, ssize_t ofs);
|
|
353
337
|
void um_update_read_buffer(VALUE buffer, ssize_t buffer_offset, __s32 result);
|
|
354
|
-
|
|
355
|
-
VALUE um_read_from_buffer_ring(struct um *machine, int bgid, __s32 result, __u32 flags);
|
|
356
|
-
void um_add_strings_to_buffer_ring(struct um *machine, int bgid, VALUE strings);
|
|
338
|
+
|
|
357
339
|
struct iovec *um_alloc_iovecs_for_writing(int argc, VALUE *argv, size_t *total_len);
|
|
358
340
|
void um_advance_iovecs_for_writing(struct iovec **ptr, int *len, size_t adv);
|
|
359
341
|
|
|
@@ -376,7 +358,7 @@ VALUE um_sleep(struct um *machine, double duration);
|
|
|
376
358
|
VALUE um_periodically(struct um *machine, double interval);
|
|
377
359
|
VALUE um_read(struct um *machine, int fd, VALUE buffer, size_t maxlen, ssize_t buffer_offset, __u64 file_offset);
|
|
378
360
|
size_t um_read_raw(struct um *machine, int fd, char *buffer, size_t maxlen);
|
|
379
|
-
VALUE um_read_each(struct um *machine, int fd
|
|
361
|
+
VALUE um_read_each(struct um *machine, int fd);
|
|
380
362
|
VALUE um_write(struct um *machine, int fd, VALUE buffer, size_t len, __u64 file_offset);
|
|
381
363
|
size_t um_write_raw(struct um *machine, int fd, const char *buffer, size_t len);
|
|
382
364
|
VALUE um_writev(struct um *machine, int fd, int argc, VALUE *argv);
|
|
@@ -405,9 +387,8 @@ VALUE um_connect(struct um *machine, int fd, const struct sockaddr *addr, sockle
|
|
|
405
387
|
VALUE um_send(struct um *machine, int fd, VALUE buffer, size_t len, int flags);
|
|
406
388
|
size_t um_send_raw(struct um *machine, int fd, const char *buffer, size_t len, int flags);
|
|
407
389
|
VALUE um_sendv(struct um *machine, int fd, int argc, VALUE *argv);
|
|
408
|
-
VALUE um_send_bundle(struct um *machine, int fd, int bgid, VALUE strings);
|
|
409
390
|
VALUE um_recv(struct um *machine, int fd, VALUE buffer, size_t maxlen, int flags);
|
|
410
|
-
VALUE um_recv_each(struct um *machine, int fd, int
|
|
391
|
+
VALUE um_recv_each(struct um *machine, int fd, int flags);
|
|
411
392
|
VALUE um_bind(struct um *machine, int fd, struct sockaddr *addr, socklen_t addrlen);
|
|
412
393
|
VALUE um_listen(struct um *machine, int fd, int backlog);
|
|
413
394
|
VALUE um_getsockopt(struct um *machine, int fd, int level, int opt);
|
data/ext/um/um_class.c
CHANGED
|
@@ -22,7 +22,6 @@ VALUE SYM_ops_free;
|
|
|
22
22
|
VALUE SYM_ops_transient;
|
|
23
23
|
VALUE SYM_time_total_cpu;
|
|
24
24
|
VALUE SYM_time_total_wait;
|
|
25
|
-
VALUE SYM_buffer_groups;
|
|
26
25
|
VALUE SYM_buffers_allocated;
|
|
27
26
|
VALUE SYM_buffers_free;
|
|
28
27
|
VALUE SYM_segments_free;
|
|
@@ -129,18 +128,6 @@ VALUE UM_initialize(int argc, VALUE *argv, VALUE self) {
|
|
|
129
128
|
return self;
|
|
130
129
|
}
|
|
131
130
|
|
|
132
|
-
/* Creates a buffer group (buffer ring) with the given buffer size and buffer count.
|
|
133
|
-
*
|
|
134
|
-
* @param size [Integer] buffer size in bytes
|
|
135
|
-
* @param count [Integer] number of buffers in group
|
|
136
|
-
* @return [Integer] buffer group id
|
|
137
|
-
*/
|
|
138
|
-
VALUE UM_setup_buffer_ring(VALUE self, VALUE size, VALUE count) {
|
|
139
|
-
struct um *machine = um_get_machine(self);
|
|
140
|
-
int bgid = um_setup_buffer_ring(machine, NUM2UINT(size), NUM2UINT(count));
|
|
141
|
-
return INT2NUM(bgid);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
131
|
/* Returns the SQ (submission queue) size.
|
|
145
132
|
*
|
|
146
133
|
* @return [Integer] SQ size
|
|
@@ -408,21 +395,19 @@ VALUE UM_read(int argc, VALUE *argv, VALUE self) {
|
|
|
408
395
|
}
|
|
409
396
|
|
|
410
397
|
/* call-seq:
|
|
411
|
-
* machine.read_each(fd
|
|
398
|
+
* machine.read_each(fd) { |data| }
|
|
412
399
|
*
|
|
413
|
-
* Reads repeatedly from the given
|
|
414
|
-
*
|
|
415
|
-
* Read data is yielded in an infinite loop to the given block.
|
|
400
|
+
* Reads repeatedly from the given fd. Read data is yielded in an infinite
|
|
401
|
+
* loop to the given block.
|
|
416
402
|
*
|
|
417
403
|
* - https://www.man7.org/linux/man-pages/man3/io_uring_prep_read_multishot.3.html
|
|
418
404
|
*
|
|
419
405
|
* @param fd [Integer] file descriptor
|
|
420
|
-
* @param bgid [Integer] buffer group id
|
|
421
406
|
* @return [void]
|
|
422
407
|
*/
|
|
423
|
-
VALUE UM_read_each(VALUE self, VALUE fd
|
|
408
|
+
VALUE UM_read_each(VALUE self, VALUE fd) {
|
|
424
409
|
struct um *machine = um_get_machine(self);
|
|
425
|
-
return um_read_each(machine, NUM2INT(fd)
|
|
410
|
+
return um_read_each(machine, NUM2INT(fd));
|
|
426
411
|
}
|
|
427
412
|
|
|
428
413
|
/* call-seq:
|
|
@@ -836,38 +821,6 @@ VALUE UM_sendv(int argc, VALUE *argv, VALUE self) {
|
|
|
836
821
|
}
|
|
837
822
|
|
|
838
823
|
|
|
839
|
-
/* call-seq:
|
|
840
|
-
* machine.send_bundle(fd, bgid, *buffers) -> bytes_sent
|
|
841
|
-
*
|
|
842
|
-
* Sends data on the given socket from the given buffers using a registered
|
|
843
|
-
* buffer group. The buffer group should have been previously registered using
|
|
844
|
-
* `#setup_buffer_ring`.
|
|
845
|
-
*
|
|
846
|
-
* - https://www.man7.org/linux/man-pages/man2/send.2.html
|
|
847
|
-
* - https://www.man7.org/linux/man-pages/man3/io_uring_prep_send.3.html
|
|
848
|
-
*
|
|
849
|
-
* @overload send_bundle(fd, bgid, *buffers)
|
|
850
|
-
* @param fd [Integer] file descriptor
|
|
851
|
-
* @param bgid [Integer] buffer group id
|
|
852
|
-
* @param *buffers [Array<String, IO::Buffer>] buffers
|
|
853
|
-
* @return [Integer] number of bytes sent
|
|
854
|
-
*/
|
|
855
|
-
VALUE UM_send_bundle(int argc, VALUE *argv, VALUE self) {
|
|
856
|
-
struct um *machine = um_get_machine(self);
|
|
857
|
-
VALUE fd;
|
|
858
|
-
VALUE bgid;
|
|
859
|
-
VALUE strings;
|
|
860
|
-
rb_scan_args(argc, argv, "2*", &fd, &bgid, &strings);
|
|
861
|
-
|
|
862
|
-
if (RARRAY_LEN(strings) == 1) {
|
|
863
|
-
VALUE first = rb_ary_entry(strings, 0);
|
|
864
|
-
if (TYPE(first) == T_ARRAY)
|
|
865
|
-
strings = first;
|
|
866
|
-
}
|
|
867
|
-
|
|
868
|
-
return um_send_bundle(machine, NUM2INT(fd), NUM2INT(bgid), strings);
|
|
869
|
-
}
|
|
870
|
-
|
|
871
824
|
/* call-seq:
|
|
872
825
|
* machine.recv(fd, buffer, maxlen, flags) -> bytes_received
|
|
873
826
|
*
|
|
@@ -888,23 +841,20 @@ VALUE UM_recv(VALUE self, VALUE fd, VALUE buffer, VALUE maxlen, VALUE flags) {
|
|
|
888
841
|
}
|
|
889
842
|
|
|
890
843
|
/* call-seq:
|
|
891
|
-
* machine.recv_each(fd,
|
|
844
|
+
* machine.recv_each(fd, flags) { |data| ... }
|
|
892
845
|
*
|
|
893
|
-
* Repeatedlty receives data from the given socket in an infinite loop
|
|
894
|
-
* given buffer group id. The buffer group should have been previously setup
|
|
895
|
-
* using `#setup_buffer_ring`.
|
|
846
|
+
* Repeatedlty receives data from the given socket in an infinite loop.
|
|
896
847
|
*
|
|
897
848
|
* - https://www.man7.org/linux/man-pages/man2/recv.2.html
|
|
898
849
|
* - https://www.man7.org/linux/man-pages/man3/io_uring_prep_recv.3.html
|
|
899
850
|
*
|
|
900
851
|
* @param fd [Integer] file descriptor
|
|
901
|
-
* @param bgid [Integer] buffer group id
|
|
902
852
|
* @param flags [Integer] flags mask
|
|
903
853
|
* @return [void]
|
|
904
854
|
*/
|
|
905
|
-
VALUE UM_recv_each(VALUE self, VALUE fd, VALUE
|
|
855
|
+
VALUE UM_recv_each(VALUE self, VALUE fd, VALUE flags) {
|
|
906
856
|
struct um *machine = um_get_machine(self);
|
|
907
|
-
return um_recv_each(machine, NUM2INT(fd), NUM2INT(
|
|
857
|
+
return um_recv_each(machine, NUM2INT(fd), NUM2INT(flags));
|
|
908
858
|
}
|
|
909
859
|
|
|
910
860
|
/* call-seq:
|
|
@@ -1512,8 +1462,6 @@ void Init_UM(void) {
|
|
|
1512
1462
|
rb_define_method(cUM, "sidecar_start", UM_sidecar_start, 0);
|
|
1513
1463
|
rb_define_method(cUM, "sidecar_stop", UM_sidecar_stop, 0);
|
|
1514
1464
|
|
|
1515
|
-
rb_define_method(cUM, "setup_buffer_ring", UM_setup_buffer_ring, 2);
|
|
1516
|
-
|
|
1517
1465
|
rb_define_method(cUM, "schedule", UM_schedule, 2);
|
|
1518
1466
|
rb_define_method(cUM, "snooze", UM_snooze, 0);
|
|
1519
1467
|
rb_define_method(cUM, "timeout", UM_timeout, 2);
|
|
@@ -1527,7 +1475,7 @@ void Init_UM(void) {
|
|
|
1527
1475
|
rb_define_method(cUM, "close_async", UM_close_async, 1);
|
|
1528
1476
|
rb_define_method(cUM, "open", UM_open, 2);
|
|
1529
1477
|
rb_define_method(cUM, "read", UM_read, -1);
|
|
1530
|
-
rb_define_method(cUM, "read_each", UM_read_each,
|
|
1478
|
+
rb_define_method(cUM, "read_each", UM_read_each, 1);
|
|
1531
1479
|
rb_define_method(cUM, "sleep", UM_sleep, 1);
|
|
1532
1480
|
rb_define_method(cUM, "periodically", UM_periodically, 1);
|
|
1533
1481
|
rb_define_method(cUM, "write", UM_write, -1);
|
|
@@ -1554,11 +1502,10 @@ void Init_UM(void) {
|
|
|
1554
1502
|
rb_define_method(cUM, "getsockopt", UM_getsockopt, 3);
|
|
1555
1503
|
rb_define_method(cUM, "listen", UM_listen, 2);
|
|
1556
1504
|
rb_define_method(cUM, "recv", UM_recv, 4);
|
|
1557
|
-
rb_define_method(cUM, "recv_each", UM_recv_each,
|
|
1505
|
+
rb_define_method(cUM, "recv_each", UM_recv_each, 2);
|
|
1558
1506
|
rb_define_method(cUM, "send", UM_send, 4);
|
|
1559
1507
|
rb_define_method(cUM, "sendv", UM_sendv, -1);
|
|
1560
1508
|
|
|
1561
|
-
rb_define_method(cUM, "send_bundle", UM_send_bundle, -1);
|
|
1562
1509
|
rb_define_method(cUM, "setsockopt", UM_setsockopt, 4);
|
|
1563
1510
|
rb_define_method(cUM, "socket", UM_socket, 4);
|
|
1564
1511
|
rb_define_method(cUM, "shutdown", UM_shutdown, 2);
|
|
@@ -1595,7 +1542,6 @@ void Init_UM(void) {
|
|
|
1595
1542
|
SYM_ops_transient = ID2SYM(rb_intern("ops_transient"));
|
|
1596
1543
|
SYM_time_total_cpu = ID2SYM(rb_intern("time_total_cpu"));
|
|
1597
1544
|
SYM_time_total_wait = ID2SYM(rb_intern("time_total_wait"));
|
|
1598
|
-
SYM_buffer_groups = ID2SYM(rb_intern("buffer_groups"));
|
|
1599
1545
|
SYM_buffers_allocated = ID2SYM(rb_intern("buffers_allocated"));
|
|
1600
1546
|
SYM_buffers_free = ID2SYM(rb_intern("buffers_free"));
|
|
1601
1547
|
SYM_segments_free = ID2SYM(rb_intern("segments_free"));
|
data/ext/um/um_io.c
CHANGED
data/ext/um/um_op.c
CHANGED
|
@@ -20,7 +20,6 @@ const char * um_op_kind_name(enum um_op_kind kind) {
|
|
|
20
20
|
case OP_RECV: return "OP_RECV";
|
|
21
21
|
case OP_RECVMSG: return "OP_RECVMSG";
|
|
22
22
|
case OP_SEND: return "OP_SEND";
|
|
23
|
-
case OP_SEND_BUNDLE: return "OP_SEND_BUNDLE";
|
|
24
23
|
case OP_SENDMSG: return "OP_SENDMSG";
|
|
25
24
|
case OP_SENDV: return "OP_SENDV";
|
|
26
25
|
case OP_SOCKET: return "OP_SOCKET";
|
data/ext/um/um_utils.c
CHANGED
|
@@ -115,92 +115,6 @@ inline int um_get_buffer_bytes_for_writing(VALUE buffer, const void **base, size
|
|
|
115
115
|
return true;
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
int um_setup_buffer_ring(struct um *machine, unsigned size, unsigned count) {
|
|
119
|
-
if (machine->buffer_ring_count == BUFFER_RING_MAX_COUNT)
|
|
120
|
-
um_raise_internal_error("Cannot setup more than BUFFER_RING_MAX_COUNT buffer rings");
|
|
121
|
-
|
|
122
|
-
struct buf_ring_descriptor *desc = machine->buffer_rings + machine->buffer_ring_count;
|
|
123
|
-
desc->buf_count = count;
|
|
124
|
-
desc->buf_size = size;
|
|
125
|
-
desc->br_size = sizeof(struct io_uring_buf) * desc->buf_count;
|
|
126
|
-
desc->buf_mask = io_uring_buf_ring_mask(desc->buf_count);
|
|
127
|
-
|
|
128
|
-
void *mapped = mmap(
|
|
129
|
-
NULL, desc->br_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0
|
|
130
|
-
);
|
|
131
|
-
if (mapped == MAP_FAILED)
|
|
132
|
-
um_raise_internal_error("Failed to allocate buffer ring");
|
|
133
|
-
|
|
134
|
-
desc->br = (struct io_uring_buf_ring *)mapped;
|
|
135
|
-
io_uring_buf_ring_init(desc->br);
|
|
136
|
-
|
|
137
|
-
unsigned bg_id = machine->buffer_ring_count;
|
|
138
|
-
int ret;
|
|
139
|
-
desc->br = io_uring_setup_buf_ring(&machine->ring, count, bg_id, 0, &ret);
|
|
140
|
-
if (!desc->br) {
|
|
141
|
-
munmap(desc->br, desc->br_size);
|
|
142
|
-
rb_syserr_fail(-ret, strerror(-ret));
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
if (size > 0) {
|
|
146
|
-
if (posix_memalign(&desc->buf_base, 4096, desc->buf_count * desc->buf_size)) {
|
|
147
|
-
io_uring_free_buf_ring(&machine->ring, desc->br, desc->buf_count, bg_id);
|
|
148
|
-
um_raise_internal_error("Failed to allocate buffers");
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
char *ptr = desc->buf_base;
|
|
152
|
-
for (unsigned i = 0; i < desc->buf_count; i++) {
|
|
153
|
-
io_uring_buf_ring_add(desc->br, ptr, desc->buf_size, i, desc->buf_mask, i);
|
|
154
|
-
ptr += desc->buf_size;
|
|
155
|
-
}
|
|
156
|
-
io_uring_buf_ring_advance(desc->br, desc->buf_count);
|
|
157
|
-
}
|
|
158
|
-
machine->buffer_ring_count++;
|
|
159
|
-
return bg_id;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
inline VALUE um_read_from_buffer_ring(struct um *machine, int bgid, __s32 result, __u32 flags) {
|
|
163
|
-
if (!result) return Qnil;
|
|
164
|
-
|
|
165
|
-
unsigned buf_idx = flags >> IORING_CQE_BUFFER_SHIFT;
|
|
166
|
-
struct buf_ring_descriptor *desc = machine->buffer_rings + bgid;
|
|
167
|
-
char *src = (char *)desc->buf_base + desc->buf_size * buf_idx;
|
|
168
|
-
// TODO: add support for UTF8
|
|
169
|
-
// buf = rd->utf8_encoding ? rb_utf8_str_new(src, cqe->res) : rb_str_new(src, cqe->res);
|
|
170
|
-
VALUE buf = rb_str_new(src, result);
|
|
171
|
-
|
|
172
|
-
// add buffer back to buffer ring
|
|
173
|
-
io_uring_buf_ring_add(
|
|
174
|
-
desc->br, src, desc->buf_size, buf_idx, desc->buf_mask, 0
|
|
175
|
-
);
|
|
176
|
-
io_uring_buf_ring_advance(desc->br, 1);
|
|
177
|
-
|
|
178
|
-
RB_GC_GUARD(buf);
|
|
179
|
-
return buf;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
inline void um_add_strings_to_buffer_ring(struct um *machine, int bgid, VALUE strings) {
|
|
183
|
-
static ID ID_to_s = 0;
|
|
184
|
-
|
|
185
|
-
struct buf_ring_descriptor *desc = machine->buffer_rings + bgid;
|
|
186
|
-
ulong count = RARRAY_LEN(strings);
|
|
187
|
-
VALUE str = Qnil;
|
|
188
|
-
VALUE converted = Qnil;
|
|
189
|
-
|
|
190
|
-
for (ulong i = 0; i < count; i++) {
|
|
191
|
-
str = rb_ary_entry(strings, i);
|
|
192
|
-
if (TYPE(str) != T_STRING) {
|
|
193
|
-
if (!ID_to_s) ID_to_s = rb_intern("to_s");
|
|
194
|
-
if (NIL_P(converted)) converted = rb_ary_new();
|
|
195
|
-
str = rb_funcall(str, ID_to_s, 0);
|
|
196
|
-
rb_ary_push(converted, str);
|
|
197
|
-
}
|
|
198
|
-
io_uring_buf_ring_add(desc->br, RSTRING_PTR(str), RSTRING_LEN(str), i, desc->buf_mask, i);
|
|
199
|
-
}
|
|
200
|
-
RB_GC_GUARD(converted);
|
|
201
|
-
io_uring_buf_ring_advance(desc->br, count);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
118
|
inline void um_raise_internal_error(const char *msg) {
|
|
205
119
|
rb_raise(eUMError, "UringMachine error: %s", msg);
|
|
206
120
|
}
|
data/lib/uringmachine/version.rb
CHANGED
data/test/test_io.rb
CHANGED
|
@@ -33,7 +33,7 @@ class IOTest < IOBaseTest
|
|
|
33
33
|
)
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
-
def
|
|
36
|
+
def test_io_basic_usage
|
|
37
37
|
assert_equal [0, 0, 0, 0, 0], buffer_metrics
|
|
38
38
|
machine.write(@wfd, "foobar")
|
|
39
39
|
machine.close(@wfd)
|
|
@@ -53,7 +53,7 @@ class IOTest < IOBaseTest
|
|
|
53
53
|
assert_equal 0, machine.metrics[:ops_pending]
|
|
54
54
|
end
|
|
55
55
|
|
|
56
|
-
def
|
|
56
|
+
def test_io_clear
|
|
57
57
|
rfd, wfd = UM.pipe
|
|
58
58
|
conn = UM::IO.new(machine, rfd)
|
|
59
59
|
|
|
@@ -77,7 +77,7 @@ class IOTest < IOBaseTest
|
|
|
77
77
|
machine.close(wfd) rescue nil
|
|
78
78
|
end
|
|
79
79
|
|
|
80
|
-
def
|
|
80
|
+
def test_io_big_read
|
|
81
81
|
s1, s2 = UM.socketpair(UM::AF_UNIX, UM::SOCK_STREAM, 0)
|
|
82
82
|
conn = UM::IO.new(machine, s2)
|
|
83
83
|
|
|
@@ -96,7 +96,7 @@ class IOTest < IOBaseTest
|
|
|
96
96
|
machine.join(f)
|
|
97
97
|
end
|
|
98
98
|
|
|
99
|
-
def
|
|
99
|
+
def test_io_buffer_reuse
|
|
100
100
|
s1, s2 = UM.socketpair(UM::AF_UNIX, UM::SOCK_STREAM, 0)
|
|
101
101
|
conn = UM::IO.new(machine, s2)
|
|
102
102
|
|
|
@@ -131,7 +131,7 @@ class IOTest < IOBaseTest
|
|
|
131
131
|
machine.join(f)
|
|
132
132
|
end
|
|
133
133
|
|
|
134
|
-
def
|
|
134
|
+
def test_io_read_line
|
|
135
135
|
machine.write(@wfd, "foo\nbar\r\nbaz")
|
|
136
136
|
machine.close(@wfd)
|
|
137
137
|
|
|
@@ -145,7 +145,7 @@ class IOTest < IOBaseTest
|
|
|
145
145
|
assert_equal "baz", conn.read(-6)
|
|
146
146
|
end
|
|
147
147
|
|
|
148
|
-
def
|
|
148
|
+
def test_io_read_line_segmented
|
|
149
149
|
machine.write(@wfd, "foo\n")
|
|
150
150
|
assert_equal 'foo', conn.read_line(0)
|
|
151
151
|
|
|
@@ -163,7 +163,7 @@ class IOTest < IOBaseTest
|
|
|
163
163
|
assert_nil conn.read_line(0)
|
|
164
164
|
end
|
|
165
165
|
|
|
166
|
-
def
|
|
166
|
+
def test_io_read_line_maxlen
|
|
167
167
|
machine.write(@wfd, "foobar\r\n")
|
|
168
168
|
|
|
169
169
|
assert_nil conn.read_line(3)
|
|
@@ -188,7 +188,7 @@ class IOTest < IOBaseTest
|
|
|
188
188
|
assert_equal [16, 0, 256, 16384 * 16, 16384 * 16 - 17], buffer_metrics
|
|
189
189
|
end
|
|
190
190
|
|
|
191
|
-
def
|
|
191
|
+
def test_io_read
|
|
192
192
|
machine.write(@wfd, "foobarbazblahzzz")
|
|
193
193
|
machine.close(@wfd)
|
|
194
194
|
|
|
@@ -198,7 +198,7 @@ class IOTest < IOBaseTest
|
|
|
198
198
|
assert_nil conn.read(4)
|
|
199
199
|
end
|
|
200
200
|
|
|
201
|
-
def
|
|
201
|
+
def test_io_read_zero_len
|
|
202
202
|
machine.write(@wfd, "foobar")
|
|
203
203
|
|
|
204
204
|
assert_equal 'foobar', conn.read(0)
|
|
@@ -209,7 +209,7 @@ class IOTest < IOBaseTest
|
|
|
209
209
|
assert_nil conn.read(0)
|
|
210
210
|
end
|
|
211
211
|
|
|
212
|
-
def
|
|
212
|
+
def test_io_read_negative_len
|
|
213
213
|
machine.write(@wfd, "foobar")
|
|
214
214
|
|
|
215
215
|
assert_equal 'foo', conn.read(-3)
|
|
@@ -221,7 +221,7 @@ class IOTest < IOBaseTest
|
|
|
221
221
|
assert_nil conn.read(-3)
|
|
222
222
|
end
|
|
223
223
|
|
|
224
|
-
def
|
|
224
|
+
def test_io_read_to_delim
|
|
225
225
|
machine.write(@wfd, "abc,def,ghi")
|
|
226
226
|
machine.close(@wfd)
|
|
227
227
|
|
|
@@ -233,7 +233,7 @@ class IOTest < IOBaseTest
|
|
|
233
233
|
assert_equal 'ghi', conn.read_to_delim(',', -3)
|
|
234
234
|
end
|
|
235
235
|
|
|
236
|
-
def
|
|
236
|
+
def test_io_read_to_delim_invalid_delim
|
|
237
237
|
machine.write(@wfd, "abc,def,ghi")
|
|
238
238
|
|
|
239
239
|
assert_raises(ArgumentError) { conn.read_to_delim(:foo, 0) }
|
|
@@ -242,7 +242,7 @@ class IOTest < IOBaseTest
|
|
|
242
242
|
assert_raises(UM::Error) { conn.read_to_delim('🙂', 0) }
|
|
243
243
|
end
|
|
244
244
|
|
|
245
|
-
def
|
|
245
|
+
def test_io_skip
|
|
246
246
|
machine.write(@wfd, "foobarbaz")
|
|
247
247
|
|
|
248
248
|
conn.skip(2)
|
|
@@ -252,7 +252,7 @@ class IOTest < IOBaseTest
|
|
|
252
252
|
assert_equal 'az', conn.read(0)
|
|
253
253
|
end
|
|
254
254
|
|
|
255
|
-
def
|
|
255
|
+
def test_io_big_data
|
|
256
256
|
data = SecureRandom.random_bytes(300_000)
|
|
257
257
|
fiber = machine.spin {
|
|
258
258
|
machine.writev(@wfd, data)
|
|
@@ -273,7 +273,7 @@ class IOTest < IOBaseTest
|
|
|
273
273
|
assert_equal data, received.join
|
|
274
274
|
end
|
|
275
275
|
|
|
276
|
-
def
|
|
276
|
+
def test_io_read_each
|
|
277
277
|
bufs = []
|
|
278
278
|
f = machine.spin do
|
|
279
279
|
bufs << :ready
|
|
@@ -323,7 +323,7 @@ class IOWriteTest < UMBaseTest
|
|
|
323
323
|
super
|
|
324
324
|
end
|
|
325
325
|
|
|
326
|
-
def
|
|
326
|
+
def test_io_write_single_buf
|
|
327
327
|
assert_equal 3, conn.write('foo')
|
|
328
328
|
|
|
329
329
|
buf = +''
|
|
@@ -331,7 +331,7 @@ class IOWriteTest < UMBaseTest
|
|
|
331
331
|
assert_equal 'foo', buf
|
|
332
332
|
end
|
|
333
333
|
|
|
334
|
-
def
|
|
334
|
+
def test_io_write_multi_buf
|
|
335
335
|
assert_equal 6, conn.write('foo', 'bar')
|
|
336
336
|
|
|
337
337
|
buf = +''
|
|
@@ -339,7 +339,7 @@ class IOWriteTest < UMBaseTest
|
|
|
339
339
|
assert_equal 'foobar', buf
|
|
340
340
|
end
|
|
341
341
|
|
|
342
|
-
def
|
|
342
|
+
def test_io_write_socket_mode
|
|
343
343
|
conn = machine.io(@s2, :socket)
|
|
344
344
|
|
|
345
345
|
assert_equal 6, conn.write('foo', 'bar')
|
|
@@ -349,7 +349,7 @@ class IOWriteTest < UMBaseTest
|
|
|
349
349
|
assert_equal 'foobar', buf
|
|
350
350
|
end
|
|
351
351
|
|
|
352
|
-
def
|
|
352
|
+
def test_io_write_ssl_mode
|
|
353
353
|
ssl1 = OpenSSL::SSL::SSLSocket.new(IO.for_fd(@s1), Localhost::Authority.fetch.server_context)
|
|
354
354
|
ssl1.sync_close = true
|
|
355
355
|
ssl2 = OpenSSL::SSL::SSLSocket.new(IO.for_fd(@s2), OpenSSL::SSL::SSLContext.new)
|
|
@@ -380,7 +380,7 @@ class IOWriteTest < UMBaseTest
|
|
|
380
380
|
end
|
|
381
381
|
|
|
382
382
|
class IORespTest < IOBaseTest
|
|
383
|
-
def
|
|
383
|
+
def test_io_resp_read
|
|
384
384
|
machine.write(@wfd, "+foo bar\r\n")
|
|
385
385
|
assert_equal "foo bar", conn.resp_read
|
|
386
386
|
|
|
@@ -443,7 +443,7 @@ class IORespTest < IOBaseTest
|
|
|
443
443
|
assert_equal({ 'a' => 42, 'b' => ['foo', 'bar', 'baz'] }, conn.resp_read)
|
|
444
444
|
end
|
|
445
445
|
|
|
446
|
-
def
|
|
446
|
+
def test_io_resp_read_segmented
|
|
447
447
|
machine.write(@wfd, "\n")
|
|
448
448
|
assert_equal "", conn.read_line(0)
|
|
449
449
|
|
|
@@ -458,7 +458,7 @@ class IORespTest < IOBaseTest
|
|
|
458
458
|
assert_equal "bazbug", conn.resp_read
|
|
459
459
|
end
|
|
460
460
|
|
|
461
|
-
def
|
|
461
|
+
def test_io_resp_write
|
|
462
462
|
writer = machine.io(@wfd)
|
|
463
463
|
|
|
464
464
|
writer.resp_write(nil);
|
|
@@ -489,7 +489,7 @@ class IORespTest < IOBaseTest
|
|
|
489
489
|
assert_equal "%2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n$3\r\nbaz\r\n:42\r\n", conn.read(-100)
|
|
490
490
|
end
|
|
491
491
|
|
|
492
|
-
def
|
|
492
|
+
def test_io_resp_encode
|
|
493
493
|
s = UM::IO
|
|
494
494
|
assert_equal "_\r\n", s.resp_encode(+'', nil)
|
|
495
495
|
assert_equal "#t\r\n", s.resp_encode(+'', true)
|
|
@@ -537,7 +537,7 @@ class IOStressTest < UMBaseTest
|
|
|
537
537
|
end
|
|
538
538
|
end
|
|
539
539
|
|
|
540
|
-
def
|
|
540
|
+
def test_io_server_big_lines
|
|
541
541
|
server_fibers = []
|
|
542
542
|
server_fibers << machine.spin do
|
|
543
543
|
machine.accept_each(@listen_fd) { |fd|
|
|
@@ -580,7 +580,7 @@ class IOStressTest < UMBaseTest
|
|
|
580
580
|
assert_equal msg * client_count, @received.map { it + "\n" }.join
|
|
581
581
|
end
|
|
582
582
|
|
|
583
|
-
def
|
|
583
|
+
def test_io_server_http
|
|
584
584
|
server_fibers = []
|
|
585
585
|
server_fibers << machine.spin do
|
|
586
586
|
machine.accept_each(@listen_fd) { |fd|
|
|
@@ -621,7 +621,7 @@ class IOStressTest < UMBaseTest
|
|
|
621
621
|
end
|
|
622
622
|
|
|
623
623
|
class IODevRandomTest < UMBaseTest
|
|
624
|
-
def
|
|
624
|
+
def test_io_dev_random_read_line
|
|
625
625
|
fd = machine.open('/dev/random', UM::O_RDONLY)
|
|
626
626
|
conn = UM::IO.new(machine, fd)
|
|
627
627
|
|
|
@@ -643,7 +643,7 @@ class IODevRandomTest < UMBaseTest
|
|
|
643
643
|
n.times { acc << conn.read_line(0) }
|
|
644
644
|
end
|
|
645
645
|
|
|
646
|
-
def
|
|
646
|
+
def test_io_dev_random_read_line_concurrent
|
|
647
647
|
acc = []
|
|
648
648
|
c = 1
|
|
649
649
|
n = 100000
|
|
@@ -654,7 +654,7 @@ class IODevRandomTest < UMBaseTest
|
|
|
654
654
|
assert_equal c * n, acc.size
|
|
655
655
|
end
|
|
656
656
|
|
|
657
|
-
def
|
|
657
|
+
def test_io_dev_random_read
|
|
658
658
|
fd = machine.open('/dev/random', UM::O_RDONLY)
|
|
659
659
|
conn = UM::IO.new(machine, fd)
|
|
660
660
|
|
|
@@ -677,7 +677,7 @@ class IODevRandomTest < UMBaseTest
|
|
|
677
677
|
end
|
|
678
678
|
|
|
679
679
|
class IOModeTest < UMBaseTest
|
|
680
|
-
def
|
|
680
|
+
def test_io_default_mode
|
|
681
681
|
r, w = UM.pipe
|
|
682
682
|
conn = UM::IO.new(machine, r)
|
|
683
683
|
assert_equal :fd, conn.mode
|
|
@@ -686,7 +686,7 @@ class IOModeTest < UMBaseTest
|
|
|
686
686
|
machine.close(w) rescue nil
|
|
687
687
|
end
|
|
688
688
|
|
|
689
|
-
def
|
|
689
|
+
def test_io_default_mode_ssl
|
|
690
690
|
authority = Localhost::Authority.fetch
|
|
691
691
|
@server_ctx = authority.server_context
|
|
692
692
|
sock1, sock2 = UNIXSocket.pair
|
|
@@ -699,7 +699,7 @@ class IOModeTest < UMBaseTest
|
|
|
699
699
|
sock2&.close rescue nil
|
|
700
700
|
end
|
|
701
701
|
|
|
702
|
-
def
|
|
702
|
+
def test_io_socket_mode_non_socket
|
|
703
703
|
r, w = UM.pipe
|
|
704
704
|
machine.write(w, 'foobar')
|
|
705
705
|
machine.close(w)
|
|
@@ -713,7 +713,7 @@ class IOModeTest < UMBaseTest
|
|
|
713
713
|
machine.close(w) rescue nil
|
|
714
714
|
end
|
|
715
715
|
|
|
716
|
-
def
|
|
716
|
+
def test_io_socket_mode_socket
|
|
717
717
|
r, w = UM.socketpair(UM::AF_UNIX, UM::SOCK_STREAM, 0)
|
|
718
718
|
machine.write(w, 'foobar')
|
|
719
719
|
machine.close(w)
|
|
@@ -727,7 +727,7 @@ class IOModeTest < UMBaseTest
|
|
|
727
727
|
machine.close(w) rescue nil
|
|
728
728
|
end
|
|
729
729
|
|
|
730
|
-
def
|
|
730
|
+
def test_io_ssl_mode
|
|
731
731
|
authority = Localhost::Authority.fetch
|
|
732
732
|
@server_ctx = authority.server_context
|
|
733
733
|
sock1, sock2 = UNIXSocket.pair
|
|
@@ -775,7 +775,7 @@ class IOModeTest < UMBaseTest
|
|
|
775
775
|
end
|
|
776
776
|
|
|
777
777
|
class IOByteCountsTest < IOBaseTest
|
|
778
|
-
def
|
|
778
|
+
def test_io_byte_counts
|
|
779
779
|
machine.write(@wfd, "foobar")
|
|
780
780
|
|
|
781
781
|
assert_equal 0, conn.consumed
|
data/test/test_um.rb
CHANGED
|
@@ -653,8 +653,6 @@ class ReadEachTest < UMBaseTest
|
|
|
653
653
|
def test_read_each
|
|
654
654
|
r, w = IO.pipe
|
|
655
655
|
bufs = []
|
|
656
|
-
bgid = machine.setup_buffer_ring(4096, 1024)
|
|
657
|
-
assert_equal 0, bgid
|
|
658
656
|
|
|
659
657
|
f = Fiber.new do
|
|
660
658
|
w << 'foo'
|
|
@@ -669,7 +667,7 @@ class ReadEachTest < UMBaseTest
|
|
|
669
667
|
|
|
670
668
|
machine.schedule(f, nil)
|
|
671
669
|
|
|
672
|
-
machine.read_each(r.fileno
|
|
670
|
+
machine.read_each(r.fileno) do |buf|
|
|
673
671
|
bufs << buf
|
|
674
672
|
end
|
|
675
673
|
|
|
@@ -681,15 +679,13 @@ class ReadEachTest < UMBaseTest
|
|
|
681
679
|
# send once and close write fd
|
|
682
680
|
def test_read_each_raising_1
|
|
683
681
|
r, w = IO.pipe
|
|
684
|
-
bgid = machine.setup_buffer_ring(4096, 1024)
|
|
685
|
-
assert_equal 0, bgid
|
|
686
682
|
|
|
687
683
|
w << 'foo'
|
|
688
684
|
w.close
|
|
689
685
|
|
|
690
686
|
e = nil
|
|
691
687
|
begin
|
|
692
|
-
machine.read_each(r.fileno
|
|
688
|
+
machine.read_each(r.fileno) do |buf|
|
|
693
689
|
raise 'hi'
|
|
694
690
|
end
|
|
695
691
|
rescue => e
|
|
@@ -704,14 +700,12 @@ class ReadEachTest < UMBaseTest
|
|
|
704
700
|
# send once and leave write fd open
|
|
705
701
|
def test_read_each_raising_2
|
|
706
702
|
r, w = IO.pipe
|
|
707
|
-
bgid = machine.setup_buffer_ring(4096, 1024)
|
|
708
|
-
assert_equal 0, bgid
|
|
709
703
|
|
|
710
704
|
w << 'foo'
|
|
711
705
|
|
|
712
706
|
e = nil
|
|
713
707
|
begin
|
|
714
|
-
machine.read_each(r.fileno
|
|
708
|
+
machine.read_each(r.fileno) do |buf|
|
|
715
709
|
raise 'hi'
|
|
716
710
|
end
|
|
717
711
|
rescue => e
|
|
@@ -728,15 +722,13 @@ class ReadEachTest < UMBaseTest
|
|
|
728
722
|
# send twice
|
|
729
723
|
def test_read_each_raising_3
|
|
730
724
|
r, w = IO.pipe
|
|
731
|
-
bgid = machine.setup_buffer_ring(4096, 1024)
|
|
732
|
-
assert_equal 0, bgid
|
|
733
725
|
|
|
734
726
|
w << 'foo'
|
|
735
727
|
w << 'bar'
|
|
736
728
|
|
|
737
729
|
e = nil
|
|
738
730
|
begin
|
|
739
|
-
machine.read_each(r.fileno
|
|
731
|
+
machine.read_each(r.fileno) do |buf|
|
|
740
732
|
raise 'hi'
|
|
741
733
|
end
|
|
742
734
|
rescue => e
|
|
@@ -752,7 +744,6 @@ class ReadEachTest < UMBaseTest
|
|
|
752
744
|
|
|
753
745
|
def test_read_each_break
|
|
754
746
|
r, w = IO.pipe
|
|
755
|
-
bgid = machine.setup_buffer_ring(4096, 1024)
|
|
756
747
|
|
|
757
748
|
t = Thread.new do
|
|
758
749
|
sleep 0.1
|
|
@@ -762,7 +753,7 @@ class ReadEachTest < UMBaseTest
|
|
|
762
753
|
end
|
|
763
754
|
|
|
764
755
|
bufs = []
|
|
765
|
-
machine.read_each(r.fileno
|
|
756
|
+
machine.read_each(r.fileno) do |b|
|
|
766
757
|
bufs << b
|
|
767
758
|
break
|
|
768
759
|
end
|
|
@@ -779,13 +770,12 @@ class ReadEachTest < UMBaseTest
|
|
|
779
770
|
|
|
780
771
|
def test_read_each_timeout
|
|
781
772
|
r, _w = IO.pipe
|
|
782
|
-
bgid = machine.setup_buffer_ring(4096, 1024)
|
|
783
773
|
|
|
784
774
|
bufs = []
|
|
785
775
|
e = nil
|
|
786
776
|
begin
|
|
787
777
|
machine.timeout(0.01, TOError) do
|
|
788
|
-
machine.read_each(r.fileno
|
|
778
|
+
machine.read_each(r.fileno) do |b|
|
|
789
779
|
bufs << b
|
|
790
780
|
end
|
|
791
781
|
end
|
|
@@ -804,10 +794,9 @@ class ReadEachTest < UMBaseTest
|
|
|
804
794
|
|
|
805
795
|
def test_read_each_bad_file
|
|
806
796
|
_r, w = IO.pipe
|
|
807
|
-
bgid = machine.setup_buffer_ring(4096, 1024)
|
|
808
797
|
|
|
809
798
|
assert_raises(Errno::EBADF) do
|
|
810
|
-
machine.read_each(w.fileno
|
|
799
|
+
machine.read_each(w.fileno)
|
|
811
800
|
end
|
|
812
801
|
assert_equal 0, machine.metrics[:ops_pending]
|
|
813
802
|
assert_equal 256, machine.metrics[:ops_free]
|
|
@@ -1892,15 +1881,9 @@ class RecvEachTest < UMBaseTest
|
|
|
1892
1881
|
res = machine.connect(fd, '127.0.0.1', @port)
|
|
1893
1882
|
assert_equal 0, res
|
|
1894
1883
|
|
|
1895
|
-
bgid = machine.setup_buffer_ring(4096, 1024)
|
|
1896
|
-
assert_equal 0, bgid
|
|
1897
|
-
|
|
1898
|
-
bgid2 = machine.setup_buffer_ring(4096, 1024)
|
|
1899
|
-
assert_equal 1, bgid2
|
|
1900
|
-
|
|
1901
1884
|
bufs = []
|
|
1902
1885
|
|
|
1903
|
-
machine.recv_each(fd,
|
|
1886
|
+
machine.recv_each(fd, 0) do |buf|
|
|
1904
1887
|
bufs << buf
|
|
1905
1888
|
end
|
|
1906
1889
|
assert_equal ['abc', 'def', 'ghi'], bufs
|
|
@@ -1922,14 +1905,11 @@ class RecvEachTest < UMBaseTest
|
|
|
1922
1905
|
res = machine.connect(fd, '127.0.0.1', @port)
|
|
1923
1906
|
assert_equal 0, res
|
|
1924
1907
|
|
|
1925
|
-
bgid = machine.setup_buffer_ring(4096, 1024)
|
|
1926
|
-
assert_equal 0, bgid
|
|
1927
|
-
|
|
1928
1908
|
bufs = []
|
|
1929
1909
|
e = nil
|
|
1930
1910
|
begin
|
|
1931
1911
|
machine.timeout(0.01, TOError) do
|
|
1932
|
-
machine.recv_each(fd,
|
|
1912
|
+
machine.recv_each(fd, 0) do |buf|
|
|
1933
1913
|
bufs << buf
|
|
1934
1914
|
end
|
|
1935
1915
|
end
|
|
@@ -1953,9 +1933,6 @@ class RecvEachTest < UMBaseTest
|
|
|
1953
1933
|
res = machine.connect(fd, '127.0.0.1', @port)
|
|
1954
1934
|
assert_equal 0, res
|
|
1955
1935
|
|
|
1956
|
-
bgid = machine.setup_buffer_ring(4096, 1024)
|
|
1957
|
-
assert_equal 0, bgid
|
|
1958
|
-
|
|
1959
1936
|
bufs = []
|
|
1960
1937
|
e = nil
|
|
1961
1938
|
|
|
@@ -1965,7 +1942,7 @@ class RecvEachTest < UMBaseTest
|
|
|
1965
1942
|
}
|
|
1966
1943
|
|
|
1967
1944
|
begin
|
|
1968
|
-
machine.recv_each(fd,
|
|
1945
|
+
machine.recv_each(fd, 0) do |buf|
|
|
1969
1946
|
bufs << buf
|
|
1970
1947
|
end
|
|
1971
1948
|
rescue => e
|
|
@@ -3097,61 +3074,6 @@ class ForkTest < UMBaseTest
|
|
|
3097
3074
|
end
|
|
3098
3075
|
end
|
|
3099
3076
|
|
|
3100
|
-
class SendBundleTest < UMBaseTest
|
|
3101
|
-
def setup
|
|
3102
|
-
super
|
|
3103
|
-
@client_fd, @server_fd = UM.socketpair(UM::AF_UNIX, UM::SOCK_STREAM, 0)
|
|
3104
|
-
end
|
|
3105
|
-
|
|
3106
|
-
def test_send_bundle_splat
|
|
3107
|
-
bgid = machine.setup_buffer_ring(0, 8)
|
|
3108
|
-
assert_equal 0, bgid
|
|
3109
|
-
|
|
3110
|
-
strs = ['foo', 'bar', 'bazzzzz']
|
|
3111
|
-
len = strs.inject(0) { |len, s| len + s.bytesize }
|
|
3112
|
-
|
|
3113
|
-
ret = machine.send_bundle(@client_fd, bgid, *strs)
|
|
3114
|
-
assert_equal len, ret
|
|
3115
|
-
|
|
3116
|
-
buf = +''
|
|
3117
|
-
ret = machine.recv(@server_fd, buf, 8192, 0)
|
|
3118
|
-
assert_equal len, ret
|
|
3119
|
-
assert_equal strs.join, buf
|
|
3120
|
-
end
|
|
3121
|
-
|
|
3122
|
-
def test_send_bundle_array
|
|
3123
|
-
bgid = machine.setup_buffer_ring(0, 8)
|
|
3124
|
-
assert_equal 0, bgid
|
|
3125
|
-
|
|
3126
|
-
strs = ['foo', 'bar', 'bazzzzz']
|
|
3127
|
-
len = strs.inject(0) { |len, s| len + s.bytesize }
|
|
3128
|
-
|
|
3129
|
-
ret = machine.send_bundle(@client_fd, bgid, strs)
|
|
3130
|
-
assert_equal len, ret
|
|
3131
|
-
|
|
3132
|
-
buf = +''
|
|
3133
|
-
ret = machine.recv(@server_fd, buf, 8192, 0)
|
|
3134
|
-
assert_equal len, ret
|
|
3135
|
-
assert_equal strs.join, buf
|
|
3136
|
-
end
|
|
3137
|
-
|
|
3138
|
-
def test_send_bundle_non_strings
|
|
3139
|
-
bgid = machine.setup_buffer_ring(0, 8)
|
|
3140
|
-
assert_equal 0, bgid
|
|
3141
|
-
|
|
3142
|
-
strs = [42, 'bar', false]
|
|
3143
|
-
len = strs.inject(0) { |len, s| len + s.to_s.bytesize }
|
|
3144
|
-
|
|
3145
|
-
ret = machine.send_bundle(@client_fd, bgid, strs)
|
|
3146
|
-
assert_equal len, ret
|
|
3147
|
-
|
|
3148
|
-
buf = +''
|
|
3149
|
-
ret = machine.recv(@server_fd, buf, 8192, 0)
|
|
3150
|
-
assert_equal len, ret
|
|
3151
|
-
assert_equal strs.map(&:to_s).join, buf
|
|
3152
|
-
end
|
|
3153
|
-
end
|
|
3154
|
-
|
|
3155
3077
|
class MetricsTest < UMBaseTest
|
|
3156
3078
|
def test_metrics_empty
|
|
3157
3079
|
assert_equal({
|