opee 1.0.4 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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