s3_multi_upload 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. data/bin/s3_multi_upload +26 -0
  2. data/lib/s3_multi_upload.rb +87 -0
  3. metadata +82 -0
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift File.join File.dirname(__FILE__), *%w[.. lib]
3
+ %w[thor s3_multi_upload].each {|l| require l}
4
+
5
+ module S3_Multi_Upload
6
+ class Task < Thor
7
+
8
+ desc 'upload', 'upload a file to s3 in parallel'
9
+ method_option :access_key_id, :required => true
10
+ method_option :secret_access_key, :required => true
11
+ method_option :bucket, :required => true
12
+ method_option :file, :required => true
13
+ method_option :threads, :required => true, :type => :numeric, :default => 5
14
+ method_option :chunk_size, :required => true, :type => :hash, :default => {10 => :mb}
15
+ method_option :progress_bar, :type => :boolean, :default => true
16
+ method_option :key, :desc => 's3 object key (default: file name)'
17
+
18
+ def upload
19
+ Upload.new(options).process
20
+ end
21
+
22
+ default_task :upload
23
+ end
24
+ end
25
+
26
+ S3_Multi_Upload::Task.start
@@ -0,0 +1,87 @@
1
+ require 'pathname'
2
+ require 'aws-sdk'
3
+ require 'progressbar'
4
+
5
+ module S3_Multi_Upload
6
+ class Upload
7
+ attr_accessor :options, :file, :s3, :bucket, :object, :progress
8
+
9
+ def initialize options
10
+
11
+ AWS.config :access_key_id => options[:access_key_id],
12
+ :secret_access_key => options[:secret_access_key]
13
+
14
+ @options = options
15
+ @file = Pathname.new options[:file]
16
+
17
+ @s3 = AWS::S3.new
18
+ @bucket = @s3.buckets.create options[:bucket]
19
+ @object = @bucket.objects[options[:key] || @file.basename]
20
+
21
+ enqueue
22
+ end
23
+
24
+ def normalize value, unit = nil
25
+ case unit.to_sym.downcase
26
+ when nil, :b, :byte, :bytes
27
+ value.to_f
28
+ when :k, :kb, :kilobyte, :kilobytes
29
+ value.to_f * 1024
30
+ when :m, :mb, :megabyte, :megabytes
31
+ value.to_f * 1024 ** 2
32
+ when :g, :gb, :gigabyte, :gigabytes
33
+ value.to_f * 1024 ** 3
34
+ end
35
+ end
36
+
37
+ def chunk_size
38
+ normalize *options[:chunk_size].first
39
+ end
40
+
41
+ def queue
42
+ @queue ||= Queue.new
43
+ end
44
+
45
+ def enqueue
46
+ (file.size.to_f / chunk_size).ceil.times do |index|
47
+ queue << [chunk_size * index, index + 1]
48
+ end
49
+ end
50
+
51
+ def upload
52
+ object.multipart_upload do |upload|
53
+ threads = []
54
+
55
+ options[:threads].times do
56
+ threads << Thread.new do
57
+ until queue.empty?
58
+ offset, index = queue.deq :asynchronously rescue nil
59
+
60
+ unless offset.nil?
61
+ upload.add_part :data => file.read(chunk_size, offset),
62
+ :part_number => index
63
+
64
+ progress.inc if options[:progress_bar]
65
+ end
66
+ end
67
+ end
68
+ end
69
+
70
+ threads.each &:join
71
+ end
72
+ end
73
+
74
+ def progress
75
+ @progress ||= ProgressBar.new :upload, queue.size
76
+ end
77
+
78
+ def process
79
+ value, unit = *options[:chunk_size].first
80
+ puts "uploading #{file} to s3://#{options[:bucket]}/#{object.key} using #{options[:threads]} threads in chunks of #{value} #{unit}"
81
+ progress if options[:progress_bar]
82
+ abort 'upload failed' unless upload
83
+ progress.finish if options[:progress_bar]
84
+ end
85
+
86
+ end
87
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: s3_multi_upload
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - dallas marlow
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-23 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: aws-sdk
16
+ requirement: &70295147055820 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70295147055820
25
+ - !ruby/object:Gem::Dependency
26
+ name: thor
27
+ requirement: &70295147055280 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70295147055280
36
+ - !ruby/object:Gem::Dependency
37
+ name: progressbar
38
+ requirement: &70295147054780 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70295147054780
47
+ description:
48
+ email:
49
+ - dallasmarlow@gmail.com
50
+ executables:
51
+ - s3_multi_upload
52
+ extensions: []
53
+ extra_rdoc_files: []
54
+ files:
55
+ - bin/s3_multi_upload
56
+ - lib/s3_multi_upload.rb
57
+ homepage: https://github.com/dallasmarlow/s3_multi_upload
58
+ licenses: []
59
+ post_install_message:
60
+ rdoc_options: []
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ! '>='
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ requirements: []
76
+ rubyforge_project:
77
+ rubygems_version: 1.8.10
78
+ signing_key:
79
+ specification_version: 3
80
+ summary: s3 multipart uploads in parallel
81
+ test_files: []
82
+ has_rdoc: