1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
module Fog
module AzureRM
class Storage
# 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?
block.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
block.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
block.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)
block.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
|