mogilefs-client 3.4.0 → 3.5.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/GIT-VERSION-GEN CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/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