io_splice 4.1.1 → 4.2.0

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