db_sucker 3.0.0
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.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/CHANGELOG.md +45 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +193 -0
- data/Rakefile +1 -0
- data/VERSION +1 -0
- data/bin/db_sucker +12 -0
- data/bin/db_sucker.sh +14 -0
- data/db_sucker.gemspec +29 -0
- data/doc/config_example.rb +53 -0
- data/doc/container_example.yml +150 -0
- data/lib/db_sucker/adapters/mysql2.rb +103 -0
- data/lib/db_sucker/application/colorize.rb +28 -0
- data/lib/db_sucker/application/container/accessors.rb +60 -0
- data/lib/db_sucker/application/container/ssh.rb +225 -0
- data/lib/db_sucker/application/container/validations.rb +53 -0
- data/lib/db_sucker/application/container/variation/accessors.rb +45 -0
- data/lib/db_sucker/application/container/variation/helpers.rb +21 -0
- data/lib/db_sucker/application/container/variation/worker_api.rb +65 -0
- data/lib/db_sucker/application/container/variation.rb +60 -0
- data/lib/db_sucker/application/container.rb +70 -0
- data/lib/db_sucker/application/container_collection.rb +47 -0
- data/lib/db_sucker/application/core.rb +222 -0
- data/lib/db_sucker/application/dispatch.rb +364 -0
- data/lib/db_sucker/application/evented_resultset.rb +149 -0
- data/lib/db_sucker/application/fake_channel.rb +22 -0
- data/lib/db_sucker/application/output_helper.rb +197 -0
- data/lib/db_sucker/application/sklaven_treiber/log_spool.rb +57 -0
- data/lib/db_sucker/application/sklaven_treiber/worker/accessors.rb +105 -0
- data/lib/db_sucker/application/sklaven_treiber/worker/core.rb +168 -0
- data/lib/db_sucker/application/sklaven_treiber/worker/helpers.rb +144 -0
- data/lib/db_sucker/application/sklaven_treiber/worker/io/base.rb +240 -0
- data/lib/db_sucker/application/sklaven_treiber/worker/io/file_copy.rb +81 -0
- data/lib/db_sucker/application/sklaven_treiber/worker/io/file_gunzip.rb +58 -0
- data/lib/db_sucker/application/sklaven_treiber/worker/io/file_import_sql.rb +80 -0
- data/lib/db_sucker/application/sklaven_treiber/worker/io/file_shasum.rb +49 -0
- data/lib/db_sucker/application/sklaven_treiber/worker/io/pv_wrapper.rb +73 -0
- data/lib/db_sucker/application/sklaven_treiber/worker/io/sftp_download.rb +57 -0
- data/lib/db_sucker/application/sklaven_treiber/worker/io/throughput.rb +219 -0
- data/lib/db_sucker/application/sklaven_treiber/worker/routines.rb +313 -0
- data/lib/db_sucker/application/sklaven_treiber/worker.rb +48 -0
- data/lib/db_sucker/application/sklaven_treiber.rb +281 -0
- data/lib/db_sucker/application/slot_pool.rb +137 -0
- data/lib/db_sucker/application/tie.rb +25 -0
- data/lib/db_sucker/application/window/core.rb +185 -0
- data/lib/db_sucker/application/window/dialog.rb +142 -0
- data/lib/db_sucker/application/window/keypad/core.rb +85 -0
- data/lib/db_sucker/application/window/keypad.rb +174 -0
- data/lib/db_sucker/application/window/prompt.rb +124 -0
- data/lib/db_sucker/application/window.rb +329 -0
- data/lib/db_sucker/application.rb +168 -0
- data/lib/db_sucker/patches/beta-warning.rb +374 -0
- data/lib/db_sucker/patches/developer.rb +29 -0
- data/lib/db_sucker/patches/net-sftp.rb +20 -0
- data/lib/db_sucker/patches/thread-count.rb +30 -0
- data/lib/db_sucker/version.rb +4 -0
- data/lib/db_sucker.rb +81 -0
- metadata +217 -0
@@ -0,0 +1,329 @@
|
|
1
|
+
module DbSucker
|
2
|
+
class Application
|
3
|
+
class Window
|
4
|
+
include Core
|
5
|
+
include Curses
|
6
|
+
COLOR_GRAY = 8
|
7
|
+
COL1 = 20
|
8
|
+
COL2 = 25
|
9
|
+
COL3 = 20
|
10
|
+
OutputHelper.hook(self)
|
11
|
+
|
12
|
+
attr_reader :app, :sklaventreiber, :keypad, :tick, :spinner_frames
|
13
|
+
attr_accessor :view, :x_offset, :force_kill
|
14
|
+
|
15
|
+
def initialize app, sklaventreiber
|
16
|
+
@app = app
|
17
|
+
@keypad = Keypad.new(self)
|
18
|
+
@sklaventreiber = sklaventreiber
|
19
|
+
@monitor = Monitor.new
|
20
|
+
@line = 0
|
21
|
+
@tick = 0
|
22
|
+
@view = :status
|
23
|
+
@force_kill = false
|
24
|
+
choose_spinner
|
25
|
+
end
|
26
|
+
|
27
|
+
def refresh_screen
|
28
|
+
Thread.current[:last_render_duration] = rt = Benchmark.realtime do
|
29
|
+
@monitor.synchronize do
|
30
|
+
@tick += 1
|
31
|
+
update { __send__(:"_view_#{@view}") }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
if rt > 0.020
|
35
|
+
@app.warning "window render took: #{"%.6f" % rt}"
|
36
|
+
else
|
37
|
+
@app.debug "window render took: #{"%.6f" % rt}", 125
|
38
|
+
end
|
39
|
+
rescue StandardError => ex
|
40
|
+
@app.notify_exception("DbSucker::Window encountered an render error on tick ##{@tick}", ex)
|
41
|
+
|
42
|
+
update do
|
43
|
+
next_line
|
44
|
+
red "RenderError occured!"
|
45
|
+
next_line
|
46
|
+
red "#{ex.class}: #{ex.message}"
|
47
|
+
ex.backtrace.each do |l|
|
48
|
+
next_line
|
49
|
+
red(" #{l}")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
Thread.current.wait(1)
|
53
|
+
end
|
54
|
+
|
55
|
+
def _view_help
|
56
|
+
_render_status(threads: false, started: false, trxid: false, database: false)
|
57
|
+
|
58
|
+
#next_line; next_line
|
59
|
+
#magenta "db_sucker"
|
60
|
+
#blue " #{VERSION}"
|
61
|
+
#yellow " – "
|
62
|
+
#cyan "(C) 2016-#{Time.current.year} Sven Pachnit (bmonkeys.net)"
|
63
|
+
|
64
|
+
#next_line
|
65
|
+
#gray "Released under the MIT license."
|
66
|
+
|
67
|
+
next_line; next_line
|
68
|
+
blue "Key Bindings (case sensitive):"
|
69
|
+
next_line
|
70
|
+
|
71
|
+
Keypad::HELP_INFO[:key_bindings].each do |key, desc|
|
72
|
+
next_line
|
73
|
+
magenta " #{key}"
|
74
|
+
yellow " #{desc}"
|
75
|
+
end
|
76
|
+
|
77
|
+
next_line; next_line
|
78
|
+
blue "Main prompt commands:"
|
79
|
+
next_line
|
80
|
+
|
81
|
+
# only build output once and save it in memory
|
82
|
+
@_view_help_memory ||= begin
|
83
|
+
mchp = Keypad::HELP_INFO[:main_commands].map do |aliases, options, desc|
|
84
|
+
[].tap do |result|
|
85
|
+
result << [].tap{|r|
|
86
|
+
aliases.each do |al|
|
87
|
+
r << (al.is_a?(Array) ? al.join("").length + 4 : al.length + 2)
|
88
|
+
end
|
89
|
+
}.sum
|
90
|
+
|
91
|
+
result << [].tap{|r|
|
92
|
+
options.each do |type, name|
|
93
|
+
r << (type == :mandatory ? "<#{[*name] * "|"}> " : "[#{[*name] * "|"}] ").length
|
94
|
+
end
|
95
|
+
}.sum
|
96
|
+
end
|
97
|
+
end
|
98
|
+
columns = { aliases: mchp.map(&:first).max, options: mchp.map(&:second).max }
|
99
|
+
|
100
|
+
# render commands
|
101
|
+
[].tap do |instruct|
|
102
|
+
Keypad::HELP_INFO[:main_commands].each do |aliases, options, desc|
|
103
|
+
# aliases
|
104
|
+
instruct << [:next_line]
|
105
|
+
instruct << [:addstr, " "]
|
106
|
+
cl = 0
|
107
|
+
aliases.each do |al|
|
108
|
+
instruct << [:magenta, ":"]
|
109
|
+
if al.is_a?(Array)
|
110
|
+
instruct << [:blue, "#{al[0]}"]
|
111
|
+
instruct << [:gray, "("]
|
112
|
+
instruct << [:cyan, "#{al[1]}"]
|
113
|
+
cl += al.join("").length + 4
|
114
|
+
instruct << [:gray, ") "]
|
115
|
+
else
|
116
|
+
cl += al.length + 2
|
117
|
+
instruct << [:blue, "#{al} "]
|
118
|
+
end
|
119
|
+
end
|
120
|
+
instruct << [:addstr, "".ljust(columns[:aliases] - cl, " ")]
|
121
|
+
|
122
|
+
# options
|
123
|
+
cl = 0
|
124
|
+
instruct << [:addstr, " "]
|
125
|
+
options.each do |type, name|
|
126
|
+
if type == :mandatory
|
127
|
+
instruct << [:red, "<"]
|
128
|
+
[*name].each_with_index do |n, i|
|
129
|
+
instruct << [:gray, "|"] if i > 0
|
130
|
+
instruct << [:blue, n]
|
131
|
+
end
|
132
|
+
instruct << [:red, "> "]
|
133
|
+
else
|
134
|
+
instruct << [:yellow, "["]
|
135
|
+
[*name].each_with_index do |n, i|
|
136
|
+
instruct << [:gray, "|"] if i > 0
|
137
|
+
instruct << [:cyan, n]
|
138
|
+
end
|
139
|
+
instruct << [:yellow, "] "]
|
140
|
+
end
|
141
|
+
cl += [*name].join("").length + 3 + [*name].length - 1
|
142
|
+
end
|
143
|
+
instruct << [:addstr, "".ljust(columns[:options] - cl, " ")]
|
144
|
+
|
145
|
+
instruct << [:yellow, " #{desc}"]
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
@_view_help_memory.each do |a|
|
151
|
+
send(*a)
|
152
|
+
end
|
153
|
+
|
154
|
+
@keypad.prompt.render(self, lines-1)
|
155
|
+
end
|
156
|
+
|
157
|
+
def _view_log
|
158
|
+
_render_status(threads: false, started: false, trxid: false, database: false)
|
159
|
+
next_line
|
160
|
+
if app.opts[:stdout].is_a?(SklavenTreiber::LogSpool)
|
161
|
+
limit = [lines - @line - 1, app.opts[:stdout].spool.length].min
|
162
|
+
app.opts[:stdout].spool[-limit..-1].each do |m, l, t|
|
163
|
+
ts = "[#{t}] "
|
164
|
+
gray(ts)
|
165
|
+
white decolorize(l.join(" "))[0..(cols - ts.length)]
|
166
|
+
next_line
|
167
|
+
end
|
168
|
+
else
|
169
|
+
red "Log spooling is not enabled, can't show log entries!"
|
170
|
+
end
|
171
|
+
@keypad.prompt.render(self, lines-1)
|
172
|
+
end
|
173
|
+
|
174
|
+
def _view_status
|
175
|
+
_render_status
|
176
|
+
_render_workers
|
177
|
+
@keypad.prompt.render(self, lines-1)
|
178
|
+
end
|
179
|
+
|
180
|
+
def _render_status opts = {}
|
181
|
+
opts = opts.reverse_merge(status: true, threads: true, started: true, trxid: true, database: true, progress: true)
|
182
|
+
|
183
|
+
if opts[:status]
|
184
|
+
next_line
|
185
|
+
yellow " Status: "
|
186
|
+
send(sklaventreiber.status[1].presence || :blue, sklaventreiber.status[0])
|
187
|
+
# shutdown message
|
188
|
+
if $core_runtime_exiting && sklaventreiber.status[0] != "terminated"
|
189
|
+
red " (HALTING … please wait)"
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
if opts[:threads]
|
194
|
+
next_line
|
195
|
+
yellow " Threads: "
|
196
|
+
blue "#{Thread.list.length} ".ljust(COL1, " ")
|
197
|
+
end
|
198
|
+
|
199
|
+
if opts[:started]
|
200
|
+
next_line
|
201
|
+
yellow " Started: "
|
202
|
+
blue "#{@app.boot}"
|
203
|
+
yellow " ("
|
204
|
+
blue human_seconds(Time.current - app.boot)
|
205
|
+
yellow ")"
|
206
|
+
end
|
207
|
+
|
208
|
+
if opts[:trxid]
|
209
|
+
next_line
|
210
|
+
yellow "Transaction ID: "
|
211
|
+
cyan sklaventreiber.trxid
|
212
|
+
end
|
213
|
+
|
214
|
+
if opts[:database]
|
215
|
+
next_line
|
216
|
+
yellow " Database: "
|
217
|
+
magenta sklaventreiber.data[:database] || "?"
|
218
|
+
yellow " (transfering "
|
219
|
+
blue "#{sklaventreiber.data[:tables_transfer] || "?"}"
|
220
|
+
yellow " of "
|
221
|
+
blue "#{sklaventreiber.data[:tables_total] || "?"}"
|
222
|
+
yellow " tables)"
|
223
|
+
end
|
224
|
+
|
225
|
+
if opts[:progress]
|
226
|
+
next_line
|
227
|
+
total, done = sklaventreiber.data[:tables_transfer], sklaventreiber.data[:tables_done]
|
228
|
+
perc = total && done ? f_percentage(done, total) : "?"
|
229
|
+
yellow " Progress: "
|
230
|
+
green perc
|
231
|
+
yellow " – "
|
232
|
+
blue "#{done}/#{total || "?"} workers done"
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
def _render_workers
|
237
|
+
if sklaventreiber.workers.any?
|
238
|
+
next_line
|
239
|
+
limit = lines - @line - 3 - (@keypad.prompt.active? ? 1 : 0) # @l starting at 0, 1 for blank line to come, placeholder
|
240
|
+
enum = sklaventreiber.workers.sort_by{|w| [w.priority, w.table] }
|
241
|
+
enum.each_with_index do |w, i|
|
242
|
+
# limit reached and more than one entry to come?
|
243
|
+
if i > limit && (enum.length - i - 1) > 0
|
244
|
+
next_line
|
245
|
+
rest = enum[i..-1]
|
246
|
+
part = rest.group_by(&:state).map do |k, v|
|
247
|
+
"#{v.length} #{k}"
|
248
|
+
end
|
249
|
+
yellow "… #{rest.length} more [#{part.join(", ")}]"
|
250
|
+
break
|
251
|
+
end
|
252
|
+
_render_worker_line(w)
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
def _render_worker_line worker
|
258
|
+
next_line
|
259
|
+
col1 = sklaventreiber.data[:window_col1]
|
260
|
+
col2 = sklaventreiber.data[:window_col2]
|
261
|
+
|
262
|
+
# status icon
|
263
|
+
case worker.state
|
264
|
+
when :pending then gray("⊙")
|
265
|
+
when :pausing, :paused then gray("♨")
|
266
|
+
when :aquired then white("⊙")
|
267
|
+
when :done then green("✔")
|
268
|
+
when :failed then red("✘")
|
269
|
+
when :canceled then red("⊘")
|
270
|
+
when :running then yellow("#{worker.spinner_frame}")
|
271
|
+
end
|
272
|
+
|
273
|
+
# table_name
|
274
|
+
send(worker.should_cancel ? :red : worker.paused? ? :gray : :magenta, " #{worker.table}".ljust(col1 + 1, " "))
|
275
|
+
gray " | "
|
276
|
+
|
277
|
+
# status
|
278
|
+
if worker.step
|
279
|
+
cyan "[#{worker.step}/#{worker.perform.length}] "
|
280
|
+
end
|
281
|
+
if worker.status[0].respond_to?(:to_curses)
|
282
|
+
worker.status[0].to_curses(self)
|
283
|
+
else
|
284
|
+
send(worker.status[1].presence || :blue, decolorize("#{worker.status[0]}"))
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
# used to render everything before exiting, can't fucking dump the pads I tried to implement -.-"
|
289
|
+
def _render_final_results
|
290
|
+
t_db, t_total, t_done = sklaventreiber.data[:database], sklaventreiber.data[:tables_transfer], sklaventreiber.data[:tables_done]
|
291
|
+
perc = t_total && t_done ? f_percentage(t_done, t_total) : "?"
|
292
|
+
|
293
|
+
puts
|
294
|
+
puts c(" Status: ") << c(sklaventreiber.status[0], sklaventreiber.status[1].presence || "red")
|
295
|
+
puts c(" Threads: ") << c("#{Thread.list.length} ".ljust(COL1, " "), :blue)
|
296
|
+
puts c(" Started: ") << c("#{@app.boot}", :blue) << c(" (") << c(human_seconds(Time.current - app.boot), :blue) << c(")")
|
297
|
+
puts c("Transaction ID: ") << c("#{sklaventreiber.trxid}", :cyan)
|
298
|
+
puts c(" Database: ") << c(t_db || "?", :magenta) << c(" (transferred ") << c(t_total || "?", :blue) << c(" of ") << c(t_done || "?", :blue) << c(" tables)")
|
299
|
+
puts c(" Progress: ") << c(perc, :green) << c(" – ") << c(t_total || "?", :blue) << c("#{t_done}/#{t_total || "?"} workers done", :blue)
|
300
|
+
|
301
|
+
if sklaventreiber.workers.any?
|
302
|
+
puts
|
303
|
+
enum = sklaventreiber.workers.sort_by{|w| [w.priority, w.table] }
|
304
|
+
enum.each do |worker|
|
305
|
+
col1 = sklaventreiber.data[:window_col1]
|
306
|
+
col2 = sklaventreiber.data[:window_col2]
|
307
|
+
|
308
|
+
puts "".tap{|res|
|
309
|
+
# status icon
|
310
|
+
res << case worker.state
|
311
|
+
when :done then c("✔", :green)
|
312
|
+
when :failed then c("✘", :red)
|
313
|
+
when :canceled then c("⊘", :red)
|
314
|
+
else "#{worker.state.inspect}"
|
315
|
+
end
|
316
|
+
# table
|
317
|
+
res << c(" #{worker.table}".ljust(col1 + 1, " "), :magenta) << c(" | ", :black)
|
318
|
+
# steps
|
319
|
+
res << c("[#{worker.step}/#{worker.perform.length}] ", :cyan) if worker.step
|
320
|
+
# status
|
321
|
+
res << c(worker.status[0], worker.status[1].presence || :blue)
|
322
|
+
}
|
323
|
+
end
|
324
|
+
puts
|
325
|
+
end
|
326
|
+
end
|
327
|
+
end
|
328
|
+
end
|
329
|
+
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
module DbSucker
|
2
|
+
class Application
|
3
|
+
attr_reader :opts, :cfg, :sklaventreiber, :boot
|
4
|
+
include Core
|
5
|
+
include Colorize
|
6
|
+
include OutputHelper
|
7
|
+
include Dispatch
|
8
|
+
GC_FORCE_RATE = 25*1024*1024
|
9
|
+
|
10
|
+
# main dispatch routine for application
|
11
|
+
def self.dispatch *a
|
12
|
+
new(*a) do |app|
|
13
|
+
begin
|
14
|
+
app.signalify_thread(Thread.main)
|
15
|
+
Thread.main[:app] = app
|
16
|
+
app.load_appconfig
|
17
|
+
app.parse_params
|
18
|
+
app.debug "Running with PID #{Process.pid}"
|
19
|
+
app.debug "Runtime: #{RUBY_DESCRIPTION}"
|
20
|
+
app.dispatch
|
21
|
+
app.haltpoint
|
22
|
+
rescue Interrupt
|
23
|
+
app.abort("Interrupted", 1)
|
24
|
+
rescue OptionParser::ParseError => ex
|
25
|
+
app.fire(:core_exception, ex)
|
26
|
+
app.abort("#{ex.message}", false)
|
27
|
+
app.log app.c("Run `#{$0} --help' for more info", :blue)
|
28
|
+
exit 1
|
29
|
+
rescue StandardError => ex
|
30
|
+
app.fire(:core_exception, ex)
|
31
|
+
app.warn app.c("[FATAL] #{ex.class}: #{ex.message}", :red)
|
32
|
+
ex.backtrace.each do |l|
|
33
|
+
app.warn app.c("\t#{l}", :red)
|
34
|
+
end
|
35
|
+
app.abort case ex
|
36
|
+
when Container::TableNotFoundError then ex.message
|
37
|
+
else "Unhandled exception terminated application!"
|
38
|
+
end
|
39
|
+
ensure
|
40
|
+
app.fire(:core_shutdown)
|
41
|
+
remain = Thread.list.length
|
42
|
+
if remain > 1
|
43
|
+
app.warning "#{remain} threads remain (should be 1)..."
|
44
|
+
else
|
45
|
+
app.debug "1 thread remains..."
|
46
|
+
end
|
47
|
+
Thread.main[:app] = nil unless app.opts[:debug]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def initialize env, argv
|
53
|
+
@boot = Time.current
|
54
|
+
@env, @argv = env, argv
|
55
|
+
@hooks = {}
|
56
|
+
@monitor = Monitor.new
|
57
|
+
@output_monitor = Monitor.new
|
58
|
+
@cfg = ContainerCollection.new(self)
|
59
|
+
@opts = {
|
60
|
+
dispatch: :index, # (internal) action to dispatch
|
61
|
+
mode: :default, # (internal) mode for action
|
62
|
+
check_for_updates: true, # -z flag
|
63
|
+
colorize: true, # --monochrome flag
|
64
|
+
debug: false, # -d flag
|
65
|
+
stdout: STDOUT, # (internal) STDOUT redirect
|
66
|
+
pipein: ARGF, # (internal) INPUT redirect
|
67
|
+
|
68
|
+
list_databases: false, # --list-databases flag
|
69
|
+
list_tables: false, # --list-tables flag
|
70
|
+
suck_only: [], # --only flag
|
71
|
+
suck_except: [], # --except flag
|
72
|
+
simulate: false, # --simulate flag
|
73
|
+
deferred_import: true, # -n flag
|
74
|
+
deferred_threshold: 50_000_000, # 50 MB
|
75
|
+
|
76
|
+
# features
|
77
|
+
status_format: :full, # used for IO operations, can be one of: none, minimal, full
|
78
|
+
pv_enabled: true, # disable pv utility autodiscovery (force non-usage)
|
79
|
+
|
80
|
+
# sklaven treiber
|
81
|
+
window_enabled: true, # if disabled effectively disables any status progress or window drawing
|
82
|
+
window_draw: true, # wether to refresh screen or not
|
83
|
+
window_refresh_delay: 0.25, # refresh screen every so many seconds
|
84
|
+
window_keypad: true, # allow keyboard controls
|
85
|
+
window_spinner: :circle_quarter, # change spinner... why is this configurable?
|
86
|
+
consumers: 10, # amount of workers to run at the same time
|
87
|
+
|
88
|
+
# thread priorities (-3..+3)
|
89
|
+
tp_window_draw_loop: -3,
|
90
|
+
tp_window_keypad_loop: +2,
|
91
|
+
tp_sklaventreiber_ssh_poll: +3,
|
92
|
+
tp_sklaventreiber_throughput: +2,
|
93
|
+
tp_sklaventreiber_worker: -1,
|
94
|
+
tp_sklaventreiber_worker_ctrl: -1,
|
95
|
+
tp_sklaventreiber_worker_slot_progress: -2,
|
96
|
+
tp_sklaventreiber_worker_second_progress: -2,
|
97
|
+
tp_sklaventreiber_worker_io_pv_killer: -2,
|
98
|
+
tp_sklaventreiber_worker_io_import_sql: +3,
|
99
|
+
|
100
|
+
# used to open core dumps (should be a blocking call, e.g. `subl -w' or `mate -w')
|
101
|
+
# MUST be windowed! vim, nano, etc. will not work!
|
102
|
+
core_dump_editor: "subl -w",
|
103
|
+
|
104
|
+
# amount of workers that can use a slot (false = infinite)
|
105
|
+
# you can create as many pools as you want and use them in `routine_pools' setting
|
106
|
+
slot_pools: {
|
107
|
+
all: false,
|
108
|
+
remote: false,
|
109
|
+
download: false,
|
110
|
+
local: false,
|
111
|
+
import: 3,
|
112
|
+
deferred: 1,
|
113
|
+
},
|
114
|
+
|
115
|
+
# assign tasks to certain slot pools
|
116
|
+
routine_pools: {
|
117
|
+
r_dump_file: [:all, :remote],
|
118
|
+
r_calculate_raw_hash: [:all, :remote],
|
119
|
+
r_compress_file: [:all, :remote],
|
120
|
+
r_calculate_compressed_hash: [:all, :remote],
|
121
|
+
l_download_file: [:all, :download],
|
122
|
+
l_verify_compressed_hash: [:all, :local],
|
123
|
+
l_copy_file: [:all, :local],
|
124
|
+
l_decompress_file: [:all, :local],
|
125
|
+
l_verify_raw_hash: [:all, :local],
|
126
|
+
l_import_file: [:all, :local, :import],
|
127
|
+
l_wait_for_workers: [], # does nothing, no need for any slots
|
128
|
+
l_import_file_deferred: [:all, :local, :deferred],
|
129
|
+
}
|
130
|
+
}
|
131
|
+
init_params
|
132
|
+
Tie.hook_all!(self)
|
133
|
+
yield(self)
|
134
|
+
end
|
135
|
+
|
136
|
+
def init_params
|
137
|
+
@optparse = OptionParser.new do |opts|
|
138
|
+
opts.banner = "Usage: db_sucker [options] [identifier [variation]]"
|
139
|
+
|
140
|
+
opts.separator("\n" << "# Application options")
|
141
|
+
opts.on( "--new NAME", String, "Generates new container config in #{core_cfg_path}") {|v| @opts[:dispatch] = :generate_config; @opts[:config_name] = v }
|
142
|
+
opts.on("-a", "--action ACTION", String, "Dispatch given action") {|v| @opts[:dispatch] = v }
|
143
|
+
opts.on("-m", "--mode MODE", String, "Dispatch action with given mode") {|v| @opts[:mode] = v.to_sym }
|
144
|
+
opts.on("-n", "--no-deffer", "Don't use deferred import for files > 50 MB SQL data size.") { @opts[:deferred_import] = false }
|
145
|
+
opts.on("-l", "--list-databases", "List databases for given identifier.") { @opts[:list_databases] = true }
|
146
|
+
opts.on("-t", "--list-tables [DATABASE]", String, "List tables for given identifier and database.", "If used with --list-databases the DATABASE parameter is optional.") {|s| @opts[:list_tables] = s || :all }
|
147
|
+
opts.on("-o", "--only table,table2", Array, "Only suck given tables. Identifier is required, variation is optional (defaults to default).", "WARNING: ignores ignore_always option") {|s| @opts[:suck_only] = s }
|
148
|
+
opts.on("-e", "--except table,table2", Array, "Don't suck given tables. Identifier is required, variation is optional (defaults to default).") {|s| @opts[:suck_except] = s }
|
149
|
+
opts.on("-c", "--consumers NUM=10", Integer, "Maximal amount of tasks to run simultaneously") {|n| @opts[:consumers] = n }
|
150
|
+
opts.on( "--stat-tmp", "Show information about the remote temporary directory.", "If no identifier is given check local temp directory instead.") { @opts[:dispatch] = :stat_tmp }
|
151
|
+
opts.on( "--cleanup-tmp", "Remove all temporary files from db_sucker in target directory.") { @opts[:dispatch] = :cleanup_tmp }
|
152
|
+
opts.on( "--simulate", "To use with --cleanup-tmp to not actually remove anything.") { @opts[:simulate] = true }
|
153
|
+
|
154
|
+
opts.separator("\n" << "# General options")
|
155
|
+
opts.on("-d", "--debug [lvl=1]", Integer, "Enable debug output") {|l| @opts[:debug] = l || 1 }
|
156
|
+
opts.on("--monochrome", "Don't colorize output (does not apply to curses)") { @opts[:colorize] = false }
|
157
|
+
opts.on("--no-window", "Disables curses window alltogether (no progress)") { @opts[:window_enabled] = false }
|
158
|
+
opts.on("-h", "--help", "Shows this help") { @opts[:dispatch] = :help }
|
159
|
+
opts.on("-v", "--version", "Shows version and other info") { @opts[:dispatch] = :info }
|
160
|
+
opts.on("-z", "Do not check for updates on GitHub (with -v/--version)") { @opts[:check_for_updates] = false }
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def parse_params
|
165
|
+
@optparse.parse!(@argv)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|