opee 1.0.4 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f79910e2d461382014985e2657c734b30a03e8e1
4
+ data.tar.gz: e8b1bfbd4a6740d62ac533c0c2922c219d0ead73
5
+ SHA512:
6
+ metadata.gz: 24d04957abaa2b38183ac5725d7bfc47d86911c507228676229bc4d3af91f0cd02e3cc0e285cba6a915fce3e2ec622894852477160ad47f274493fa5e6df8193
7
+ data.tar.gz: 3d7203e89585ed3343c7278cfc981d5bf92c4f76e08d62daf14d91e151c14ea7b5e2aea9a9906606666e0558d905b29e1b1c19a08336c1a042ec4373ce4c018b
data/README.md CHANGED
@@ -20,17 +20,19 @@ Give it a try. Any comments, thoughts, or suggestions are welcome.
20
20
 
21
21
  ## <a name="links">Links of Interest</a>
22
22
 
23
- [Not Your Usual Threading](http://www.ohler.com/dev/http://www.ohler.com/dev/not_your_usual_threading/not_your_usual_threading.html) discussion about how OPEE use changes the way multi-threaded systems are designed.
23
+ [Not Your Usual Threading](http://www.ohler.com/dev/not_your_usual_threading/not_your_usual_threading.html) discussion about how OPEE use changes the way multi-threaded systems are designed.
24
+
25
+ [Open Remote Encrypted File Synchronization](http://www.ohler.com/orefs) is a sample application that makes use of the Opee gem.
24
26
 
25
27
  ## <a name="release">Release Notes</a>
26
28
 
27
- ### Release 1.0.4
29
+ ### Release 1.1.0
28
30
 
29
- - Fixed a bug in queue size reporting for the Queue class.
31
+ - Added Inspector that uses the OTerm for real time interaction with Actors.
30
32
 
31
33
  # Plans and Notes
32
34
 
33
- - implement in C if there is enough interest
35
+ - Implement in C if there is enough interest
34
36
 
35
37
  ### License:
36
38
 
@@ -11,3 +11,4 @@ require 'opee/workqueue'
11
11
  require 'opee/askqueue'
12
12
  require 'opee/job'
13
13
  require 'opee/collector'
14
+ require 'opee/inspector'
@@ -40,6 +40,7 @@ module Opee
40
40
  @state = RUNNING
41
41
  @busy = false
42
42
  @name = nil
43
+ @proc_cnt = 0
43
44
  Env.add_actor(self)
44
45
  set_options(options)
45
46
  @loop = Thread.start(self) do |me|
@@ -67,6 +68,7 @@ module Opee
67
68
  end
68
69
  @busy = true
69
70
  send(a.op, *a.args) unless a.nil?
71
+ @proc_cnt += 1
70
72
  @busy = false
71
73
  if STEP == @state
72
74
  @step_thread.wakeup() unless @step_thread.nil?
@@ -102,6 +104,21 @@ module Opee
102
104
  @loop[:name] = name
103
105
  end
104
106
 
107
+ def state_string()
108
+ ss = 'UNKNOWN'
109
+ case @state
110
+ when STOPPED
111
+ ss = 'STOPPED'
112
+ when RUNNING
113
+ ss = 'RUNNING'
114
+ when CLOSING
115
+ ss = 'CLOSING'
116
+ when STEP
117
+ ss = 'STEP'
118
+ end
119
+ ss
120
+ end
121
+
105
122
  # Calls {#ask}() but uses the specified timeout instead of the default
106
123
  # {#ask_timeout} to determine how long to wait if the Actor's queue is full.
107
124
  # @param [Fixnum|Float] timeout maximum time to wait trying to add a request to the Actor's queue
@@ -169,6 +186,19 @@ module Opee
169
186
  @queue.length + @priority.length + @idle.length
170
187
  end
171
188
 
189
+ # Returns a score indicating how backed up the queue is. This is used for
190
+ # selecting an Actor when stepping from the Inspector.
191
+ def backed_up()
192
+ cnt = @queue.size()
193
+ return 0 if 0 == cnt
194
+ if @max_queue_count.nil? || 0 == @max_queue_count
195
+ cnt = 80 if 80 < cnt
196
+ cnt
197
+ else
198
+ cnt * 100 / @max_queue_count
199
+ end
200
+ end
201
+
172
202
  # Returns the true if any requests are queued or a request is being processed.
173
203
  # @return [true|false] true if busy, false otherwise
174
204
  def busy?()
@@ -189,6 +219,12 @@ module Opee
189
219
  @max_queue_count
190
220
  end
191
221
 
222
+ # Returns the total number of requested processed.
223
+ # @return [Fixnum] number of request processed
224
+ def proc_count()
225
+ @proc_cnt
226
+ end
227
+
192
228
  # Causes the Actor to stop processing any more requests after the current
193
229
  # request has finished.
194
230
  def stop()
@@ -62,7 +62,11 @@ module Opee
62
62
  def self.shutdown()
63
63
  until @@actors.empty?
64
64
  a = @@actors.pop()
65
- a.close()
65
+ begin
66
+ a.close()
67
+ rescue Exception => e
68
+ puts "*** shutdown error #{e.class}: #{e.message}"
69
+ end
66
70
  end
67
71
  @@log = nil
68
72
  end
@@ -211,7 +215,7 @@ module Opee
211
215
  @@actors.each { |a| a.wakeup() }
212
216
  while busy?
213
217
  sleep(0.2) # actors should wake up when queue is empty
214
- if Logger::DEBUG >= @@log.severity
218
+ if !@@log.nil? && Logger::DEBUG >= @@log.severity
215
219
  now = Time.now
216
220
  if next_time <= now
217
221
  log_status()
@@ -224,10 +228,16 @@ module Opee
224
228
  # Wakes up the calling thread when an Actor is finished. It is called by
225
229
  # the Actor and should not be called by any other code.
226
230
  def self.wake_finish()
227
- @@finish_thread.wakeup() unless @@finish_thread.nil?
231
+ unless @@finish_thread.nil?
232
+ # if thread has already exited the an exception will be raised. Ignore it.
233
+ begin
234
+ @@finish_thread.wakeup()
235
+ rescue
236
+ end
237
+ end
228
238
  end
229
239
 
230
- # Waits until all Actors are not longer busy and then closes all Actors.
240
+ # Waits until all Actors are no longer busy and then closes all Actors.
231
241
  def self.wait_close()
232
242
  while 0 < queue_count()
233
243
  wait_finish()
@@ -0,0 +1,363 @@
1
+
2
+ require 'oterm'
3
+
4
+ module Opee
5
+
6
+ class SocketInspector < ::OTerm::Executor
7
+
8
+ def initialize(port=6060)
9
+ super()
10
+ register('actor_count', self, :actor_count, 'Returns the number of active Actors.', nil)
11
+ register('actors', self, :actors, 'Displays a list of all Actor names.', nil)
12
+ register('busy', self, :busy, 'Returns the busy state of the system.', nil)
13
+ register('queued', self, :queued, 'Returns the total number of queued requests.', nil)
14
+ register('show', self, :show, '<actor name> Shows the details of an Actor.',
15
+ %|[<actor name>] Shows the details of an Actor. Attributes are:
16
+ name - identifies the Actor
17
+ state - state of the Actor [ STOPPED \| RUNNING \| STEP \| CLOSING ]
18
+ busy - true if the Actor has requested queued
19
+ queued - number of requested in the queue
20
+ max queue - maximum number of requested that can be queued
21
+ ask timeout - seconds to wait before rejecting an ask
22
+ |)
23
+ register('start', self, :start, '[<actor name>] Start or restart an Actor.', nil)
24
+ register('status', self, :status, 'Displays status of all Actors.',
25
+ %|Displays the Actor name and queued count. If the terminal supports real time
26
+ updates the displays stays active until the X character is pressed. While running
27
+ options are available for sorting on name, activity, or queue size.|)
28
+ register('step', self, :step, '[<actor name>] Step once.',
29
+ %|Step once for the actor specfified or once for some actor that is
30
+ waiting if not actor is identified.
31
+ |)
32
+ register('stop', self, :stop, '[<actor name>] Stops an Actor.', nil)
33
+ register('verbosity', self, :verbosity, '[<level>] Show or set the verbosity or log level.', nil)
34
+
35
+ @server = ::OTerm::Server.new(self, port, false)
36
+ end
37
+
38
+ def join()
39
+ @server.join()
40
+ end
41
+
42
+ def shutdown(listener, args)
43
+ super
44
+ Env.shutdown()
45
+ end
46
+
47
+ def greeting()
48
+ "Welcome to the Inspector."
49
+ end
50
+
51
+ def tab(cmd, listener)
52
+ start = cmd.index(' ')
53
+ if nil == start
54
+ super
55
+ else
56
+ op = cmd[0...start]
57
+ until cmd.size <= start || ' ' != cmd[start]
58
+ start += 1
59
+ end
60
+ arg = cmd[start..-1]
61
+
62
+ if 'show' == op || 'start' == op || 'step' == op || 'stop' == op
63
+ names = []
64
+ Env.each_actor { |a| names << a.name if a.name.start_with?(arg) }
65
+ return if 0 == names.size
66
+ if 1 == names.size
67
+ listener.move_col(1000)
68
+ listener.insert(names[0][arg.size..-1])
69
+ listener.out.prompt()
70
+ listener.out.p(listener.buf)
71
+ else
72
+ listener.out.pl()
73
+ names.each do |name|
74
+ listener.out.pl("#{op} #{name}")
75
+ end
76
+ best = best_completion(arg, names)
77
+ if best == arg
78
+ listener.update_cmd(0)
79
+ else
80
+ listener.move_col(1000)
81
+ listener.insert(best[arg.size..-1])
82
+ listener.out.prompt()
83
+ listener.out.p(listener.buf)
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+
90
+ def actor_count(listener, args)
91
+ listener.out.pl("There are currently #{Opee::Env.actor_count()} active Actors.")
92
+ end
93
+
94
+ def actors(listener, args)
95
+ max = 0
96
+ ::Opee::Env.each_actor() do |a|
97
+ max = a.name.size if max < a.name.size
98
+ end
99
+ ::Opee::Env.each_actor() do |a|
100
+ listener.out.pl(" %1$*2$s: %3$s" % [a.name, -max, a.class.to_s])
101
+ end
102
+ end
103
+
104
+ def queued(listener, args)
105
+ listener.out.pl("There are currently #{Opee::Env.queue_count()} unprocessed requests queued.")
106
+ end
107
+
108
+ def busy(listener, args)
109
+ if Opee::Env.busy?()
110
+ listener.out.pl("One or more actors is busy.")
111
+ else
112
+ listener.out.pl("All actors are idle.")
113
+ end
114
+ end
115
+
116
+ def stop(listener, args)
117
+ if nil == args || 0 == args.size()
118
+ ::Opee::Env.stop()
119
+ listener.out.pl("All Actors stopped(paused)")
120
+ else
121
+ args.strip!
122
+ a = ::Opee::Env.find_actor(args)
123
+ if nil == a
124
+ listener.out.pl("--- Failed to find '#{args}'")
125
+ else
126
+ a.stop()
127
+ listener.out.pl("#{a.name} stopped(paused)")
128
+ end
129
+ end
130
+ end
131
+
132
+ def start(listener, args)
133
+ if nil == args || 0 == args.size()
134
+ ::Opee::Env.start()
135
+ listener.out.pl("All Actors restarted")
136
+ else
137
+ args.strip!
138
+ a = ::Opee::Env.find_actor(args)
139
+ if nil == a
140
+ listener.out.pl("--- Failed to find '#{args}'")
141
+ else
142
+ a.start()
143
+ listener.out.pl("#{a.name} started")
144
+ end
145
+ end
146
+ end
147
+
148
+ def step(listener, args)
149
+ la = ::Opee::Env.logger()
150
+ stop_after = false
151
+ if ::Opee::Actor::STOPPED == la.state
152
+ la.start()
153
+ stop_after = true
154
+ end
155
+ if nil == args || 0 == args.size()
156
+ ma = nil
157
+ mb = 0
158
+ ::Opee::Env.each_actor() do |a|
159
+ next unless ::Opee::Actor::STOPPED == a.state
160
+ if ma.nil?
161
+ ma = a
162
+ mb = ma.backed_up()
163
+ else
164
+ b = a.backed_up()
165
+ if mb < b
166
+ ma = a
167
+ mb = b
168
+ end
169
+ end
170
+ end
171
+ unless ma.nil? || 0 == ma.queue_count()
172
+ ma.step()
173
+ listener.out.pl("#{ma.name} stepped")
174
+ end
175
+ else
176
+ a = ::Opee::Env.find_actor(args)
177
+ if nil == a
178
+ listener.out.pl("--- Failed to find '#{args}'")
179
+ else
180
+ a.step()
181
+ listener.out.pl("#{a.name} stepped")
182
+ end
183
+ end
184
+ la.stop() if stop_after
185
+ end
186
+
187
+ def verbosity(listener, args)
188
+ v = ::Opee::Env.logger.severity
189
+ if nil != args && 0 < args.size()
190
+ args.strip!
191
+ begin
192
+ v = ::Opee::Env.logger.severity = args
193
+ rescue Exception
194
+ listener.out.pl("'#{line}' is not a value verbosity")
195
+ end
196
+ end
197
+ listener.out.pl("verbosity: #{v}")
198
+ end
199
+
200
+ def show(listener, args)
201
+ if nil == args
202
+ listener.out.pl("--- No Actor specified")
203
+ return
204
+ end
205
+ a = ::Opee::Env.find_actor(args)
206
+ if nil == a
207
+ listener.out.pl("--- Failed to find '#{args}'")
208
+ else
209
+ args.strip!
210
+ listener.out.pl("#{a.name}:")
211
+ listener.out.pl(" state: #{a.state_string()}")
212
+ listener.out.pl(" busy?: #{a.busy?()}")
213
+ listener.out.pl(" queued count: #{a.queue_count()}")
214
+ listener.out.pl(" max queue count: #{a.max_queue_count()}")
215
+ listener.out.pl(" ask timeout: #{a.ask_timeout()}")
216
+ end
217
+ end
218
+
219
+ def status(listener, args)
220
+ if listener.out.is_vt100?
221
+ dynamic_status(listener)
222
+ else
223
+ listener.out.pl(" %20s %-11s %5s %5s" % ['Actor Name', 'Q-cnt/max', 'busy?', 'processed'])
224
+ ::Opee::Env.each_actor() do |a|
225
+ listener.out.pl(" %20s %5d/%-5d %5s %5d" % [a.name, a.queue_count(), a.max_queue_count().to_i, a.busy?(), a.proc_count()])
226
+ end
227
+ end
228
+ end
229
+
230
+ BY_NAME = 'n'
231
+ BY_ACTIVITY = 'a'
232
+ BY_QUEUE = 'q'
233
+
234
+ def dynamic_status(listener)
235
+ o = listener.out
236
+ actors = [] # ActorStat
237
+ sort_by = BY_NAME
238
+ rev = false
239
+ delay = 0.4
240
+ max = 6
241
+ ::Opee::Env.each_actor() do |a|
242
+ actors << ActorStat.new(a)
243
+ max = a.name.size if max < a.name.size
244
+ end
245
+ lines = actors.size + 2
246
+ h, w = o.screen_size()
247
+ lines = h - 2 if lines > h - 2
248
+ o.clear_screen()
249
+ max_q = w - max - 4
250
+ done = false
251
+ until done
252
+ actors.each { |as| as.refresh() }
253
+ case sort_by
254
+ when BY_NAME
255
+ if rev
256
+ actors.sort! { |a,b| b.name <=> a.name }
257
+ else
258
+ actors.sort! { |a,b| a.name <=> b.name }
259
+ end
260
+ when BY_ACTIVITY
261
+ if rev
262
+ actors.sort! { |a,b| a.activity <=> b.activity }
263
+ else
264
+ actors.sort! { |a,b| b.activity <=> a.activity }
265
+ end
266
+ when BY_QUEUE
267
+ if rev
268
+ actors.sort! { |a,b| a.queued <=> b.queued }
269
+ else
270
+ actors.sort! { |a,b| b.queued <=> a.queued }
271
+ end
272
+ end
273
+ o.set_cursor(1, 1)
274
+ o.bold()
275
+ o.p("%1$*2$s @ Queued" % ['Actor', -max])
276
+ o.attrs_off()
277
+ i = 2
278
+ actors[0..lines].each do |as|
279
+ o.set_cursor(i, 1)
280
+ o.p("%1$*2$s " % [as.name, -max])
281
+ o.set_cursor(i, max + 2)
282
+ case as.activity
283
+ when 0
284
+ o.p(' ')
285
+ when 1
286
+ o.p('.')
287
+ when 2, 3
288
+ o.p('o')
289
+ else
290
+ o.p('O')
291
+ end
292
+ o.p(' ')
293
+ qlen = as.queued
294
+ qlen = max_q if max_q < qlen
295
+ if 0 < qlen
296
+ o.reverse()
297
+ o.p("%1$*2$d" % [as.queued, -qlen])
298
+ o.attrs_off()
299
+ end
300
+ o.clear_to_end()
301
+ i += 1
302
+ end
303
+ o.set_cursor(i, 1)
304
+ o.bold()
305
+ o.p('E) exit N) by name A) by activity Q) by queued R) reverse ')
306
+ o.graphic_font()
307
+ o.p(::OTerm::VT100::PLUS_MINUS)
308
+ o.default_font()
309
+ o.p(") faster/slower [%0.1f]" % [delay])
310
+ o.attrs_off()
311
+ c = o.recv_wait(1, delay, /./)
312
+ unless c.nil?
313
+ case c[0]
314
+ when 'e', 'E'
315
+ done = true
316
+ when 'n', 'N'
317
+ sort_by = BY_NAME
318
+ rev = false
319
+ when 'a', 'A'
320
+ sort_by = BY_ACTIVITY
321
+ rev = false
322
+ when 'q', 'Q'
323
+ sort_by = BY_QUEUE
324
+ rev = false
325
+ when 'r', 'R'
326
+ rev = !rev
327
+ when 'f', 'F', '+'
328
+ delay /= 2.0 unless delay <= 0.1
329
+ when 's', 'S', '-'
330
+ delay *= 2.0 unless 3.0 <= delay
331
+ end
332
+ end
333
+ end
334
+ o.pl()
335
+ end
336
+
337
+ class ActorStat
338
+ attr_reader :actor
339
+ attr_reader :queued
340
+ attr_reader :activity
341
+
342
+ def initialize(a)
343
+ @actor = a
344
+ @proc_cnt = a.proc_count()
345
+ @activity = 0
346
+ @queued = a.queue_count()
347
+ end
348
+
349
+ def refresh()
350
+ cnt = @actor.proc_count()
351
+ @activity = cnt - @proc_cnt
352
+ @proc_cnt = cnt
353
+ @queued = @actor.queue_count()
354
+ end
355
+
356
+ def name()
357
+ @actor.name
358
+ end
359
+
360
+ end # ActorStat
361
+
362
+ end # SocketInspector
363
+ end # Opee
@@ -125,8 +125,13 @@ module Opee
125
125
  'ERROR' => Logger::Severity::ERROR,
126
126
  'WARN' => Logger::Severity::WARN,
127
127
  'INFO' => Logger::Severity::INFO,
128
- 'DEBUG' => Logger::Severity::DEBUG
129
- }[level]
128
+ 'DEBUG' => Logger::Severity::DEBUG,
129
+ '4' => Logger::Severity::FATAL,
130
+ '3' => Logger::Severity::ERROR,
131
+ '2' => Logger::Severity::WARN,
132
+ '1' => Logger::Severity::INFO,
133
+ '0' => Logger::Severity::DEBUG
134
+ }[level.upcase()]
130
135
  raise "#{level} is not a severity" if severity.nil?
131
136
  level = severity
132
137
  elsif level < Logger::Severity::DEBUG || Logger::Severity::FATAL < level
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Opee
3
3
  # Current version of the module.
4
- VERSION = '1.0.4'
4
+ VERSION = '1.1.0'
5
5
  end
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ # Ubuntu does not accept arguments to ruby when called using env. To get warnings to show up the -w options is
5
+ # required. That can be set in the RUBYOPT environment variable.
6
+ # export RUBYOPT=-w
7
+
8
+ $VERBOSE = true
9
+
10
+ $: << File.join(File.dirname(__FILE__), "../lib")
11
+
12
+ $: << File.join(File.dirname(__FILE__), "../../oterm/lib")
13
+
14
+ require 'opee'
15
+
16
+
17
+ inspector = Opee::SocketInspector.new(6060)
18
+ inspector.join()
metadata CHANGED
@@ -1,34 +1,51 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opee
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.4
5
- prerelease:
4
+ version: 1.1.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Peter Ohler
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2012-07-03 00:00:00.000000000 Z
13
- dependencies: []
14
- description: ! 'An experimental Object-base Parallel Evaluation Environment. '
11
+ date: 2013-12-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: oterm
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: 'An experimental Object-base Parallel Evaluation Environment. '
15
28
  email: peter@ohler.com
16
29
  executables: []
17
30
  extensions: []
18
31
  extra_rdoc_files:
19
32
  - README.md
20
33
  files:
34
+ - LICENSE
35
+ - README.md
36
+ - lib/opee.rb
21
37
  - lib/opee/actor.rb
22
38
  - lib/opee/askqueue.rb
23
39
  - lib/opee/collector.rb
24
40
  - lib/opee/env.rb
25
41
  - lib/opee/errors.rb
42
+ - lib/opee/inspector.rb
26
43
  - lib/opee/job.rb
27
44
  - lib/opee/log.rb
28
45
  - lib/opee/queue.rb
29
46
  - lib/opee/version.rb
30
47
  - lib/opee/workqueue.rb
31
- - lib/opee.rb
48
+ - test/inspector_test.rb
32
49
  - test/relay.rb
33
50
  - test/tc_opee_actor.rb
34
51
  - test/tc_opee_collector.rb
@@ -36,33 +53,29 @@ files:
36
53
  - test/tc_opee_log.rb
37
54
  - test/tc_opee_workqueue.rb
38
55
  - test/ts_opee.rb
39
- - LICENSE
40
- - README.md
41
56
  homepage: http://www.ohler.com/opee
42
57
  licenses: []
58
+ metadata: {}
43
59
  post_install_message:
44
60
  rdoc_options:
45
- - --main
61
+ - "--main"
46
62
  - README.md
47
63
  require_paths:
48
64
  - lib
49
65
  required_ruby_version: !ruby/object:Gem::Requirement
50
- none: false
51
66
  requirements:
52
- - - ! '>='
67
+ - - ">="
53
68
  - !ruby/object:Gem::Version
54
69
  version: '0'
55
70
  required_rubygems_version: !ruby/object:Gem::Requirement
56
- none: false
57
71
  requirements:
58
- - - ! '>='
72
+ - - ">="
59
73
  - !ruby/object:Gem::Version
60
74
  version: '0'
61
75
  requirements: []
62
76
  rubyforge_project: opee
63
- rubygems_version: 1.8.21
77
+ rubygems_version: 2.2.0
64
78
  signing_key:
65
- specification_version: 3
79
+ specification_version: 4
66
80
  summary: An experimental Object-base Parallel Evaluation Environment.
67
81
  test_files: []
68
- has_rdoc: true