mogilefs-client 2.0.0 → 2.0.1

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/.gitignore CHANGED
@@ -1,2 +1,4 @@
1
1
  /pkg
2
2
  /doc
3
+ /.config
4
+ /InstalledFiles
data/History.txt CHANGED
@@ -1,3 +1,9 @@
1
+ = 2.0.1
2
+ * verify_uris method made more robust
3
+ * preliminary Ruby 1.9 compatibility, tests still need some work
4
+ * allow store_content to be used with a streamable object of known length
5
+ * add setup.rb for non-RubyGems users
6
+
1
7
  = 2.0.0
2
8
 
3
9
  * use a set of standard exceptions based on MogileFS::Error,
data/README.txt CHANGED
@@ -60,7 +60,7 @@ Then install the gem:
60
60
 
61
61
  # Store the contents of 'image.jpeg' into the key 'my_image' with a class of
62
62
  # 'image' using an open IO.
63
- File.open 'image.jpeg' do |fp|
63
+ File.open 'image.jpeg', 'rb' do |fp|
64
64
  mg.store_file 'my_image', 'image', fp
65
65
  end
66
66
 
data/bin/mog CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'mogilefs'
3
3
  require 'optparse'
4
+ [ STDIN, STDOUT, STDERR].each { |io| io.binmode }
4
5
 
5
6
  trap('INT') { exit 130 }
6
7
  trap('PIPE') { exit 0 }
data/lib/mogilefs.rb CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  module MogileFS
8
8
 
9
- VERSION = '2.0.0'.freeze
9
+ VERSION = '2.0.1'.freeze
10
10
 
11
11
  ##
12
12
  # Raised when a socket remains unreadable for too long.
@@ -274,9 +274,14 @@ class MogileFS::Backend
274
274
 
275
275
  ##
276
276
  # Escapes naughty URL characters.
277
-
278
- def url_escape(str)
279
- str.gsub(/([^\w\,\-.\/\\\: ])/) { "%%%02x" % $1[0] }.tr(' ', '+')
277
+ if ''.respond_to?(:ord) # Ruby 1.9
278
+ def url_escape(str)
279
+ str.gsub(/([^\w\,\-.\/\\\: ])/) { "%%%02x" % $1.ord }.tr(' ', '+')
280
+ end
281
+ else # Ruby 1.8
282
+ def url_escape(str)
283
+ str.gsub(/([^\w\,\-.\/\\\: ])/) { "%%%02x" % $1[0] }.tr(' ', '+')
284
+ end
280
285
  end
281
286
 
282
287
  ##
@@ -44,12 +44,15 @@ class MogileFS::HTTPFile < StringIO
44
44
 
45
45
  attr_accessor :big_io
46
46
 
47
+ attr_accessor :streaming_io
48
+
47
49
  ##
48
50
  # Works like File.open. Use MogileFS::MogileFS#new_file instead of this
49
51
  # method.
50
52
 
51
53
  def self.open(*args)
52
54
  fp = new(*args)
55
+ fp.set_encoding(Encoding::BINARY) if fp.respond_to?(:set_encoding)
53
56
 
54
57
  return fp unless block_given?
55
58
 
@@ -72,6 +75,7 @@ class MogileFS::HTTPFile < StringIO
72
75
  @klass = klass
73
76
  @key = key
74
77
  @big_io = nil
78
+ @streaming_io = nil
75
79
 
76
80
  @dests = dests
77
81
  @tried = {}
@@ -87,9 +91,16 @@ class MogileFS::HTTPFile < StringIO
87
91
  sock = Socket.mogilefs_new(uri.host, uri.port)
88
92
  sock.mogilefs_tcp_cork = true
89
93
 
90
- if @big_io
94
+ if @streaming_io
95
+ file_size = @streaming_io.length
96
+ syswrite_full(sock, "PUT #{uri.request_uri} HTTP/1.0\r\n" \
97
+ "Content-Length: #{file_size}\r\n\r\n")
98
+ @streaming_io.call(Proc.new do |data_to_write|
99
+ syswrite_full(sock, data_to_write)
100
+ end)
101
+ elsif @big_io
91
102
  # Don't try to run out of memory
92
- File.open(@big_io) do |fp|
103
+ File.open(@big_io, "rb") do |fp|
93
104
  file_size = fp.stat.size
94
105
  fp.sync = true
95
106
  syswrite_full(sock, "PUT #{uri.request_uri} HTTP/1.0\r\n" \
@@ -148,7 +148,7 @@ class MogileFS::MogileFS < MogileFS::Client
148
148
  mfp.big_io = file
149
149
  return
150
150
  else
151
- return File.open(file) { |fp| sysrwloop(fp, mfp) }
151
+ return File.open(file, "rb") { |fp| sysrwloop(fp, mfp) }
152
152
  end
153
153
  end
154
154
  end
@@ -161,7 +161,11 @@ class MogileFS::MogileFS < MogileFS::Client
161
161
  raise MogileFS::ReadOnlyError if readonly?
162
162
 
163
163
  new_file key, klass do |mfp|
164
- mfp << content
164
+ if content.is_a?(MogileFS::Util::StoreContent)
165
+ mfp.streaming_io = content
166
+ else
167
+ mfp << content
168
+ end
165
169
  end
166
170
 
167
171
  content.length
@@ -7,8 +7,6 @@ module MogileFS::Network
7
7
  # with the expected HTTP code within the timeout period (in seconds).
8
8
  def verify_uris(uris = [], expect = '200', timeout = 2.00)
9
9
  uri_socks = {}
10
- ok_uris = []
11
- sockets = []
12
10
 
13
11
  # first, we asynchronously connect to all of them
14
12
  uris.each do |uri|
@@ -18,47 +16,89 @@ module MogileFS::Network
18
16
 
19
17
  # wait for at least one of them to finish connecting and send
20
18
  # HTTP requests to the connected ones
21
- begin
22
- t0 = Time.now
23
- r = IO.select(nil, uri_socks.keys, nil, timeout > 0 ? timeout : 0)
24
- timeout -= (Time.now - t0)
25
- break unless r && r[1]
26
- r[1].each do |sock|
27
- begin
28
- # we don't about short/interrupted writes here, if the following
29
- # request fails or blocks then the server is flat-out hopeless
30
- sock.syswrite "HEAD #{uri_socks[sock].request_uri} HTTP/1.0\r\n\r\n"
31
- sockets << sock
32
- rescue
33
- sock.close rescue nil
34
- end
35
- end
36
- end until sockets[0] || timeout < 0
19
+ sockets, timeout = get_writable_set(uri_socks, timeout)
37
20
 
38
21
  # Await a response from the sockets we had written to, we only need one
39
22
  # valid response, but we'll take more if they return simultaneously
40
- if sockets[0]
23
+ sockets[0] ? get_readable_uris(sockets, uri_socks, expect, timeout) : []
24
+
25
+ ensure
26
+ uri_socks.keys.each { |sock| sock.close rescue nil }
27
+ end
28
+
29
+ private
30
+ include MogileFS::Util
31
+
32
+ # returns an array of writeable Sockets and leftover from timeout
33
+ def get_writable_set(uri_socks, timeout)
34
+ sockets = []
41
35
  begin
42
36
  t0 = Time.now
43
- r = IO.select(sockets, nil, nil, timeout > 0 ? timeout : 0)
37
+ r = begin
38
+ IO.select(nil, uri_socks.keys, nil, timeout > 0 ? timeout : 0)
39
+ rescue
40
+ # get rid of bad descriptors
41
+ uri_socks.delete_if do |sock, uri|
42
+ begin
43
+ sock.recv_nonblock(1)
44
+ false # should never get here for HTTP, really...
45
+ rescue Errno::EAGAIN, Errno::EINTR
46
+ false
47
+ rescue
48
+ sock.close rescue nil
49
+ true
50
+ end
51
+ end
52
+ timeout -= (Time.now - t0)
53
+ retry if timeout >= 0
54
+ end
55
+
56
+ break unless r && r[1]
57
+
58
+ r[1].each do |sock|
59
+ begin
60
+ # we don't about short/interrupted writes here, if the following
61
+ # request fails or blocks then the server is flat-out hopeless
62
+ sock.syswrite "HEAD #{uri_socks[sock].request_uri} HTTP/1.0\r\n\r\n"
63
+ sockets << sock
64
+ rescue
65
+ sock.close rescue nil
66
+ end
67
+ end
68
+
44
69
  timeout -= (Time.now - t0)
45
- break unless r && r[0]
46
- r[0].each do |sock|
47
- buf = sock.recv_nonblock(128, Socket::MSG_PEEK) rescue next
70
+ end until (sockets[0] || timeout < 0)
71
+
72
+ [ sockets, timeout ]
73
+ end
74
+
75
+ # returns an array of URIs from uri_socks that are good
76
+ def get_readable_uris(sockets, uri_socks, expect, timeout)
77
+ ok_uris = []
78
+
79
+ begin
80
+ t0 = Time.now
81
+ r = IO.select(sockets, nil, nil, timeout > 0 ? timeout : 0) rescue nil
82
+
83
+ (r && r[0] ? r[0] : sockets).each do |sock|
84
+ buf = begin
85
+ sock.recv_nonblock(128, Socket::MSG_PEEK)
86
+ rescue Errno::EAGAIN, Errno::EINTR
87
+ next
88
+ rescue
89
+ sockets.delete(sock) # socket went bad
90
+ next
91
+ end
92
+
48
93
  if buf && /\AHTTP\/[\d\.]+ #{expect} / =~ buf
49
94
  ok_uris << uri_socks.delete(sock)
50
95
  sock.close rescue nil
51
96
  end
52
97
  end
53
- end
54
- end until ok_uris[0] || timeout < 0
55
-
56
- ok_uris
57
- ensure
58
- uri_socks.keys.each { |sock| sock.close rescue nil }
59
- end
98
+ timeout -= (Time.now - t0)
99
+ end until ok_uris[0] || timeout < 0
60
100
 
61
- private
62
- include MogileFS::Util
101
+ ok_uris
102
+ end
63
103
 
64
104
  end # module MogileFS::Network
data/lib/mogilefs/pool.rb CHANGED
@@ -31,8 +31,10 @@ class MogileFS::Pool
31
31
  def use
32
32
  object = get
33
33
  yield object
34
+ nil
34
35
  ensure
35
36
  put object
37
+ nil
36
38
  end
37
39
 
38
40
  def purge
data/lib/mogilefs/util.rb CHANGED
@@ -67,6 +67,16 @@ module MogileFS::Util
67
67
  # should never get here
68
68
  end
69
69
 
70
+ class StoreContent < Proc
71
+ def initialize(total_size, &writer_proc)
72
+ @total_size = total_size
73
+ super(&writer_proc)
74
+ end
75
+ def length
76
+ @total_size
77
+ end
78
+ end
79
+
70
80
  end
71
81
 
72
82
  require 'timeout'
data/test/setup.rb CHANGED
@@ -1,10 +1,12 @@
1
1
  STDIN.sync = STDOUT.sync = STDERR.sync = true
2
2
  require 'test/unit'
3
-
3
+ require 'tempfile'
4
4
  require 'fileutils'
5
5
  require 'tmpdir'
6
6
  require 'stringio'
7
7
 
8
+ trap('CHLD') { Process.waitpid(-1, Process::WNOHANG) rescue nil }
9
+
8
10
  $TESTING = true
9
11
 
10
12
  require 'mogilefs'
@@ -52,37 +54,41 @@ end
52
54
 
53
55
  require 'socket'
54
56
  class TempServer
55
- attr_reader :port
57
+ attr_reader :port, :pid
56
58
 
57
59
  def self.destroy_all!
58
60
  ObjectSpace.each_object(TempServer) { |t| t.destroy! }
59
61
  end
60
62
 
61
- def initialize(server_proc)
62
- @thr = @port = @sock = nil
63
+ at_exit { TempServer.destroy_all! }
64
+
65
+ def initialize(server_proc, port = nil)
66
+ @pid = @sock = nil
67
+ @port = port
63
68
  retries = 0
64
69
  begin
65
- @port = 1024 + rand(32768 - 1024)
70
+ @port ||= 1024 + rand(32768 - 1024)
66
71
  @sock = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
67
- @sock.bind(Socket.pack_sockaddr_in(@port, '127.0.0.1'))
72
+ @sock.bind(Socket.pack_sockaddr_in(@port.to_i, '127.0.0.1'))
68
73
  @sock.listen(5)
69
74
  rescue Errno::EADDRINUSE, Errno::EACCES
70
75
  @sock.close rescue nil
71
76
  retry if (retries += 1) < 10
72
77
  end
73
- @thr = Thread.new(@sock, @port) { |s,p| server_proc.call(s, p) }
78
+ @pid = fork { server_proc.call(@sock, @port) }
79
+ @sock.close rescue nil
74
80
  end
75
81
 
76
82
  def destroy!
77
83
  @sock.close rescue nil
78
- Thread.kill(@thr) rescue nil
84
+ Process.kill('KILL', @pid) rescue nil
79
85
  end
80
86
 
81
87
  end
82
88
 
83
89
  class TestMogileFS < Test::Unit::TestCase
84
90
 
85
- undef_method :default_test
91
+ undef_method :default_test if method_defined?(:default_test)
86
92
 
87
93
  def setup
88
94
  @client = @klass.new :hosts => ['kaa:6001'], :domain => 'test'
data/test/test_backend.rb CHANGED
@@ -35,19 +35,20 @@ class TestBackend < Test::Unit::TestCase
35
35
  end
36
36
 
37
37
  def test_do_request
38
- received = ''
38
+ received = Tempfile.new('received')
39
39
  tmp = TempServer.new(Proc.new do |serv, port|
40
40
  client, client_addr = serv.accept
41
41
  client.sync = true
42
- received = client.recv 4096
42
+ received.syswrite(client.recv(4096))
43
43
  client.send "OK 1 you=win\r\n", 0
44
44
  end)
45
45
 
46
- @backend.hosts = "127.0.0.1:#{tmp.port}"
46
+ @backend.hosts = [ "127.0.0.1:#{tmp.port}" ]
47
47
 
48
48
  assert_equal({'you' => 'win'},
49
49
  @backend.do_request('go!', { 'fight' => 'team fight!' }))
50
- assert_equal "go! fight=team+fight%21\r\n", received
50
+ received.sysseek(0)
51
+ assert_equal "go! fight=team+fight%21\r\n", received.sysread(4096)
51
52
  ensure
52
53
  TempServer.destroy_all!
53
54
  end
@@ -118,24 +119,24 @@ class TestBackend < Test::Unit::TestCase
118
119
  end
119
120
 
120
121
  def test_readable_eh_readable
121
- accept_nr = 0
122
+ accept = Tempfile.new('accept')
122
123
  tmp = TempServer.new(Proc.new do |serv, port|
123
124
  client, client_addr = serv.accept
124
125
  client.sync = true
125
- accept_nr += 1
126
+ accept.syswrite('.')
126
127
  client.send('.', 0)
127
128
  sleep
128
129
  end)
129
130
 
130
131
  @backend = MogileFS::Backend.new :hosts => [ "127.0.0.1:#{tmp.port}" ]
131
132
  assert_equal true, @backend.readable?
132
- assert_equal 1, accept_nr
133
+ assert_equal 1, accept.stat.size
133
134
  ensure
134
135
  TempServer.destroy_all!
135
136
  end
136
137
 
137
138
  def test_readable_eh_not_readable
138
- tmp = TempServer.new(Proc.new { |a,b| sleep })
139
+ tmp = TempServer.new(Proc.new { |serv,port| serv.accept; sleep })
139
140
  @backend = MogileFS::Backend.new(:hosts => [ "127.0.0.1:#{tmp.port}" ],
140
141
  :timeout => 0.5)
141
142
  begin
@@ -158,36 +159,45 @@ class TestBackend < Test::Unit::TestCase
158
159
  end
159
160
 
160
161
  def test_socket_robust
161
- bad_accept_nr = accept_nr = 0
162
- queue = Queue.new
163
- bad = Proc.new { |serv,port| sleep; bad_accept_nr += 1 }
162
+ bad_accept = Tempfile.new('bad_accept')
163
+ accept = Tempfile.new('accept')
164
+ bad = Proc.new do |serv,port|
165
+ client, client_addr = serv.accept
166
+ bad_accept.syswrite('!')
167
+ end
164
168
  good = Proc.new do |serv,port|
165
169
  client, client_addr = serv.accept
166
- client.sync = true
167
- accept_nr += 1
168
- client.send '.', 0
169
- client.flush
170
- queue.push true
170
+ accept.syswrite('.')
171
+ client.syswrite('.')
172
+ client.close
171
173
  sleep
172
174
  end
173
175
  nr = 10
174
176
 
175
177
  nr.times do
176
178
  begin
177
- t1 = TempServer.new(bad)
179
+ t1 = TempServer.new(bad, ENV['TEST_DEAD_PORT'])
178
180
  t2 = TempServer.new(good)
179
- hosts = ["0:#{t1.port}", "0:#{t2.port}"]
180
- @backend = MogileFS::Backend.new(:hosts => hosts)
181
+ hosts = ["127.0.0.1:#{t1.port}", "127.0.0.1:#{t2.port}"]
182
+ @backend = MogileFS::Backend.new(:hosts => hosts.dup)
181
183
  assert_equal({}, @backend.dead)
184
+ old_chld_handler = trap('CHLD', 'DEFAULT')
182
185
  t1.destroy!
183
- @backend.socket
184
- wait = queue.pop
186
+ Process.waitpid(t1.pid)
187
+ trap('CHLD', old_chld_handler)
188
+ sock = @backend.socket
189
+ assert_equal Socket, sock.class
190
+ port = Socket.unpack_sockaddr_in(sock.getpeername).first
191
+ # p [ 'ports', "port=#{port}", "t1=#{t1.port}", "t2=#{t2.port}" ]
192
+ assert_equal t2.port, port
193
+ IO.select([sock])
194
+ assert_equal '.', sock.sysread(1)
185
195
  ensure
186
196
  TempServer.destroy_all!
187
197
  end
188
198
  end # nr.times
189
- assert_equal 0, bad_accept_nr
190
- assert_equal nr, accept_nr
199
+ assert_equal 0, bad_accept.stat.size
200
+ assert_equal nr, accept.stat.size
191
201
  end
192
202
 
193
203
  def test_shutdown
@@ -195,15 +205,18 @@ class TestBackend < Test::Unit::TestCase
195
205
  tmp = TempServer.new(Proc.new do |serv,port|
196
206
  client, client_addr = serv.accept
197
207
  accept_nr += 1
208
+ r = IO.select([client], [client])
209
+ client.syswrite(accept_nr.to_s)
198
210
  sleep
199
211
  end)
200
212
  @backend = MogileFS::Backend.new :hosts => [ "127.0.0.1:#{tmp.port}" ]
201
213
  assert @backend.socket
202
214
  assert ! @backend.socket.closed?
215
+ IO.select([@backend.socket])
216
+ resp = @backend.socket.sysread(4096)
203
217
  @backend.shutdown
204
218
  assert_equal nil, @backend.instance_variable_get(:@socket)
205
- assert_equal 1, accept_nr
206
-
219
+ assert_equal 1, resp.to_i
207
220
  ensure
208
221
  TempServer.destroy_all!
209
222
  end
@@ -20,15 +20,16 @@ class TestMogileFS__MogileFS < TestMogileFS
20
20
  end
21
21
 
22
22
  def test_get_file_data_http
23
- accept_nr = 0
23
+ tmp = Tempfile.new('accept')
24
+ accept = File.open(tmp.path, "ab")
24
25
  svr = Proc.new do |serv, port|
25
26
  client, client_addr = serv.accept
26
27
  client.sync = true
27
28
  readed = client.recv(4096, 0)
28
29
  assert(readed =~ \
29
30
  %r{\AGET /dev[12]/0/000/000/0000000062\.fid HTTP/1.[01]\r\n\r\n\Z})
31
+ accept.syswrite('.')
30
32
  client.send("HTTP/1.0 200 OK\r\nContent-Length: 5\r\n\r\ndata!", 0)
31
- accept_nr += 1
32
33
  client.close
33
34
  end
34
35
  t1 = TempServer.new(svr)
@@ -39,13 +40,14 @@ class TestMogileFS__MogileFS < TestMogileFS
39
40
  @backend.get_paths = { 'paths' => 2, 'path1' => path1, 'path2' => path2 }
40
41
 
41
42
  assert_equal 'data!', @client.get_file_data('key')
42
- assert_equal 1, accept_nr
43
+ assert_equal 1, accept.stat.size
43
44
  ensure
44
45
  TempServer.destroy_all!
45
46
  end
46
47
 
47
48
  def test_get_file_data_http_not_found_failover
48
- accept_nr = 0
49
+ tmp = Tempfile.new('accept')
50
+ accept = File.open(tmp.path, 'ab')
49
51
  svr1 = Proc.new do |serv, port|
50
52
  client, client_addr = serv.accept
51
53
  client.sync = true
@@ -53,7 +55,7 @@ class TestMogileFS__MogileFS < TestMogileFS
53
55
  assert(readed =~ \
54
56
  %r{\AGET /dev1/0/000/000/0000000062\.fid HTTP/1.[01]\r\n\r\n\Z})
55
57
  client.send("HTTP/1.0 404 Not Found\r\n\r\ndata!", 0)
56
- accept_nr += 1
58
+ accept.syswrite('.')
57
59
  client.close
58
60
  end
59
61
 
@@ -64,7 +66,7 @@ class TestMogileFS__MogileFS < TestMogileFS
64
66
  assert(readed =~ \
65
67
  %r{\AGET /dev2/0/000/000/0000000062\.fid HTTP/1.[01]\r\n\r\n\Z})
66
68
  client.send("HTTP/1.0 200 OK\r\nContent-Length: 5\r\n\r\ndata!", 0)
67
- accept_nr += 1
69
+ accept.syswrite('.')
68
70
  client.close
69
71
  end
70
72
 
@@ -75,7 +77,7 @@ class TestMogileFS__MogileFS < TestMogileFS
75
77
  @backend.get_paths = { 'paths' => 2, 'path1' => path1, 'path2' => path2 }
76
78
 
77
79
  assert_equal 'data!', @client.get_file_data('key')
78
- assert_equal 2, accept_nr
80
+ assert_equal 2, accept.stat.size
79
81
  ensure
80
82
  TempServer.destroy_all!
81
83
  end
@@ -92,16 +94,17 @@ class TestMogileFS__MogileFS < TestMogileFS
92
94
  assert_equal expect_size + header.size, File.size(tmpfp.path)
93
95
  tmpfp.sysseek(0)
94
96
 
95
- accept_nr = 0
97
+ accept = Tempfile.new('accept')
96
98
  svr = Proc.new do |serv, port|
97
99
  client, client_addr = serv.accept
98
100
  client.sync = true
99
- accept_nr += 1
101
+ accept.syswrite('.')
100
102
  readed = client.recv(4096, 0)
101
103
  assert(readed =~ \
102
104
  %r{\AGET /dev[12]/0/000/000/0000000062\.fid HTTP/1.[01]\r\n\r\n\Z})
103
105
  sysrwloop(tmpfp, client)
104
106
  client.close
107
+ exit 0
105
108
  end
106
109
  t1 = TempServer.new(svr)
107
110
  t2 = TempServer.new(svr)
@@ -120,13 +123,15 @@ class TestMogileFS__MogileFS < TestMogileFS
120
123
  read_nr = buf.size
121
124
  nr += read_nr
122
125
  assert_equal read_nr, data.syswrite(buf), "partial write"
126
+ rescue Errno::EAGAIN
127
+ retry
123
128
  rescue EOFError
124
129
  break
125
130
  end
126
131
  end
127
132
  end
128
133
  assert_equal expect_size, nr, "size mismatch"
129
- assert_equal 1, accept_nr
134
+ assert_equal 1, accept.stat.size
130
135
  end
131
136
 
132
137
  def test_get_paths
@@ -241,14 +246,14 @@ class TestMogileFS__MogileFS < TestMogileFS
241
246
  end
242
247
 
243
248
  def test_size_http
244
- accept_nr = 0
249
+ accept = Tempfile.new('accept')
245
250
  t = TempServer.new(Proc.new do |serv,port|
246
251
  client, client_addr = serv.accept
247
252
  client.sync = true
248
253
  readed = client.recv(4096, 0) rescue nil
254
+ accept.syswrite('.')
249
255
  assert_equal "HEAD /path HTTP/1.0\r\n\r\n", readed
250
256
  client.send("HTTP/1.0 200 OK\r\nContent-Length: 5\r\n\r\n", 0)
251
- accept_nr += 1
252
257
  client.close
253
258
  end)
254
259
 
@@ -256,18 +261,18 @@ class TestMogileFS__MogileFS < TestMogileFS
256
261
  @backend.get_paths = { 'paths' => 1, 'path1' => path }
257
262
 
258
263
  assert_equal 5, @client.size('key')
259
- assert_equal 1, accept_nr
264
+ assert_equal 1, accept.stat.size
260
265
  end
261
266
 
262
267
  def test_bad_size_http
263
- accept_nr = 0
268
+ tmp = Tempfile.new('accept')
264
269
  t = TempServer.new(Proc.new do |serv,port|
265
270
  client, client_addr = serv.accept
266
271
  client.sync = true
267
272
  readed = client.recv(4096, 0) rescue nil
268
273
  assert_equal "HEAD /path HTTP/1.0\r\n\r\n", readed
269
274
  client.send("HTTP/1.0 404 Not Found\r\nContent-Length: 5\r\n\r\n", 0)
270
- accept_nr += 1
275
+ tmp.syswrite('.')
271
276
  client.close
272
277
  end)
273
278
 
@@ -275,17 +280,17 @@ class TestMogileFS__MogileFS < TestMogileFS
275
280
  @backend.get_paths = { 'paths' => 1, 'path1' => path }
276
281
 
277
282
  assert_nil @client.size('key')
278
- assert_equal 1, accept_nr
283
+ assert_equal 1, tmp.stat.size
279
284
  end
280
285
 
281
286
  def test_store_content_http
282
- received = ''
287
+ received = Tempfile.new('recieved')
283
288
  expected = "PUT /path HTTP/1.0\r\nContent-Length: 4\r\n\r\ndata"
284
289
 
285
290
  t = TempServer.new(Proc.new do |serv, accept|
286
291
  client, client_addr = serv.accept
287
292
  client.sync = true
288
- received = client.recv(4096, 0)
293
+ received.syswrite(client.recv(4096, 0))
289
294
  client.send("HTTP/1.0 200 OK\r\n\r\n", 0)
290
295
  client.close
291
296
  end)
@@ -297,19 +302,61 @@ class TestMogileFS__MogileFS < TestMogileFS
297
302
 
298
303
  @client.store_content 'new_key', 'test', 'data'
299
304
 
300
- assert_equal expected, received
305
+ received.sysseek(0)
306
+ assert_equal expected, received.sysread(4096)
307
+ ensure
308
+ TempServer.destroy_all!
309
+ end
310
+
311
+
312
+ def test_store_content_with_writer_callback
313
+ received = Tempfile.new('recieved')
314
+ expected = "PUT /path HTTP/1.0\r\nContent-Length: 40\r\n\r\n"
315
+ 10.times do
316
+ expected += "data"
317
+ end
318
+ t = TempServer.new(Proc.new do |serv, accept|
319
+ client, client_addr = serv.accept
320
+ client.sync = true
321
+ nr = 0
322
+ loop do
323
+ buf = client.readpartial(8192) or break
324
+ break if buf.length == 0
325
+ assert_equal buf.length, received.syswrite(buf)
326
+ nr += buf.length
327
+ break if nr >= expected.size
328
+ end
329
+ client.send("HTTP/1.0 200 OK\r\n\r\n", 0)
330
+ client.close
331
+ end)
332
+
333
+ @backend.create_open = {
334
+ 'devid' => '1',
335
+ 'path' => "http://127.0.0.1:#{t.port}/path",
336
+ }
337
+
338
+ cbk = MogileFS::Util::StoreContent.new(40) do |write_callback|
339
+ 10.times do
340
+ write_callback.call("data")
341
+ end
342
+ end
343
+ @client.store_content('new_key', 'test', cbk)
344
+
345
+ received.sysseek(0)
346
+ assert_equal expected, received.sysread(4096)
301
347
  ensure
302
348
  TempServer.destroy_all!
303
349
  end
304
350
 
305
351
  def test_store_content_multi_dest_failover
306
- received1 = received2 = nil
352
+ received1 = Tempfile.new('received')
353
+ received2 = Tempfile.new('received')
307
354
  expected = "PUT /path HTTP/1.0\r\nContent-Length: 4\r\n\r\ndata"
308
355
 
309
356
  t1 = TempServer.new(Proc.new do |serv, accept|
310
357
  client, client_addr = serv.accept
311
358
  client.sync = true
312
- received1 = client.recv(4096, 0)
359
+ received1.syswrite(client.recv(4096, 0))
313
360
  client.send("HTTP/1.0 500 Internal Server Error\r\n\r\n", 0)
314
361
  client.close
315
362
  end)
@@ -317,7 +364,7 @@ class TestMogileFS__MogileFS < TestMogileFS
317
364
  t2 = TempServer.new(Proc.new do |serv, accept|
318
365
  client, client_addr = serv.accept
319
366
  client.sync = true
320
- received2 = client.recv(4096, 0)
367
+ received2.syswrite(client.recv(4096, 0))
321
368
  client.send("HTTP/1.0 200 OK\r\n\r\n", 0)
322
369
  client.close
323
370
  end)
@@ -331,8 +378,10 @@ class TestMogileFS__MogileFS < TestMogileFS
331
378
  }
332
379
 
333
380
  @client.store_content 'new_key', 'test', 'data'
334
- assert_equal expected, received1
335
- assert_equal expected, received2
381
+ received1.sysseek(0)
382
+ received2.sysseek(0)
383
+ assert_equal expected, received1.sysread(4096)
384
+ assert_equal expected, received2.sysread(4096)
336
385
  ensure
337
386
  TempServer.destroy_all!
338
387
  end
@@ -357,12 +406,12 @@ class TestMogileFS__MogileFS < TestMogileFS
357
406
  end
358
407
 
359
408
  def test_store_content_http_empty
360
- received = ''
409
+ received = Tempfile.new('received')
361
410
  expected = "PUT /path HTTP/1.0\r\nContent-Length: 0\r\n\r\n"
362
411
  t = TempServer.new(Proc.new do |serv, accept|
363
412
  client, client_addr = serv.accept
364
413
  client.sync = true
365
- received = client.recv(4096, 0)
414
+ received.syswrite(client.recv(4096, 0))
366
415
  client.send("HTTP/1.0 200 OK\r\n\r\n", 0)
367
416
  client.close
368
417
  end)
@@ -373,7 +422,8 @@ class TestMogileFS__MogileFS < TestMogileFS
373
422
  }
374
423
 
375
424
  @client.store_content 'new_key', 'test', ''
376
- assert_equal expected, received
425
+ received.sysseek(0)
426
+ assert_equal expected, received.sysread(4096)
377
427
  end
378
428
 
379
429
  def test_store_content_nfs
@@ -406,17 +456,19 @@ class TestMogileFS__MogileFS < TestMogileFS
406
456
  assert_equal expect_size + header.size, expect.stat.size
407
457
  assert_equal expect_size, to_put.stat.size
408
458
 
409
- readed = 0
459
+ readed = Tempfile.new('readed')
410
460
  t = TempServer.new(Proc.new do |serv, accept|
411
461
  client, client_addr = serv.accept
412
462
  client.sync = true
463
+ nr = 0
413
464
  loop do
414
465
  buf = client.readpartial(8192) or break
415
466
  break if buf.length == 0
416
467
  assert_equal buf.length, received.syswrite(buf)
417
- readed += buf.length
418
- break if readed >= expect.stat.size
468
+ nr += buf.length
469
+ break if nr >= expect.stat.size
419
470
  end
471
+ readed.syswrite("#{nr}")
420
472
  client.send("HTTP/1.0 200 OK\r\n\r\n", 0)
421
473
  client.close
422
474
  end)
@@ -427,7 +479,8 @@ class TestMogileFS__MogileFS < TestMogileFS
427
479
  }
428
480
 
429
481
  @client.store_file('new_key', 'test', to_put.path)
430
- assert_equal expect.stat.size, readed
482
+ readed.sysseek(0)
483
+ assert_equal expect.stat.size, readed.sysread(4096).to_i
431
484
 
432
485
  ENV['PATH'].split(/:/).each do |path|
433
486
  cmp_bin = "#{path}/cmp"
data/test/test_network.rb CHANGED
@@ -24,4 +24,32 @@ class TestNetwork < Test::Unit::TestCase
24
24
  TempServer.destroy_all!
25
25
  end
26
26
 
27
+ def test_verify_non_existent
28
+ good = TempServer.new(Proc.new do |serv,port|
29
+ client,client_addr = serv.accept
30
+ client.readpartial(4096)
31
+ client.syswrite("HTTP/1.0 200 OK\r\nContent-Length: 0\r\n\r\n")
32
+ end)
33
+ bad = TempServer.new(Proc.new { |serv,port| serv.close })
34
+
35
+ good_uri = URI.parse("http://127.0.0.1:#{good.port}/")
36
+ bad_uri = URI.parse("http://127.0.0.1:#{bad.port}/")
37
+ ok = verify_uris([ good_uri, bad_uri ])
38
+ assert_equal [ good_uri ], ok
39
+ ensure
40
+ TempServer.destroy_all!
41
+ end
42
+
43
+ def test_verify_all_bad
44
+ good = TempServer.new(Proc.new { |serv,port| serv.close })
45
+ bad = TempServer.new(Proc.new { |serv,port| serv.close })
46
+
47
+ good_uri = URI.parse("http://127.0.0.1:#{good.port}/")
48
+ bad_uri = URI.parse("http://127.0.0.1:#{bad.port}/")
49
+ ok = verify_uris([ good_uri, bad_uri ], '200', 1.0)
50
+ assert ok.empty?, "nothing returned"
51
+ ensure
52
+ TempServer.destroy_all!
53
+ end
54
+
27
55
  end
data/test/test_util.rb CHANGED
@@ -1,24 +1,23 @@
1
1
  require 'test/setup'
2
- require 'tempfile'
3
2
 
4
3
  class TestMogileFS__Util < Test::Unit::TestCase
5
4
  include MogileFS::Util
6
5
 
7
6
  def test_mogilefs_write
8
- done = Queue.new
7
+ rd, wr = IO.pipe
9
8
 
10
9
  svr = Proc.new do |serv, port|
11
10
  client, client_addr = serv.accept
12
11
  client.sync = true
13
- readed = 0
12
+ nr = 0
14
13
  loop do
15
14
  begin
16
- readed += client.readpartial(16384).length
15
+ nr += client.readpartial(16384).length
17
16
  rescue EOFError
18
17
  break
19
18
  end
20
19
  end
21
- done << readed
20
+ wr.syswrite("#{nr}\n")
22
21
  client.close rescue nil
23
22
  end
24
23
  t = TempServer.new(svr)
@@ -32,14 +31,13 @@ class TestMogileFS__Util < Test::Unit::TestCase
32
31
 
33
32
  syswrite_full(s, big_string)
34
33
  s.close rescue nil
35
- readed = done.pop
36
-
37
- assert_equal((sent + big_string.length), readed)
34
+ IO.select([rd])
35
+ assert_equal((sent + big_string.length), rd.sysread(4096).to_i)
36
+ ensure
37
+ t.destroy!
38
38
  end
39
39
 
40
40
  def test_write_timeout
41
- done = Queue.new
42
-
43
41
  svr = Proc.new do |serv, port|
44
42
  client, client_addr = serv.accept
45
43
  client.sync = true
@@ -54,6 +52,8 @@ class TestMogileFS__Util < Test::Unit::TestCase
54
52
 
55
53
  assert_raises(MogileFS::Timeout) { syswrite_full(s, big_string, 0.1) }
56
54
  s.close rescue nil
55
+ ensure
56
+ t.destroy!
57
57
  end
58
58
 
59
59
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mogilefs-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Wong
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2009-02-02 00:00:00 -08:00
13
+ date: 2009-02-25 00:00:00 -08:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -31,7 +31,7 @@ dependencies:
31
31
  requirements:
32
32
  - - ">="
33
33
  - !ruby/object:Gem::Version
34
- version: 1.8.2
34
+ version: 1.8.3
35
35
  version:
36
36
  description: git://git.bogomips.org/mogilefs-client.git
37
37
  email: normalperson@yhbt.net