io_splice 4.1.1 → 4.2.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.
data/GIT-VERSION-GEN CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/bin/sh
2
2
 
3
3
  GVF=GIT-VERSION-FILE
4
- DEF_VER=v4.1.1.GIT
4
+ DEF_VER=v4.2.0
5
5
 
6
6
  LF='
7
7
  '
data/README CHANGED
@@ -89,11 +89,11 @@ don't email the git mailing list or maintainer with io_splice patches.
89
89
  == Contact
90
90
 
91
91
  All feedback (bug reports, user/development discussion, patches, pull
92
- requests) go to the mailing list: mailto:ruby.io.splice@librelist.com
92
+ requests) go to the mailing list: mailto:ruby.io.splice@librelist.org
93
93
 
94
94
  == Mailing List Archives
95
95
 
96
- In addition to the rsync-able archives provided by http://librelist.com/, we
96
+ In addition to the rsync-able archives provided by http://librelist.org/, we
97
97
  are also mirrored to
98
98
  {Gmane}[http://gmane.org/info.php?group=gmane.comp.lang.ruby.io-splice.general]
99
99
  and maintain our own mbox mirrors downloadable via HTTP.
@@ -10,11 +10,14 @@
10
10
  #include <sys/uio.h>
11
11
  #include <limits.h>
12
12
  #include <alloca.h>
13
- #include <sys/utsname.h>
13
+ #include <unistd.h>
14
14
 
15
15
  static VALUE sym_EAGAIN;
16
16
  #define WAITALL 0x4000000
17
17
 
18
+ /* taken from haproxy */
19
+ #define MAX_AT_ONCE (1 << 30)
20
+
18
21
  #ifndef F_LINUX_SPECIFIC_BASE
19
22
  # define F_LINUX_SPECIFIC_BASE 1024
20
23
  #endif
@@ -130,6 +133,9 @@ static VALUE nogvl_splice(void *ptr)
130
133
  {
131
134
  struct splice_args *a = ptr;
132
135
 
136
+ if (a->len > MAX_AT_ONCE)
137
+ a->len = MAX_AT_ONCE;
138
+
133
139
  return (VALUE)splice(a->fd_in, a->off_in, a->fd_out, a->off_out,
134
140
  a->len, a->flags);
135
141
  }
@@ -276,6 +282,9 @@ static VALUE nogvl_tee(void *ptr)
276
282
  {
277
283
  struct tee_args *a = ptr;
278
284
 
285
+ if (a->len > MAX_AT_ONCE)
286
+ a->len = MAX_AT_ONCE;
287
+
279
288
  return (VALUE)tee(a->fd_in, a->fd_out, a->len, a->flags);
280
289
  }
281
290
 
@@ -468,7 +477,7 @@ static void advance_vmsplice_args(struct vmsplice_args *a, long n)
468
477
  * This may allow the kernel to avoid data copies in some cases.
469
478
  * but is (probably) of limited usefulness in Ruby. If you have
470
479
  * use cases or ideas for making this more useful for Ruby users,
471
- * please tell us at ruby.io.splice@librelist.com!
480
+ * please tell us at ruby.io.splice@librelist.org!
472
481
  *
473
482
  * Also consider the "sendfile" RubyGem or IO.copy_stream in Ruby 1.9
474
483
  * if you want to do zero-copy file transfers to pipes or sockets. As
@@ -483,19 +492,19 @@ static VALUE my_vmsplice(int argc, VALUE * argv, VALUE self)
483
492
  ssize_t rv = 0;
484
493
  ssize_t left;
485
494
  struct vmsplice_args a;
495
+ struct iovec iov;
496
+ ssize_t n;
497
+
486
498
  VALUE io, data, flags;
487
499
 
488
500
  rb_scan_args(argc, argv, "21", &io, &data, &flags);
489
501
 
490
502
  switch (TYPE(data)) {
491
- case T_STRING: {
492
- struct iovec iov;
493
-
503
+ case T_STRING:
494
504
  iov.iov_base = RSTRING_PTR(data);
495
505
  iov.iov_len = (size_t)(left = (ssize_t)RSTRING_LEN(data));
496
506
  a.iov = &iov;
497
507
  a.nr_segs = 1;
498
- }
499
508
  break;
500
509
  case T_ARRAY:
501
510
  ARY2IOVEC(a.iov, a.nr_segs, left, data);
@@ -505,21 +514,19 @@ static VALUE my_vmsplice(int argc, VALUE * argv, VALUE self)
505
514
  "(expected a String or Array of strings)",
506
515
  rb_obj_classname(data));
507
516
  }
508
- a.fd = my_fileno(io);
517
+
509
518
  a.flags = NIL_P(flags) ? 0 : NUM2UINT(flags);
510
519
 
511
520
  for (;;) {
512
- ssize_t n = (ssize_t)io_run(nogvl_vmsplice, &a);
521
+ a.fd = check_fileno(io);
522
+ n = (ssize_t)io_run(nogvl_vmsplice, &a);
513
523
 
514
524
  if (n == -1) {
515
525
  if (errno == EAGAIN) {
516
- if (a.flags & SPLICE_F_NONBLOCK) {
526
+ if (a.flags & SPLICE_F_NONBLOCK)
517
527
  rb_sys_fail("vmsplice");
518
- } else {
519
- a.fd = check_fileno(io);
520
- if (rb_io_wait_writable(a.fd))
521
- continue;
522
- }
528
+ if (rb_io_wait_writable(check_fileno(io)))
529
+ continue;
523
530
  /* fall through on error */
524
531
  }
525
532
  /*
@@ -529,10 +536,8 @@ static VALUE my_vmsplice(int argc, VALUE * argv, VALUE self)
529
536
  */
530
537
  if (rv > 0)
531
538
  break;
532
- if (errno == EINTR) {
533
- a.fd = check_fileno(io);
539
+ if (errno == EINTR)
534
540
  continue;
535
- }
536
541
  rb_sys_fail("vmsplice");
537
542
  }
538
543
 
@@ -612,10 +617,28 @@ static VALUE set_pipe_size(VALUE self, VALUE size)
612
617
  return size;
613
618
  }
614
619
 
620
+ static int can_mod_pipe_size(void)
621
+ {
622
+ int fds[2];
623
+ int rc = pipe(fds);
624
+
625
+ if (rc == 0) {
626
+ rc = fcntl(fds[0], F_GETPIPE_SZ);
627
+ rc = rc < 0 ? 0 : 1;
628
+
629
+ (void)close(fds[0]);
630
+ (void)close(fds[1]);
631
+ } else {
632
+ /* weird error, but don't raise during init */
633
+ rc = 0;
634
+ }
635
+ errno = 0;
636
+ return rc;
637
+ }
638
+
615
639
  void Init_io_splice_ext(void)
616
640
  {
617
641
  VALUE mSplice = rb_define_module_under(rb_cIO, "Splice");
618
- struct utsname utsname;
619
642
 
620
643
  rb_define_singleton_method(rb_cIO, "splice", my_splice, -1);
621
644
  rb_define_singleton_method(rb_cIO, "trysplice", trysplice, -1);
@@ -682,11 +705,14 @@ void Init_io_splice_ext(void)
682
705
  */
683
706
  rb_define_const(mSplice, "PIPE_BUF", UINT2NUM(PIPE_BUF));
684
707
 
685
- if (uname(&utsname) == -1)
686
- rb_sys_fail("uname");
708
+ /*
709
+ * The maximum size we're allowed to splice at once. Larger
710
+ * sizes will be broken up and retried if the WAITALL flag or
711
+ * IO::Splice.copy_stream is used.
712
+ */
713
+ rb_define_const(mSplice, "MAX_AT_ONCE", SIZET2NUM(MAX_AT_ONCE));
687
714
 
688
- /* includes 2.6.35-rc[1-6] */
689
- if (strcmp(utsname.release, "2.6.35") >= 0) {
715
+ if (can_mod_pipe_size()) {
690
716
  rb_define_method(rb_cIO, "pipe_size", pipe_size, 0);
691
717
  rb_define_method(rb_cIO, "pipe_size=", set_pipe_size, 1);
692
718
 
data/io_splice.gemspec CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |s|
11
11
  s.authors = ["Ruby io_splice hackers"]
12
12
  s.date = Time.now.utc.strftime('%Y-%m-%d')
13
13
  s.description = readme_description
14
- s.email = %q{ruby.io.splice@librelist.com}
14
+ s.email = %q{ruby.io.splice@librelist.org}
15
15
  s.extensions = %w(ext/io_splice/extconf.rb)
16
16
  s.extra_rdoc_files = extra_rdoc_files(manifest)
17
17
  s.files = manifest
data/lib/io/splice.rb CHANGED
@@ -47,26 +47,24 @@ module IO::Splice
47
47
  src, dst = src.to_io, dst.to_io
48
48
 
49
49
  if src.stat.pipe? || dst.stat.pipe?
50
- if len
51
- len -= full(src, dst, len, src_offset) until len == 0
52
- else
53
- rv = 0
54
- while n = partial(src, dst, PIPE_CAPA, src_offset)
55
- rv += n
56
- src_offset += n if src_offset
57
- end
50
+ return full(src, dst, len, src_offset) if len
51
+ rv = 0
52
+ while n = partial(src, dst, MAX_AT_ONCE, src_offset)
53
+ rv += n
54
+ src_offset += n if src_offset
58
55
  end
59
56
  else
60
57
  r, w = tmp = IO.pipe
61
58
  close.concat(tmp)
59
+ rv = 0
62
60
  if len
63
61
  while len != 0 && n = partial(src, w, len, src_offset)
64
62
  src_offset += n if src_offset
63
+ rv += n
65
64
  len -= full(r, dst, n, nil)
66
65
  end
67
66
  else
68
- rv = 0
69
- while n = partial(src, w, PIPE_CAPA, src_offset)
67
+ while n = partial(src, w, MAX_AT_ONCE, src_offset)
70
68
  src_offset += n if src_offset
71
69
  rv += full(r, dst, n, nil)
72
70
  end
@@ -46,4 +46,21 @@ class TestTCPCopyStream < Test::Unit::TestCase
46
46
  bytes = IO::Splice.copy_stream(@accept, "/dev/null", expect)
47
47
  assert_equal expect, bytes
48
48
  end
49
+
50
+ def test_mega_splice
51
+ nr = 2000
52
+ buf = '0123456789abcdef' * 1024
53
+ expect = buf.size * nr
54
+ thr = Thread.new do
55
+ nr.times { @client.write(buf) }
56
+ @client.close
57
+ end
58
+ size_t_max = if (1 << 30).kind_of?(Bignum)
59
+ 0xffffffff
60
+ else
61
+ 0xffffffffffffffff
62
+ end
63
+ bytes = IO::Splice.copy_stream(@accept, "/dev/null", size_t_max)
64
+ assert_equal expect, bytes
65
+ end
49
66
  end
metadata CHANGED
@@ -1,63 +1,75 @@
1
- --- !ruby/object:Gem::Specification
2
- name: io_splice
3
- version: !ruby/object:Gem::Version
4
- hash: 57
1
+ --- !ruby/object:Gem::Specification
2
+ name: !binary |-
3
+ aW9fc3BsaWNl
4
+ version: !ruby/object:Gem::Version
5
+ version: 4.2.0
5
6
  prerelease:
6
- segments:
7
- - 4
8
- - 1
9
- - 1
10
- version: 4.1.1
11
7
  platform: ruby
12
- authors:
13
- - Ruby io_splice hackers
8
+ authors:
9
+ - !binary |-
10
+ UnVieSBpb19zcGxpY2UgaGFja2Vycw==
14
11
  autorequire:
15
12
  bindir: bin
16
13
  cert_chain: []
17
-
18
- date: 2011-05-18 00:00:00 Z
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
21
- name: wrongdoc
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
14
+ date: 2013-01-19 00:00:00.000000000 Z
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: !binary |-
18
+ d3Jvbmdkb2M=
19
+ requirement: !ruby/object:Gem::Requirement
24
20
  none: false
25
- requirements:
26
- - - ~>
27
- - !ruby/object:Gem::Version
28
- hash: 5
29
- segments:
30
- - 1
31
- - 5
32
- version: "1.5"
21
+ requirements:
22
+ - - !binary |-
23
+ fj4=
24
+ - !ruby/object:Gem::Version
25
+ version: !binary |-
26
+ MS41
33
27
  type: :development
34
- version_requirements: *id001
35
- - !ruby/object:Gem::Dependency
36
- name: rack
37
28
  prerelease: false
38
- requirement: &id002 !ruby/object:Gem::Requirement
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - !binary |-
33
+ fj4=
34
+ - !ruby/object:Gem::Version
35
+ version: !binary |-
36
+ MS41
37
+ - !ruby/object:Gem::Dependency
38
+ name: !binary |-
39
+ cmFjaw==
40
+ requirement: !ruby/object:Gem::Requirement
39
41
  none: false
40
- requirements:
41
- - - ~>
42
- - !ruby/object:Gem::Version
43
- hash: 11
44
- segments:
45
- - 1
46
- - 2
47
- version: "1.2"
42
+ requirements:
43
+ - - !binary |-
44
+ fj4=
45
+ - !ruby/object:Gem::Version
46
+ version: !binary |-
47
+ MS4y
48
48
  type: :development
49
- version_requirements: *id002
50
- description: |-
51
- The splice family of Linux system calls can transfer data between file
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - !binary |-
54
+ fj4=
55
+ - !ruby/object:Gem::Version
56
+ version: !binary |-
57
+ MS4y
58
+ description: ! 'The splice family of Linux system calls can transfer data between
59
+ file
60
+
52
61
  descriptors without the need to copy data into userspace. Instead of a
62
+
53
63
  userspace buffer, they rely on an ordinary Unix pipe as a kernel-level
54
- buffer.
55
- email: ruby.io.splice@librelist.com
56
- executables: []
57
64
 
58
- extensions:
59
- - ext/io_splice/extconf.rb
60
- extra_rdoc_files:
65
+ buffer.'
66
+ email: !binary |-
67
+ cnVieS5pby5zcGxpY2VAbGlicmVsaXN0Lm9yZw==
68
+ executables: []
69
+ extensions:
70
+ - !binary |-
71
+ ZXh0L2lvX3NwbGljZS9leHRjb25mLnJi
72
+ extra_rdoc_files:
61
73
  - README
62
74
  - LICENSE
63
75
  - NEWS
@@ -66,7 +78,7 @@ extra_rdoc_files:
66
78
  - lib/io/splice/mri_18.rb
67
79
  - ext/io_splice/io_splice_ext.c
68
80
  - LATEST
69
- files:
81
+ files:
70
82
  - .document
71
83
  - .gitignore
72
84
  - .manifest
@@ -99,44 +111,43 @@ files:
99
111
  - test/test_tcp_splice.rb
100
112
  homepage: http://bogomips.org/ruby_io_splice/
101
113
  licenses: []
102
-
103
114
  post_install_message:
104
- rdoc_options:
115
+ rdoc_options:
105
116
  - -t
106
117
  - io_splice - zero-copy pipe I/O for Linux and Ruby
107
118
  - -W
108
119
  - http://bogomips.org/ruby_io_splice.git/tree/%s
109
- require_paths:
120
+ require_paths:
110
121
  - lib
111
- required_ruby_version: !ruby/object:Gem::Requirement
122
+ required_ruby_version: !ruby/object:Gem::Requirement
112
123
  none: false
113
- requirements:
114
- - - ">="
115
- - !ruby/object:Gem::Version
116
- hash: 3
117
- segments:
118
- - 0
119
- version: "0"
120
- required_rubygems_version: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - ! '>='
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ required_rubygems_version: !ruby/object:Gem::Requirement
121
129
  none: false
122
- requirements:
123
- - - ">="
124
- - !ruby/object:Gem::Version
125
- hash: 3
126
- segments:
127
- - 0
128
- version: "0"
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
129
134
  requirements: []
130
-
131
- rubyforge_project: qrp
132
- rubygems_version: 1.8.2
135
+ rubyforge_project: !binary |-
136
+ cXJw
137
+ rubygems_version: 1.8.23
133
138
  signing_key:
134
139
  specification_version: 3
135
140
  summary: zero-copy pipe I/O for Linux and Ruby
136
- test_files:
137
- - test/test_rack_file_compat.rb
138
- - test/test_io_splice_in_full.rb
139
- - test/test_tcp_splice.rb
140
- - test/test_io_splice.rb
141
- - test/test_copy_stream.rb
142
- - test/test_io_splice_eintr.rb
141
+ test_files:
142
+ - !binary |-
143
+ dGVzdC90ZXN0X3JhY2tfZmlsZV9jb21wYXQucmI=
144
+ - !binary |-
145
+ dGVzdC90ZXN0X2lvX3NwbGljZV9pbl9mdWxsLnJi
146
+ - !binary |-
147
+ dGVzdC90ZXN0X3RjcF9zcGxpY2UucmI=
148
+ - !binary |-
149
+ dGVzdC90ZXN0X2lvX3NwbGljZS5yYg==
150
+ - !binary |-
151
+ dGVzdC90ZXN0X2NvcHlfc3RyZWFtLnJi
152
+ - !binary |-
153
+ dGVzdC90ZXN0X2lvX3NwbGljZV9laW50ci5yYg==