lib/fog/azurerm/requests/storage/get_blob.rb
module Fog
module Storage
class AzureRM
# This class provides the actual implemention for service calls.
class Real
BLOCK_SIZE = 32 * 1024 * 1024 # 32 MB
def get_blob_with_block_given(container_name, blob_name, options, &_block)
options[:request_id] = SecureRandom.uuid
msg = "get_blob_with_block_given: blob #{blob_name} in the container #{container_name}. options: #{options}"
Fog::Logger.debug msg
begin
blob = @blob_client.get_blob_properties(container_name, blob_name, options)
rescue Azure::Core::Http::HTTPError => ex
raise 'NotFound' if ex.message.include?('(404)')
raise_azure_exception(ex, msg)
end
content_length = blob.properties[:content_length]
if content_length.zero?
Proc.new.call('', 0, 0)
return [blob, '']
end
start_range = 0
end_range = content_length - 1
start_range = options[:start_range] if options[:start_range]
end_range = options[:end_range] if options[:end_range]
raise ArgumentError.new(':end_range MUST be greater than :start_range') if start_range > end_range
if start_range == end_range
Proc.new.call('', 0, 0)
return [blob, '']
end
buffer_size = BLOCK_SIZE
buffer_size = options[:block_size] if options[:block_size]
buffer_start_range = start_range
total_bytes = end_range - start_range + 1
params = options.dup
while buffer_start_range < end_range
buffer_end_range = [end_range, buffer_start_range + buffer_size - 1].min
params[:start_range] = buffer_start_range
params[:end_range] = buffer_end_range
params[:request_id] = SecureRandom.uuid
begin
msg = "get_blob_with_block_given: blob #{blob_name} in the container #{container_name}. options: #{params}"
Fog::Logger.debug msg
_, content = @blob_client.get_blob(container_name, blob_name, params)
rescue Azure::Core::Http::HTTPError => ex
raise 'NotFound' if ex.message.include?('(404)')
raise_azure_exception(ex, msg)
end
Proc.new.call(content, end_range - buffer_end_range, total_bytes)
buffer_start_range += buffer_size
end
# No need to return content when block is given.
[blob, '']
end
def get_blob(container_name, blob_name, options = {}, &block)
if block_given?
get_blob_with_block_given(container_name, blob_name, options, &block)
else
options[:request_id] = SecureRandom.uuid
msg = "get_blob blob #{blob_name} in the container #{container_name}. options: #{options}"
Fog::Logger.debug msg
begin
blob, content = @blob_client.get_blob(container_name, blob_name, options)
Fog::Logger.debug "Get blob #{blob_name} successfully."
[blob, content]
rescue Azure::Core::Http::HTTPError => ex
raise 'NotFound' if ex.message.include?('(404)')
raise_azure_exception(ex, msg)
end
end
end
end
# This class provides the mock implementation for unit tests.
class Mock
def get_blob(_container_name, _blob_name, _options = {}, &_block)
Fog::Logger.debug 'get_blob successfully.'
unless block_given?
return [
{
'name' => 'test_blob',
'metadata' => {},
'properties' => {
'last_modified' => 'Mon, 04 Jul 2016 09:30:31 GMT',
'etag' => '0x8D3A3EDD7C2B777',
'lease_status' => 'unlocked',
'lease_state' => 'available',
'lease_duration' => nil,
'content_length' => 4_194_304,
'content_type' => 'application/octet-stream',
'content_encoding' => nil,
'content_language' => nil,
'content_disposition' => nil,
'content_md5' => 'tXAohIyxuu/t94Lp/ujeRw==',
'cache_control' => nil,
'sequence_number' => 0,
'blob_type' => 'PageBlob',
'copy_id' => '095adc3b-e277-4c3d-97e0-0abca881f60c',
'copy_status' => 'success',
'copy_source' => 'https://testaccount.blob.core.windows.net/testblob/4m?snapshot=2016-02-04T08%3A35%3A50.3157696Z',
'copy_progress' => '4194304/4194304',
'copy_completion_time' => 'Thu, 04 Feb 2016 08:35:52 GMT',
'copy_status_description' => nil,
'accept_ranges' => 0
}
},
'content'
]
end
data = StringIO.new('content')
remaining = total_bytes = data.length
while remaining > 0
chunk = data.read([remaining, 2].min)
Proc.new.call(chunk, remaining, total_bytes)
remaining -= 2
end
[
{
'name' => 'test_blob',
'metadata' => {},
'properties' => {
'last_modified' => 'Mon, 04 Jul 2016 09:30:31 GMT',
'etag' => '0x8D3A3EDD7C2B777',
'lease_status' => 'unlocked',
'lease_state' => 'available',
'lease_duration' => nil,
'content_length' => 4_194_304,
'content_type' => 'application/octet-stream',
'content_encoding' => nil,
'content_language' => nil,
'content_disposition' => nil,
'content_md5' => 'tXAohIyxuu/t94Lp/ujeRw==',
'cache_control' => nil,
'sequence_number' => 0,
'blob_type' => 'PageBlob',
'copy_id' => '095adc3b-e277-4c3d-97e0-0abca881f60c',
'copy_status' => 'success',
'copy_source' => 'https://testaccount.blob.core.windows.net/testblob/4m?snapshot=2016-02-04T08%3A35%3A50.3157696Z',
'copy_progress' => '4194304/4194304',
'copy_completion_time' => 'Thu, 04 Feb 2016 08:35:52 GMT',
'copy_status_description' => nil,
'accept_ranges' => 0
}
},
''
]
end
end
end
end
end