# Path: python/boto/glacier/writer.py
# def chunk_hashes(bytestring, chunk_size=_ONE_MEGABYTE):
#     chunk_count = int(math.ceil(len(bytestring) / float(chunk_size)))
#     hashes = []
#     for i in xrange(chunk_count):
#         start = i * chunk_size
#         end = (i + 1) * chunk_size
#         hashes.append(hashlib.sha256(bytestring[start:end]).digest())
#     return hashes
# 
# def tree_hash(fo):
#     """
#     Given a hash of each 1MB chunk (from chunk_hashes) this will hash
#     together adjacent hashes until it ends up with one big one. So a
#     tree of hashes.
#     """
#     hashes = []
#     hashes.extend(fo)
#     while len(hashes) > 1:
#         new_hashes = []
#         while True:
#             if len(hashes) > 1:
#                 first = hashes.pop(0)
#                 second = hashes.pop(0)
#                 new_hashes.append(hashlib.sha256(first + second).digest())
#             elif len(hashes) == 1:
#                 only = hashes.pop(0)
#                 new_hashes.append(only)
#             else:
#                 break
#         hashes.extend(new_hashes)
#     return hashes[0]
# 
# def bytes_to_hex(str):
#     return ''.join(["%02x" % ord(x) for x in str]).strip()
# 
# Path: python/boto/glacier/exceptions.py
# class UploadArchiveError(Exception):
#     pass


import os
import math
import threading
import hashlib
import time
import logging
from Queue import Queue, Empty
from .writer import chunk_hashes, tree_hash, bytes_to_hex
from .exceptions import UploadArchiveError
        while self.should_continue:
            try:
                work = self._worker_queue.get(timeout=1)
            except Empty:
                continue
            if work is _END_SENTINEL:
                return
            result = self._process_chunk(work)
            self._result_queue.put(result)

    def _process_chunk(self, work):
        result = None
        for _ in xrange(self._num_retries):
            try:
                result = self._upload_chunk(work)
                break
            except self._retry_exceptions, e:
                log.error("Exception caught uploading part number %s for "
                          "vault %s, filename: %s", work[0], self._vault_name,
                          self._filename)
                time.sleep(self._time_between_retries)
                result = e
        return result

    def _upload_chunk(self, work):
        part_number, part_size = work
        start_byte = part_number * part_size
        self._fileobj.seek(start_byte)
        contents = self._fileobj.read(part_size)
        linear_hash = hashlib.sha256(contents).hexdigest()

# Path: python/boto/glacier/writer.py
# def chunk_hashes(bytestring, chunk_size=_ONE_MEGABYTE):
#     chunk_count = int(math.ceil(len(bytestring) / float(chunk_size)))
#     hashes = []
#     for i in xrange(chunk_count):
#         start = i * chunk_size
#         end = (i + 1) * chunk_size
#         hashes.append(hashlib.sha256(bytestring[start:end]).digest())
#     return hashes
# 
# def tree_hash(fo):
#     """
#     Given a hash of each 1MB chunk (from chunk_hashes) this will hash
#     together adjacent hashes until it ends up with one big one. So a
#     tree of hashes.
#     """
#     hashes = []
#     hashes.extend(fo)
#     while len(hashes) > 1:
#         new_hashes = []
#         while True:
#             if len(hashes) > 1:
#                 first = hashes.pop(0)
#                 second = hashes.pop(0)
#                 new_hashes.append(hashlib.sha256(first + second).digest())
#             elif len(hashes) == 1:
#                 only = hashes.pop(0)
#                 new_hashes.append(only)
#             else:
#                 break
#         hashes.extend(new_hashes)
#     return hashes[0]
# 
# def bytes_to_hex(str):
#     return ''.join(["%02x" % ord(x) for x in str]).strip()
# 
# Path: python/boto/glacier/exceptions.py
# class UploadArchiveError(Exception):
#     pass


# Path: python/boto/glacier/concurrent.py
import os
import math
import threading
import hashlib
import time
import logging
from Queue import Queue, Empty
from .writer import chunk_hashes, tree_hash, bytes_to_hex
from .exceptions import UploadArchiveError

        while self.should_continue:
            try:
                work = self._worker_queue.get(timeout=1)
            except Empty:
                continue
            if work is _END_SENTINEL:
                return
            result = self._process_chunk(work)
            self._result_queue.put(result)

    def _process_chunk(self, work):
        result = None
        for _ in xrange(self._num_retries):
            try:
                result = self._upload_chunk(work)
                break
            except self._retry_exceptions, e:
                log.error("Exception caught uploading part number %s for "
                          "vault %s, filename: %s", work[0], self._vault_name,
                          self._filename)
                time.sleep(self._time_between_retries)
                result = e
        return result

    def _upload_chunk(self, work):
        part_number, part_size = work
        start_byte = part_number * part_size
        self._fileobj.seek(start_byte)
        contents = self._fileobj.read(part_size)
        linear_hash = hashlib.sha256(contents).hexdigest()

        tree_hash_bytes = tree_hash(chunk_hashes(contents))