polyphony 0.61 → 0.65

Sign up to get free protection for your applications and to get access to all the features.
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