@glacier_connect
    @sdb_connect
    @log_class_call("Uploading archive.",
                    "Upload of archive finished.")
    def upload(self, vault_name, file_name, description, region,
               stdin, alternative_name, part_size, uploadid, resume):
        """
        Uploads a file to Amazon Glacier.

        :param vault_name: Name of the vault.
        :type vault_name: str
        :param file_name: Name of the file to upload.
        :type file_name: str
        :param description: Description of the upload.
        :type description: str
        :param region: region where to upload to.
        :type region: str
        :param stdin: whether to use stdin to read data from.
        :type stdin: boolan
        :param part_size: the size (in MB) of the blocks to upload.
        :type part_size: int

        :returns: Tupple of (archive_id, sha256hash)
        :rtype: tupple
        :raises: :py:exc:`glacier.glacierexception.InputException`,
                 :py:exc:`glacier.glacierexception.ResponseException`
        """

        # Switch off debug logging for boto, as otherwise it's
        # filling up the log with the data sent!
        if self.logger.getEffectiveLevel() == 10:
            logging.getLogger('boto').setLevel(logging.INFO)

        # Do some sanity checking on the user values.
        self._check_vault_name(vault_name)
        self._check_region(region)
        if not description:
            description = file_name if file_name else 'No description.'

        if description:
            self._check_vault_description(description)

        if uploadid:
            self._check_id(uploadid, 'UploadId')

        if resume and stdin:
            raise InputException(
                'You must provide the UploadId to resume upload of streams from stdin.\nUse glacier-cmd listmultiparts <vault> to find the UploadId.',
                code='CommandError')

        # If file_name is given, try to use this file(s).
        # Otherwise try to read data from stdin.
        total_size = 0
        reader = None
        mmapped_file = None
        if not stdin:
            if not file_name:
                raise InputException(
                    "No file name given for upload.",
                    code='CommandError')

            try:
                f = open(file_name, 'rb')
                mmapped_file = mmap(f)
                total_size = os.path.getsize(file_name)
            except IOError as e:
                raise InputException(
                    "Could not access file: %s."% file_name,
                    cause=e,
                    code='FileError')

        elif select.select([sys.stdin,],[],[],0.0)[0]:
            reader = sys.stdin
            total_size = 0
        else:
            raise InputException(
                "There is nothing to upload.",
                code='CommandError')

        # Log the kind of upload we're going to do.
        if uploadid:
            self.logger.info('Attempting resumption of upload of %s to %s.'% (file_name if file_name else 'data from stdin', vault_name))
        elif resume:
            self.logger.info('Attempting resumption of upload of %s to %s.'% (file_name, vault_name))
        else:
            self.logger.info('Starting upload of %s to %s.\nDescription: %s'% (file_name if file_name else 'data from stdin', vault_name, description))

        # If user did not specify part_size, compute the optimal (i.e. lowest
        # value to stay within the self.MAX_PARTS (10,000) block limit).
        part_size = self._check_part_size(part_size, total_size)
        part_size_in_bytes = part_size * 1024 * 1024

        # If we have an UploadId, check whether it is linked to a current
        # job. If so, check whether uploaded data matches the input data and
        # try to resume uploading.
        upload = None
        if uploadid:
            uploads = self.listmultiparts(vault_name)
            for upload in uploads:
                if uploadid == upload['MultipartUploadId']:
                    self.logger.debug('Found a matching upload id. Continuing upload resumption attempt.')
                    self.logger.debug(upload)
                    part_size_in_bytes = upload['PartSizeInBytes']
                    break
            else:
                raise InputException(
                    'Can not resume upload of this data as no existing job with this uploadid could be found.',
                    code='IdError')

        # Initialise the writer task.
        writer = GlacierWriter(self.glacierconn, vault_name, description=description,
                               part_size_in_bytes=part_size_in_bytes, uploadid=uploadid, logger=self.logger)

        if upload:
            marker = None
            while True:

                # Fetch a list of already uploaded parts and their SHA hashes.
                try:
                    response = self.glacierconn.list_parts(vault_name, uploadid, marker=marker)
                except boto.glacier.exceptions.UnexpectedHTTPResponseError as e:
                    raise ResponseException(
                        'Failed to get a list already uploaded parts for interrupted upload %s.'% uploadid,
                        cause=self._decode_error_message(e.body),
                        code=e.code)

                list_parts_response = response.copy()
                current_position = 0
                stop = 0
                # Process the parts list.
                # For each part of data, take the matching data range from
                # the local file, and compare hashes.
                # If recieving data over stdin, the parts must be sequential
                # and the first must start at 0. For file, we can use the seek()
                # function to handle non-sequential parts.
                for part in list_parts_response['Parts']:
                    start, stop = (int(p) for p in part['RangeInBytes'].split('-'))
                    stop += 1
                    if not start == current_position:
                        if stdin:
                            raise InputException(
                                'Cannot verify non-sequential upload data from stdin.',
                                code='ResumeError')
                        if reader:
                            reader.seek(start)

                    if mmapped_file and stop > mmapped_file.size:
                        raise InputException(
                            'File does not match uploaded data; please check your uploadid and try again.',
                            cause='File is smaller than uploaded data.',
                            code='ResumeError')

                    # Try to read the chunk of data, and take the hash if we
                    # have received anything.
                    # If no data or hash mismatch, stop checking raise an
                    # exception.
                    data = None
                    data = reader.read(stop-start) if reader else mmapped_file[start:stop]
                    if data:
                        data_hash = glaciercorecalls.tree_hash(glaciercorecalls.chunk_hashes(data))
                        if glaciercorecalls.bytes_to_hex(data_hash) == part['SHA256TreeHash']:
                            self.logger.debug('Part %s hash matches.'% part['RangeInBytes'])
                            writer.tree_hashes.append(data_hash)
                        else:
                            raise InputException(
                                'Received data does not match uploaded data; please check your uploadid and try again.',
                                cause='SHA256 hash mismatch.',
                                code='ResumeError')

                    else:
                        raise InputException(
                            'Received data does not match uploaded data; please check your uploadid and try again.',
                            cause='No or not enough data to match.',
                            code='ResumeError')

                    current_position += stop - start

                # If a marker is present, this means there are more pages
                # of parts available. If no marker, we have the last page.
                marker = list_parts_response['Marker']
                writer.uploaded_size = stop
                if not marker:
                    break

                if total_size > 0:
                    msg = 'Checked %s of %s (%s%%).' \
                          % (self._size_fmt(writer.uploaded_size),
                             self._size_fmt(total_size),
                             self._bold(str(int(100 * writer.uploaded_size/total_size))))
                else:
                    msg = 'Checked %s.' \
                          % (self._size_fmt(writer.uploaded_size))

                self._progress(msg)

            # Finished checking; log this and print the final status update
            # before resuming the upload.
            self.logger.info('Already uploaded: %s. Continuing from there.'% self._size_fmt(stop))
            if total_size > 0:
                msg = 'Checked %s of %s (%s%%). Check done; resuming upload.' \
                      % (self._size_fmt(writer.uploaded_size),
                         self._size_fmt(total_size),
                         self._bold(str(int(100 * writer.uploaded_size/total_size))))
            else:
                msg = 'Checked %s. Check done; resuming upload.' \
                      % (self._size_fmt(writer.uploaded_size))

            self._progress(msg)

        # Read file in parts so we don't fill the whole memory.
        start_time = current_time = previous_time = time.time()
        start_bytes = writer.uploaded_size
        while True:
            if reader:
                part = reader.read(part_size_in_bytes)
            else:
                if mmapped_file.size > writer.uploaded_size+part_size_in_bytes:
                    part = mmapped_file[writer.uploaded_size:writer.uploaded_size+part_size_in_bytes]
                else:
                    part = mmapped_file[writer.uploaded_size:]

            if not part:
                break

            writer.write(part)
            current_time = time.time()
            overall_rate = int((writer.uploaded_size-start_bytes)/(current_time - start_time))
            if total_size > 0:

                # Calculate transfer rates in bytes per second.
                current_rate = int(part_size_in_bytes/(current_time - previous_time))

                # Estimate finish time, based on overall transfer rate.
                if overall_rate > 0:
                    time_left = (total_size - writer.uploaded_size)/overall_rate
                    eta_seconds = current_time + time_left
                    if datetime.fromtimestamp(eta_seconds).day is not\
                            datetime.now().day:
                        eta_template = "%a, %d %b, %H:%M:%S"
                    else:
                        eta_template = "%H:%M:%S"
                    eta = time.strftime(eta_template,
                                        time.localtime(eta_seconds))
                else:
                    time_left = "Unknown"
                    eta = "Unknown"

                msg = 'Wrote %s of %s (%s%%). Rate %s/s, average %s/s, ETA %s.' \
                      % (self._size_fmt(writer.uploaded_size),
                         self._size_fmt(total_size),
                         self._bold(str(int(100 * writer.uploaded_size/total_size))),
                         self._size_fmt(current_rate, 2),
                         self._size_fmt(overall_rate, 2),
                         eta)

            else:
                msg = 'Wrote %s. Rate %s/s.' \
                      % (self._size_fmt(writer.uploaded_size),
                         self._size_fmt(overall_rate, 2))

            self._progress(msg)
            previous_time = current_time
            self.logger.debug(msg)

        writer.close()
        if not stdin:
            f.close()
        current_time = time.time()
        overall_rate = int(writer.uploaded_size/(current_time - start_time))
        msg = 'Wrote %s. Rate %s/s.\n' % (self._size_fmt(writer.uploaded_size),
                                            self._size_fmt(overall_rate, 2))
        self._progress(msg)
        self.logger.info(msg)

        archive_id = writer.get_archive_id()
        sha256hash = writer.get_hash()
        location = writer.get_location()

        if self.bookkeeping:
            self.logger.info('Writing upload information into the bookkeeping database.')

            # Use the alternative name as given by --name <name> if we have it.
            file_name = alternative_name if alternative_name else file_name

            # If still no name this is an stdin job, so set name accordingly.
            file_name = file_name if file_name else 'Data from stdin.'
            file_attrs = {
                'region': region,
                'vault': vault_name,
                'filename': file_name,
                'archive_id': archive_id,
                'location': location,
                'description': description,
                'date':'%s' % datetime.utcnow().replace(tzinfo=pytz.utc),
                'hash': sha256hash,
                'size': writer.uploaded_size
            }

##            if file_name:
##                file_attrs['filename'] = file_name
##            elif stdin:
##                file_attrs['filename'] = 'data from stdin'

            self.sdb_domain.put_attributes(file_attrs['filename'], file_attrs)

        return (archive_id, sha256hash)
dataset/ETHPy150Open uskudnik/amazon-glacier-cmd-interface/glacier/GlacierWrapper.py/GlacierWrapper.upload/original