mirror of
https://github.com/fog/fog.git
synced 2022-11-09 13:51:43 -05:00
Refactoring: #each_part in MockObject.
@bytes => @bytes_used in MockObject as well, for consistency with MockContainer.
This commit is contained in:
parent
4e309df4e2
commit
6642ae013d
7 changed files with 84 additions and 87 deletions
|
@ -55,7 +55,7 @@ module Fog
|
|||
return not_found(object) unless o
|
||||
|
||||
# What happens if o isn't a static large object?
|
||||
raise Fog::Storage::Rackspace::BadRequest.new unless o.static_manifest
|
||||
raise Fog::Storage::Rackspace::BadRequest.new unless o.static_manifest?
|
||||
|
||||
segments = Fog::JSON.decode(o.body)
|
||||
paths = segments.map { |s| s['path'] }
|
||||
|
|
|
@ -54,7 +54,7 @@ module Fog
|
|||
results << {
|
||||
"hash" => mock_file.hash,
|
||||
"last_modified" => mock_file.last_modified.strftime('%Y-%m-%dT%H:%M:%S.%L'),
|
||||
"bytes" => mock_file.bytes,
|
||||
"bytes" => mock_file.bytes_used,
|
||||
"name" => key,
|
||||
"content_type" => mock_file.content_type
|
||||
}
|
||||
|
|
|
@ -36,38 +36,9 @@ module Fog
|
|||
|
||||
body, size = "", 0
|
||||
|
||||
# Recognize an X-Object-Manifest header.
|
||||
prefix = o.large_object_prefix
|
||||
if prefix
|
||||
# Concatenate the contents and sizes of each matching object.
|
||||
# Note that cname and oprefix are already escaped.
|
||||
cname, oprefix = prefix.split('/', 2)
|
||||
|
||||
target_container = data[cname]
|
||||
if target_container
|
||||
target_container.objects.each do |name, obj|
|
||||
next unless name.start_with? oprefix
|
||||
body << obj.body
|
||||
size += obj.bytes
|
||||
end
|
||||
end
|
||||
elsif o.static_manifest
|
||||
segments = Fog::JSON.decode(o.body)
|
||||
segments.each do |segment|
|
||||
cname, oname = segment['path'].split('/', 2)
|
||||
|
||||
target_container = mock_container cname
|
||||
next unless target_container
|
||||
|
||||
target_object = target_container.mock_object oname
|
||||
next unless target_object
|
||||
|
||||
body << target_object.body
|
||||
size += target_object.bytes
|
||||
end
|
||||
else
|
||||
body = o.body
|
||||
size = o.bytes
|
||||
o.each_part do |part|
|
||||
body << part.body
|
||||
size += part.bytes_used
|
||||
end
|
||||
|
||||
if block_given?
|
||||
|
@ -75,9 +46,9 @@ module Fog
|
|||
block.call(body, 0, size)
|
||||
end
|
||||
|
||||
# TODO set headers
|
||||
response = Excon::Response.new
|
||||
response.body = body
|
||||
response.headers = o.to_headers
|
||||
response
|
||||
end
|
||||
end
|
||||
|
|
|
@ -30,41 +30,16 @@ module Fog
|
|||
|
||||
headers = o.to_headers
|
||||
|
||||
prefix = o.large_object_prefix
|
||||
if prefix
|
||||
# Concatenate the contents and sizes of each matching object.
|
||||
# Note that cname and oprefix are already escaped.
|
||||
cname, oprefix = prefix.split('/', 2)
|
||||
|
||||
target_container = data[cname]
|
||||
if target_container
|
||||
ohash = target_container.objects
|
||||
matching = ohash.keys.select { |k| k.start_with? oprefix }
|
||||
hashes = matching.sort.map { |k| ohash[k].hash }
|
||||
|
||||
headers['Etag'] = "\"#{Digest::MD5.hexdigest(hashes.join)}\""
|
||||
end
|
||||
elsif o.static_manifest
|
||||
hashes, length = [], 0
|
||||
segments = Fog::JSON.decode(o.body)
|
||||
segments.each do |segment|
|
||||
cname, oname = segment['path'].split('/', 2)
|
||||
|
||||
target_container = mock_container cname
|
||||
next unless target_container
|
||||
|
||||
target_object = target_container.mock_object oname
|
||||
next unless target_object
|
||||
|
||||
hashes << target_object.hash
|
||||
length += target_object.bytes
|
||||
end
|
||||
|
||||
headers['Etag'] = "\"#{Digest::MD5.hexdigest(hashes.join)}\""
|
||||
headers['Content-Length'] = length.to_s
|
||||
headers['X-Static-Large-Object'] = "True"
|
||||
hashes, length = [], 0
|
||||
o.each_part do |part|
|
||||
hashes << part.hash
|
||||
length += part.bytes_used
|
||||
end
|
||||
|
||||
headers['Etag'] = "\"#{Digest::MD5.hexdigest(hashes.join)}\""
|
||||
headers['Content-Length'] = length.to_s
|
||||
headers['X-Static-Large-Object'] = "True" if o.static_manifest?
|
||||
|
||||
response = Excon::Response.new
|
||||
response.status = 200
|
||||
response.headers = headers
|
||||
|
|
|
@ -25,20 +25,14 @@ module Fog
|
|||
|
||||
class Mock
|
||||
def put_container(name, options={})
|
||||
escaped = Fog::Rackspace.escape(name)
|
||||
|
||||
container = MockContainer.new
|
||||
existed = ! mock_container(name).nil?
|
||||
container = add_container(name)
|
||||
options.keys.each do |k|
|
||||
container.meta[k] = options[k].to_s if k =~ /^X-Container-Meta/
|
||||
end
|
||||
data[escaped] = container
|
||||
|
||||
response = Excon::Response.new
|
||||
if data.has_key?(escaped)
|
||||
response.status = 202 # Accepted
|
||||
else
|
||||
response.status = 201 # Created
|
||||
end
|
||||
response.status = existed ? 202 : 201
|
||||
response
|
||||
end
|
||||
end
|
||||
|
|
|
@ -77,7 +77,7 @@ module Fog
|
|||
errors << [segment[:path], 'Etag Mismatch']
|
||||
end
|
||||
|
||||
unless target_object.bytes == segment[:size_bytes]
|
||||
unless target_object.bytes_used == segment[:size_bytes]
|
||||
errors << [segment[:path], 'Size Mismatch']
|
||||
end
|
||||
end
|
||||
|
|
|
@ -121,9 +121,10 @@ module Fog
|
|||
include Common
|
||||
|
||||
class MockContainer
|
||||
attr_reader :objects, :meta
|
||||
attr_reader :objects, :meta, :service
|
||||
|
||||
def initialize
|
||||
def initialize service
|
||||
@service = service
|
||||
@objects, @meta = {}, {}
|
||||
end
|
||||
|
||||
|
@ -132,7 +133,7 @@ module Fog
|
|||
end
|
||||
|
||||
def bytes_used
|
||||
@objects.values.map { |o| o.bytes }.inject(0) { |a, b| a + b }
|
||||
@objects.values.map { |o| o.bytes_used }.inject(0) { |a, b| a + b }
|
||||
end
|
||||
|
||||
def to_headers
|
||||
|
@ -151,7 +152,7 @@ module Fog
|
|||
end
|
||||
|
||||
def add_object name, data
|
||||
@objects[Fog::Rackspace.escape(name)] = MockObject.new(data)
|
||||
@objects[Fog::Rackspace.escape(name)] = MockObject.new(data, service)
|
||||
end
|
||||
|
||||
def remove_object name
|
||||
|
@ -160,14 +161,15 @@ module Fog
|
|||
end
|
||||
|
||||
class MockObject
|
||||
attr_reader :hash, :bytes, :content_type, :last_modified
|
||||
attr_reader :body, :meta
|
||||
attr_reader :hash, :bytes_used, :content_type, :last_modified
|
||||
attr_reader :body, :meta, :service
|
||||
attr_accessor :static_manifest
|
||||
|
||||
def initialize data
|
||||
def initialize data, service
|
||||
data = Fog::Storage.parse_data(data)
|
||||
@service = service
|
||||
|
||||
@bytes = data[:headers]['Content-Length']
|
||||
@bytes_used = data[:headers]['Content-Length']
|
||||
@content_type = data[:headers]['Content-Type']
|
||||
if data[:body].respond_to? :read
|
||||
@body = data[:body].read
|
||||
|
@ -180,6 +182,57 @@ module Fog
|
|||
@static_manifest = false
|
||||
end
|
||||
|
||||
def static_manifest?
|
||||
@static_manifest
|
||||
end
|
||||
|
||||
def dynamic_manifest?
|
||||
! large_object_prefix.nil?
|
||||
end
|
||||
|
||||
def each_part
|
||||
case
|
||||
when dynamic_manifest?
|
||||
# Concatenate the contents and sizes of each matching object.
|
||||
# Note that cname and oprefix are already escaped.
|
||||
cname, oprefix = large_object_prefix.split('/', 2)
|
||||
|
||||
target_container = service.data[cname]
|
||||
if target_container
|
||||
keys = target_container.objects.keys.
|
||||
select { |name| name.start_with? oprefix }.
|
||||
sort
|
||||
|
||||
keys.each do |name|
|
||||
yield target_container.objects[name]
|
||||
end
|
||||
else
|
||||
Fog::Logger.warning "Invalid container in dynamic object manifest: #{cname}"
|
||||
yield self
|
||||
end
|
||||
when static_manifest?
|
||||
Fog::JSON.decode(body).each do |segment|
|
||||
cname, oname = segment['path'].split('/', 2)
|
||||
|
||||
cont = service.mock_container cname
|
||||
unless cont
|
||||
Fog::Logger.warning "Invalid container in static object manifest: #{cname}"
|
||||
next
|
||||
end
|
||||
|
||||
obj = cont.mock_object oname
|
||||
unless obj
|
||||
Fog::Logger.warning "Invalid object in static object manifest: #{oname}"
|
||||
next
|
||||
end
|
||||
|
||||
yield obj
|
||||
end
|
||||
else
|
||||
yield self
|
||||
end
|
||||
end
|
||||
|
||||
def large_object_prefix
|
||||
@meta['X-Object-Manifest']
|
||||
end
|
||||
|
@ -187,7 +240,7 @@ module Fog
|
|||
def to_headers
|
||||
{
|
||||
'Content-Type' => @content_type,
|
||||
'Content-Length' => @bytes,
|
||||
'Content-Length' => @bytes_used,
|
||||
'Last-Modified' => @last_modified.strftime('%a, %b %d %Y %H:%M:%S %Z'),
|
||||
'ETag' => @hash
|
||||
}.merge(@meta)
|
||||
|
@ -239,6 +292,10 @@ module Fog
|
|||
mock_container(cname) or raise Fog::Storage::Rackspace::NotFound.new
|
||||
end
|
||||
|
||||
def add_container cname
|
||||
data[Fog::Rackspace.escape(cname)] = MockContainer.new(self)
|
||||
end
|
||||
|
||||
def remove_container cname
|
||||
data.delete Fog::Rackspace.escape(cname)
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue