mogilefs-client 2.0.0 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/History.txt +6 -0
- data/README.txt +1 -1
- data/bin/mog +1 -0
- data/lib/mogilefs.rb +1 -1
- data/lib/mogilefs/backend.rb +8 -3
- data/lib/mogilefs/httpfile.rb +13 -2
- data/lib/mogilefs/mogilefs.rb +6 -2
- data/lib/mogilefs/network.rb +72 -32
- data/lib/mogilefs/pool.rb +2 -0
- data/lib/mogilefs/util.rb +10 -0
- data/test/setup.rb +15 -9
- data/test/test_backend.rb +38 -25
- data/test/test_mogilefs.rb +84 -31
- data/test/test_network.rb +28 -0
- data/test/test_util.rb +10 -10
- metadata +3 -3
data/.gitignore
CHANGED
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
data/lib/mogilefs.rb
CHANGED
data/lib/mogilefs/backend.rb
CHANGED
@@ -274,9 +274,14 @@ class MogileFS::Backend
|
|
274
274
|
|
275
275
|
##
|
276
276
|
# Escapes naughty URL characters.
|
277
|
-
|
278
|
-
|
279
|
-
|
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
|
##
|
data/lib/mogilefs/httpfile.rb
CHANGED
@@ -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 @
|
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" \
|
data/lib/mogilefs/mogilefs.rb
CHANGED
@@ -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
|
-
|
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
|
data/lib/mogilefs/network.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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 =
|
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
|
-
|
46
|
-
|
47
|
-
|
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
|
-
|
54
|
-
|
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
|
-
|
62
|
-
|
101
|
+
ok_uris
|
102
|
+
end
|
63
103
|
|
64
104
|
end # module MogileFS::Network
|
data/lib/mogilefs/pool.rb
CHANGED
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
|
-
|
62
|
-
|
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
|
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
|
-
@
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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,
|
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 { |
|
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
|
-
|
162
|
-
|
163
|
-
bad = Proc.new
|
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
|
-
|
167
|
-
|
168
|
-
client.
|
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
|
-
|
184
|
-
|
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,
|
190
|
-
assert_equal 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,
|
206
|
-
|
219
|
+
assert_equal 1, resp.to_i
|
207
220
|
ensure
|
208
221
|
TempServer.destroy_all!
|
209
222
|
end
|
data/test/test_mogilefs.rb
CHANGED
@@ -20,15 +20,16 @@ class TestMogileFS__MogileFS < TestMogileFS
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def test_get_file_data_http
|
23
|
-
|
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,
|
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
|
-
|
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
|
-
|
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
|
-
|
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,
|
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
|
-
|
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
|
-
|
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,
|
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
|
-
|
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,
|
264
|
+
assert_equal 1, accept.stat.size
|
260
265
|
end
|
261
266
|
|
262
267
|
def test_bad_size_http
|
263
|
-
|
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
|
-
|
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,
|
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
|
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
|
-
|
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 =
|
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
|
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
|
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
|
-
|
335
|
-
|
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
|
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
|
-
|
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 =
|
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
|
-
|
418
|
-
break if
|
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
|
-
|
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
|
-
|
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
|
-
|
12
|
+
nr = 0
|
14
13
|
loop do
|
15
14
|
begin
|
16
|
-
|
15
|
+
nr += client.readpartial(16384).length
|
17
16
|
rescue EOFError
|
18
17
|
break
|
19
18
|
end
|
20
19
|
end
|
21
|
-
|
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
|
-
|
36
|
-
|
37
|
-
|
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.
|
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-
|
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.
|
34
|
+
version: 1.8.3
|
35
35
|
version:
|
36
36
|
description: git://git.bogomips.org/mogilefs-client.git
|
37
37
|
email: normalperson@yhbt.net
|