class Fog::AWS::Glacier::TreeHash
Public Class Methods
digest(body)
click to toggle source
# File lib/fog/aws/glacier.rb, line 38 def self.digest(body) new.add_part(body) end
new()
click to toggle source
# File lib/fog/aws/glacier.rb, line 42 def initialize @last_chunk_digest = nil # Digest OBJECT for last chunk (Digest::SHA256) @last_chunk_digest_temp = nil # Digest VALUE for last chunk @last_chunk_length = 0 # Length of last chunk, always smaller than 1MB. @digest_stack = [] # First position on stack corresponds to 1MB, second 2MB, third 4MB, fourt 8MB and so on. # In any time, the size of all already added parts is equal to sum of all existing (non-nil) # positions multiplied by that number, plus last_chunk_length for the remainder smaller than # one megabyte. So, if last_chunk_length is half megabyte, stack[0] is filled, stack[1] and # stack[2] empty and stack[3] filled, the size is 0.5MB + 1x1MB + 0x2MB + 0x4MB + 1x8MB = 9.5MB. end
Public Instance Methods
add_part(bytes)
click to toggle source
# File lib/fog/aws/glacier.rb, line 81 def add_part(bytes) part = self.digest_for_part(bytes) part.unpack('H*').first end
digest()
click to toggle source
# File lib/fog/aws/glacier.rb, line 144 def digest reduce_digest_stack(@last_chunk_digest_temp, @digest_stack) end
digest_for_part(body)
click to toggle source
# File lib/fog/aws/glacier.rb, line 102 def digest_for_part(body) part_stack = [] part_temp = nil body_size = body.bytesize prepare_body_for_slice(body) {|body, slice| start_offset = 0 if @last_chunk_length != 0 start_offset = MEGABYTE - @last_chunk_length @last_chunk_hash.update(body.send(slice, 0, start_offset)) hash = @last_chunk_hash.digest @last_chunk_digest_temp = hash if body_size > start_offset @last_chunk_length = 0 @last_chunk_hash = nil @last_chunk_digest_temp = nil update_digest_stack(hash, @digest_stack) else part_temp = hash @last_chunk_digest_temp = hash @last_chunk_length += body_size next end end whole_chunk_count = (body_size - start_offset) / MEGABYTE whole_chunk_count.times.each {|chunk_index| hash = Digest::SHA256.digest(body.send(slice, start_offset + chunk_index * MEGABYTE, MEGABYTE)) update_digest_stack(hash, part_stack) update_digest_stack(hash, @digest_stack) } rest_size = body_size - start_offset - whole_chunk_count * MEGABYTE if rest_size > 0 || whole_chunk_count == 0 @last_chunk_hash = Digest::SHA256.new @last_chunk_length = rest_size @last_chunk_hash.update(body.send(slice, start_offset + whole_chunk_count * MEGABYTE, rest_size)) hash = @last_chunk_hash.digest @last_chunk_digest_temp = hash part_temp = hash end } reduce_digest_stack(part_temp, part_stack) end
hexdigest()
click to toggle source
# File lib/fog/aws/glacier.rb, line 148 def hexdigest digest.unpack('H*').first end
prepare_body_for_slice(body) { |body, :byteslice| ... }
click to toggle source
# File lib/fog/aws/glacier.rb, line 86 def prepare_body_for_slice(body) if body.respond_to? :byteslice r = yield(body, :byteslice) else if body.respond_to? :encoding old_encoding = body.encoding body.force_encoding('BINARY') end r = yield(body, :slice) if body.respond_to? :encoding body.force_encoding(old_encoding) end end r end
reduce_digest_stack(digest, stack)
click to toggle source
# File lib/fog/aws/glacier.rb, line 68 def reduce_digest_stack(digest, stack) stack.each_with_index{|s,i| unless digest digest = stack[i] next end if stack[i] digest = Digest::SHA256.digest(stack[i] + digest) end } digest end
update_digest_stack(digest, stack)
click to toggle source
# File lib/fog/aws/glacier.rb, line 54 def update_digest_stack(digest, stack) stack.each_with_index{|s,i| if s digest = Digest::SHA256.digest(s + digest) stack[i] = nil else stack[i] = digest # Update this position with value obtained in previous run of cycle. digest = nil break end } stack << digest if digest end