module DbSucker::Application::Core

Public Instance Methods

channelfy_thread(thr) click to toggle source
# File lib/db_sucker/application/core.rb, line 134
def channelfy_thread thr
  def thr.active?
    alive?
  end

  def thr.closed?
    !alive?
  end

  def thr.closing?
    false
  end

  thr
end
core_cfg_configfile() click to toggle source
# File lib/db_sucker/application/core.rb, line 173
def core_cfg_configfile
  "#{core_cfg_path}/config.rb"
end
core_cfg_path() click to toggle source

Configuration =

# File lib/db_sucker/application/core.rb, line 165
def core_cfg_path
  File.expand_path(ENV["DBS_CFGDIR"].presence || "~/.db_sucker")
end
core_tmp_path() click to toggle source
# File lib/db_sucker/application/core.rb, line 169
def core_tmp_path
  "#{File.expand_path(ENV["DBS_TMPDIR"] || ENV["TMPDIR"] || "/tmp")}/db_sucker_temp"
end
dump_core() click to toggle source
# File lib/db_sucker/application/core.rb, line 37
def dump_core
  dump_file "coredump", true do |f|
    # thread info
    f.puts "#{Thread.list.length} threads:\n"
    Thread.list.each do |thr|
      f.puts "#{thr.inspect}"
      f.puts "      iType: #{thr == Thread.main ? :main_thread : thr[:itype] || :uncategorized}"
      f.puts "    Aborts?: #{thr.abort_on_exception}"
      f.puts "   Priority: #{thr.priority}"
      f.puts "     T-Vars: #{thr.thread_variables.inspect}"
      thr.thread_variables.each {|k| f.puts "             #{k} => #{thr.thread_variable(k)}" }
      f.puts "     F-Vars: #{thr.keys.inspect}"
      thr.keys.each {|k| f.puts "             #{k} => #{thr[k]}" }
      f.puts "  Backtrace: #{thr.backtrace.length}"
      thr.backtrace.each {|l| f.puts "             #{l}" }
      #f.puts "     Caller: #{thr.backtrace_locations.try(:length) || "unknown"}"
      #thr.backtrace_locations.each {|l| f.puts "             #{l}" } if thr.backtrace_locations
      f.puts
    end

    # worker info
    if sklaventreiber
      f.puts "\n\n#{sklaventreiber.workers.length} workers:\n"
      sklaventreiber.workers.each do |w|
        f.puts "#{"[SSH] " if w.sshing} #{w.descriptive} #{w.state}".strip
      end

      # slot pool
      f.puts "\n\n#{sklaventreiber.slot_pools.length} slot pools:\n"
      sklaventreiber.slot_pools.each do |name, pool|
        f.puts "#{name}: #{pool.slots}"
        pool.active.each do |thr|
          f.puts "\tactive\t #{thr} [#{thr[:itype]}]"
        end
        pool.waiting.each do |wthr, tthr|
          f.puts "\twaiting\t #{tthr} [#{tthr[:itype]}]"
        end
      end
    end
  end
end
dump_file(ctx, open = false, &block) click to toggle source
# File lib/db_sucker/application/core.rb, line 27
def dump_file ctx, open = false, &block
  "#{core_tmp_path}/#{ctx}-#{Time.current.to_i}-#{uniqid}.log".tap do |df|
    FileUtils.mkdir_p(File.dirname(df))
    File.open(df, "wb", &block) if block
    if block && open && sdf = Shellwords.shellescape(df)
      fork { exec("#{opts[:core_dump_editor]} #{sdf} ; rm #{sdf}") }
    end
  end
end
fake_channel(&block) click to toggle source
# File lib/db_sucker/application/core.rb, line 150
def fake_channel &block
  FakeChannel.new(&block).tap do |ch|
    channelfy_thread(ch)
    signalify_thread(ch)
  end
end
filtered_threads() click to toggle source
# File lib/db_sucker/application/core.rb, line 4
def filtered_threads
  Thread.list.reject do |thr|
    thr.backtrace[0]["gems/concurrent-ruby"] rescue false
  end
end
fire(which, *args) click to toggle source
# File lib/db_sucker/application/core.rb, line 223
def fire which, *args
  return if @disable_event_firing
  sync { debug "[Event] Firing #{which} (#{@hooks[which].try(:length) || 0} handlers) #{args.map(&:to_s)}", 99 }
  @hooks[which] && @hooks[which].each{|h| h.call(self, *args) }
end
haltpoint() click to toggle source
# File lib/db_sucker/application/core.rb, line 208
def haltpoint
  raise Interrupt if $core_runtime_exiting && !$core_runtime_graceful
end
hook(*which, &hook_block) click to toggle source

Events =

# File lib/db_sucker/application/core.rb, line 216
def hook *which, &hook_block
  which.each do |w|
    @hooks[w.to_sym] ||= []
    @hooks[w.to_sym] << hook_block
  end
end
load_appconfig() click to toggle source
# File lib/db_sucker/application/core.rb, line 177
def load_appconfig
  return unless File.exist?(core_cfg_configfile)
  instance_eval File.read(core_cfg_configfile, encoding: "utf-8"), core_cfg_configfile
end
notify_exception(label_or_ex, ex = nil) click to toggle source
# File lib/db_sucker/application/core.rb, line 19
def notify_exception label_or_ex, ex = nil
  error [].tap{|e|
    e << label_or_ex if ex
    e << "#{"\t" if ex}#{ex ? ex.class : label_or_ex.class}: #{ex ? ex.message : label_or_ex.message}"
    (ex ? ex : label_or_ex).backtrace.each{|l| e << "\t#{"  " if ex}#{l}" }
  }.join("\n")
end
outsync(&block) click to toggle source
# File lib/db_sucker/application/core.rb, line 83
def outsync &block
  @output_monitor.synchronize(&block)
end
release_signals() click to toggle source
# File lib/db_sucker/application/core.rb, line 201
def release_signals
  debug "Releasing signal traps..."
  Signal.trap("INT", "DEFAULT")
  Signal.trap("TERM", "DEFAULT")
  Signal.trap("USR1", "DEFAULT")
end
sandboxed(&block) click to toggle source
# File lib/db_sucker/application/core.rb, line 10
def sandboxed &block
  block.call
rescue StandardError => ex
  e = ["#{ex.class}: #{ex.message}"]
  ex.backtrace.each{|l| e << "\t#{l}" }
  error(e.join("\n"))
  return false
end
signalify_thread(thr) click to toggle source
# File lib/db_sucker/application/core.rb, line 117
def signalify_thread thr
  # set lock and signal
  thr[:monitor] = Monitor.new
  thr[:signal] = thr[:monitor].new_cond

  # define helper methods
  def thr.signal
    self[:monitor].synchronize{ self[:signal].broadcast } ; self
  end
  def thr.wait(*a)
    self[:monitor].synchronize{ self[:signal].wait(*a) }
  end
  def thr.sync(&b)
    self[:monitor].synchronize(&b)
  end
end
spawn_thread(type, &block) click to toggle source
# File lib/db_sucker/application/core.rb, line 91
def spawn_thread type, &block
  waitlock = Queue.new
  sync do
    if !@opts[:"tp_#{type}"]
      warning "Thread type `#{type}' has no priority setting, defaulting to 0..."
    end

    # spawn thread
    Thread.new do
      waitlock.pop
      block.call(Thread.current)
    end.tap do |thr|
      # set type and priority
      thr[:itype] = type
      thr.priority = @opts[:"tp_#{type}"] || 0
      thr.abort_on_exception = true

      # add signal methods
      signalify_thread(thr)

      # start thread
      waitlock << true
    end
  end
end
sync(&block) click to toggle source
# File lib/db_sucker/application/core.rb, line 79
def sync &block
  @monitor.synchronize(&block)
end
trap_signals() click to toggle source

Signal trapping =

# File lib/db_sucker/application/core.rb, line 186
def trap_signals
  debug "Trapping signals..."
  Signal.trap("INT") do
    $core_runtime_exiting = 1
    Kernel.puts "Interrupting..."
  end
  Signal.trap("TERM") do
    $core_runtime_exiting = 2
    Kernel.puts "Terminating..."
  end
  Signal.trap("USR1") do
    dump_core
  end
end
uniqid() click to toggle source
# File lib/db_sucker/application/core.rb, line 87
def uniqid
  Digest::SHA1.hexdigest(SecureRandom.urlsafe_base64(128))
end
wakeup_handlers() click to toggle source
# File lib/db_sucker/application/core.rb, line 157
def wakeup_handlers
  Thread.list.each{|thr| thr.try(:signal) }
end