mogilefs-client 3.4.0 → 3.5.0.rc1

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
  #!/usr/bin/env ruby
2
2
  CONSTANT = "MogileFS::VERSION"
3
3
  RVF = "lib/mogilefs/version.rb"
4
- DEF_VER = "v3.4.0"
4
+ DEF_VER = "v3.5.0-rc1"
5
5
  vn = DEF_VER
6
6
 
7
7
  # First see if there is a version file (included in release tarballs),
data/lib/mogilefs.rb CHANGED
@@ -64,6 +64,14 @@ module MogileFS
64
64
  @io = MogileFS::CopyStream
65
65
  end
66
66
 
67
+ begin
68
+ require 'net/http/persistent'
69
+ NHP = Net::HTTP::Persistent
70
+ rescue LoadError
71
+ require 'mogilefs/nhp_fake'
72
+ NHP = MogileFS::NhpFake
73
+ end
74
+
67
75
  # autoload rarely-used things:
68
76
  autoload :Mysql, 'mogilefs/mysql'
69
77
  autoload :Pool, 'mogilefs/pool'
@@ -95,7 +95,6 @@ class MogileFS::HTTPFile < StringIO
95
95
  # returns file size if the socket finished writing
96
96
  def upload(devid, uri) # :nodoc:
97
97
  sock = MogileFS::Socket.tcp(uri.host, uri.port)
98
- set_socket_options(sock)
99
98
  file_size = length
100
99
 
101
100
  if @streaming_io
@@ -136,14 +135,41 @@ class MogileFS::HTTPFile < StringIO
136
135
  sock.close if sock
137
136
  end
138
137
 
138
+ def nhp_put(devid, uri)
139
+ clen = @opts[:content_length]
140
+ if clen && clen != size
141
+ raise MogileFS::SizeMismatchError,
142
+ ":content_length expected: #{clen.inspect}, actual: #{size}"
143
+ end
144
+
145
+ put = Net::HTTP::Put.new(uri.path)
146
+ put["Content-Type"] = "application/octet-stream"
147
+ if md5 = @opts[:content_md5]
148
+ if md5.respond_to?(:call)
149
+ md5 = md5.call.strip
150
+ elsif md5 == :trailer
151
+ md5 = [ Digest::MD5.digest(string) ].pack("m").chomp!
152
+ end
153
+ put["Content-MD5"] = md5
154
+ end
155
+ put.body = string
156
+ res = @opts[:nhp_put].request(uri, put)
157
+ return size if Net::HTTPSuccess === res
158
+ raise BadResponseError, "#{res.code} #{res.message}"
159
+ rescue => e
160
+ /\ANet::/ =~ "#{e.class}" and
161
+ raise RetryableError, "#{e.message} (#{e.class})", e.backtrace
162
+ raise
163
+ end
164
+
139
165
  def commit
140
166
  errors = nil
141
167
  @dests.each do |devid, path|
142
168
  begin
143
169
  uri = URI.parse(path)
144
- bytes_uploaded = upload(devid, uri)
170
+ bytes_uploaded = size > 0 ? nhp_put(devid, uri) : upload(devid, uri)
145
171
  return create_close(devid, uri, bytes_uploaded)
146
- rescue SystemCallError, RetryableError => e
172
+ rescue Timeout::Error, SystemCallError, RetryableError => e
147
173
  errors ||= []
148
174
  errors << "#{path} - #{e.message} (#{e.class})"
149
175
  end
@@ -26,13 +26,9 @@ class MogileFS::HTTPReader < MogileFS::Socket
26
26
  "read=#{rv} bytes, expected=#@content_length from #@uri", []
27
27
  end
28
28
 
29
- def self.first(paths, timeout, count = nil, offset = nil)
29
+ def self.first(paths, timeout, range = nil)
30
30
  errors = nil
31
- if offset || count
32
- offset ||= 0
33
- range_end = count ? offset + count - 1 : ""
34
- range = "Range: bytes=#{offset}-#{range_end}\r\n"
35
- end
31
+ range = "Range: bytes=#{range[0]}-#{range[1]}\r\n" if range
36
32
 
37
33
  paths.each do |path|
38
34
  begin
@@ -50,17 +46,18 @@ class MogileFS::HTTPReader < MogileFS::Socket
50
46
  # body of the response.
51
47
  def self.try(path, timeout, range) # :nodoc:
52
48
  uri = URI.parse(path)
49
+ expire_at = Time.now + timeout
53
50
  sock = tcp(uri.host, uri.port, timeout)
54
51
  buf = "GET #{uri.request_uri} HTTP/1.0\r\n#{range}\r\n" # no chunking
55
52
  sock.timed_write(buf, timeout)
56
53
 
57
- sock.timed_peek(2048, buf, timeout) or
58
- raise MogileFS::InvalidResponseError, "EOF while reading header", []
54
+ begin
55
+ raise MogileFS::Timeout if Time.now > expire_at
56
+ sock.timed_peek(2048, buf, timeout) or
57
+ raise MogileFS::InvalidResponseError, "EOF while reading header", []
58
+ end until /\r\n\r\n/ =~ buf
59
59
 
60
60
  head, _ = buf.split(/\r\n\r\n/, 2)
61
-
62
- # we're dealing with a seriously slow/stupid HTTP server if we can't
63
- # get the header in a single recv(2) syscall.
64
61
  if ((range && head =~ %r{\AHTTP/\d+\.\d+\s+206\s*}) ||
65
62
  (!range && head =~ %r{\AHTTP/\d+\.\d+\s+200\s*})) &&
66
63
  head =~ %r{^Content-Length:\s*(\d+)}i
@@ -69,6 +69,10 @@ class MogileFS::MogileFS < MogileFS::Client
69
69
 
70
70
  @get_file_data_timeout = args[:get_file_data_timeout] || 5
71
71
  @new_file_max_time = args[:new_file_max_time] || 3600.0
72
+ @nhp_get = MogileFS::NHP.new('get')
73
+ @nhp_get.open_timeout = @nhp_get.read_timeout = @get_file_data_timeout
74
+ @nhp_put = MogileFS::NHP.new('put')
75
+ @nhp_put.open_timeout = @nhp_put.read_timeout = @new_file_max_time
72
76
 
73
77
  raise ArgumentError, "you must specify a domain" unless @domain
74
78
 
@@ -146,17 +150,40 @@ class MogileFS::MogileFS < MogileFS::Client
146
150
  # start position of the copy.
147
151
  def get_file_data(key, dst = nil, copy_length = nil, src_offset = nil)
148
152
  paths = get_paths(key)
149
- sock = MogileFS::HTTPReader.first(paths, @get_file_data_timeout,
150
- copy_length, src_offset)
153
+ if src_offset || copy_length
154
+ src_offset ||= 0
155
+ range_end = copy_length ? src_offset + copy_length - 1 : nil
156
+ range = [ src_offset, range_end ]
157
+ end
158
+
151
159
  if dst
160
+ sock = MogileFS::HTTPReader.first(paths, @get_file_data_timeout, range)
152
161
  sock.stream_to(dst)
153
162
  elsif block_given?
163
+ sock = MogileFS::HTTPReader.first(paths, @get_file_data_timeout, range)
154
164
  yield(sock)
155
165
  else
156
- sock.to_s
166
+ errors = nil
167
+ paths.each do |path|
168
+ uri = URI.parse(path)
169
+ get = Net::HTTP::Get.new(uri.path)
170
+ get["range"] = "bytes=#{range[0]}-#{range[1]}" if range
171
+ begin
172
+ res = @nhp_get.request(uri, get)
173
+ case res.code.to_i
174
+ when 200, 206
175
+ return res.body
176
+ end
177
+ (errors ||= []) << "#{path} - #{res.message} (#{res.class})"
178
+ rescue => e
179
+ (errors ||= []) << "#{path} - #{e.message} (#{e.class})"
180
+ end
181
+ end
182
+ raise MogileFS::Error,
183
+ "all paths failed with GET: #{errors.join(', ')}", []
157
184
  end
158
- ensure
159
- sock.close if sock && ! sock.closed?
185
+ ensure
186
+ sock.close if sock && ! sock.closed?
160
187
  end
161
188
 
162
189
  # Get the paths (URLs as strings) for +key+. If +args+ is specified,
@@ -244,18 +271,26 @@ class MogileFS::MogileFS < MogileFS::Client
244
271
  # Keep in mind most HTTP servers do not support HTTP trailers, so
245
272
  # passing a String is usually the safest way to use this.
246
273
  #
274
+ # [:info => Hash]
275
+ #
276
+ # This is an empty hash that will be filled the same information
277
+ # MogileFS::MogileFS#file_info.
278
+ #
279
+ # Additionally, it contains one additional key: :uris,
280
+ # an array of URI::HTTP objects to the stored destinations
247
281
  def new_file(key, args = nil, bytes = nil) # :yields: file
248
282
  raise MogileFS::ReadOnlyError if readonly?
249
- opts = { :key => key, :multi_dest => 1 }
283
+ opts = { :key => key, :multi_dest => 1, :nhp_put => @nhp_put }
250
284
  case args
251
285
  when Hash
252
286
  opts[:domain] = args[:domain]
287
+ open_args = args[:create_open_args]
253
288
  klass = args[:class] and "default" != klass and opts[:class] = klass
254
289
  when String
255
290
  opts[:class] = args if "default" != args
256
291
  end
257
292
  opts[:domain] ||= @domain
258
- res = @backend.create_open(opts)
293
+ res = @backend.create_open(open_args ? open_args.merge(opts) : opts)
259
294
 
260
295
  dests = if dev_count = res['dev_count'] # multi_dest succeeded
261
296
  (1..dev_count.to_i).map { |i| [res["devid_#{i}"], res["path_#{i}"]] }
@@ -275,6 +310,7 @@ class MogileFS::MogileFS < MogileFS::Client
275
310
  opts[:content_length] ||= bytes if bytes
276
311
  opts[:new_file_max_time] ||= @new_file_max_time
277
312
  opts[:start_time] = Time.now
313
+ info = opts[:info] and info["class"] = klass || "default"
278
314
 
279
315
  case (dests[0][1] rescue nil)
280
316
  when %r{\Ahttp://}
@@ -21,6 +21,7 @@ module MogileFS::NewFile::Common
21
21
  def read_response(sock)
22
22
  tout = @opts[:new_file_max_time] || 3600.0
23
23
  start_time = @opts[:start_time] and tout -= Time.now - start_time
24
+ set_socket_options(sock)
24
25
  case line = sock.timed_read(23, "", tout > 0.0 ? tout : 0)
25
26
  when %r{^HTTP/\d\.\d\s+(2\d\d)\s} # success!
26
27
  when nil
@@ -34,21 +35,23 @@ module MogileFS::NewFile::Common
34
35
  end
35
36
 
36
37
  def create_close(devid, uri, bytes_uploaded)
37
- args = {
38
- :fid => @opts[:fid],
39
- :devid => devid,
40
- :key => @opts[:key],
41
- :domain => @opts[:domain],
42
- :size => bytes_uploaded,
43
- :path => uri.to_s,
44
- }
38
+ close_args = @opts[:create_close_args]
39
+
40
+ dest_info = @opts[:info] ||= {}
41
+ dest_info["fid"] = @opts[:fid].to_i
42
+ dest_info["key"] = @opts[:key]
43
+ dest_info["domain"] = @opts[:domain]
44
+ dest_info[:devid] = devid
45
+ dest_info[:path] = uri.to_s
46
+ dest_info[:size] = bytes_uploaded
45
47
  if @md5
46
- args[:checksum] = "MD5:#{@md5.hexdigest}"
48
+ dest_info["checksum"] = "MD5:#{@md5.hexdigest}"
47
49
  elsif String === @opts[:content_md5]
48
50
  hex = @opts[:content_md5].unpack('m')[0].unpack('H*')[0]
49
- args[:checksum] = "MD5:#{hex}"
51
+ dest_info["checksum"] = "MD5:#{hex}"
50
52
  end
51
- args[:checksumverify] = 1 if @opts[:checksumverify]
53
+
54
+ dest_info[:checksumverify] = 1 if @opts[:checksumverify]
52
55
  backend = @opts[:backend]
53
56
 
54
57
  # upload could've taken a long time, ping and try to ensure socket
@@ -61,7 +64,16 @@ module MogileFS::NewFile::Common
61
64
  # twice will hurt us...
62
65
  backend.noop
63
66
 
64
- backend.create_close(args)
67
+ backend.create_close(close_args ? close_args.merge(dest_info) : dest_info)
68
+
69
+ # make this look like file_info + get_uris
70
+ dest_info.delete(:checksumverify)
71
+ dest_info.delete(:path)
72
+ dest_info[:uris] = [ uri ]
73
+ dest_info["devcount"] = 1
74
+ dest_info["devids"] = [ dest_info.delete(:devid).to_i ]
75
+ dest_info["length"] = dest_info.delete(:size)
76
+
65
77
  bytes_uploaded
66
78
  end
67
79
 
@@ -1,6 +1,5 @@
1
1
  # -*- encoding: binary -*-
2
2
  # here are internal implementation details, do not rely on them in your code
3
- require 'net/http'
4
3
  require 'mogilefs/new_file/writer'
5
4
 
6
5
  # an IO-like object
@@ -9,18 +8,8 @@ class MogileFS::NewFile::ContentRange
9
8
  include MogileFS::NewFile::Common
10
9
  attr_reader :md5
11
10
 
12
- # :stopdoc:
13
- begin
14
- require 'net/http/persistent'
15
- NHP = Net::HTTP::Persistent.new('mogilefs')
16
-
17
- def hit(uri, req)
18
- NHP.request(uri, req).value
19
- end
20
- rescue LoadError
21
- def hit(uri, req)
22
- Net::HTTP.start(uri.host, uri.port) { |h| h.request(req).value }
23
- end
11
+ def hit(uri, req)
12
+ @opts[:nhp_put].request(uri, req).value
24
13
  end
25
14
  # :startdoc:
26
15
 
@@ -18,7 +18,6 @@ class MogileFS::NewFile::Stream
18
18
  begin
19
19
  uri = URI.parse(path)
20
20
  sock = MogileFS::Socket.tcp(uri.host, uri.port)
21
- set_socket_options(sock)
22
21
  start_sock(sock, uri) # raise on errors
23
22
  @to_io = sock
24
23
  @uri = uri
@@ -0,0 +1,18 @@
1
+ # :enddoc:
2
+ require 'net/http'
3
+
4
+ # This is just for folks that don't have net-http-persistent
5
+ class MogileFS::NhpFake # :nodoc:
6
+ attr_accessor :read_timeout, :open_timeout
7
+
8
+ def initialize(name)
9
+ @read_timeout = @open_timeout = nil
10
+ end
11
+
12
+ def request(uri, req) # :nodoc:
13
+ http = Net::HTTP.new(uri.host, uri.port)
14
+ http.read_timeout = @read_timeout
15
+ http.open_timeout = @open_timeout
16
+ http.request(req)
17
+ end
18
+ end
data/test/fresh.rb CHANGED
@@ -90,17 +90,14 @@ EOF
90
90
  @admin.create_domain(domain)
91
91
  yield_for_monitor_update { @admin.get_domains.include?(domain) and break }
92
92
 
93
- assert_nothing_raised do
94
- @admin.create_class(domain, "klassy", 1)
95
- end
93
+ @admin.create_class(domain, "klassy", 1)
94
+
96
95
  assert_raises(MogileFS::Backend::ClassExistsError) do
97
96
  @admin.create_class(domain, "klassy", 1)
98
97
  end
99
98
 
100
- assert_nothing_raised do
101
- @admin.update_class(domain, "klassy",
102
- :mindevcount => 1, :replpolicy => "MultipleHosts(1)")
103
- end
99
+ @admin.update_class(domain, "klassy",
100
+ :mindevcount => 1, :replpolicy => "MultipleHosts(1)")
104
101
 
105
102
  tmp = nil
106
103
  yield_for_monitor_update do
@@ -110,7 +107,7 @@ EOF
110
107
  assert tmp, "domain did not show up"
111
108
  assert_equal 1, tmp["mindevcount"]
112
109
  assert_equal "MultipleHosts(1)", tmp["replpolicy"]
113
- assert_nothing_raised { @admin.update_class(domain, "klassy", 2) }
110
+ @admin.update_class(domain, "klassy", 2)
114
111
  ensure
115
112
  @admin.delete_class(domain, "klassy") rescue nil
116
113
  end
data/test/socket_test.rb CHANGED
@@ -11,11 +11,9 @@ module SocketTest
11
11
  def test_start
12
12
  sock = MogileFS::Socket.start(@host, @port)
13
13
  assert_instance_of MogileFS::Socket, sock, sock.inspect
14
- assert_nothing_raised do
15
- begin
16
- sock.write_nonblock("a")
17
- rescue Errno::EAGAIN
18
- end
14
+ begin
15
+ sock.write_nonblock("a")
16
+ rescue Errno::EAGAIN
19
17
  end
20
18
  thr = Thread.new { @srv.accept }
21
19
  accepted = thr.value
@@ -26,9 +24,7 @@ module SocketTest
26
24
  def test_new
27
25
  sock = MogileFS::Socket.tcp(@host, @port)
28
26
  assert_instance_of MogileFS::Socket, sock, sock.inspect
29
- assert_nothing_raised do
30
- sock.write_nonblock("a")
31
- end
27
+ sock.write_nonblock("a")
32
28
  thr = Thread.new { @srv.accept }
33
29
  accepted = thr.value
34
30
  assert_instance_of TCPSocket, accepted, accepted.inspect
@@ -99,7 +95,7 @@ module SocketTest
99
95
  def test_read_in_full
100
96
  sock = MogileFS::Socket.tcp(@host, @port)
101
97
  accepted = @srv.accept
102
- thr = Thread.new do
98
+ Thread.new do
103
99
  accepted.write "HELLO"
104
100
  sleep 0.1
105
101
  accepted.write " "
data/test/test_backend.rb CHANGED
@@ -59,9 +59,6 @@ class TestBackend < Test::Unit::TestCase
59
59
  assert_equal MogileFS::Error, @backend.error('PebKacError').superclass
60
60
  assert MogileFS::Backend.const_defined?('PebKacError')
61
61
 
62
- assert_nothing_raised do
63
- MogileFS::Backend::OMFGWTFBBQError
64
- end
65
62
  assert_equal MogileFS::Error, MogileFS::Backend::OMFGWTFBBQError.superclass
66
63
  assert_raises(NameError) do
67
64
  MogileFS::Backend::FailFailFail
@@ -146,10 +143,7 @@ class TestBackend < Test::Unit::TestCase
146
143
  client.write("OK 1 foo=bar\r\n")
147
144
  client
148
145
  end
149
- rv = nil
150
- assert_nothing_raised do
151
- rv = @backend.do_request('test', { "all" => "ALL" })
152
- end
146
+ rv = @backend.do_request('test', { "all" => "ALL" })
153
147
  accepted = thr.value
154
148
  assert_equal "test all=ALL\r\n", accepted.readpartial(666)
155
149
  assert_equal({"foo"=>"bar"}, rv)
@@ -66,7 +66,7 @@ class TestMogileFS__DbBackend < Test::Unit::TestCase
66
66
  end
67
67
 
68
68
  def test_sleep
69
- assert_nothing_raised { assert_equal({}, @mg.sleep(1)) }
69
+ assert_equal({}, @mg.sleep(1))
70
70
  end
71
71
 
72
72
  end
data/test/test_fresh.rb CHANGED
@@ -32,4 +32,119 @@ class TestMogFresh < Test::Unit::TestCase
32
32
  client = MogileFS::MogileFS.new :hosts => @hosts, :domain => @domain
33
33
  assert_equal false, client.exist?("non-existent")
34
34
  end
35
+
36
+ def test_new_file_info(checksum = nil)
37
+ add_host_device_domain unless checksum
38
+ @client = MogileFS::MogileFS.new :hosts => @hosts, :domain => @domain
39
+ info = {}
40
+ opts = { :info => info }
41
+ key = "new_file_info"
42
+ content = "ZZZZ"
43
+ if checksum
44
+ opts[:content_md5] = [ Digest::MD5.digest(content) ].pack('m').rstrip
45
+ opts[:class] = "check"
46
+ end
47
+ @client.new_file(key, opts) do |http_file|
48
+ http_file << content
49
+ end
50
+
51
+ uris = info.delete(:uris)
52
+ assert_kind_of Array, uris
53
+ assert_equal(uris, (@client.get_uris(key) & uris))
54
+ expect_info = @client.file_info(key, :devices => true)
55
+ match_keys = %w(class fid key domain length)
56
+ match_keys << "checksum" if checksum
57
+ match_keys.each do |field|
58
+ assert_equal expect_info.delete(field), info.delete(field)
59
+ end
60
+ assert_operator expect_info.delete("devcount"), :>=, info.delete("devcount")
61
+ devids = info.delete("devids")
62
+ assert_equal(devids, (expect_info.delete("devids") & devids))
63
+
64
+ assert info.empty?, info.inspect
65
+ assert expect_info.empty?, expect_info.inspect
66
+ ensure
67
+ @client.delete(key)
68
+ end
69
+
70
+ def test_new_file_info_checksum
71
+ add_host_device_domain
72
+ opts = @admin.get_domains[@domain]["default"]
73
+ opts["hashtype"] = "MD5"
74
+ @admin.create_class(@domain, "check", opts)
75
+ yield_for_monitor_update do
76
+ tmp = @admin.get_domains[@domain]["check"]
77
+ if tmp
78
+ case tmp["hashtype"]
79
+ when "MD5"
80
+ break
81
+ when nil
82
+ warn "skipping checksum test, MogileFS server too old"
83
+ return
84
+ else
85
+ raise "Unhandled hashtype: #{tmp['hashtype']}"
86
+ end
87
+ end
88
+ end
89
+ test_new_file_info(:md5)
90
+ ensure
91
+ @admin.delete_class @domain, "check"
92
+ end
93
+
94
+ def test_create_open_close_opts
95
+ add_host_device_domain
96
+ client = MogileFS::MogileFS.new :hosts => @hosts, :domain => @domain
97
+ socket = client.backend.socket
98
+ args = {
99
+ :create_open_args => { :hello => "world" },
100
+ :create_close_args => { :farewell => "goodnight" },
101
+ }
102
+ io = client.new_file("foo", args)
103
+ socket.write "!recent\n"
104
+ buf = ""
105
+ buf << socket.readpartial(666) until buf =~ /\.\r?\n\z/
106
+ line = buf.split(/\r?\n/).grep(/\screate_open\s/)[0]
107
+ assert_equal 0, buf.split(/\r?\n/).grep(/\screate_close\s/).size
108
+ assert_equal 0, buf.split(/\r?\n/).grep(/\sfarewell\s/).size
109
+ assert_match(/\bhello=world\b/, line)
110
+ assert_equal 1, io.write('.')
111
+ assert_nil io.close
112
+
113
+ socket.write "!recent\n"
114
+ buf = ""
115
+ buf << socket.readpartial(666) until buf =~ /\.\r?\n\z/
116
+ line = buf.split(/\r?\n/).grep(/\screate_close\s/)[0]
117
+ assert_match(/\bfarewell=goodnight\b/, line)
118
+ end
119
+
120
+ def test_get_file_data_range
121
+ add_host_device_domain
122
+ client = MogileFS::MogileFS.new :hosts => @hosts, :domain => @domain
123
+ data = "data"
124
+ client.store_content("key", "default", data)
125
+
126
+ assert_equal data, client.get_file_data("key")
127
+
128
+ # ensure offset/length matches IO.copy_stream
129
+ src = Tempfile.new("tmp")
130
+ src.write(data)
131
+ src.flush
132
+ [ [1,nil], [1,2], [3,1] ].each do |range|
133
+ dst2 = StringIO.new
134
+ client.get_file_data("key", dst2, *range)
135
+
136
+ src.rewind
137
+
138
+ if IO.respond_to?(:copy_stream)
139
+ # ensure we match IO.copy_stream semantics
140
+ dst = StringIO.new
141
+ IO.copy_stream(src, dst, *range)
142
+ assert_equal dst.string, dst2.string
143
+ assert_equal dst.string, client.get_file_data("key", nil, *range)
144
+ end
145
+
146
+ assert_equal dst2.string, client.get_file_data("key", nil, *range)
147
+ end
148
+ src.close!
149
+ end
35
150
  end
@@ -10,6 +10,14 @@ class TestMogileFS__MogileFS < TestMogileFS
10
10
  super
11
11
  end
12
12
 
13
+ def read_headers(client)
14
+ headers = ""
15
+ while line = client.gets
16
+ headers << line
17
+ return headers if line == "\r\n"
18
+ end
19
+ end
20
+
13
21
  def test_initialize
14
22
  assert_equal 'test', @client.domain
15
23
 
@@ -24,9 +32,10 @@ class TestMogileFS__MogileFS < TestMogileFS
24
32
  svr = Proc.new do |serv, port|
25
33
  client, _ = serv.accept
26
34
  client.sync = true
27
- readed = client.recv(4096, 0)
28
- assert(readed =~ \
29
- %r{\AGET /dev[12]/0/000/000/0000000062\.fid HTTP/1.[01]\r\n\r\n\Z})
35
+ readed = read_headers(client)
36
+ assert_match(
37
+ %r{\AGET /dev[12]/0/000/000/0000000062\.fid HTTP/1.[01]\r\n},
38
+ readed)
30
39
  accept.syswrite('.')
31
40
  client.send("HTTP/1.0 200 OK\r\nContent-Length: 5\r\n\r\ndata!", 0)
32
41
  client.close
@@ -50,9 +59,10 @@ class TestMogileFS__MogileFS < TestMogileFS
50
59
  svr1 = Proc.new do |serv, port|
51
60
  client, _ = serv.accept
52
61
  client.sync = true
53
- readed = client.recv(4096, 0)
54
- assert(readed =~ \
55
- %r{\AGET /dev1/0/000/000/0000000062\.fid HTTP/1.[01]\r\n\r\n\Z})
62
+ readed = read_headers(client)
63
+ assert_match(
64
+ %r{\AGET /dev1/0/000/000/0000000062\.fid HTTP/1.[01]\r\n},
65
+ readed)
56
66
  accept.syswrite('.')
57
67
  client.send("HTTP/1.0 404 Not Found\r\n\r\ndata!", 0)
58
68
  client.close
@@ -61,9 +71,10 @@ class TestMogileFS__MogileFS < TestMogileFS
61
71
  svr2 = Proc.new do |serv, port|
62
72
  client, _ = serv.accept
63
73
  client.sync = true
64
- readed = client.recv(4096, 0)
65
- assert(readed =~ \
66
- %r{\AGET /dev2/0/000/000/0000000062\.fid HTTP/1.[01]\r\n\r\n\Z})
74
+ readed = read_headers(client)
75
+ assert_match(
76
+ %r{\AGET /dev2/0/000/000/0000000062\.fid HTTP/1.[01].*\r\n},
77
+ readed)
67
78
  accept.syswrite('.')
68
79
  client.send("HTTP/1.0 200 OK\r\nContent-Length: 5\r\n\r\ndata!", 0)
69
80
  client.close
@@ -98,9 +109,10 @@ class TestMogileFS__MogileFS < TestMogileFS
98
109
  client, _ = serv.accept
99
110
  client.sync = true
100
111
  accept.syswrite('.')
101
- readed = client.recv(4096, 0)
102
- assert(readed =~ \
103
- %r{\AGET /dev[12]/0/000/000/0000000062\.fid HTTP/1.[01]\r\n\r\n\Z})
112
+ readed = read_headers(client)
113
+ assert_match(
114
+ %r{\AGET /dev[12]/0/000/000/0000000062\.fid HTTP/1.[01]\r\n},
115
+ readed)
104
116
  MogileFS.io.copy_stream(tmpfp, client)
105
117
  client.close
106
118
  exit 0
@@ -166,9 +178,7 @@ class TestMogileFS__MogileFS < TestMogileFS
166
178
 
167
179
  def test_delete_existing
168
180
  @backend.delete = { }
169
- assert_nothing_raised do
170
- @client.delete 'no_such_key'
171
- end
181
+ @client.delete 'no_such_key'
172
182
  end
173
183
 
174
184
  def test_delete_nonexisting
@@ -227,11 +237,12 @@ class TestMogileFS__MogileFS < TestMogileFS
227
237
  to_store = Tempfile.new('small')
228
238
  to_store.syswrite('data')
229
239
 
230
- expected = "PUT /path HTTP/1.0\r\nContent-Length: 4\r\n\r\ndata"
231
240
  t = TempServer.new(Proc.new do |serv, accept|
232
241
  client, _ = serv.accept
233
- client.sync = true
234
- received.syswrite(client.read(expected.bytesize))
242
+ while buf = client.readpartial(666)
243
+ received.syswrite(buf)
244
+ break if buf =~ /data/
245
+ end
235
246
  client.send("HTTP/1.0 200 OK\r\n\r\n", 0)
236
247
  client.close
237
248
  end)
@@ -243,14 +254,18 @@ class TestMogileFS__MogileFS < TestMogileFS
243
254
  nr = @client.store_file 'new_key', 'test', to_store.path
244
255
  assert_equal 4, nr
245
256
  received.sysseek(0)
246
- assert_equal expected, received.sysread(4096)
257
+
258
+ a = received.sysread(999999).split(/\r\n/)
259
+ assert_match(%r{\APUT /path HTTP/1\.[01]\z}, a[0])
260
+ assert_equal("data", a[-1])
261
+ assert_equal("", a[-2])
262
+ assert a.grep(%r{\AContent-Length: 4\z})[0]
247
263
  ensure
248
264
  TempServer.destroy_all!
249
265
  end
250
266
 
251
267
  def test_store_content_http
252
268
  received = Tempfile.new('received')
253
- expected = "PUT /path HTTP/1.0\r\nContent-Length: 4\r\n\r\ndata"
254
269
 
255
270
  t = TempServer.new(Proc.new do |serv, accept|
256
271
  client, _ = serv.accept
@@ -275,7 +290,11 @@ class TestMogileFS__MogileFS < TestMogileFS
275
290
  assert_equal 4, nr
276
291
 
277
292
  received.sysseek(0)
278
- assert_equal expected, received.sysread(4096)
293
+ a = received.sysread(999999).split(/\r\n/)
294
+ assert_match(%r{\APUT /path HTTP/1\.[01]\z}, a[0])
295
+ assert_equal("data", a[-1])
296
+ assert_equal("", a[-2])
297
+ assert a.grep(%r{\AContent-Length: 4\z})[0]
279
298
  ensure
280
299
  TempServer.destroy_all!
281
300
  end
@@ -291,12 +310,14 @@ class TestMogileFS__MogileFS < TestMogileFS
291
310
  client, _ = serv.accept
292
311
  client.sync = true
293
312
  nr = 0
313
+ seen = ''
294
314
  loop do
295
315
  buf = client.readpartial(8192) or break
296
316
  break if buf.length == 0
297
317
  assert_equal buf.length, received.syswrite(buf)
298
318
  nr += buf.length
299
- break if nr >= expected.size
319
+ seen << buf
320
+ break if seen =~ /\r\n\r\n(?:data){10}/
300
321
  end
301
322
  client.send("HTTP/1.0 200 OK\r\n\r\n", 0)
302
323
  client.close
@@ -317,7 +338,11 @@ class TestMogileFS__MogileFS < TestMogileFS
317
338
  assert_equal 40, nr
318
339
 
319
340
  received.sysseek(0)
320
- assert_equal expected, received.sysread(4096)
341
+ a = received.sysread(999999).split(/\r\n/)
342
+ assert_match(%r{\APUT /path HTTP/1\.[01]\z}, a[0])
343
+ assert_equal("data" * 10, a[-1])
344
+ assert_equal("", a[-2])
345
+ assert a.grep(%r{\AContent-Length: 40\z})[0]
321
346
  ensure
322
347
  TempServer.destroy_all!
323
348
  end
@@ -329,7 +354,6 @@ class TestMogileFS__MogileFS < TestMogileFS
329
354
  def test_store_content_multi_dest_failover(big_io = false)
330
355
  received1 = Tempfile.new('received')
331
356
  received2 = Tempfile.new('received')
332
- expected = "PUT /path HTTP/1.0\r\nContent-Length: 4\r\n\r\ndata"
333
357
 
334
358
  t1 = TempServer.new(Proc.new do |serv, accept|
335
359
  client, _ = serv.accept
@@ -375,8 +399,17 @@ class TestMogileFS__MogileFS < TestMogileFS
375
399
  assert_equal 4, nr
376
400
  received1.sysseek(0)
377
401
  received2.sysseek(0)
378
- assert_equal expected, received1.sysread(4096)
379
- assert_equal expected, received2.sysread(4096)
402
+ a = received1.sysread(4096).split(/\r\n/)
403
+ b = received2.sysread(4096).split(/\r\n/)
404
+ assert_equal a[0], b[0]
405
+ assert_match(%r{\APUT /path HTTP/1\.[01]\z}, a[0])
406
+ assert_match(%r{\APUT /path HTTP/1\.[01]\z}, b[0])
407
+ assert_equal("data", a[-1])
408
+ assert_equal("data", b[-1])
409
+ assert_equal("", a[-2])
410
+ assert_equal("", b[-2])
411
+ assert a.grep(%r{\AContent-Length: 4\z})[0]
412
+ assert b.grep(%r{\AContent-Length: 4\z})[0]
380
413
  ensure
381
414
  TempServer.destroy_all!
382
415
  end
@@ -385,7 +418,7 @@ class TestMogileFS__MogileFS < TestMogileFS
385
418
  t = TempServer.new(Proc.new do |serv, accept|
386
419
  client, _ = serv.accept
387
420
  client.sync = true
388
- client.recv(4096, 0)
421
+ read_headers(client)
389
422
  client.send("HTTP/1.0 500 Internal Server Error\r\n\r\n", 0)
390
423
  client.close
391
424
  end)
@@ -402,7 +435,6 @@ class TestMogileFS__MogileFS < TestMogileFS
402
435
 
403
436
  def test_store_content_http_empty
404
437
  received = Tempfile.new('received')
405
- expected = "PUT /path HTTP/1.0\r\nContent-Length: 0\r\n\r\n"
406
438
  t = TempServer.new(Proc.new do |serv, accept|
407
439
  client, _ = serv.accept
408
440
  client.sync = true
@@ -419,7 +451,9 @@ class TestMogileFS__MogileFS < TestMogileFS
419
451
  nr = @client.store_content 'new_key', 'test', ''
420
452
  assert_equal 0, nr
421
453
  received.sysseek(0)
422
- assert_equal expected, received.sysread(4096)
454
+ a = received.sysread(4096).split(/\r\n/)
455
+ assert_match(%r{\APUT /path HTTP/1\.[01]\z}, a[0])
456
+ assert a.grep(%r{\AContent-Length: 0\z})[0]
423
457
  end
424
458
 
425
459
  def test_store_content_nfs
@@ -613,7 +647,6 @@ class TestMogileFS__MogileFS < TestMogileFS
613
647
  timeout = 1
614
648
  args = { :hosts => hosts, :domain => "foo", :timeout => timeout }
615
649
  c = MogileFS::MogileFS.new(args)
616
- received = []
617
650
  secs = timeout + 1
618
651
  th = Thread.new do
619
652
  close_later = []
@@ -832,9 +865,7 @@ class TestMogileFS__MogileFS < TestMogileFS
832
865
 
833
866
  def test_sleep
834
867
  @backend.sleep = {}
835
- assert_nothing_raised do
836
- assert_equal({}, @client.sleep(2))
837
- end
868
+ assert_equal({}, @client.sleep(2))
838
869
  end
839
870
 
840
871
  private
@@ -47,10 +47,8 @@ class TestMogileFSIntegration < TestMogIntegration
47
47
  w.close
48
48
  end
49
49
  assert_equal data.size, @client.store_file("pipe", nil, r)
50
- assert_nothing_raised do
51
- r.close
52
- th.join
53
- end
50
+ r.close
51
+ th.join
54
52
  assert_equal(data, @client.get_file_data("pipe"))
55
53
 
56
54
  cbk = MogileFS::Util::StoreContent.new(nil) do |write_callback|
@@ -177,19 +175,19 @@ class TestMogileFSIntegration < TestMogIntegration
177
175
 
178
176
  def test_new_file_no_block
179
177
  rv = @client.new_file("no_block")
180
- assert_nothing_raised { rv.write "HELLO" }
178
+ rv.write "HELLO"
181
179
  assert_nil rv.close
182
180
  assert_equal "HELLO", @client.get_file_data("no_block")
183
181
  end
184
182
 
185
183
  def test_new_file_known_content_length
186
184
  rv = @client.new_file("a", :content_length => 5)
187
- assert_nothing_raised { rv.write "HELLO" }
185
+ rv.write "HELLO"
188
186
  assert_nil rv.close
189
187
  assert_equal "HELLO", @client.get_file_data("a")
190
188
 
191
189
  rv = @client.new_file("a", :content_length => 6)
192
- assert_nothing_raised { rv.write "GOOD" }
190
+ rv.write "GOOD"
193
191
  assert_raises(MogileFS::SizeMismatchError) { rv.close }
194
192
  assert_equal "HELLO", @client.get_file_data("a")
195
193
 
@@ -204,19 +202,18 @@ class TestMogileFSIntegration < TestMogIntegration
204
202
  r, w = IO.pipe
205
203
  b64digest = [ Digest::MD5.digest("HELLO") ].pack('m').strip
206
204
  rv = @client.new_file("a", :content_md5 => b64digest, :content_length => 5)
207
- assert_nothing_raised { rv.write "HELLO" }
205
+ rv.write "HELLO"
208
206
  assert_nil rv.close
209
207
  assert_equal "HELLO", @client.get_file_data("a")
210
208
 
211
- assert_nothing_raised { w.write "HIHI"; w.close }
209
+ w.write "HIHI"
210
+ w.close
212
211
  assert_raises(ArgumentError) do
213
212
  @client.new_file("a", :content_md5 => b64digest) { |f| f.big_io = r }
214
213
  end
215
214
  assert_equal "HELLO", @client.get_file_data("a")
216
215
 
217
- assert_nothing_raised do
218
- @client.new_file("a", :content_md5 => :trailer) { |f| f.big_io = r }
219
- end
216
+ @client.new_file("a", :content_md5 => :trailer) { |f| f.big_io = r }
220
217
  assert_equal "HIHI", @client.get_file_data("a")
221
218
 
222
219
  # legacy, in case anybody used it
@@ -241,9 +238,7 @@ class TestMogileFSIntegration < TestMogIntegration
241
238
 
242
239
  def test_store_content_opts
243
240
  b64digest = [ Digest::MD5.digest("HELLO") ].pack('m').strip
244
- assert_nothing_raised do
245
- @client.store_content("c", nil, "HELLO", :content_md5 => b64digest)
246
- end
241
+ @client.store_content("c", nil, "HELLO", :content_md5 => b64digest)
247
242
  assert_raises(MogileFS::SizeMismatchError) do
248
243
  @client.store_content("c", nil, "GOODBYE", :content_length => 2)
249
244
  end
@@ -253,9 +248,7 @@ class TestMogileFSIntegration < TestMogIntegration
253
248
  def test_store_file_opts
254
249
  b64digest = [ Digest::MD5.digest("HELLO") ].pack('m').strip
255
250
  io = StringIO.new("HELLO")
256
- assert_nothing_raised do
257
- @client.store_file("c", nil, io, :content_md5 => b64digest)
258
- end
251
+ @client.store_file("c", nil, io, :content_md5 => b64digest)
259
252
 
260
253
  io = StringIO.new("GOODBYE")
261
254
  assert_raises(MogileFS::SizeMismatchError) do
@@ -271,9 +264,7 @@ class TestMogileFSIntegration < TestMogIntegration
271
264
  [ Digest::MD5.digest("HELLO") ].pack('m').strip
272
265
  end
273
266
  io = StringIO.new("HELLO")
274
- assert_nothing_raised do
275
- @client.store_file("c", nil, io, :content_md5 => expect_md5)
276
- end
267
+ @client.store_file("c", nil, io, :content_md5 => expect_md5)
277
268
 
278
269
  assert_equal true, checked, "expect_md5 lambda called"
279
270
  end
@@ -284,9 +275,7 @@ class TestMogileFSIntegration < TestMogIntegration
284
275
  tmp.sync = true
285
276
  tmp.write "HIHI"
286
277
  tmp.rewind
287
- assert_nothing_raised do
288
- @client.store_file("unlinked", nil, tmp)
289
- end
278
+ @client.store_file("unlinked", nil, tmp)
290
279
 
291
280
  assert_equal "HIHI", @client.get_file_data("unlinked")
292
281
  end
@@ -51,7 +51,7 @@ class TestMogtoolBigfile < TestMogIntegration
51
51
 
52
52
  # corrupt the existing data in part1
53
53
  @client.store_content(part1, nil, "HELLO")
54
- assert_nothing_raised { @client.get_uris(part1) }
54
+ @client.get_uris(part1)
55
55
 
56
56
  # corruption is detected on verify
57
57
  junk = tmpfile("junk")
@@ -61,9 +61,7 @@ class TestMogtoolBigfile < TestMogIntegration
61
61
 
62
62
  # corruption is NOT detected on verify
63
63
  junk = tmpfile("junk")
64
- assert_nothing_raised do
65
- @client.bigfile_write("_big_info:#@big_uuid", junk, :verify => false)
66
- end
64
+ @client.bigfile_write("_big_info:#@big_uuid", junk, :verify => false)
67
65
 
68
66
  # restoring no-corrupted data succeeds!
69
67
  @client.store_file(part1, nil, tmp.path)
data/test/test_mysql.rb CHANGED
@@ -120,7 +120,7 @@ class TestMogileFS__Mysql < Test::Unit::TestCase
120
120
  end
121
121
 
122
122
  def test_sleep
123
- assert_nothing_raised { assert_equal({}, @mg.sleep(:duration => 1)) }
123
+ assert_equal({}, @mg.sleep(:duration => 1))
124
124
  end
125
125
 
126
126
  end
metadata CHANGED
@@ -1,66 +1,59 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: mogilefs-client
3
- version: !ruby/object:Gem::Version
4
- hash: 23
5
- prerelease:
6
- segments:
7
- - 3
8
- - 4
9
- - 0
10
- version: 3.4.0
3
+ version: !ruby/object:Gem::Version
4
+ version: 3.5.0.rc1
5
+ prerelease: 6
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Eric Wong
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2012-10-09 00:00:00 Z
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
12
+ date: 2012-10-31 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
21
15
  name: rdoc
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
24
17
  none: false
25
- requirements:
18
+ requirements:
26
19
  - - ~>
27
- - !ruby/object:Gem::Version
28
- hash: 19
29
- segments:
30
- - 3
31
- - 10
32
- version: "3.10"
20
+ - !ruby/object:Gem::Version
21
+ version: '3.10'
33
22
  type: :development
34
- version_requirements: *id001
35
- - !ruby/object:Gem::Dependency
36
- name: hoe
37
23
  prerelease: false
38
- requirement: &id002 !ruby/object:Gem::Requirement
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '3.10'
30
+ - !ruby/object:Gem::Dependency
31
+ name: hoe
32
+ requirement: !ruby/object:Gem::Requirement
39
33
  none: false
40
- requirements:
34
+ requirements:
41
35
  - - ~>
42
- - !ruby/object:Gem::Version
43
- hash: 7
44
- segments:
45
- - 3
46
- - 0
47
- version: "3.0"
36
+ - !ruby/object:Gem::Version
37
+ version: '3.0'
48
38
  type: :development
49
- version_requirements: *id002
50
- description: |-
51
- A MogileFS client library for Ruby. MogileFS is an open source
52
- distributed filesystem, see: http://mogilefs.org for more details. This
53
- library allows any Ruby application to read, write and delete files in a
54
- MogileFS instance.
55
- email:
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '3.0'
46
+ description: ! '["A MogileFS client library for Ruby. MogileFS is an open source\ndistributed
47
+ filesystem, see: http://mogilefs.org for more details. This\nlibrary allows any
48
+ Ruby application to read, write and delete files in a\nMogileFS instance."]'
49
+ email:
56
50
  - normalperson@yhbt.net
57
- executables:
51
+ executables:
58
52
  - mog
59
53
  extensions: []
60
-
61
- extra_rdoc_files:
54
+ extra_rdoc_files:
62
55
  - Manifest.txt
63
- files:
56
+ files:
64
57
  - .document
65
58
  - .gitignore
66
59
  - .wrongdoc.yml
@@ -92,6 +85,7 @@ files:
92
85
  - lib/mogilefs/new_file/stream.rb
93
86
  - lib/mogilefs/new_file/tempfile.rb
94
87
  - lib/mogilefs/new_file/writer.rb
88
+ - lib/mogilefs/nhp_fake.rb
95
89
  - lib/mogilefs/paths_size.rb
96
90
  - lib/mogilefs/pool.rb
97
91
  - lib/mogilefs/socket.rb
@@ -131,53 +125,45 @@ files:
131
125
  - .gemtest
132
126
  homepage: http://bogomips.org/mogilefs-client/
133
127
  licenses: []
134
-
135
128
  post_install_message:
136
- rdoc_options:
129
+ rdoc_options:
137
130
  - --main
138
131
  - README
139
- require_paths:
132
+ require_paths:
140
133
  - lib
141
- required_ruby_version: !ruby/object:Gem::Requirement
134
+ required_ruby_version: !ruby/object:Gem::Requirement
142
135
  none: false
143
- requirements:
144
- - - ">="
145
- - !ruby/object:Gem::Version
146
- hash: 3
147
- segments:
148
- - 0
149
- version: "0"
150
- required_rubygems_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ! '>='
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ required_rubygems_version: !ruby/object:Gem::Requirement
151
141
  none: false
152
- requirements:
153
- - - ">="
154
- - !ruby/object:Gem::Version
155
- hash: 3
156
- segments:
157
- - 0
158
- version: "0"
142
+ requirements:
143
+ - - ! '>'
144
+ - !ruby/object:Gem::Version
145
+ version: 1.3.1
159
146
  requirements: []
160
-
161
147
  rubyforge_project: seattlerb
162
148
  rubygems_version: 1.8.24
163
149
  signing_key:
164
150
  specification_version: 3
165
151
  summary: MogileFS client library for Ruby
166
- test_files:
167
- - test/test_http_reader.rb
168
- - test/test_mogilefs_integration_list_keys.rb
152
+ test_files:
153
+ - test/test_bigfile.rb
154
+ - test/test_admin.rb
155
+ - test/test_pool.rb
169
156
  - test/test_db_backend.rb
170
- - test/test_mogilefs_socket_pure.rb
171
- - test/test_mysql.rb
172
- - test/test_backend.rb
173
- - test/test_mogilefs.rb
157
+ - test/test_mogilefs_integration_list_keys.rb
158
+ - test/test_http_reader.rb
174
159
  - test/test_mogtool_bigfile.rb
160
+ - test/test_backend.rb
175
161
  - test/test_client.rb
176
- - test/test_admin.rb
177
- - test/test_mogilefs_socket_kgio.rb
178
162
  - test/test_mogilefs_integration.rb
163
+ - test/test_mogilefs_socket_pure.rb
164
+ - test/test_mogilefs_socket_kgio.rb
179
165
  - test/test_fresh.rb
180
- - test/test_pool.rb
181
- - test/test_bigfile.rb
182
- - test/test_mogilefs_integration_large_pipe.rb
183
166
  - test/test_mogstored_rack.rb
167
+ - test/test_mogilefs.rb
168
+ - test/test_mogilefs_integration_large_pipe.rb
169
+ - test/test_mysql.rb