class MSS::S3::MultipartUpload

Represents a multipart upload to an S3 object. See {S3Object#multipart_upload} for a convenient way to initiate a multipart upload.

Note: After you initiate multipart upload and upload one or more parts, you must either complete or abort multipart upload in order to stop getting charged for storage of the uploaded parts. Only after you either complete or abort multipart upload, Amazon S3 frees up the parts storage and stops charging you for the parts storage.

Attributes

id[R]

@return [String] Returns the upload id.

object[R]

@return [S3Object] Returns the object this upload is intended for.

upload_id[R]

@return [String] Returns the upload id.

Public Class Methods

new(object, id, options = {}) click to toggle source

@api private

Calls superclass method MSS::Core::Model::new
# File lib/mss/s3/multipart_upload.rb, line 35
def initialize(object, id, options = {})
  @id = id
  @object = object

  super

  @completed_parts = {}
  @increment_mutex = Mutex.new
  @completed_mutex = Mutex.new
  @last_part = 0
end

Public Instance Methods

==(other) click to toggle source

@return [Boolean] Returns true if both multipart uploads

represent the same object and upload.
# File lib/mss/s3/multipart_upload.rb, line 64
def ==(other)
  other.kind_of?(MultipartUpload) and
    other.object == object and
    other.id == id
end
Also aliased as: eql?
abort() click to toggle source

Aborts the upload. After a multipart upload is aborted, no additional parts can be uploaded using that upload ID. The storage consumed by any previously uploaded parts will be freed. However, if any part uploads are currently in progress, those part uploads might or might not succeed. As a result, it might be necessary to abort a given multipart upload multiple times in order to completely free all storage consumed by all parts. @return [nil]

# File lib/mss/s3/multipart_upload.rb, line 120
def abort
  unless aborted?
    client.abort_multipart_upload(base_opts)
    @aborted = true
  end
  nil
end
Also aliased as: delete, cancel
aborted?() click to toggle source

@return [Boolean] True if the upload has been aborted. @see abort

# File lib/mss/s3/multipart_upload.rb, line 132
def aborted?
  @aborted
end
add_part(data_or_options, options = {}) click to toggle source

Uploads a part.

@overload add_part(data, options = {})

@param data The data to upload.
  Valid values include:

    * A string
    * A Pathname object
    * Any object responding to `read` and `eof?`; the object
      must support the following access methods:

          read                     # all at once
          read(length) until eof?  # in chunks

      If you specify data this way, you must also include
      the `:content_length` option.

@param [Hash] options Additional options for the upload.

@option options [Integer] :content_length If provided,
  this option must match the total number of bytes written
  to S3 during the operation.  This option is required if
  `:data` is an IO-like object without a `size` method.

@overload add_part(options)

@param [Hash] options Options for the upload.  Either
  `:data` or `:file` is required.

@option options :data The data to upload.  Valid values
  include:

    * A string
    * A Pathname object
    * Any object responding to `read` and `eof?`; the object
      must support the following access methods:

           read                     # all at once
           read(length) until eof?  # in chunks

      If you specify data this way, you must also include
      the `:content_length` option.

@option options [String] :file Can be specified instead of
  `:data`; its value specifies the path of a file to
  upload.

@option options [Integer] :content_length If provided,
  this option must match the total number of bytes written
  to S3 during the operation.  This option is required if
  `:data` is an IO-like object without a `size` method.

@option options [Integer] :part_number The part number.
# File lib/mss/s3/multipart_upload.rb, line 190
def add_part(data_or_options, options = {})
  if data_or_options.kind_of?(Hash)
    part_options = base_opts.merge(data_or_options)
  else
    part_options = base_opts.merge(:data => data_or_options)
  end
  part_options.merge!(options)

  unless part_options[:part_number]
    @increment_mutex.synchronize do
      part_options[:part_number] = (@last_part += 1)
    end
  end
  part_number = part_options[:part_number]

  resp = client.upload_part(part_options)
  @completed_mutex.synchronize do
    @completed_parts[part_number] = {
      :part_number => part_number,
      :etag => resp.etag
    }
  end
  UploadedPart.new(self, part_number)
end
bucket() click to toggle source
# File lib/mss/s3/multipart_upload.rb, line 47
def bucket
  object.bucket
end
cancel()
Alias for: abort
close() click to toggle source

Completes the upload or aborts it if no parts have been uploaded yet. Does nothing if the upload has already been aborted.

@return [S3Object, ObjectVersion] If the bucket has versioning

enabled, returns the {ObjectVersion} representing the
version that was uploaded.  If versioning is disabled,
returns the object.  If no upload was attempted (e.g. if it
was aborted or if no parts were uploaded), returns `nil`.
# File lib/mss/s3/multipart_upload.rb, line 297
def close
  if aborted?
    nil
  elsif completed_parts.empty?
    abort
  else
    complete
  end
end
complete() click to toggle source
Completes the upload by assembling previously uploaded
parts.

@return [S3Object, ObjectVersion] If the bucket has versioning
  enabled, returns the {ObjectVersion} representing the
  version that was uploaded.  If versioning is disabled,
  returns the object.

def complete(*parts)

# File lib/mss/s3/multipart_upload.rb, line 253
def complete()
  #parts = parts.flatten
  #case parts.first
  #when :remote_parts
  #  complete_opts = get_complete_opts
  #when :local_parts, nil
    complete_opts = base_opts.merge(:parts => completed_parts)
  #else
  #  part_numbers = parts.map do |part|
  #    case part
  #    when Integer
  #      part
  #    when UploadedPart
  #      raise ArgumentError.new("cannot complete an upload with parts "+
  #                              "from a different upload") unless
  #        part.upload == self

  #      part.part_number
  #    else
  #      raise ArgumentError.new("expected number or UploadedPart")
  #    end
  #  end
  #  complete_opts = get_complete_opts(part_numbers)
  #end

  raise EmptyUploadError.new("Unable to complete an empty upload.") if complete_opts[:parts].empty?

  resp = client.complete_multipart_upload(complete_opts)
  if resp.data[:version_id]
    ObjectVersion.new(object, resp.data[:version_id])
  else
    object
  end
end
completed_parts() click to toggle source

@api private

# File lib/mss/s3/multipart_upload.rb, line 314
def completed_parts
  @completed_parts.values.
    sort { |a, b| a[:part_number] <=> b[:part_number] }
end
delete()
Alias for: abort
eql?(other)
Alias for: ==
inspect() click to toggle source
# File lib/mss/s3/multipart_upload.rb, line 51
def inspect
  "<#{self.class}:#{object.bucket.name}/#{object.key}:#{id}>"
end

Private Instance Methods

base_opts() click to toggle source
base_opts.merge(:parts => parts)

end

# File lib/mss/s3/multipart_upload.rb, line 341
def base_opts
  opts = {
    :bucket_name => object.bucket.name,
    :key => object.key
  }
  opts[:upload_id] = upload_id if upload_id
  opts
end