db_sucker 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|