polyphony 0.81.1 → 0.84

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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +1 -1
  3. data/.gitmodules +3 -0
  4. data/CHANGELOG.md +17 -0
  5. data/Gemfile.lock +1 -1
  6. data/Rakefile +14 -0
  7. data/bin/test +1 -1
  8. data/ext/polyphony/backend_common.c +33 -10
  9. data/ext/polyphony/backend_common.h +20 -2
  10. data/ext/polyphony/backend_io_uring.c +182 -220
  11. data/ext/polyphony/backend_libev.c +212 -197
  12. data/ext/polyphony/extconf.rb +21 -2
  13. data/ext/polyphony/io_extensions.c +440 -0
  14. data/ext/polyphony/pipe.c +109 -0
  15. data/ext/polyphony/polyphony.c +50 -1
  16. data/ext/polyphony/polyphony.h +6 -11
  17. data/ext/polyphony/polyphony_ext.c +7 -2
  18. data/ext/polyphony/zlib_conf.rb +119 -0
  19. data/lib/polyphony/extensions/io.rb +20 -2
  20. data/lib/polyphony/extensions/pipe.rb +171 -0
  21. data/lib/polyphony/extensions.rb +1 -0
  22. data/lib/polyphony/version.rb +1 -1
  23. data/lib/polyphony.rb +4 -0
  24. data/test/helper.rb +4 -0
  25. data/test/test_backend.rb +3 -48
  26. data/test/test_global_api.rb +23 -23
  27. data/test/test_io.rb +426 -0
  28. data/test/test_pipe.rb +41 -0
  29. data/test/test_process_supervision.rb +1 -1
  30. data/test/test_raw_buffer.rb +37 -0
  31. data/test/test_socket.rb +50 -0
  32. metadata +8 -13
  33. data/ext/liburing/liburing/README.md +0 -4
  34. data/ext/liburing/liburing/barrier.h +0 -73
  35. data/ext/liburing/liburing/compat.h +0 -15
  36. data/ext/liburing/liburing/io_uring.h +0 -343
  37. data/ext/liburing/liburing.h +0 -585
  38. data/ext/liburing/queue.c +0 -333
  39. data/ext/liburing/register.c +0 -187
  40. data/ext/liburing/setup.c +0 -210
  41. data/ext/liburing/syscall.c +0 -54
  42. data/ext/liburing/syscall.h +0 -18
  43. data/ext/polyphony/liburing.c +0 -8
data/test/test_io.rb CHANGED
@@ -279,6 +279,188 @@ class IOTest < MiniTest::Test
279
279
  sleep 0.01
280
280
  assert_equal ['foo', 'bar', 'baz'], receiver.buffer
281
281
  end
282
+
283
+ def test_splice_from
284
+ i1, o1 = IO.pipe
285
+ i2, o2 = IO.pipe
286
+ len = nil
287
+
288
+ spin {
289
+ len = o2.splice_from(i1, 1000)
290
+ o2.close
291
+ }
292
+
293
+ o1.write('foobar')
294
+ result = i2.read
295
+
296
+ assert_equal 'foobar', result
297
+ assert_equal 6, len
298
+ end
299
+
300
+ def test_splice_class_method
301
+ i1, o1 = IO.pipe
302
+ i2, o2 = IO.pipe
303
+ len = nil
304
+
305
+ spin {
306
+ len = IO.splice(i1, o2, 1000)
307
+ o2.close
308
+ }
309
+
310
+ o1.write('foobar')
311
+ result = i2.read
312
+
313
+ assert_equal 'foobar', result
314
+ assert_equal 6, len
315
+ end
316
+
317
+ def test_splice_to_eof_from
318
+ i1, o1 = IO.pipe
319
+ i2, o2 = IO.pipe
320
+ len = nil
321
+
322
+ f = spin {
323
+ len = o2.splice_to_eof_from(i1, 1000)
324
+ o2.close
325
+ }
326
+
327
+ o1.write('foo')
328
+ result = i2.readpartial(1000)
329
+ assert_equal 'foo', result
330
+
331
+ o1.write('bar')
332
+ result = i2.readpartial(1000)
333
+ assert_equal 'bar', result
334
+ o1.close
335
+ f.await
336
+ assert_equal 6, len
337
+ ensure
338
+ if f.alive?
339
+ f.interrupt
340
+ f.await
341
+ end
342
+ end
343
+
344
+ def test_splice_to_eof_class_method
345
+ i1, o1 = IO.pipe
346
+ i2, o2 = IO.pipe
347
+ len = nil
348
+
349
+ f = spin {
350
+ len = IO.splice_to_eof(i1, o2, 1000)
351
+ o2.close
352
+ }
353
+
354
+ o1.write('foo')
355
+ result = i2.readpartial(1000)
356
+ assert_equal 'foo', result
357
+
358
+ o1.write('bar')
359
+ result = i2.readpartial(1000)
360
+ assert_equal 'bar', result
361
+ o1.close
362
+ f.await
363
+ assert_equal 6, len
364
+ ensure
365
+ if f.alive?
366
+ f.interrupt
367
+ f.await
368
+ end
369
+ end
370
+
371
+ def test_tee_from
372
+ skip "tested only on Linux" unless RUBY_PLATFORM =~ /linux/
373
+
374
+ src = Polyphony.pipe
375
+ dest1 = Polyphony.pipe
376
+ dest2 = Polyphony.pipe
377
+
378
+ len1 = len2 = nil
379
+
380
+ spin {
381
+ len1 = dest1.tee_from(src, 1000)
382
+ dest1.close
383
+ len2 = IO.splice(src, dest2, 1000)
384
+ dest2.close
385
+ }
386
+
387
+ src << 'foobar'
388
+ src.close
389
+ result1 = dest1.read
390
+ result2 = dest2.read
391
+
392
+ assert_equal 'foobar', result1
393
+ assert_equal 6, len1
394
+
395
+ assert_equal 'foobar', result2
396
+ assert_equal 6, len2
397
+ end
398
+
399
+ def test_tee_class_method
400
+ skip "tested only on Linux" unless RUBY_PLATFORM =~ /linux/
401
+
402
+ src = Polyphony.pipe
403
+ dest1 = Polyphony.pipe
404
+ dest2 = Polyphony.pipe
405
+
406
+ len1 = len2 = nil
407
+
408
+ spin {
409
+ len1 = IO.tee(src, dest1, 1000)
410
+ dest1.close
411
+ len2 = IO.splice(src, dest2, 1000)
412
+ dest2.close
413
+ }
414
+
415
+ src << 'foobar'
416
+ src.close
417
+ result1 = dest1.read
418
+ result2 = dest2.read
419
+
420
+ assert_equal 'foobar', result1
421
+ assert_equal 6, len1
422
+
423
+ assert_equal 'foobar', result2
424
+ assert_equal 6, len2
425
+ end
426
+
427
+
428
+
429
+ end
430
+
431
+ class IOWithRawBufferTest < MiniTest::Test
432
+ def setup
433
+ super
434
+ @i, @o = IO.pipe
435
+ end
436
+
437
+ def test_write_with_raw_buffer
438
+ Polyphony.__with_raw_buffer__(64) do |b|
439
+ Polyphony.__raw_buffer_set__(b, 'foobar')
440
+ @o << b
441
+ @o.close
442
+ end
443
+
444
+ str = @i.read
445
+ assert_equal 'foobar', str
446
+ end
447
+
448
+ def test_read_with_raw_buffer
449
+ @o << '*' * 65
450
+ @o.close
451
+ chunks = []
452
+ Polyphony.__with_raw_buffer__(64) do |b|
453
+ res = @i.read(64, b)
454
+ assert_equal 64, res
455
+ chunks << Polyphony.__raw_buffer_get__(b, res)
456
+
457
+ res = @i.read(64, b)
458
+ assert_equal 1, res
459
+ assert_equal 64, Polyphony.__raw_buffer_size__(b)
460
+ chunks << Polyphony.__raw_buffer_get__(b, res)
461
+ end
462
+ assert_equal ['*' * 64, '*'], chunks
463
+ end
282
464
  end
283
465
 
284
466
  class IOClassMethodsTest < MiniTest::Test
@@ -468,3 +650,247 @@ class IOClassMethodsTest < MiniTest::Test
468
650
  assert_equal ['foo', 'bar'], buf
469
651
  end
470
652
  end
653
+
654
+ class IOExtensionsTest < MiniTest::Test
655
+ def test_deflate
656
+ i, o = IO.pipe
657
+ r, w = IO.pipe
658
+
659
+ spin {
660
+ IO.deflate(i, w)
661
+ w.close
662
+ }
663
+
664
+ o << 'foobar' * 20
665
+ o.close
666
+
667
+ data = r.read
668
+ msg = Zlib::Inflate.inflate(data)
669
+ assert_equal 'foobar' * 20, msg
670
+ end
671
+
672
+ def test_inflate
673
+ i, o = IO.pipe
674
+ r, w = IO.pipe
675
+
676
+ spin {
677
+ data = Zlib::Deflate.deflate('foobar', 9)
678
+ o << data
679
+ o.close
680
+ }
681
+
682
+ IO.inflate(i, w)
683
+ w.close
684
+ msg = r.read
685
+ assert_equal 'foobar', msg
686
+ end
687
+
688
+ def test_gzip
689
+ src = Polyphony.pipe
690
+ dest = Polyphony.pipe
691
+ now = nil
692
+
693
+ spin {
694
+ now = Time.now
695
+ IO.gzip(src, dest)
696
+ dest.close
697
+ }
698
+
699
+ src << IO.read(__FILE__)
700
+ src.close
701
+
702
+ gz = Zlib::GzipReader.new(dest)
703
+ data = gz.read
704
+ assert_equal IO.read(__FILE__), data
705
+ assert_in_range (now-2)..(now+1), gz.mtime
706
+ assert_nil gz.orig_name
707
+ assert_nil gz.comment
708
+ end
709
+
710
+ def test_gzip_with_mtime_int
711
+ src = Polyphony.pipe
712
+ dest = Polyphony.pipe
713
+
714
+ spin {
715
+ IO.gzip(src, dest, mtime: 42)
716
+ dest.close
717
+ }
718
+
719
+ src << IO.read(__FILE__)
720
+ src.close
721
+
722
+ gz = Zlib::GzipReader.new(dest)
723
+ data = gz.read
724
+ assert_equal IO.read(__FILE__), data
725
+ assert_equal Time.at(42), gz.mtime
726
+ end
727
+
728
+ def test_gzip_with_mtime_false
729
+ src = Polyphony.pipe
730
+ dest = Polyphony.pipe
731
+
732
+ spin {
733
+ IO.gzip(src, dest, mtime: false)
734
+ dest.close
735
+ }
736
+
737
+ src << IO.read(__FILE__)
738
+ src.close
739
+
740
+ gz = Zlib::GzipReader.new(dest)
741
+ data = gz.read
742
+ assert_equal IO.read(__FILE__), data
743
+ assert_equal Time.at(0), gz.mtime
744
+ end
745
+
746
+ def test_gzip_with_mtime_time
747
+ src = Polyphony.pipe
748
+ dest = Polyphony.pipe
749
+ t = Time.at(Time.now.to_i) - rand(300000)
750
+
751
+ spin {
752
+ IO.gzip(src, dest, mtime: t)
753
+ dest.close
754
+ }
755
+
756
+ src << IO.read(__FILE__)
757
+ src.close
758
+
759
+ gz = Zlib::GzipReader.new(dest)
760
+ data = gz.read
761
+ assert_equal IO.read(__FILE__), data
762
+ assert_equal t, gz.mtime
763
+ end
764
+
765
+ def test_gzip_with_orig_name
766
+ src = Polyphony.pipe
767
+ dest = Polyphony.pipe
768
+
769
+ spin {
770
+ IO.gzip(src, dest, orig_name: '/foo/bar')
771
+ dest.close
772
+ }
773
+
774
+ src << IO.read(__FILE__)
775
+ src.close
776
+
777
+ gz = Zlib::GzipReader.new(dest)
778
+ data = gz.read
779
+ assert_equal IO.read(__FILE__), data
780
+ assert_equal '/foo/bar', gz.orig_name
781
+ end
782
+
783
+ def test_gzip_with_comment
784
+ src = Polyphony.pipe
785
+ dest = Polyphony.pipe
786
+
787
+ spin {
788
+ IO.gzip(src, dest, comment: 'hello!')
789
+ dest.close
790
+ }
791
+
792
+ src << IO.read(__FILE__)
793
+ src.close
794
+
795
+ gz = Zlib::GzipReader.new(dest)
796
+ data = gz.read
797
+ assert_equal IO.read(__FILE__), data
798
+ assert_equal 'hello!', gz.comment
799
+ end
800
+
801
+ def test_gunzip
802
+ src = Polyphony.pipe
803
+ dest = Polyphony.pipe
804
+
805
+ spin {
806
+ IO.gunzip(src, dest)
807
+ dest.close
808
+ }
809
+
810
+ gz = Zlib::GzipWriter.new(src, 9)
811
+ gz << 'foobar'#IO.read(__FILE__)
812
+ gz.close
813
+
814
+ data = dest.read
815
+ # assert_equal IO.read(__FILE__), data
816
+ assert_equal 'foobar', data
817
+ end
818
+
819
+ def test_gunzip_multi
820
+ src1 = Polyphony.pipe
821
+ src2 = Polyphony.pipe
822
+ dest = Polyphony.pipe
823
+
824
+ spin {
825
+ IO.gunzip(src1, dest)
826
+ IO.gunzip(src2, dest)
827
+ dest.close
828
+ }
829
+
830
+ gz1 = Zlib::GzipWriter.new(src1)
831
+ gz1 << 'foobar'
832
+ gz1.close
833
+
834
+ gz1 = Zlib::GzipWriter.new(src2)
835
+ gz1 << 'raboof'
836
+ gz1.close
837
+
838
+ data = dest.read
839
+ assert_equal 'foobarraboof', data
840
+ end
841
+
842
+ def test_gzip_gunzip
843
+ gzipped = Polyphony.pipe
844
+ gunzipped = Polyphony.pipe
845
+
846
+ spin { File.open(__FILE__, 'r') { |f| IO.gzip(f, gzipped) }; gzipped.close }
847
+ spin { IO.gunzip(gzipped, gunzipped); gunzipped.close }
848
+
849
+ data = gunzipped.read
850
+ assert_equal IO.read(__FILE__), data
851
+ end
852
+
853
+ def test_gunzip_with_empty_info
854
+ gzipped = Polyphony.pipe
855
+ gunzipped = Polyphony.pipe
856
+ info = {}
857
+
858
+ spin {
859
+ File.open(__FILE__, 'r') { |f| IO.gzip(f, gzipped, mtime: false) }
860
+ gzipped.close
861
+ }
862
+ spin { IO.gunzip(gzipped, gunzipped, info); gunzipped.close }
863
+
864
+ data = gunzipped.read
865
+ assert_equal IO.read(__FILE__), data
866
+ assert_equal Time.at(0), info[:mtime]
867
+ assert_nil info[:orig_name]
868
+ assert_nil info[:comment]
869
+ end
870
+
871
+ def test_gunzip_with_info
872
+ src = Polyphony.pipe
873
+ gzipped = Polyphony.pipe
874
+ gunzipped = Polyphony.pipe
875
+
876
+ src_info = {
877
+ mtime: 42,
878
+ orig_name: 'foo.bar',
879
+ comment: 'hello!'
880
+ }
881
+
882
+ dest_info = {}
883
+
884
+ spin { IO.gzip(src, gzipped, src_info); gzipped.close }
885
+ spin { IO.gunzip(gzipped, gunzipped, dest_info); gunzipped.close }
886
+
887
+ src << 'foobar'
888
+ src.close
889
+
890
+ data = gunzipped.read
891
+ assert_equal 'foobar', data
892
+ assert_equal Time.at(42), dest_info[:mtime]
893
+ assert_equal 'foo.bar', dest_info[:orig_name]
894
+ assert_equal 'hello!', dest_info[:comment]
895
+ end
896
+ end
data/test/test_pipe.rb ADDED
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+
5
+ class PipeTest < MiniTest::Test
6
+ def test_pipe_creation
7
+ pipe = Polyphony::Pipe.new
8
+
9
+ fds = pipe.fds
10
+ assert_equal 2, fds.size
11
+ assert_kind_of Integer, fds[0]
12
+ assert_kind_of Integer, fds[1]
13
+ assert_equal false, pipe.closed?
14
+ end
15
+
16
+ def test_polyphony_pipe_method
17
+ pipe = Polyphony.pipe
18
+
19
+ fds = pipe.fds
20
+ assert_equal 2, fds.size
21
+ assert_kind_of Integer, fds[0]
22
+ assert_kind_of Integer, fds[1]
23
+ assert_equal false, pipe.closed?
24
+ end
25
+
26
+ def test_pipe_splice
27
+ src = Polyphony::Pipe.new
28
+ dest = Polyphony::Pipe.new
29
+
30
+ spin {
31
+ IO.splice(src, dest, 8192)
32
+ dest.close
33
+ }
34
+
35
+ src << IO.read(__FILE__)
36
+ src.close
37
+
38
+ data = dest.read
39
+ assert_equal IO.read(__FILE__), data
40
+ end
41
+ end
@@ -65,7 +65,7 @@ class ProcessSupervisionTest < MiniTest::Test
65
65
 
66
66
  supervisor = spin { supervise(watcher) }
67
67
 
68
- sleep 0.1
68
+ sleep 0.2
69
69
  supervisor.terminate
70
70
  supervisor.await
71
71
 
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+ require 'msgpack'
5
+
6
+ class RawBufferTest < MiniTest::Test
7
+ def test_with_raw_buffer
8
+ result = Polyphony.__with_raw_buffer__(64) do |b|
9
+ assert_kind_of Integer, b
10
+ assert_equal 64, Polyphony.__raw_buffer_size__(b)
11
+ :foo
12
+ end
13
+ assert_equal :foo, result
14
+ end
15
+
16
+ def test_raw_buffer_get_set
17
+ Polyphony.__with_raw_buffer__(64) do |b|
18
+ # should raise if buffer not big enough
19
+ assert_raises { Polyphony.__raw_buffer_set__(b, '*' * 65) }
20
+
21
+ Polyphony.__raw_buffer_set__(b, 'foobar')
22
+ assert_equal 6, Polyphony.__raw_buffer_size__(b)
23
+
24
+ str = Polyphony.__raw_buffer_get__(b)
25
+ assert_equal 'foobar', str
26
+
27
+ str = Polyphony.__raw_buffer_get__(b, 3)
28
+ assert_equal 'foo', str
29
+
30
+ Polyphony.__raw_buffer_set__(b, '')
31
+ assert_equal 0, Polyphony.__raw_buffer_size__(b)
32
+
33
+ str = Polyphony.__raw_buffer_get__(b)
34
+ assert_equal '', str
35
+ end
36
+ end
37
+ end
data/test/test_socket.rb CHANGED
@@ -193,6 +193,56 @@ class SocketTest < MiniTest::Test
193
193
  end
194
194
  end
195
195
 
196
+ class SocketWithRawBufferTest < MiniTest::Test
197
+ def start_tcp_server_on_random_port(host = '127.0.0.1')
198
+ port = rand(1100..60000)
199
+ server = TCPServer.new(host, port)
200
+ [port, server]
201
+ rescue Errno::EADDRINUSE
202
+ retry
203
+ end
204
+
205
+ def setup
206
+ super
207
+
208
+ port, server = start_tcp_server_on_random_port
209
+ connector = spin { @o = TCPSocket.new('127.0.0.1', port) }
210
+ @i = server.accept
211
+ connector.await
212
+ end
213
+
214
+ def test_send_with_raw_buffer
215
+ Polyphony.__with_raw_buffer__(64) do |b|
216
+ Polyphony.__raw_buffer_set__(b, 'foobar')
217
+ @o << b
218
+ @o.close
219
+ end
220
+
221
+ str = @i.read
222
+ assert_equal 'foobar', str
223
+ end
224
+
225
+ def test_recv_with_raw_buffer
226
+ @o << '*' * 65
227
+ @o.close
228
+ chunks = []
229
+ Polyphony.__with_raw_buffer__(64) do |b|
230
+ res = @i.recv(64, 0, b)
231
+ assert_equal 64, res
232
+ chunks << Polyphony.__raw_buffer_get__(b, res)
233
+
234
+ res = @i.recv(64, 0, b)
235
+ assert_equal 1, res
236
+ assert_equal 64, Polyphony.__raw_buffer_size__(b)
237
+ chunks << Polyphony.__raw_buffer_get__(b, res)
238
+
239
+ res = @i.recv(64, 0, b)
240
+ assert_nil res
241
+ end
242
+ assert_equal ['*' * 64, '*'], chunks
243
+ end
244
+ end
245
+
196
246
  if IS_LINUX
197
247
  class HTTPClientTest < MiniTest::Test
198
248
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: polyphony
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.81.1
4
+ version: '0.84'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-03-03 00:00:00.000000000 Z
11
+ date: 2022-03-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -315,16 +315,6 @@ files:
315
315
  - ext/libev/ev_win32.c
316
316
  - ext/libev/ev_wrap.h
317
317
  - ext/libev/test_libev_win32.c
318
- - ext/liburing/liburing.h
319
- - ext/liburing/liburing/README.md
320
- - ext/liburing/liburing/barrier.h
321
- - ext/liburing/liburing/compat.h
322
- - ext/liburing/liburing/io_uring.h
323
- - ext/liburing/queue.c
324
- - ext/liburing/register.c
325
- - ext/liburing/setup.c
326
- - ext/liburing/syscall.c
327
- - ext/liburing/syscall.h
328
318
  - ext/polyphony/backend_common.c
329
319
  - ext/polyphony/backend_common.h
330
320
  - ext/polyphony/backend_io_uring.c
@@ -334,9 +324,10 @@ files:
334
324
  - ext/polyphony/event.c
335
325
  - ext/polyphony/extconf.rb
336
326
  - ext/polyphony/fiber.c
327
+ - ext/polyphony/io_extensions.c
337
328
  - ext/polyphony/libev.c
338
329
  - ext/polyphony/libev.h
339
- - ext/polyphony/liburing.c
330
+ - ext/polyphony/pipe.c
340
331
  - ext/polyphony/playground.c
341
332
  - ext/polyphony/polyphony.c
342
333
  - ext/polyphony/polyphony.h
@@ -350,6 +341,7 @@ files:
350
341
  - ext/polyphony/runqueue_ring_buffer.h
351
342
  - ext/polyphony/socket_extensions.c
352
343
  - ext/polyphony/thread.c
344
+ - ext/polyphony/zlib_conf.rb
353
345
  - ext/test_eintr.c
354
346
  - lib/polyphony.rb
355
347
  - lib/polyphony/adapters/fs.rb
@@ -376,6 +368,7 @@ files:
376
368
  - lib/polyphony/extensions/kernel.rb
377
369
  - lib/polyphony/extensions/object.rb
378
370
  - lib/polyphony/extensions/openssl.rb
371
+ - lib/polyphony/extensions/pipe.rb
379
372
  - lib/polyphony/extensions/process.rb
380
373
  - lib/polyphony/extensions/socket.rb
381
374
  - lib/polyphony/extensions/thread.rb
@@ -397,8 +390,10 @@ files:
397
390
  - test/test_global_api.rb
398
391
  - test/test_io.rb
399
392
  - test/test_kernel.rb
393
+ - test/test_pipe.rb
400
394
  - test/test_process_supervision.rb
401
395
  - test/test_queue.rb
396
+ - test/test_raw_buffer.rb
402
397
  - test/test_resource_pool.rb
403
398
  - test/test_signal.rb
404
399
  - test/test_socket.rb
@@ -1,4 +0,0 @@
1
- ## Updating the liburing source code
2
-
3
- - copy liburing/src/**/* into ext/liburing
4
- - move ext/liburing/include/**/* to ext/liburing/