uringmachine 0.8.2 → 0.10

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 24d5dacdb24cc1da4928d753803bd8012502147aaae23c4c7d9e53945550233c
4
- data.tar.gz: 783c8359ae60e149944bd7f79ac588c9b85241f5cec66de11eeae60b92e99753
3
+ metadata.gz: 85de1c3c67da5ef2a64b64a0370312208009683e9a42504bfbd7577bb6bee9f7
4
+ data.tar.gz: 13a34495c1987c85891ee5db9c196fbf09b6ebcd9a2221026341023e63e5a8e8
5
5
  SHA512:
6
- metadata.gz: 84c77a3826b01acd67bfca663d93e8a8e2a093b7415861040087d7bdcac97f34f3ed829c67529e6dd52abdc0ac88ac8395a0a39315f98fb2966f617c9b8f8dcb
7
- data.tar.gz: 238b77b0a4d669b3421d8ce26e888dad76d0885b19405017c1ce2c118f5fb0ac022c4ffed7288ae6389dda6f54810e511e77209bcc8f2e8872aee9a4573fa704
6
+ metadata.gz: 7b10f6a2c6e4d0bccaebb75c50e702ca0126eeb712a25ac32631b21ddcafd550dcceab2028a4f1a9b380538aa19067e0fa08346137a760307193af0acef64ed1
7
+ data.tar.gz: 0dc3949e9256f139cc1caab14b2de6b63e16af61c569de59b761153d8d05a2030bad0e299ca9044452cc628fd25accff8fe3e89c59e6d4c053f049339ddce2c3
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ # 2025-05-05 Version 0.10
2
+
3
+ - Add `Thread#machine`
4
+ - Add `Fiber#mailbox`
5
+
6
+ # 2025-05-05 Version 0.9
7
+
8
+ - Add `#statx`
9
+
1
10
  # 2025-05-05 Version 0.8.2
2
11
 
3
12
  - Correctly deal with -EAGAIN when waiting for CQEs
data/TODO.md CHANGED
@@ -10,7 +10,6 @@
10
10
  - poll_add / poll_remove / poll_multishot / poll_update
11
11
  - fsync
12
12
  - mkdir / mkdirat
13
- - statx
14
13
  - link / linkat / unlink / unlinkat / symlink
15
14
  - rename / renameat
16
15
  - fadvise
data/ext/um/um.c CHANGED
@@ -521,7 +521,7 @@ VALUE um_setsockopt(struct um *machine, int fd, int level, int opt, int value) {
521
521
 
522
522
  #ifdef HAVE_IO_URING_PREP_CMD_SOCK
523
523
  struct um_op op;
524
- um_prep_op(machine, &op, OP_GETSOCKOPT);
524
+ um_prep_op(machine, &op, OP_SETSOCKOPT);
525
525
  struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
526
526
  io_uring_prep_cmd_sock(sqe, SOCKET_URING_OP_SETSOCKOPT, fd, level, opt, &value, sizeof(value));
527
527
 
@@ -557,7 +557,7 @@ VALUE um_shutdown(struct um *machine, int fd, int how) {
557
557
 
558
558
  VALUE um_open(struct um *machine, VALUE pathname, int flags, int mode) {
559
559
  struct um_op op;
560
- um_prep_op(machine, &op, OP_BIND);
560
+ um_prep_op(machine, &op, OP_OPEN);
561
561
  struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
562
562
  io_uring_prep_open(sqe, StringValueCStr(pathname), flags, mode);
563
563
 
@@ -571,7 +571,7 @@ VALUE um_open(struct um *machine, VALUE pathname, int flags, int mode) {
571
571
 
572
572
  VALUE um_waitpid(struct um *machine, int pid, int options) {
573
573
  struct um_op op;
574
- um_prep_op(machine, &op, OP_BIND);
574
+ um_prep_op(machine, &op, OP_WAITPID);
575
575
  struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
576
576
 
577
577
  siginfo_t infop;
@@ -587,6 +587,52 @@ VALUE um_waitpid(struct um *machine, int pid, int options) {
587
587
  return rb_ary_new_from_args(2, INT2NUM(infop.si_pid), INT2NUM(infop.si_status));
588
588
  }
589
589
 
590
+ #define hash_set(h, sym, v) rb_hash_aset(h, ID2SYM(rb_intern(sym)), v)
591
+
592
+ VALUE statx_to_hash(struct statx *stat) {
593
+ VALUE hash = rb_hash_new();
594
+
595
+ hash_set(hash, "dev", UINT2NUM(stat->stx_dev_major << 8 | stat->stx_dev_minor));
596
+ hash_set(hash, "rdev", UINT2NUM(stat->stx_rdev_major << 8 | stat->stx_rdev_minor));
597
+ hash_set(hash, "blksize", UINT2NUM(stat->stx_blksize));
598
+ hash_set(hash, "attributes", UINT2NUM(stat->stx_attributes));
599
+ hash_set(hash, "nlink", UINT2NUM(stat->stx_nlink));
600
+ hash_set(hash, "uid", UINT2NUM(stat->stx_uid));
601
+ hash_set(hash, "gid", UINT2NUM(stat->stx_gid));
602
+ hash_set(hash, "mode", UINT2NUM(stat->stx_mode));
603
+ hash_set(hash, "ino", UINT2NUM(stat->stx_ino));
604
+ hash_set(hash, "size", UINT2NUM(stat->stx_size));
605
+ hash_set(hash, "blocks", UINT2NUM(stat->stx_blocks));
606
+ hash_set(hash, "atime", DBL2NUM(um_timestamp_to_double(stat->stx_atime.tv_sec, stat->stx_atime.tv_nsec)));
607
+ hash_set(hash, "btime", DBL2NUM(um_timestamp_to_double(stat->stx_btime.tv_sec, stat->stx_btime.tv_nsec)));
608
+ hash_set(hash, "ctime", DBL2NUM(um_timestamp_to_double(stat->stx_ctime.tv_sec, stat->stx_ctime.tv_nsec)));
609
+ hash_set(hash, "mtime", DBL2NUM(um_timestamp_to_double(stat->stx_mtime.tv_sec, stat->stx_mtime.tv_nsec)));
610
+ return hash;
611
+ }
612
+
613
+ VALUE um_statx(struct um *machine, int dirfd, VALUE path, int flags, unsigned int mask) {
614
+ struct um_op op;
615
+ um_prep_op(machine, &op, OP_STATX);
616
+ struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
617
+
618
+ struct statx stat;
619
+ memset(&stat, 0, sizeof(stat));
620
+
621
+ if (NIL_P(path))
622
+ path = rb_str_new_literal("");
623
+
624
+ io_uring_prep_statx(sqe, dirfd, StringValueCStr(path), flags, mask, &stat);
625
+
626
+ VALUE ret = um_fiber_switch(machine);
627
+ if (um_check_completion(machine, &op))
628
+ ret = INT2NUM(op.result.res);
629
+
630
+ RB_GC_GUARD(ret);
631
+ raise_if_exception(ret);
632
+
633
+ return statx_to_hash(&stat);
634
+ }
635
+
590
636
  /*******************************************************************************
591
637
  multishot ops
592
638
  *******************************************************************************/
data/ext/um/um.h CHANGED
@@ -25,9 +25,12 @@ enum op_kind {
25
25
  OP_SCHEDULE,
26
26
 
27
27
  OP_SLEEP,
28
+ OP_OPEN,
28
29
  OP_READ,
29
30
  OP_WRITE,
30
31
  OP_CLOSE,
32
+ OP_STATX,
33
+
31
34
  OP_ACCEPT,
32
35
  OP_RECV,
33
36
  OP_SEND,
@@ -38,6 +41,8 @@ enum op_kind {
38
41
  OP_GETSOCKOPT,
39
42
  OP_SETSOCKOPT,
40
43
  OP_SHUTDOWN,
44
+
45
+ OP_WAITPID,
41
46
 
42
47
  OP_FUTEX_WAIT,
43
48
  OP_FUTEX_WAKE,
@@ -176,6 +181,7 @@ void um_buffer_checkin(struct um *machine, struct um_buffer *buffer);
176
181
  void um_free_buffer_linked_list(struct um *machine);
177
182
 
178
183
  struct __kernel_timespec um_double_to_timespec(double value);
184
+ double um_timestamp_to_double(__s64 tv_sec, __u32 tv_nsec);
179
185
  int um_value_is_exception_p(VALUE v);
180
186
  VALUE um_raise_exception(VALUE v);
181
187
 
@@ -209,6 +215,7 @@ VALUE um_write(struct um *machine, int fd, VALUE str, int len);
209
215
  VALUE um_close(struct um *machine, int fd);
210
216
  VALUE um_open(struct um *machine, VALUE pathname, int flags, int mode);
211
217
  VALUE um_waitpid(struct um *machine, int pid, int options);
218
+ VALUE um_statx(struct um *machine, int dirfd, VALUE path, int flags, unsigned int mask);
212
219
 
213
220
  VALUE um_accept(struct um *machine, int fd);
214
221
  VALUE um_accept_each(struct um *machine, int fd);
data/ext/um/um_class.c CHANGED
@@ -130,6 +130,11 @@ VALUE UM_write(int argc, VALUE *argv, VALUE self) {
130
130
  return um_write(machine, NUM2INT(fd), buffer, bytes);
131
131
  }
132
132
 
133
+ VALUE UM_statx(VALUE self, VALUE dirfd, VALUE path, VALUE flags, VALUE mask) {
134
+ struct um *machine = um_get_machine(self);
135
+ return um_statx(machine, NUM2INT(dirfd), path, NUM2INT(flags), NUM2UINT(mask));
136
+ }
137
+
133
138
  VALUE UM_close(VALUE self, VALUE fd) {
134
139
  struct um *machine = um_get_machine(self);
135
140
  return um_close(machine, NUM2INT(fd));
@@ -342,6 +347,7 @@ void Init_UM(void) {
342
347
  rb_define_method(cUM, "sleep", UM_sleep, 1);
343
348
  rb_define_method(cUM, "periodically", UM_periodically, 1);
344
349
  rb_define_method(cUM, "write", UM_write, -1);
350
+ rb_define_method(cUM, "statx", UM_statx, 4);
345
351
 
346
352
  rb_define_method(cUM, "waitpid", UM_waitpid, 2);
347
353
 
data/ext/um/um_const.c CHANGED
@@ -1,6 +1,7 @@
1
1
  #include "ruby.h"
2
2
 
3
3
  #include <fcntl.h>
4
+ #include <sys/stat.h>
4
5
  #include <sys/wait.h>
5
6
 
6
7
  #include <arpa/inet.h>
@@ -16,6 +17,41 @@
16
17
  #define DEF_CONST_INT(mod, v) rb_define_const(mod, #v, INT2NUM(v))
17
18
 
18
19
  void um_define_net_constants(VALUE mod) {
20
+ DEF_CONST_INT(mod, AT_FDCWD);
21
+ DEF_CONST_INT(mod, AT_EMPTY_PATH);
22
+ DEF_CONST_INT(mod, AT_NO_AUTOMOUNT);
23
+ DEF_CONST_INT(mod, AT_SYMLINK_NOFOLLOW);
24
+ DEF_CONST_INT(mod, AT_STATX_SYNC_AS_STAT);
25
+ DEF_CONST_INT(mod, AT_STATX_FORCE_SYNC);
26
+ DEF_CONST_INT(mod, AT_STATX_DONT_SYNC);
27
+
28
+ DEF_CONST_INT(mod, STATX_TYPE);
29
+ DEF_CONST_INT(mod, STATX_MODE);
30
+ DEF_CONST_INT(mod, STATX_NLINK);
31
+ DEF_CONST_INT(mod, STATX_UID);
32
+ DEF_CONST_INT(mod, STATX_GID);
33
+ DEF_CONST_INT(mod, STATX_ATIME);
34
+ DEF_CONST_INT(mod, STATX_MTIME);
35
+ DEF_CONST_INT(mod, STATX_CTIME);
36
+ DEF_CONST_INT(mod, STATX_INO);
37
+ DEF_CONST_INT(mod, STATX_SIZE);
38
+ DEF_CONST_INT(mod, STATX_BLOCKS);
39
+ DEF_CONST_INT(mod, STATX_BASIC_STATS);
40
+ DEF_CONST_INT(mod, STATX_BTIME);
41
+ DEF_CONST_INT(mod, STATX_ALL);
42
+ DEF_CONST_INT(mod, STATX_MNT_ID);
43
+ DEF_CONST_INT(mod, STATX_DIOALIGN);
44
+ DEF_CONST_INT(mod, STATX_MNT_ID_UNIQUE);
45
+ #ifdef STATX_SUBVOL
46
+ DEF_CONST_INT(mod, STATX_SUBVOL);
47
+ #endif
48
+ #ifdef STATX_WRITE_ATOMIC
49
+ DEF_CONST_INT(mod, STATX_WRITE_ATOMIC);
50
+ #endif
51
+ #ifdef STATX_DIO_READ_ALIGN
52
+ DEF_CONST_INT(mod, STATX_DIO_READ_ALIGN);
53
+ #endif
54
+
19
55
  DEF_CONST_INT(mod, MSG_CONFIRM);
20
56
  DEF_CONST_INT(mod, MSG_DONTROUTE);
21
57
  DEF_CONST_INT(mod, MSG_DONTWAIT);
data/ext/um/um_utils.c CHANGED
@@ -11,6 +11,10 @@ inline struct __kernel_timespec um_double_to_timespec(double value) {
11
11
  return ts;
12
12
  }
13
13
 
14
+ inline double um_timestamp_to_double(__s64 tv_sec, __u32 tv_nsec) {
15
+ return (double)tv_sec + ((double)tv_nsec) / 1000000000;
16
+ }
17
+
14
18
  #define RAISE_EXCEPTION(e) rb_funcall(e, ID_invoke, 0);
15
19
 
16
20
  inline int um_value_is_exception_p(VALUE v) {
@@ -15,7 +15,7 @@ class UringMachine
15
15
  target = Object.new.extend(mod)
16
16
  mailbox = UM::Queue.new
17
17
  actor = Actor.new
18
- thread = Thread.new do
18
+ Thread.new do
19
19
  actor.run(machine, target, mailbox)
20
20
  end
21
21
  target.setup(*a, **k)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class UringMachine
4
- VERSION = '0.8.2'
4
+ VERSION = '0.10'
5
5
  end
data/lib/uringmachine.rb CHANGED
@@ -88,9 +88,23 @@ class UringMachine
88
88
  def add_done_listener(queue)
89
89
  (@done_listeners ||= []) << queue
90
90
  end
91
+
92
+ def mailbox
93
+ @mailbox ||= UM::Queue.new
94
+ end
91
95
  end
92
96
 
93
97
  class ::Fiber
94
- include UringMachine::FiberExtensions
98
+ include FiberExtensions
99
+ end
100
+
101
+ module ThreadExtensions
102
+ def machine
103
+ @machine ||= UM.new
104
+ end
105
+ end
106
+
107
+ class ::Thread
108
+ include ThreadExtensions
95
109
  end
96
110
  end
data/test/test_fiber.rb CHANGED
@@ -63,7 +63,7 @@ class FiberTerminateTest < UMBaseTest
63
63
  end
64
64
  end
65
65
 
66
- class JoinTest < UMBaseTest
66
+ class FiberJoinTest < UMBaseTest
67
67
  def test_join
68
68
  q = UM::Queue.new
69
69
  x = nil
@@ -151,14 +151,14 @@ class ScopeTest < UMBaseTest
151
151
 
152
152
  t0 = monotonic_clock
153
153
  machine.scope do
154
- f1 = machine.spin do
154
+ machine.spin do
155
155
  x1 = 1
156
156
  machine.sleep 0.01
157
157
  ensure
158
158
  x1 = 0
159
159
  end
160
160
 
161
- f2 = machine.spin do
161
+ machine.spin do
162
162
  x2 = 1
163
163
  machine.sleep 0.03
164
164
  ensure
@@ -172,3 +172,23 @@ class ScopeTest < UMBaseTest
172
172
  assert_equal 0, x2
173
173
  end
174
174
  end
175
+
176
+ class FiberMailboxTest < UMBaseTest
177
+ def test_fiber_mailbox
178
+ m = Fiber.current.mailbox
179
+ assert_kind_of UM::Queue, m
180
+
181
+ m2 = Fiber.current.mailbox
182
+ assert_equal m, m2
183
+ end
184
+ end
185
+
186
+ class ThreadMachineTest < UMBaseTest
187
+ def test_thread_machine
188
+ m = Thread.current.machine
189
+ assert_kind_of UM, m
190
+
191
+ m2 = Thread.current.machine
192
+ assert_equal m, m2
193
+ end
194
+ end
data/test/test_um.rb CHANGED
@@ -29,7 +29,7 @@ end
29
29
 
30
30
  class SnoozeTest < UMBaseTest
31
31
  def test_snooze_while_sleeping_fiber
32
- f = machine.spin do
32
+ machine.spin do
33
33
  machine.sleep(0.1)
34
34
  end
35
35
 
@@ -655,7 +655,6 @@ class AcceptEachTest < UMBaseTest
655
655
  end
656
656
 
657
657
  def test_accept_each_interrupted
658
- conns = []
659
658
  count = 0
660
659
  terminated = nil
661
660
  f = @machine.spin do
@@ -678,6 +677,8 @@ class AcceptEachTest < UMBaseTest
678
677
 
679
678
  assert f.done?
680
679
  assert terminated
680
+ ensure
681
+ s.close
681
682
  end
682
683
  end
683
684
 
@@ -1231,3 +1232,46 @@ class WaitTest < UMBaseTest
1231
1232
  assert_raises(Errno::ECHILD) { machine.waitpid(1, UM::WEXITED) }
1232
1233
  end
1233
1234
  end
1235
+
1236
+ class StatxTest < UMBaseTest
1237
+ def test_statx
1238
+ io = File.open(__FILE__, 'r')
1239
+ ustat = machine.statx(io.fileno, nil, UM::AT_EMPTY_PATH, UM::STATX_ALL)
1240
+ rstat = File.stat(__FILE__)
1241
+
1242
+ assert_equal rstat.dev, ustat[:dev]
1243
+ assert_equal rstat.ino, ustat[:ino]
1244
+ assert_equal rstat.mode, ustat[:mode]
1245
+ assert_equal rstat.nlink, ustat[:nlink]
1246
+ assert_equal rstat.uid, ustat[:uid]
1247
+ assert_equal rstat.gid, ustat[:gid]
1248
+ assert_equal rstat.rdev, ustat[:rdev]
1249
+ assert_equal rstat.size, ustat[:size]
1250
+ assert_equal rstat.blksize, ustat[:blksize]
1251
+ assert_equal rstat.blocks, ustat[:blocks]
1252
+ assert_equal rstat.atime.to_i, ustat[:atime].to_i
1253
+ assert_equal rstat.ctime.to_i, ustat[:ctime].to_i
1254
+ assert_equal rstat.mtime.to_i, ustat[:mtime].to_i
1255
+
1256
+ ustat2 = machine.statx(UM::AT_FDCWD, __FILE__, 0, UM::STATX_ALL)
1257
+ assert_equal rstat.dev, ustat2[:dev]
1258
+ assert_equal rstat.ino, ustat2[:ino]
1259
+ assert_equal rstat.mode, ustat2[:mode]
1260
+ assert_equal rstat.nlink, ustat2[:nlink]
1261
+ assert_equal rstat.uid, ustat2[:uid]
1262
+ assert_equal rstat.gid, ustat2[:gid]
1263
+ assert_equal rstat.rdev, ustat2[:rdev]
1264
+ assert_equal rstat.size, ustat2[:size]
1265
+ assert_equal rstat.blksize, ustat2[:blksize]
1266
+ assert_equal rstat.blocks, ustat2[:blocks]
1267
+ assert_equal rstat.atime.to_i, ustat2[:atime].to_i
1268
+ assert_equal rstat.ctime.to_i, ustat2[:ctime].to_i
1269
+ assert_equal rstat.mtime.to_i, ustat2[:mtime].to_i
1270
+ ensure
1271
+ io.close
1272
+ end
1273
+
1274
+ def test_statx_bad_path
1275
+ assert_raises(Errno::ENOENT) { machine.statx(UM::AT_FDCWD, 'foobar', 0, UM::STATX_ALL) }
1276
+ end
1277
+ end
data/uringmachine.gemspec CHANGED
@@ -22,7 +22,5 @@ Gem::Specification.new do |s|
22
22
 
23
23
  s.add_development_dependency 'rake-compiler', '1.2.9'
24
24
  s.add_development_dependency 'minitest', '5.25.4'
25
- s.add_development_dependency 'http_parser.rb', '0.8.0'
26
25
  s.add_development_dependency 'benchmark-ips', '2.14.0'
27
- s.add_development_dependency 'localhost', '1.3.1'
28
26
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: uringmachine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.2
4
+ version: '0.10'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner
@@ -37,20 +37,6 @@ dependencies:
37
37
  - - '='
38
38
  - !ruby/object:Gem::Version
39
39
  version: 5.25.4
40
- - !ruby/object:Gem::Dependency
41
- name: http_parser.rb
42
- requirement: !ruby/object:Gem::Requirement
43
- requirements:
44
- - - '='
45
- - !ruby/object:Gem::Version
46
- version: 0.8.0
47
- type: :development
48
- prerelease: false
49
- version_requirements: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - '='
52
- - !ruby/object:Gem::Version
53
- version: 0.8.0
54
40
  - !ruby/object:Gem::Dependency
55
41
  name: benchmark-ips
56
42
  requirement: !ruby/object:Gem::Requirement
@@ -65,20 +51,6 @@ dependencies:
65
51
  - - '='
66
52
  - !ruby/object:Gem::Version
67
53
  version: 2.14.0
68
- - !ruby/object:Gem::Dependency
69
- name: localhost
70
- requirement: !ruby/object:Gem::Requirement
71
- requirements:
72
- - - '='
73
- - !ruby/object:Gem::Version
74
- version: 1.3.1
75
- type: :development
76
- prerelease: false
77
- version_requirements: !ruby/object:Gem::Requirement
78
- requirements:
79
- - - '='
80
- - !ruby/object:Gem::Version
81
- version: 1.3.1
82
54
  email: sharon@noteflakes.com
83
55
  executables: []
84
56
  extensions: