hobo-inviqa 0.0.8 → 0.0.9.pre.alpha

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.
@@ -1,216 +0,0 @@
1
- require 'aws-sdk'
2
- require 'fileutils'
3
-
4
- module Hobo
5
- module Lib
6
- class S3Sync
7
- include Hobo::Logging
8
-
9
- def initialize key_id, secret
10
- opts = {
11
- :access_key_id => key_id,
12
- :secret_access_key => secret,
13
- :verify_response_body_content_length => false,
14
- :max_retries => 15
15
- }
16
-
17
- logger.debug("s3sync: Options #{opts}")
18
-
19
- @s3 = AWS::S3.new opts
20
- end
21
-
22
- def sync source, dest, opts = {}
23
- opts = { :progress => Hobo.method(:progress) }.merge(opts)
24
-
25
- source_io = io_handler(source)
26
- destination_io = io_handler(dest)
27
-
28
- logger.debug("s3sync: Synchronzing (#{source_io.class.name} -> #{destination_io.class.name}")
29
-
30
- raise "S3 -> S3 synchronisation not supported" if source_io.is_a? Remote and destination_io.is_a? Remote
31
-
32
- source_listing = source_io.ls
33
- destination_listing = destination_io.ls
34
- logger.debug("s3sync: Source listing - #{source_listing}")
35
- logger.debug("s3sync: Destination listing - #{destination_listing}")
36
-
37
- delta = delta(source_listing, destination_listing)
38
- logger.debug("s3sync: Delta #{delta}")
39
-
40
- delta[:add].each do |file|
41
- logger.debug("s3sync: Synchronizing #{file}")
42
- source_file = source_io.open(file, "r")
43
- destination_file = destination_io.open(file, "wb+")
44
-
45
- source_file.buffer
46
-
47
- size = source_file.size
48
- destination_file.write({ :size => source_file.size }) do |buffer, bytes|
49
- chunk = source_file.read(bytes)
50
- buffer.write(chunk)
51
- opts[:progress].call(file, chunk.length, size, :update)
52
- end
53
-
54
- destination_file.close
55
- source_file.close
56
-
57
- opts[:progress].call(file, 0, size, :finish)
58
- end
59
-
60
- delta[:remove].each do |file|
61
- logger.debug("s3sync: Removing #{file}")
62
- destination_io.rm(file)
63
- end
64
-
65
- return delta
66
- end
67
-
68
- private
69
-
70
- def delta source, dest
71
- to_add = (source.sort - dest.sort).map(&:first)
72
- to_remove = (dest.sort - source.sort).map(&:first)
73
- to_remove = to_remove - to_add
74
-
75
- {
76
- :add => to_add,
77
- :remove => to_remove
78
- }
79
- end
80
-
81
- def io_handler uri
82
- parsed = URI.parse(uri)
83
- parsed.scheme == 's3' ?
84
- Remote.new(@s3, parsed.host, parsed.path) :
85
- Local.new(uri)
86
- end
87
-
88
- class Local
89
- include Hobo::Logging
90
-
91
- def initialize path
92
- @path = path
93
- end
94
-
95
- def ls
96
- logger.debug("s3sync: Listing local directory: #{@path}")
97
- out = {}
98
- dir = "#{@path.chomp('/')}/"
99
- files = Dir.glob("#{dir}**/*")
100
- files.each do |file|
101
- out[file.gsub(/^#{dir}/, '')] = Digest::MD5.file(file).hexdigest
102
- end
103
- return out
104
- end
105
-
106
- def open file, mode
107
- file_path = File.join(@path, file)
108
- FileUtils.mkdir_p File.dirname(file_path)
109
- LocalFile.new File.open(file_path, mode)
110
- end
111
-
112
- def rm file
113
- File.unlink File.join(@path, file)
114
- end
115
- end
116
-
117
- class Remote
118
- include Hobo::Logging
119
-
120
- def initialize s3, bucket, prefix
121
- @s3 = s3
122
- @bucket = bucket
123
- @prefix = prefix ? "#{prefix.gsub(/^\//, '').chomp('/')}/" : ""
124
- end
125
-
126
- def ls
127
- out = {}
128
- logger.debug("s3sync: Listing remote bucket: #{@bucket} w/ prefix #{@prefix}")
129
- @s3.buckets[@bucket].objects.with_prefix(@prefix).each do |file|
130
- filename = file.key.gsub(/^#{@prefix}/, '')
131
- next if filename == ""
132
- out[filename] = file.etag.gsub('"', '')
133
- end
134
- return out
135
- end
136
-
137
- def open file, mode
138
- s3_key = File.join(@prefix, file)
139
- RemoteFile.new @s3.buckets[@bucket].objects[s3_key], @prefix
140
- end
141
-
142
- def rm file
143
- s3_key = File.join(@prefix, file)
144
- @s3.buckets[@bucket].objects[s3_key].delete
145
- end
146
- end
147
-
148
- class LocalFile
149
- def initialize file
150
- @file = file
151
- end
152
-
153
- def buffer
154
- # NOP
155
- end
156
-
157
- def read bytes
158
- @file.read bytes
159
- end
160
-
161
- def write opts = {}
162
- opts = { :chunk_size => 4096 }.merge(opts)
163
- while @file.size < opts[:size] do
164
- yield @file, opts[:chunk_size]
165
- end
166
- end
167
-
168
- def size
169
- @file.size
170
- end
171
-
172
- def close
173
- @file.close
174
- end
175
- end
176
-
177
- class RemoteFile
178
- def initialize object, prefix
179
- @object = object
180
- @prefix = prefix
181
- @r_buffer, @w_buffer = IO.pipe
182
- @buffer_thread = nil
183
- end
184
-
185
- def buffer
186
- @buffer_thread = Thread.new do
187
- @object.read do |chunk|
188
- @w_buffer.write chunk
189
- end
190
- end
191
- end
192
-
193
- def read bytes
194
- @r_buffer.readpartial(bytes)
195
- end
196
-
197
- def write opts = {}
198
- s3_opts = { :single_request => true, :content_length => opts[:size] }
199
- @object.write s3_opts do |buffer, bytes|
200
- yield buffer, bytes
201
- end
202
- end
203
-
204
- def size
205
- @object.content_length
206
- end
207
-
208
- def close
209
- @r_buffer.close
210
- @w_buffer.close
211
- @buffer_thread.exit if @buffer_thread
212
- end
213
- end
214
- end
215
- end
216
- end