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
22
# File 'lib/rbbt/util/log/progress.rb', line 8

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

  @max = max
  @ticks = 0
  @frequency = frequency
  @last_time = nil
  @last_count = nil
  @last_percent = nil
  @depth = depth
  @desc = desc.nil? ? "" : desc.gsub(/\n/,' ')
  @file = file
  @bytes = bytes
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.



12
13
14
# File 'lib/rbbt/util/log/progress/report.rb', line 12

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

#max_historyObject

Returns the value of attribute max_history.



12
13
14
# File 'lib/rbbt/util/log/progress/report.rb', line 12

def max_history
  @max_history
end

#mean_maxObject

Returns the value of attribute mean_max.



12
13
14
# File 'lib/rbbt/util/log/progress/report.rb', line 12

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

.add_offset(value = 1) ⇒ Object



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

def self.add_offset(value = 1)
  value = 1 if TrueClass === value
  @@offset = offset + value.to_i
  @@offset = 0 if @@offset < 0
  @@offset
end

.cleanup_barsObject



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

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



29
30
31
32
33
34
35
36
37
# File 'lib/rbbt/util/log/progress/util.rb', line 29

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 + Log::ProgressBar.offset
    BARS << (bar = ProgressBar.new(max, options))
    bar
  end
end

.offsetObject



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

def self.offset
  @@offset ||= 0
  @@offset = 0 if @@offset < 0
  @@offset
end

.remove_bar(bar, error = false) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/rbbt/util/log/progress/util.rb', line 62

def self.remove_bar(bar, error = false)
  BAR_MUTEX.synchronize do
    return if REMOVE.include? bar
  end
  if error
    bar.error if bar.respond_to? :error
  else
    bar.done if bar.respond_to? :done
  end
  BAR_MUTEX.synchronize do
    REMOVE << bar
  end
  Log::LAST.replace "remove_bar" if Log::LAST == "progress"
end

.remove_offset(value = 1) ⇒ Object



15
16
17
18
19
20
# File 'lib/rbbt/util/log/progress/util.rb', line 15

def self.remove_offset(value = 1)
  value = 1 if TrueClass === value
  @@offset = offset - value.to_i
  @@offset = 0 if @@offset < 0
  @@offset
end

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



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/rbbt/util/log/progress/util.rb', line 77

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

Instance Method Details

#done(io = STDERR) ⇒ Object



223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/rbbt/util/log/progress/report.rb', line 223

def done(io = STDERR)
  done_msg = Log.color(:magenta, "· ") << 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) << " #{bytes ? 'bytes' : 'items'} in " << Log.color(:green, ellapsed)
  @last_count = 0
  @last_time = @start
  done_msg << " - " << thr_msg 
  done_msg << Log.color(:magenta, " · " << desc)
  print(io, Log.up_lines(@depth) << done_msg << Log.down_lines(@depth)) 
  Open.rm @file if @file and Open.exists? @file
end

#error(io = STDERR) ⇒ Object



240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
# File 'lib/rbbt/util/log/progress/report.rb', line 240

def error(io = STDERR)
  done_msg = Log.color(:magenta, "· ") << Log.color(:red, "error")
  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
  done_msg << Log.color(:magenta, " · " << desc)      
  print(io, Log.up_lines(@depth) << done_msg << Log.down_lines(@depth)) 
  Open.rm @file if @file and Open.exists? @file
end

#eta_msgObject



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/rbbt/util/log/progress/report.rb', line 136

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



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

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

#percentObject



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

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

#pos(pos) ⇒ Object



60
61
62
63
# File 'lib/rbbt/util/log/progress.rb', line 60

def pos(pos)
  step = pos - (@ticks || 0)
  tick(step)
end


3
4
5
6
7
8
9
10
# File 'lib/rbbt/util/log/progress/report.rb', line 3

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



192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/rbbt/util/log/progress/report.rb', line 192

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

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

#report_msgObject



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/rbbt/util/log/progress/report.rb', line 167

def report_msg
  str = Log.color(:magenta, "·")
  if @ticks == 0
    if @max
      return str << " " << Log.color(:magenta, "waiting on #{@max} #{bytes ? 'bytes' : 'items'}") <<  Log.color(:magenta, " · " << desc)
    else
      return str << " " << Log.color(:magenta, "waiting - PID: #{Process.pid}") <<  Log.color(:magenta, " · " << desc)
    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 <<  Log.color(:magenta, " · " << desc)
  str
end

#saveObject



186
187
188
189
190
# File 'lib/rbbt/util/log/progress/report.rb', line 186

def save
  info = {:start => @start, :last_time => @last_time, :last_count => @last_count, :last_percent => @last_percent, :desc => @desc, :ticks => @ticks, :max => @max, :mean => @mean}
  info.delete_if{|k,v| v.nil?}
  Open.write(@file, info.to_yaml)
end

#thr_msgObject

str end



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/rbbt/util/log/progress/report.rb', line 75

def thr_msg
  if @history.nil?
    @history ||= [[@ticks, Time.now] ]
  else
    @history << [@ticks, Time.now]
    max_history ||= case 
                  when @ticks > 20
                    count = @ticks - @last_count
                    count = 1 if count == 0
                    if @max
                      times = @max / count
                      num = times / 20
                      num = 2 if num < 2
                    else
                      num = 10
                    end
                    count * num
                  else
                    20
                  end
    max_history = 30 if max_history > 30
    @history.shift if @history.length > max_history
  end

  @mean_max ||= 0
  if @history.length > 3

    sticks, stime = @history.first
    ssticks, sstime = @history[-3]
    lticks, ltime = @history.last

    mean = @mean = (lticks - sticks).to_f / (ltime - stime)
    short_mean = (lticks - ssticks).to_f / (ltime - sstime)

    @mean_max = mean if mean > @mean_max
  end

  if short_mean
    thr = short_mean
  else
    thr = begin
            (@ticks || 1) / (Time.now - @start) 
          rescue
            1
          end
  end

  thr = 0.0000001 if thr == 0
  
  if mean.nil? or mean.to_i > 1
    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
  else
    str = "#{ Log.color :blue, (1/thr).ceil.to_s } secs each"
    #str << " #{ Log.color :yellow, (1/mean).ceil.to_s } avg. #{Log.color :yellow, (1/@mean_max).ceil.to_s} min." if @mean_max > 0
  end

  str
end

#tick(step = 1) ⇒ Object



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

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

  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
end