Class: Log::ProgressBar

Inherits:
Object
  • Object
show all
Defined in:
lib/rbbt/util/log/progress.rb,
lib/rbbt/util/log/progress/util.rb,
lib/rbbt/util/log/progress/report.rb

Constant Summary collapse

BAR_MUTEX =
Mutex.new
BARS =
[]
REMOVE =
[]
SILENCED =
[]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(max = nil, options = {}) ⇒ ProgressBar

Returns a new instance of ProgressBar.



8
9
10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/rbbt/util/log/progress.rb', line 8

def initialize(max = nil, options = {})
  options = Misc.add_defaults options, :depth => 0, :num_reports => 100, :desc => "Progress", :io => STDERR, :severity => Log.severity
  depth, num_reports, desc, io, severity, file, bytes = Misc.process_options options, :depth, :num_reports, :desc, :io, :severity, :file, :bytes

  @max = max
  @ticks = 0
  @frequency = 2
  @last_time = nil
  @last_count = nil
  @last_percent = nil
  @depth = depth
  @desc = desc.nil? ? nil : desc.gsub(/\n/,' ')
  @file = file
end

Instance Attribute Details

#bytesObject

Returns the value of attribute bytes.



7
8
9
# File 'lib/rbbt/util/log/progress.rb', line 7

def bytes
  @bytes
end

#depthObject

Returns the value of attribute depth.



7
8
9
# File 'lib/rbbt/util/log/progress.rb', line 7

def depth
  @depth
end

#descObject

Returns the value of attribute desc.



7
8
9
# File 'lib/rbbt/util/log/progress.rb', line 7

def desc
  @desc
end

#fileObject

Returns the value of attribute file.



7
8
9
# File 'lib/rbbt/util/log/progress.rb', line 7

def file
  @file
end

#frequencyObject

Returns the value of attribute frequency.



7
8
9
# File 'lib/rbbt/util/log/progress.rb', line 7

def frequency
  @frequency
end

#historyObject

Returns the value of attribute history.



20
21
22
# File 'lib/rbbt/util/log/progress/report.rb', line 20

def history
  @history
end

#maxObject

Returns the value of attribute max.



7
8
9
# File 'lib/rbbt/util/log/progress.rb', line 7

def max
  @max
end

#mean_maxObject

Returns the value of attribute mean_max.



20
21
22
# File 'lib/rbbt/util/log/progress/report.rb', line 20

def mean_max
  @mean_max
end

#ticksObject

Returns the value of attribute ticks.



7
8
9
# File 'lib/rbbt/util/log/progress.rb', line 7

def ticks
  @ticks
end

Class Method Details

.cleanup_barsObject



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/rbbt/util/log/progress/util.rb', line 18

def self.cleanup_bars
  BAR_MUTEX.synchronize do
    REMOVE.each do |bar|
      index = BARS.index bar
      if index
        BARS.delete_at index
        BARS.each_with_index do |bar,i|
          bar.depth = i
        end
      end
      index = SILENCED.index bar
      if index
        SILENCED.delete_at index
        SILENCED.each_with_index do |bar,i|
          bar.depth = i
        end
      end
    end
    REMOVE.clear
    BARS.length
  end
end

.new_bar(max, options = {}) ⇒ Object



8
9
10
11
12
13
14
15
16
# File 'lib/rbbt/util/log/progress/util.rb', line 8

def self.new_bar(max, options = {})
  cleanup_bars
  BAR_MUTEX.synchronize do
    #Log::LAST.replace "new_bar" if Log::LAST == "progress"
    options = Misc.add_defaults options, :depth => BARS.length
    BARS << (bar = ProgressBar.new(max, options))
    bar
  end
end

.remove_bar(bar) ⇒ Object



41
42
43
44
45
46
# File 'lib/rbbt/util/log/progress/util.rb', line 41

def self.remove_bar(bar)
  bar.done if bar.respond_to? :done
  BAR_MUTEX.synchronize do
    REMOVE << bar
  end
end

.with_bar(max, options = {}) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
# File 'lib/rbbt/util/log/progress/util.rb', line 48

def self.with_bar(max, options = {})
  bar = new_bar(max, options)
  begin
    yield bar
    keep = false
  rescue KeepBar
    keep = true
  ensure
    remove_bar(bar) if bar
  end
end

Instance Method Details

#done(io = STDERR) ⇒ Object



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/rbbt/util/log/progress/report.rb', line 129

def done(io = STDERR)
  done_msg = Log.color(:magenta, desc) << " " << Log.color(:green, "done")
  if @start
    ellapsed = (Time.now - @start).to_i
  else
    ellapsed = 0
  end
  ellapsed = [ellapsed/3600, ellapsed/60 % 60, ellapsed % 60].map{|t| "%02i" % t }.join(':')
  done_msg << " " << Log.color(:blue, (@ticks).to_s) << " in " << Log.color(:green, ellapsed)
  @last_count = 0
  @last_time = @start
  done_msg << " (" << thr_msg << ")"
  print(io, up_lines(@depth) << done_msg << down_lines(@depth)) 
  Open.rm @file if @file and Open.exists? @file
end

#down_lines(depth) ⇒ Object



7
8
9
# File 'lib/rbbt/util/log/progress/report.rb', line 7

def down_lines(depth)
  "\n\033[#{depth + 2}E"
end

#eta_msgObject



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/rbbt/util/log/progress/report.rb', line 51

def eta_msg
  percent = self.percent
  time = Time.now

  indicator = ""
  10.times{|i|
    if i < percent / 10 then
      indicator << Log.color(:yellow, ".")
    else
      indicator << " "
    end
  }

  indicator << " #{Log.color(:blue, percent.to_s << "%")}"

  used = time - @start
  if @mean_max and @mean_max > 0 and @mean > 0
    eta =  (@max - @ticks) / @mean
  else
    eta =  (@max - @ticks) / (@ticks/used)
  end

  used = Misc.format_seconds(used) 
  eta = [eta/3600, eta/60 % 60, eta % 60].map{|t| "%02i" % t }.join(':')

  #indicator << " #{Log.color :yellow, used} used #{Log.color :yellow, eta} left - #{Log.color :yellow, ticks.to_s} of #{Log.color :yellow, @max.to_s} #{bytes ? 'bytes' : 'items'}"
  indicator << " #{Log.color :yellow, eta} => #{Log.color :yellow, used} - #{Log.color :yellow, ticks.to_s} of #{Log.color :yellow, @max.to_s} #{bytes ? 'bytes' : 'items'}"

  indicator
end

#initObject



28
29
30
31
32
# File 'lib/rbbt/util/log/progress.rb', line 28

def init
  @start = @last_time = Time.now
  @last_count = 0
  report
end

#percentObject



23
24
25
26
# File 'lib/rbbt/util/log/progress.rb', line 23

def percent
  return 0 if @ticks == 0
  (@ticks * 100) / @max
end


11
12
13
14
15
16
17
18
# File 'lib/rbbt/util/log/progress/report.rb', line 11

def print(io, str)
  return if ENV["RBBT_NO_PROGRESS"] == "true"
  LOG_MUTEX.synchronize do
    STDERR.print str
    Log.logfile.puts str unless Log.logfile.nil?
    Log::LAST.replace "progress"
  end
end

#report(io = STDERR) ⇒ Object



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/rbbt/util/log/progress/report.rb', line 105

def report(io = STDERR)
  if Log::LAST != "progress"
    length = Log::ProgressBar.cleanup_bars
    bars = BARS
    print(io, Log.color(:yellow, "...Progress\n"))
    bars.sort_by{|b| b.depth }.reverse.each do |bar|
      if SILENCED.include? bar
        print(io, Log.color(:yellow ,bar.report_msg) << "\n") 
      else
        print(io, "\n") 
      end
    end
  else
    bars = BARS
  end

  print(io, up_lines(bars.length) << Log.color(:yellow, "...Progress\n") << down_lines(bars.length)) 
  print(io, up_lines(@depth) << report_msg << down_lines(@depth)) 
  @last_time = Time.now
  @last_count = ticks
  @last_percent = percent if max and max > 0
  save if @file
end

#report_msgObject



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/rbbt/util/log/progress/report.rb', line 82

def report_msg
  str = Log.color :magenta, desc
  if @ticks == 0
    if @max
      return str << " " << Log.color(:yellow, "waiting on #{@max} #{bytes ? 'bytes' : 'items'}") 
    else
      return str << " " << Log.color(:yellow, "waiting - #{Process.pid}") 
    end
  end
  str << " " << thr_msg
  if max
    str << Log.color(:blue, " -- ") << eta_msg
  else
    str << Log.color(:blue, " -- ") << ticks.to_s << " #{bytes ? 'bytes' : 'items'}"
  end
  str
end

#saveObject



100
101
102
103
# File 'lib/rbbt/util/log/progress/report.rb', line 100

def save
  info = {:start => @start, :last_time => @last_time, :last_count => @last_count, :last_percent => @last_percent, :desc => @desc, :ticks => @ticks, :max => @max}
  Open.write(@file, info.to_yaml)
end

#thrObject



21
22
23
24
25
26
27
28
29
# File 'lib/rbbt/util/log/progress/report.rb', line 21

def thr
  count = @ticks - @last_count
  if @last_time.nil?
    seconds = 0.001
  else
    seconds = Time.now - @last_time
  end
  thr = count / seconds
end

#thr_msgObject



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/rbbt/util/log/progress/report.rb', line 31

def thr_msg
  thr = self.thr
  if @history.nil?
    @history ||= [thr]
  else
    @history << thr
    @history.shift if @history.length > 20
  end

  @mean_max ||= 0
  if @history.length > 3
    mean = @mean = Misc.mean(@history)
    @mean_max = mean if mean > @mean_max
  end

  str = "#{ Log.color :blue, thr.to_i.to_s } per sec."
  str << " #{ Log.color :yellow, mean.to_i.to_s } avg. #{Log.color :yellow, @mean_max.to_i.to_s} max." if @mean_max > 0
  str
end

#tick(step = 1) ⇒ Object



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/rbbt/util/log/progress.rb', line 34

def tick(step = 1)
  return if ENV["RBBT_NO_PROGRESS"] == "true"
  @ticks += step

  begin
    time = Time.now
    if @last_time.nil?
      @last_time = time
      @last_count = @ticks
      @start = time
      return
    end

    diff = time - @last_time
    report and return if diff > @frequency
    return unless max and max > 0

    percent = self.percent
    if @last_percent.nil?
      @last_percent = percent
      return
    end
    report and return if percent > @last_percent and diff > 0.3
  rescue Exception
    Log.warn "Exception during report: " << $!.message
    Log.exception $!
  end
end

#up_lines(depth) ⇒ Object



3
4
5
# File 'lib/rbbt/util/log/progress/report.rb', line 3

def up_lines(depth)
  "\033[#{depth + 1}F\033[2K"
end