Class: Console::Mux::CommandSet

Inherits:
Object
  • Object
show all
Includes:
Events
Defined in:
lib/console/mux/command_set.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Events

#event_handlers, #on

Constructor Details

#initializeCommandSet

Returns a new instance of CommandSet.



48
49
50
51
52
53
54
55
# File 'lib/console/mux/command_set.rb', line 48

def initialize
  @max_width = 0
  @commands = Array.new
  @commands_by_name = Hash.new

  @processes = Hash.new
  @stopped_at = Hash.new
end

Instance Attribute Details

#max_widthObject (readonly)

Returns the value of attribute max_width.



46
47
48
# File 'lib/console/mux/command_set.rb', line 46

def max_width
  @max_width
end

Class Method Details

.join(processes, &block) ⇒ Object

Yield to the block only after all processes are stopped. Does not check that all processes are actually running; just waits for an :exit event from each.

Parameters:



34
35
36
37
38
39
40
41
42
43
# File 'lib/console/mux/command_set.rb', line 34

def join(processes, &block)
  q = EventMachine::Queue.new

  processes.each do |proc|
    proc.on(:exit) { q.push :exit }
  end

  (processes.size - 1).times { q.pop {} }
  q.pop { block.call }  # all have exited
end

Instance Method Details

#[](name) ⇒ Object



109
110
111
# File 'lib/console/mux/command_set.rb', line 109

def [](name)
  @commands_by_name[name]
end

#add(command) ⇒ String

Add a command to this CommandSet.

command.name if required to be unique within this CommandSet

Parameters:

Returns:

  • (String)

    the command name, which may be different from



69
70
71
72
73
74
75
76
77
# File 'lib/console/mux/command_set.rb', line 69

def add(command)
  name = unique_name(command.name)

  @commands << command
  @commands_by_name[name] = command
  @max_width = [@max_width, name.size].max

  name
end

#add_and_start(command) ⇒ Object

Add a command (see #add) and start it (see #start).



58
59
60
61
# File 'lib/console/mux/command_set.rb', line 58

def add_and_start(command)
  name = add(command)
  start(name)
end

#countObject



211
212
213
# File 'lib/console/mux/command_set.rb', line 211

def count
  "#{@commands.size} commands with #{@processes.size} running"
end

#each(&block) ⇒ Object



105
106
107
# File 'lib/console/mux/command_set.rb', line 105

def each(&block)
  @commands.each(&block)
end

#include?(command) ⇒ Boolean

TODO: make this work? def merge(command)

if i = @commands.first_index(command)
  @commands[i] = command
  @commands_by_name[command.name] = command
else
  add(command)
end

end

Returns:

  • (Boolean)


97
98
99
# File 'lib/console/mux/command_set.rb', line 97

def include?(command)
  @commands.include?(command)
end

#join(&block) ⇒ Object

When all currently-running processes stop, yield to the block



144
145
146
# File 'lib/console/mux/command_set.rb', line 144

def join(&block)
  self.class.join(@processes.values, &block)
end

#pretty_bytes(bytes) ⇒ Object



174
175
176
177
178
179
180
181
182
183
184
# File 'lib/console/mux/command_set.rb', line 174

def pretty_bytes(bytes)
  if bytes < 1024
    "#{bytes}B"
  elsif bytes < 1024 * 1024
    "#{bytes/1024} kiB"
  elsif bytes < 1024* 1024 * 1024
    "#{bytes/1024/1024} MiB"
  else
    "%0.2d GiB" % (bytes.to_f/(1024**3))
  end
end

#pretty_seconds(secs) ⇒ Object



162
163
164
165
166
167
168
169
170
171
172
# File 'lib/console/mux/command_set.rb', line 162

def pretty_seconds(secs)
  if secs < 60
    "#{secs} s"
  elsif secs < (60 * 60)
    "#{secs/60} min"
  elsif secs < (60 * 60 * 24)
    "#{secs/60/60} hr"
  else
    "%0.1f days" % (secs/60.0/60.0/24.0)
  end
end

#remove(name) ⇒ Object



79
80
81
82
83
84
85
# File 'lib/console/mux/command_set.rb', line 79

def remove(name)
  return unless @commands_by_name[name]

  stop(name) rescue nil
  @stopped_at.delete(name)
  @commands.delete(@commands_by_name.delete(name))
end

#restart(name) ⇒ Object

Stop and then start the process name.



149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/console/mux/command_set.rb', line 149

def restart(name)
  if proc = @processes[name]
    proc.on(:exit) do
      start(name)
    end
    proc.stop
  elsif @commands_by_name[name]
    start(name)
  else
    raise "no process for #{name}"
  end
end

#start(name) ⇒ Object



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/console/mux/command_set.rb', line 113

def start(name)
  if proc = @processes[name]
    raise "already have process for #{name}: #{proc.pid}"
  end
  
  @stopped_at.delete(name)
  proc = Process.start(@commands_by_name[name], name)
  proc.on(:exit) do
    @processes.delete(name)
    @stopped_at[name] = Time.now
    fire(:stopped) if @processes.empty?
  end
  @processes[name] = proc
  proc
end

#statusObject



186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
# File 'lib/console/mux/command_set.rb', line 186

def status
  fmt = "%-#{max_width}s %8s %12s %8s %10s\n"

  rows = []
  rows << fmt % ['NAME', 'PID', 'RSS', 'TIME', 'CPUTIME']
  @commands_by_name.each do |name, c|
    pid, rss, time, cputime =
      if proc = @processes[name]
        [proc.pid.to_s,
         pretty_bytes(proc.rss),
         proc.etime,
         proc.cputime]
      elsif @stopped_at[name]
        downtime = Time.now.to_i - @stopped_at[name].to_i
        ['-', "  down #{pretty_seconds(downtime)}", nil, nil]
      else
        ['-', "        (pending)", nil, nil]
      end
    
    rows << (fmt % [name, pid, rss, time, cputime])
  end

  rows
end

#stop(name) ⇒ Object



129
130
131
132
133
134
135
# File 'lib/console/mux/command_set.rb', line 129

def stop(name)
  if proc = @processes.delete(name)
    proc.stop
  else
    raise "no process for #{name}"
  end
end

#stop_allObject



137
138
139
140
141
# File 'lib/console/mux/command_set.rb', line 137

def stop_all
  @processes.each do |name, proc|
    proc.stop
  end
end

#stopped?Boolean

Returns:

  • (Boolean)


101
102
103
# File 'lib/console/mux/command_set.rb', line 101

def stopped?
  @processes.empty?
end