polyphony 0.61 → 0.65

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: b7056ec954b2264a15f88934d2b1e65f53c76c301453851ceadf60715570e474
4
- data.tar.gz: 1cd5835b7a5a3d4036e1eabf45ded2e09efdc7cacb207fc0a1a60ac67da02d90
3
+ metadata.gz: 3ffef1fb2b3d081c388c32219346ace5c99b689c73549fed65be882ff1f9e1eb
4
+ data.tar.gz: 20f2a26377b984f23c427f65fb6f776fe6cfda504667cc710fa3152ec63c920d
5
5
  SHA512:
6
- metadata.gz: b5e32edc6bc22ba580e7c6d7d42a73982803080e9a9782326cb7b8796aa62ad6b75bccb1e6607879f0d3e5a5c4db8e5597d8407b76014f08f3945d1d8ad0097a
7
- data.tar.gz: b8fe0f9419061295f830ed12ae9c8ea089a966686388cff580ddb6e1f7cd8c17a04928f9af41083019a5a11e8cccce25af404959db30a730a2ade2359a7e07ef
6
+ metadata.gz: 31223abf79dad98bfa68c43159474756e1a5e4c713b54239117ec8a57e540ce2914fcfac244b598d36ff3bed49e6efb0b979efc775fdd0a1a8b9e5e1cbe2d25e
7
+ data.tar.gz: d126c5da62b17a96ae915304c291e520662030dcabe856bcbe4a18d22f2f9c5dfde913a3d89b09a0ad00562ae949aa26a25942163a2decdf2f3184cae0df4a7b
data/CHANGELOG.md CHANGED
@@ -1,3 +1,20 @@
1
+ ## 0.65 2021-07-29
2
+
3
+ - Add `#__polyphony_read_method__` method for read method detection
4
+
5
+ ## 0.64 2021-07-26
6
+
7
+ - Add optional raise_on_eof argument to `#readpartial`
8
+
9
+ ## 0.63 2021-07-26
10
+
11
+ - Add support for specifying buf and buf_pos in `IO#read`
12
+ - Fix `Socket#read` to work and conform to `IO#read` interface
13
+
14
+ ## 0.62 2021-07-21
15
+
16
+ - Add `runqueue_size` to backend stats
17
+
1
18
  ## 0.61 2021-07-20
2
19
 
3
20
  - Add more statistics, move stats to `Backend#stats`
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- polyphony (0.61)
4
+ polyphony (0.65)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/Rakefile CHANGED
@@ -9,8 +9,8 @@ Rake::ExtensionTask.new("polyphony_ext") do |ext|
9
9
  end
10
10
 
11
11
  task :recompile => [:clean, :compile]
12
-
13
12
  task :default => [:compile, :test]
13
+
14
14
  task :test do
15
15
  exec 'ruby test/run.rb'
16
16
  end
@@ -112,22 +112,6 @@ inline void backend_trace(struct Backend_base *base, int argc, VALUE *argv) {
112
112
  rb_funcallv(base->trace_proc, ID_call, argc, argv);
113
113
  }
114
114
 
115
- inline struct backend_stats backend_base_stats(struct Backend_base *base) {
116
- struct backend_stats stats = {
117
- .runqueue_length = runqueue_len(&base->runqueue),
118
- .runqueue_max_length = runqueue_max_len(&base->runqueue),
119
- .op_count = base->op_count,
120
- .switch_count = base->switch_count,
121
- .poll_count = base->poll_count,
122
- .pending_ops = base->pending_count
123
- };
124
-
125
- base->op_count = 0;
126
- base->switch_count = 0;
127
- base->poll_count = 0;
128
- return stats;
129
- }
130
-
131
115
  #ifdef POLYPHONY_USE_PIDFD_OPEN
132
116
  #ifndef __NR_pidfd_open
133
117
  #define __NR_pidfd_open 434 /* System call # on most architectures */
@@ -312,6 +296,24 @@ inline void backend_run_idle_tasks(struct Backend_base *base) {
312
296
  rb_gc_disable();
313
297
  }
314
298
 
299
+ inline struct backend_stats backend_base_stats(struct Backend_base *base) {
300
+ struct backend_stats stats = {
301
+ .runqueue_size = runqueue_size(&base->runqueue),
302
+ .runqueue_length = runqueue_len(&base->runqueue),
303
+ .runqueue_max_length = runqueue_max_len(&base->runqueue),
304
+ .op_count = base->op_count,
305
+ .switch_count = base->switch_count,
306
+ .poll_count = base->poll_count,
307
+ .pending_ops = base->pending_count
308
+ };
309
+
310
+ base->op_count = 0;
311
+ base->switch_count = 0;
312
+ base->poll_count = 0;
313
+ return stats;
314
+ }
315
+
316
+ VALUE SYM_runqueue_size;
315
317
  VALUE SYM_runqueue_length;
316
318
  VALUE SYM_runqueue_max_length;
317
319
  VALUE SYM_op_count;
@@ -323,6 +325,7 @@ VALUE Backend_stats(VALUE self) {
323
325
  struct backend_stats backend_stats = backend_get_stats(self);
324
326
 
325
327
  VALUE stats = rb_hash_new();
328
+ rb_hash_aset(stats, SYM_runqueue_size, INT2NUM(backend_stats.runqueue_size));
326
329
  rb_hash_aset(stats, SYM_runqueue_length, INT2NUM(backend_stats.runqueue_length));
327
330
  rb_hash_aset(stats, SYM_runqueue_max_length, INT2NUM(backend_stats.runqueue_max_length));
328
331
  rb_hash_aset(stats, SYM_op_count, INT2NUM(backend_stats.op_count));
@@ -334,13 +337,15 @@ VALUE Backend_stats(VALUE self) {
334
337
  }
335
338
 
336
339
  void backend_setup_stats_symbols() {
337
- SYM_runqueue_length = ID2SYM(rb_intern("runqueue_length"));
340
+ SYM_runqueue_size = ID2SYM(rb_intern("runqueue_size"));
341
+ SYM_runqueue_length = ID2SYM(rb_intern("runqueue_length"));
338
342
  SYM_runqueue_max_length = ID2SYM(rb_intern("runqueue_max_length"));
339
- SYM_op_count = ID2SYM(rb_intern("op_count"));
340
- SYM_switch_count = ID2SYM(rb_intern("switch_count"));
341
- SYM_poll_count = ID2SYM(rb_intern("poll_count"));
342
- SYM_pending_ops = ID2SYM(rb_intern("pending_ops"));
343
+ SYM_op_count = ID2SYM(rb_intern("op_count"));
344
+ SYM_switch_count = ID2SYM(rb_intern("switch_count"));
345
+ SYM_poll_count = ID2SYM(rb_intern("poll_count"));
346
+ SYM_pending_ops = ID2SYM(rb_intern("pending_ops"));
343
347
 
348
+ rb_global_variable(&SYM_runqueue_size);
344
349
  rb_global_variable(&SYM_runqueue_length);
345
350
  rb_global_variable(&SYM_runqueue_max_length);
346
351
  rb_global_variable(&SYM_op_count);
@@ -6,6 +6,7 @@
6
6
  #include "runqueue.h"
7
7
 
8
8
  struct backend_stats {
9
+ unsigned int runqueue_size;
9
10
  unsigned int runqueue_length;
10
11
  unsigned int runqueue_max_length;
11
12
  unsigned int op_count;
@@ -44,6 +44,10 @@ inline void runqueue_clear(runqueue_t *runqueue) {
44
44
  runqueue_ring_buffer_clear(&runqueue->entries);
45
45
  }
46
46
 
47
+ inline long runqueue_size(runqueue_t *runqueue) {
48
+ return runqueue->entries.size;
49
+ }
50
+
47
51
  inline long runqueue_len(runqueue_t *runqueue) {
48
52
  return runqueue->entries.count;
49
53
  }
@@ -19,6 +19,7 @@ runqueue_entry runqueue_shift(runqueue_t *runqueue);
19
19
  void runqueue_delete(runqueue_t *runqueue, VALUE fiber);
20
20
  int runqueue_index_of(runqueue_t *runqueue, VALUE fiber);
21
21
  void runqueue_clear(runqueue_t *runqueue);
22
+ long runqueue_size(runqueue_t *runqueue);
22
23
  long runqueue_len(runqueue_t *runqueue);
23
24
  long runqueue_max_len(runqueue_t *runqueue);
24
25
  int runqueue_empty_p(runqueue_t *runqueue);
@@ -76,6 +76,10 @@ end
76
76
 
77
77
  # IO instance method patches
78
78
  class ::IO
79
+ def __polyphony_read_method__
80
+ :backend_read
81
+ end
82
+
79
83
  # def each(sep = $/, limit = nil, chomp: nil)
80
84
  # sep, limit = $/, sep if sep.is_a?(Integer)
81
85
  # end
@@ -108,7 +112,11 @@ class ::IO
108
112
  end
109
113
 
110
114
  alias_method :orig_read, :read
111
- def read(len = nil)
115
+ def read(len = nil, buf = nil, buf_pos = 0)
116
+ if buf
117
+ return Polyphony.backend_read(self, buf, len, true, buf_pos)
118
+ end
119
+
112
120
  @read_buffer ||= +''
113
121
  result = Polyphony.backend_read(self, @read_buffer, len, true, -1)
114
122
  return nil unless result
@@ -119,9 +127,9 @@ class ::IO
119
127
  end
120
128
 
121
129
  alias_method :orig_readpartial, :read
122
- def readpartial(len, str = +'', buffer_pos = 0)
130
+ def readpartial(len, str = +'', buffer_pos = 0, raise_on_eof = true)
123
131
  result = Polyphony.backend_read(self, str, len, false, buffer_pos)
124
- raise EOFError unless result
132
+ raise EOFError if !result && raise_on_eof
125
133
 
126
134
  result
127
135
  end
@@ -5,6 +5,10 @@ require_relative './socket'
5
5
 
6
6
  # OpenSSL socket helper methods (to make it compatible with Socket API) and overrides
7
7
  class ::OpenSSL::SSL::SSLSocket
8
+ def __polyphony_read_method__
9
+ :readpartial
10
+ end
11
+
8
12
  alias_method :orig_initialize, :initialize
9
13
  def initialize(socket, context = nil)
10
14
  socket = socket.respond_to?(:io) ? socket.io || socket : socket
@@ -64,7 +68,21 @@ class ::OpenSSL::SSL::SSLSocket
64
68
  # @sync = osync
65
69
  end
66
70
 
67
- def readpartial(maxlen, buf = +'', buffer_pos = 0)
71
+ alias_method :orig_read, :read
72
+ def read(maxlen = nil, buf = nil, buf_pos = 0)
73
+ return readpartial(maxlen, buf, buf_pos) if buf
74
+
75
+ buf = +''
76
+ return readpartial(maxlen, buf) if maxlen
77
+
78
+ while true
79
+ readpartial(4096, buf, -1)
80
+ end
81
+ rescue EOFError
82
+ buf
83
+ end
84
+
85
+ def readpartial(maxlen, buf = +'', buffer_pos = 0, raise_on_eof = true)
68
86
  if buffer_pos != 0
69
87
  if (result = sysread(maxlen, +''))
70
88
  if buffer_pos == -1
@@ -76,7 +94,9 @@ class ::OpenSSL::SSL::SSLSocket
76
94
  else
77
95
  result = sysread(maxlen, buf)
78
96
  end
79
- result || (raise EOFError)
97
+
98
+ raise EOFError if !result && raise_on_eof
99
+ result
80
100
  end
81
101
 
82
102
  def read_loop(maxlen = 8192)
@@ -5,6 +5,12 @@ require 'socket'
5
5
  require_relative './io'
6
6
  require_relative '../core/thread_pool'
7
7
 
8
+ class BasicSocket
9
+ def __polyphony_read_method__
10
+ :backend_recv
11
+ end
12
+ end
13
+
8
14
  # Socket overrides (eventually rewritten in C)
9
15
  class ::Socket
10
16
  def accept
@@ -22,6 +28,23 @@ class ::Socket
22
28
  Polyphony.backend_connect(self, addr.ip_address, addr.ip_port)
23
29
  end
24
30
 
31
+ alias_method :orig_read, :read
32
+ def read(maxlen = nil, buf = nil, buf_pos = 0)
33
+ return Polyphony.backend_recv(self, buf, maxlen, buf_pos) if buf
34
+ return Polyphony.backend_recv(self, buf || +'', maxlen, 0) if maxlen
35
+
36
+ buf = +''
37
+ len = buf.bytesize
38
+ while true
39
+ Polyphony.backend_recv(self, buf, maxlen || 4096, -1)
40
+ new_len = buf.bytesize
41
+ break if new_len == len
42
+
43
+ len = new_len
44
+ end
45
+ buf
46
+ end
47
+
25
48
  def recv(maxlen, flags = 0, outbuf = nil)
26
49
  Polyphony.backend_recv(self, outbuf || +'', maxlen, 0)
27
50
  end
@@ -60,8 +83,9 @@ class ::Socket
60
83
  # Polyphony.backend_send(self, mesg, 0)
61
84
  # end
62
85
 
63
- def readpartial(maxlen, str = +'', buffer_pos = 0)
64
- Polyphony.backend_recv(self, str, maxlen, buffer_pos)
86
+ def readpartial(maxlen, str = +'', buffer_pos = 0, raise_on_eof = true)
87
+ result = Polyphony.backend_recv(self, str, maxlen, buffer_pos)
88
+ raise EOFError if !result && raise_on_eof
65
89
  end
66
90
 
67
91
  ZERO_LINGER = [0, 0].pack('ii').freeze
@@ -140,6 +164,23 @@ class ::TCPSocket
140
164
  setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_REUSEPORT, 1)
141
165
  end
142
166
 
167
+ alias_method :orig_read, :read
168
+ def read(maxlen = nil, buf = nil, buf_pos = 0)
169
+ return Polyphony.backend_recv(self, buf, maxlen, buf_pos) if buf
170
+ return Polyphony.backend_recv(self, buf || +'', maxlen, 0) if maxlen
171
+
172
+ buf = +''
173
+ len = buf.bytesize
174
+ while true
175
+ Polyphony.backend_recv(self, buf, maxlen || 4096, -1)
176
+ new_len = buf.bytesize
177
+ break if new_len == len
178
+
179
+ len = new_len
180
+ end
181
+ buf
182
+ end
183
+
143
184
  def recv(maxlen, flags = 0, outbuf = nil)
144
185
  Polyphony.backend_recv(self, outbuf || +'', maxlen, 0)
145
186
  end
@@ -165,11 +206,10 @@ class ::TCPSocket
165
206
  # Polyphony.backend_send(self, mesg, 0)
166
207
  # end
167
208
 
168
- def readpartial(maxlen, str = +'', buffer_pos = 0)
209
+ def readpartial(maxlen, str = +'', buffer_pos = 0, raise_on_eof)
169
210
  result = Polyphony.backend_recv(self, str, maxlen, buffer_pos)
170
- raise EOFError unless result
171
-
172
- str
211
+ raise EOFError if !result && raise_on_eof
212
+ result
173
213
  end
174
214
 
175
215
  def read_nonblock(len, str = nil, exception: true)
@@ -217,6 +257,23 @@ class ::UNIXServer
217
257
  end
218
258
 
219
259
  class ::UNIXSocket
260
+ alias_method :orig_read, :read
261
+ def read(maxlen = nil, buf = nil, buf_pos = 0)
262
+ return Polyphony.backend_recv(self, buf, maxlen, buf_pos) if buf
263
+ return Polyphony.backend_recv(self, buf || +'', maxlen, 0) if maxlen
264
+
265
+ buf = +''
266
+ len = buf.bytesize
267
+ while true
268
+ Polyphony.backend_recv(self, buf, maxlen || 4096, -1)
269
+ new_len = buf.bytesize
270
+ break if new_len == len
271
+
272
+ len = new_len
273
+ end
274
+ buf
275
+ end
276
+
220
277
  def recv(maxlen, flags = 0, outbuf = nil)
221
278
  Polyphony.backend_recv(self, outbuf || +'', maxlen, 0)
222
279
  end
@@ -242,11 +299,10 @@ class ::UNIXSocket
242
299
  Polyphony.backend_send(self, mesg, 0)
243
300
  end
244
301
 
245
- def readpartial(maxlen, str = +'', buffer_pos = 0)
302
+ def readpartial(maxlen, str = +'', buffer_pos = 0, raise_on_eof)
246
303
  result = Polyphony.backend_recv(self, str, maxlen, buffer_pos)
247
- raise EOFError unless result
248
-
249
- str
304
+ raise EOFError if !result && raise_on_eof
305
+ result
250
306
  end
251
307
 
252
308
  def read_nonblock(len, str = nil, exception: true)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Polyphony
4
- VERSION = '0.61'
4
+ VERSION = '0.65'
5
5
  end
data/test/test_backend.rb CHANGED
@@ -98,6 +98,32 @@ class BackendTest < MiniTest::Test
98
98
  assert_equal return_value, buf
99
99
  end
100
100
 
101
+ def test_read_concat_big
102
+ i, o = IO.pipe
103
+
104
+ body = " " * 4000
105
+
106
+ data = "post /?q=time&blah=blah HTTP/1\r\nHost: dev.realiteq.net\r\n\r\n" +
107
+ "get /?q=time HTTP/1.1\r\nContent-Length: #{body.bytesize}\r\n\r\n#{body}" +
108
+ "get /?q=time HTTP/1.1\r\nCookie: foo\r\nCookie: bar\r\n\r\n"
109
+
110
+ o << data
111
+ o.close
112
+
113
+ buf = +''
114
+
115
+ @backend.read(i, buf, 4096, false, -1)
116
+ assert_equal 4096, buf.bytesize
117
+
118
+ @backend.read(i, buf, 1, false, -1)
119
+ assert_equal 4097, buf.bytesize
120
+
121
+ @backend.read(i, buf, 4096, false, -1)
122
+
123
+ assert_equal data.bytesize, buf.bytesize
124
+ assert_equal data, buf
125
+ end
126
+
101
127
  def test_waitpid
102
128
  pid = fork do
103
129
  @backend.post_fork
data/test/test_io.rb CHANGED
@@ -73,6 +73,26 @@ class IOTest < MiniTest::Test
73
73
  assert_equal [:wait_readable, 'foo'], results
74
74
  end
75
75
 
76
+ def test_read
77
+ i, o = IO.pipe
78
+
79
+ o << 'hi'
80
+ assert_equal 'hi', i.read(2)
81
+
82
+ o << 'foobarbaz'
83
+ assert_equal 'foo', i.read(3)
84
+ assert_equal 'bar', i.read(3)
85
+
86
+ buf = +'abc'
87
+ assert_equal 'baz', i.read(3, buf)
88
+ assert_equal 'baz', buf
89
+
90
+ buf = +'def'
91
+ o << 'foobar'
92
+ assert_equal 'deffoobar', i.read(6, buf, -1)
93
+ assert_equal 'deffoobar', buf
94
+ end
95
+
76
96
  def test_readpartial
77
97
  i, o = IO.pipe
78
98
 
data/test/test_socket.rb CHANGED
@@ -12,7 +12,6 @@ class SocketTest < MiniTest::Test
12
12
  def test_tcp
13
13
  port = rand(1234..5678)
14
14
  server = TCPServer.new('127.0.0.1', port)
15
-
16
15
  server_fiber = spin do
17
16
  while (socket = server.accept)
18
17
  spin do
@@ -34,6 +33,45 @@ class SocketTest < MiniTest::Test
34
33
  server&.close
35
34
  end
36
35
 
36
+ def test_read
37
+ port = rand(1234..5678)
38
+ server = TCPServer.new('127.0.0.1', port)
39
+ server_fiber = spin do
40
+ while (socket = server.accept)
41
+ spin do
42
+ while (data = socket.read(8192))
43
+ socket << data
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ snooze
50
+ client = TCPSocket.new('127.0.0.1', port)
51
+
52
+ client << 'hi'
53
+ assert_equal 'hi', client.read(2)
54
+
55
+ client << 'foobarbaz'
56
+ assert_equal 'foo', client.read(3)
57
+ assert_equal 'bar', client.read(3)
58
+
59
+ buf = +'abc'
60
+ assert_equal 'baz', client.read(3, buf)
61
+ assert_equal 'baz', buf
62
+
63
+ buf = +'def'
64
+ client << 'foobar'
65
+ assert_equal 'deffoobar', client.read(6, buf, -1)
66
+ assert_equal 'deffoobar', buf
67
+
68
+ client.close
69
+ ensure
70
+ server_fiber&.stop
71
+ server_fiber&.await
72
+ server&.close
73
+ end
74
+
37
75
  # sending multiple strings at once
38
76
  def test_sendv
39
77
  port = rand(1234..5678)
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.61'
4
+ version: '0.65'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-07-20 00:00:00.000000000 Z
11
+ date: 2021-07-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler