flor 0.0.1 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. data/CHANGELOG.md +13 -0
  2. data/LICENSE.txt +1 -1
  3. data/Makefile +66 -0
  4. data/README.md +57 -0
  5. data/fail.txt +7 -0
  6. data/flor.gemspec +12 -9
  7. data/intercepted.txt +123 -0
  8. data/lib/flor/colours.rb +140 -0
  9. data/lib/flor/conf.rb +88 -0
  10. data/lib/flor/core/executor.rb +473 -0
  11. data/lib/flor/core/node.rb +397 -0
  12. data/lib/flor/core/procedure.rb +600 -0
  13. data/lib/flor/core/texecutor.rb +209 -0
  14. data/lib/flor/core.rb +93 -0
  15. data/lib/flor/dollar.rb +248 -0
  16. data/lib/flor/errors.rb +36 -0
  17. data/lib/flor/flor.rb +556 -0
  18. data/lib/flor/log.rb +336 -0
  19. data/lib/flor/migrations/0001_tables.rb +122 -0
  20. data/lib/flor/parser.rb +414 -0
  21. data/lib/flor/pcore/_arr.rb +49 -0
  22. data/lib/flor/pcore/_atom.rb +43 -0
  23. data/lib/flor/pcore/_att.rb +160 -0
  24. data/lib/flor/pcore/_dump.rb +60 -0
  25. data/lib/flor/pcore/_err.rb +30 -0
  26. data/lib/flor/pcore/_happly.rb +73 -0
  27. data/lib/flor/pcore/_obj.rb +65 -0
  28. data/lib/flor/pcore/_skip.rb +63 -0
  29. data/lib/flor/pcore/apply.rb +60 -0
  30. data/lib/flor/pcore/arith.rb +46 -0
  31. data/lib/flor/pcore/break.rb +71 -0
  32. data/lib/flor/pcore/cmp.rb +72 -0
  33. data/lib/flor/pcore/cond.rb +57 -0
  34. data/lib/flor/pcore/cursor.rb +223 -0
  35. data/lib/flor/pcore/define.rb +96 -0
  36. data/lib/flor/pcore/fail.rb +45 -0
  37. data/lib/flor/pcore/ife.rb +56 -0
  38. data/lib/flor/pcore/loop.rb +53 -0
  39. data/lib/flor/pcore/map.rb +75 -0
  40. data/lib/flor/pcore/match.rb +70 -0
  41. data/lib/flor/pcore/move.rb +65 -0
  42. data/lib/flor/pcore/noeval.rb +46 -0
  43. data/lib/flor/pcore/noret.rb +47 -0
  44. data/lib/flor/pcore/push.rb +69 -0
  45. data/lib/flor/pcore/sequence.rb +39 -0
  46. data/lib/flor/pcore/set.rb +76 -0
  47. data/lib/flor/pcore/stall.rb +35 -0
  48. data/lib/flor/pcore/until.rb +122 -0
  49. data/lib/flor/pcore/val.rb +40 -0
  50. data/lib/flor/punit/cancel.rb +69 -0
  51. data/lib/flor/punit/cmap.rb +76 -0
  52. data/lib/flor/punit/concurrence.rb +149 -0
  53. data/lib/flor/punit/every.rb +46 -0
  54. data/lib/flor/punit/on.rb +81 -0
  55. data/lib/flor/punit/schedule.rb +68 -0
  56. data/lib/flor/punit/signal.rb +47 -0
  57. data/lib/flor/punit/sleep.rb +53 -0
  58. data/lib/flor/punit/task.rb +109 -0
  59. data/lib/flor/punit/trace.rb +51 -0
  60. data/lib/flor/punit/trap.rb +100 -0
  61. data/lib/flor/to_string.rb +81 -0
  62. data/lib/flor/tools/env.rb +103 -0
  63. data/lib/flor/tools/repl.rb +231 -0
  64. data/lib/flor/unit/executor.rb +260 -0
  65. data/lib/flor/unit/hooker.rb +186 -0
  66. data/lib/flor/unit/journal.rb +52 -0
  67. data/lib/flor/unit/loader.rb +181 -0
  68. data/lib/flor/unit/logger.rb +181 -0
  69. data/lib/flor/unit/models/execution.rb +105 -0
  70. data/lib/flor/unit/models/pointer.rb +31 -0
  71. data/lib/flor/unit/models/timer.rb +52 -0
  72. data/lib/flor/unit/models/trace.rb +31 -0
  73. data/lib/flor/unit/models/trap.rb +130 -0
  74. data/lib/flor/unit/models.rb +106 -0
  75. data/lib/flor/unit/scheduler.rb +419 -0
  76. data/lib/flor/unit/storage.rb +633 -0
  77. data/lib/flor/unit/tasker.rb +191 -0
  78. data/lib/flor/unit/waiter.rb +146 -0
  79. data/lib/flor/unit/wlist.rb +77 -0
  80. data/lib/flor/unit.rb +50 -0
  81. data/lib/flor.rb +40 -3
  82. metadata +152 -22
  83. checksums.yaml +0 -7
  84. data/Rakefile +0 -52
@@ -0,0 +1,81 @@
1
+ #--
2
+ # Copyright (c) 2015-2017, John Mettraux, jmettraux+flor@gmail.com
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in
12
+ # all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ # THE SOFTWARE.
21
+ #
22
+ # Made in Japan.
23
+ #++
24
+
25
+
26
+ module Flor
27
+
28
+ def self.to_s(o=nil, k=nil)
29
+
30
+ return 'FlorModule' if o == nil && k == nil
31
+ # should it emerge somewhere...
32
+
33
+ return o.collect { |e| Flor.to_s(e, k) }.join("\n") if o.is_a?(Array)
34
+
35
+ if o.is_a?(Hash)
36
+
37
+ return send("message_#{k}_to_s", o) if k && o['point'].is_a?(String)
38
+ return message_to_s(o) if o['point'].is_a?(String)
39
+
40
+ return send("node_#{k}_to_s", o) if k && o.has_key?('parent')
41
+ return node_to_s(o) if o['parent'].is_a?(String)
42
+ end
43
+
44
+ return [ o, k ].inspect if k
45
+ o.inspect
46
+ end
47
+
48
+ def self.message_to_s(m)
49
+
50
+ s = StringIO.new
51
+ s << '(msg ' << m['nid'] << ' ' << m['point']
52
+ %w[ from flavour ].each { |k|
53
+ s << ' ' << k << ':' << m[k].to_s if m.has_key?(k) }
54
+ s << ')'
55
+
56
+ s.string
57
+ end
58
+
59
+ def self.node_status_to_s(n)
60
+
61
+ s = StringIO.new
62
+ stas = n['status'].reverse
63
+ while sta = stas.shift
64
+ s << '(status ' << (sta['status'] || 'o') # o for open
65
+ s << ' pt:' << sta['point']
66
+ if f = sta['flavour']; s << ' fla:' << f; end
67
+ if f = sta['from']; s << ' fro:' << f; end
68
+ if m = sta['m']; s << ' m:' << m; end
69
+ s << ')'
70
+ s << "\n" if stas.any?
71
+ end
72
+
73
+ s.string
74
+ end
75
+
76
+ def self.node_to_s(n) # there is already a .node_to_s in log.rb
77
+
78
+ n.inspect
79
+ end
80
+ end
81
+
@@ -0,0 +1,103 @@
1
+ #--
2
+ # Copyright (c) 2015-2017, John Mettraux, jmettraux+flor@gmail.com
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in
12
+ # all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ # THE SOFTWARE.
21
+ #
22
+ # Made in Japan.
23
+ #++
24
+
25
+ require 'fileutils'
26
+
27
+
28
+ module Flor; end
29
+ module Flor::Tools; end
30
+
31
+ module Flor::Tools::Env
32
+
33
+ def self.make(path, envname=nil, opts={})
34
+
35
+ if envname.is_a?(Hash)
36
+ opts = envname
37
+ envname = nil
38
+ end
39
+
40
+ opts[:env] = envname || 'production'
41
+ opts[:sto_uri] ||= 'sqlite://tmp/dev.db'
42
+ opts[:gitkeep] = true unless opts.has_key?(:gitkeep)
43
+
44
+ mkdir(path, envname) if envname
45
+
46
+ mk_etc(path, envname, opts)
47
+ mk_lib(path, envname, opts)
48
+ mk_usr(path, envname, opts)
49
+ mk_var(path, envname, opts)
50
+ end
51
+
52
+ # protected, somehow
53
+
54
+ def self.mk_etc(*ps, opts)
55
+
56
+ mkdir(*ps, 'etc')
57
+ mkdir(*ps, 'etc', 'variables')
58
+ touch(*ps, 'etc', 'variables', '.gitkeep') if opts[:gitkeep]
59
+
60
+ write(*ps, 'etc', 'conf.json') do
61
+ "env: #{opts[:env]}\n" +
62
+ "sto_uri: #{opts[:sto_uri].inspect}"
63
+ end
64
+ end
65
+
66
+ def self.mk_lib(*ps, opts)
67
+
68
+ mkdir(*ps, 'lib')
69
+ mkdir(*ps, 'lib', 'flows')
70
+ touch(*ps, 'lib', 'flows', '.gitkeep') if opts[:gitkeep]
71
+ mkdir(*ps, 'lib', 'taskers')
72
+ touch(*ps, 'lib', 'taskers', '.gitkeep') if opts[:gitkeep]
73
+ end
74
+
75
+ def self.mk_usr(*ps, opts)
76
+
77
+ mkdir(*ps, 'usr')
78
+
79
+ if opts[:acme] == false
80
+ touch(*ps, 'usr', '.gitkeep') if opts[:gitkeep]
81
+ else
82
+ mkdir(*ps, 'usr', 'com.acme')
83
+ mk_etc(*ps, 'usr', 'com.acme', opts)
84
+ mk_lib(*ps, 'usr', 'com.acme', opts)
85
+ end
86
+ end
87
+
88
+ def self.mk_var(*ps, opts)
89
+
90
+ mkdir(*ps, 'var')
91
+ mkdir(*ps, 'var', 'log')
92
+ touch(*ps, 'var', 'log', '.gitkeep') if opts[:gitkeep]
93
+ end
94
+
95
+ def self.mkdir(*ps); FileUtils.mkdir(File.join(*ps.compact)); end
96
+ def self.touch(*ps); FileUtils.touch(File.join(*ps.compact)); end
97
+
98
+ def self.write(*ps, &block)
99
+
100
+ File.open(File.join(*ps.compact), 'wb') { |f| f.write(block.call) }
101
+ end
102
+ end
103
+
@@ -0,0 +1,231 @@
1
+
2
+ require 'flor'
3
+ require 'flor/unit'
4
+
5
+
6
+ module Flor::Tools
7
+
8
+ class Repl
9
+
10
+ def initialize(env)
11
+
12
+ @unit = Flor::Unit.new("envs/#{env}/etc/conf.json")
13
+
14
+ #pp @unit.conf
15
+ @unit.conf[:unit] = 'repl'
16
+
17
+ #unit.hooker.add('journal', Flor::Journal)
18
+ if @unit.conf['sto_uri'].match(/memory/)
19
+ @unit.storage.delete_tables
20
+ @unit.storage.migrate
21
+ end
22
+ @unit.start
23
+
24
+ @lines = []
25
+ @payload = {}
26
+ @vars = {}
27
+
28
+ @outcome = nil
29
+
30
+ @unit.hook do |message|
31
+
32
+ if ! message['consumed']
33
+ # do nothing
34
+ elsif %w[ terminated failed ].include?(message['point'])
35
+ @outcome = message
36
+ out = Flor.to_pretty_s(@outcome)
37
+ col = message['point'] == 'failed' ? _rd : _gr
38
+ out = out.gsub(/"point"=>"([^"]+)"/, "\"point\"=>\"#{col}\\1#{_yl}\"")
39
+ out = "\n" + _yl + out + _rs
40
+ out = out.split("\n").collect { |l| ' ' + l }.join("\n")
41
+ print(out)
42
+ end
43
+ end
44
+
45
+ @_c, @_dg, @_yl, @_bl, @_lg, @_gr, @_lr, @_rd = Flor.colours({})
46
+
47
+ do_loop
48
+ end
49
+
50
+ # reset dark_grey light_yellow blue light_grey light_green light_red red
51
+ attr_reader :_rs, :_dg, :_yl, :_bl, :_lg, :_gr, :_lr, :_rd
52
+
53
+ protected
54
+
55
+ def prompt
56
+
57
+ "flor l#{@lines.size} > "
58
+ end
59
+
60
+ def do_loop
61
+
62
+ loop do
63
+
64
+ line = prompt_and_read
65
+
66
+ break unless line
67
+ next if line.strip == ''
68
+
69
+ cmd = "cmd_#{line.split(/\s/).first}".to_sym
70
+
71
+ if cmd.size > 4 && methods.include?(cmd)
72
+ begin
73
+ send(cmd, line)
74
+ rescue StandardError, NotImplementedError => err
75
+ p err
76
+ err.backtrace[0, 7].each { |l| puts " #{l}" }
77
+ end
78
+ else
79
+ @lines << line
80
+ end
81
+ end
82
+
83
+ $stdout.puts
84
+ end
85
+
86
+ def hlp_launch
87
+ %{ launches the current execution code }
88
+ end
89
+ def cmd_launch(line)
90
+
91
+ exid = @unit.launch(@lines.join("\n"), vars: @vars, payload: @payload)
92
+ puts " launched #{_yl}#{exid}#{_rs}"
93
+ end
94
+
95
+ alias hlp_run hlp_launch
96
+ alias cmd_run cmd_launch
97
+
98
+ def hlp_help
99
+ %{ displays this help }
100
+ end
101
+ def cmd_help(line)
102
+
103
+ puts
104
+ puts "## available commands:"
105
+ puts
106
+ COMMANDS.each do |cmd|
107
+ print "* #{cmd}"
108
+ if hlp = (send("hlp_#{cmd}") rescue nil); print " - #{hlp.strip}"; end
109
+ puts
110
+ end
111
+ puts
112
+ end
113
+
114
+ def hlp_exit
115
+ %{ exits this repl, with the given int exit code or 0 }
116
+ end
117
+ def cmd_exit(line)
118
+
119
+ exit(line.split(/\s+/)[1].to_i)
120
+ end
121
+
122
+ def hlp_list
123
+ %{ lists the lines of the current execution code }
124
+ end
125
+ def do_list(lines)
126
+
127
+ lw = [ 2, lines.size.to_s.length ].max
128
+ sw = 5 - lw
129
+
130
+ lines.each_with_index do |l, i|
131
+ puts "#{_dg}% #{sw}s%0#{lw}i #{_yl}%s#{_rs}" % [ '', i + 1, l ]
132
+ end
133
+ end
134
+ def cmd_list(line)
135
+
136
+ do_list(@lines)
137
+ end
138
+
139
+ def hlp_parse
140
+ %{ parses the current execution code and displays its tree }
141
+ end
142
+ def cmd_parse(line)
143
+
144
+ Flor.print_tree(
145
+ Flor::Lang.parse(@lines.join("\n"), nil, {}),
146
+ '0',
147
+ headers: false)
148
+ end
149
+
150
+ def hlp_new
151
+ %w{ erases current execution code, vars and payload }
152
+ end
153
+ def cmd_new(line)
154
+
155
+ @lines = []
156
+ @vars = {}
157
+ @payload = {}
158
+ end
159
+
160
+ def fname(line)
161
+
162
+ line.split(/\s+/)[1]
163
+ end
164
+
165
+ def hlp_save
166
+ %{ saves the current execution code to the given file }
167
+ end
168
+ def cmd_save(line)
169
+
170
+ File.open(fname(line), 'wb') { |f| f.puts @lines }
171
+ end
172
+
173
+ def hlp_cat
174
+ %{ outputs the content of the give file }
175
+ end
176
+ def cmd_cat(line)
177
+
178
+ do_list(File.readlines(fname(line)).collect(&:chomp))
179
+ end
180
+
181
+ def hlp_load
182
+ %{ loads a file as execution code }
183
+ end
184
+ def cmd_load(line)
185
+
186
+ @lines = File.readlines(fname(line)).collect(&:chomp)
187
+ end
188
+
189
+ def cmd_cont(line)
190
+
191
+ fail NotImplementedError
192
+ end
193
+
194
+ def hlp_edit
195
+ %{ saves the current execution code to .tmp.flo and opens it for edition }
196
+ end
197
+ def cmd_edit(line)
198
+
199
+ cmd_save('save .tmp.flo')
200
+ system('$EDITOR .tmp.flo')
201
+ cmd_load('load .tmp.flo')
202
+ FileUtils.rm('.tmp.flo')
203
+ end
204
+
205
+ #
206
+ # use Readline if possible
207
+
208
+ COMMANDS = self.allocate.methods \
209
+ .select { |m| m.to_s.match(/^cmd_/) }.collect { |m| m[4..-1] }.sort
210
+
211
+ begin
212
+ require 'readline'
213
+ def prompt_and_read
214
+ Readline.readline(prompt, true)
215
+ end
216
+ Readline.completion_proc =
217
+ proc { |s|
218
+ r = /^#{Regexp.escape(s)}/
219
+ COMMANDS.grep(r) + Dir["#{s}*"].grep(r)
220
+ }
221
+ #Readline.completion_append_character =
222
+ # " "
223
+ rescue LoadError => le
224
+ def prompt_and_read
225
+ print(prompt)
226
+ ($stdin.readline rescue false)
227
+ end
228
+ end
229
+ end
230
+ end
231
+
@@ -0,0 +1,260 @@
1
+ #--
2
+ # Copyright (c) 2015-2017, John Mettraux, jmettraux+flor@gmail.com
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in
12
+ # all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ # THE SOFTWARE.
21
+ #
22
+ # Made in Japan.
23
+ #++
24
+
25
+
26
+ module Flor
27
+
28
+ class UnitExecutor < Flor::Executor
29
+
30
+ attr_reader :exid
31
+
32
+ def initialize(unit, exid)
33
+
34
+ super(
35
+ unit,
36
+ unit.storage.fetch_traps(exid),
37
+ unit.storage.load_execution(exid))
38
+
39
+ @exid = exid
40
+ @messages = unit.storage.fetch_messages(exid)
41
+ @consumed = []
42
+
43
+ @alive = true
44
+ @shutdown = false
45
+
46
+ @thread = nil
47
+ end
48
+
49
+ def alive?; @alive; end
50
+
51
+ def run
52
+
53
+ @thread = Thread.new { do_run }
54
+ #p [ :unit_executor, :thread, @thread.object_id ]
55
+
56
+ self
57
+ end
58
+
59
+ def shutdown
60
+
61
+ @shutdown = true
62
+ @thread.join
63
+ end
64
+
65
+ protected
66
+
67
+ def do_run
68
+
69
+ log_run_start if @unit.conf['log_run']
70
+
71
+ counter_next('runs')
72
+
73
+ t0 = Time.now
74
+
75
+ (@unit.conf['exe_max_messages'] || 77).times do |i|
76
+
77
+ m = @messages.shift
78
+ break unless m
79
+ break if @shutdown
80
+
81
+ if m['point'] == 'terminated' && @messages.any?
82
+ #
83
+ # try to handle 'terminated' last
84
+ #
85
+ @messages << m
86
+ m = @messages.shift
87
+ end
88
+
89
+ point = m['point']
90
+
91
+ ms = process(m)
92
+
93
+ @consumed << m
94
+ #
95
+ #@consumed << m unless ms.include?(m)
96
+ # TODO what if msg is held / pushed back?
97
+
98
+ ims, oms = ms.partition { |m| m['exid'] == @exid }
99
+ # qui est "in", qui est "out"?
100
+
101
+ counter_add('omsgs', oms.size)
102
+ # keep track of "out" messages, messages to other executions
103
+
104
+ @messages.concat(ims)
105
+ @unit.storage.put_messages(oms)
106
+ end
107
+
108
+ @unit.storage.consume(@consumed)
109
+
110
+ @alive = false
111
+
112
+ @unit.storage.put_execution(@execution)
113
+ @unit.storage.put_messages(@messages)
114
+
115
+ log_run_end(t0) if @unit.conf['log_run']
116
+
117
+ @consumed.clear
118
+
119
+ rescue Exception => exc
120
+
121
+ # TODO eventually, have a dump dir
122
+ fn =
123
+ [
124
+ 'flor',
125
+ @unit.conf['env'], @unit.identifier, @exid,
126
+ 'r' + counter('runs').to_s
127
+ ].collect(&:to_s).join('_') + '.dump'
128
+
129
+ @unit.logger.error(
130
+ "#{self.class}#do_run()", exc, "(dumping to #{fn})")
131
+
132
+ File.open(fn, 'wb') do |f|
133
+ #f.puts(JSON.pretty_generate({
134
+ f.puts(Flor.to_pretty_s({
135
+ execution: @execution,
136
+ messages: @messages,
137
+ consumed: @consumed,
138
+ traps: @traps.collect(&:to_h),
139
+ exid: @exid,
140
+ alive: @alive,
141
+ shutdown: @shutdown,
142
+ thread: [ @thread.object_id, @thread.to_s ]
143
+ }))
144
+ f.puts('-' * 80)
145
+ f.puts(on_do_run_exc(exc))
146
+ end
147
+
148
+ puts on_do_run_exc(exc)
149
+ end
150
+
151
+ def schedule(message)
152
+
153
+ @unit.put_timer(message)
154
+
155
+ []
156
+ end
157
+
158
+ def trigger(message)
159
+
160
+ m = message['message']
161
+
162
+ m['nid'] = Flor.sub_nid(m['nid'], counter_next('subs')) \
163
+ if m['point'] == 'execute'
164
+
165
+ [ m ]
166
+ end
167
+
168
+ def log_run_start
169
+
170
+ _c = Flor.colours
171
+
172
+ s = StringIO.new
173
+
174
+ s << _c.dg
175
+ s << " /--- #{_c.lg}run starts#{_c.dg} "
176
+ s << "#{self.class} #{self.object_id} #{@exid}"
177
+ s << "\n | "
178
+ s << { thread: Thread.current.object_id }.inspect
179
+ s << "\n | "
180
+ s << {
181
+ counters: @execution['counters'],
182
+ nodes: @execution['nodes'].size,
183
+ size: @execution['size']
184
+ }.inspect
185
+ s << _c.rs
186
+
187
+ puts s.string
188
+ end
189
+
190
+ def log_run_end(t0)
191
+
192
+ _c = Flor.colours
193
+
194
+ s = StringIO.new
195
+
196
+ s << _c.dg
197
+ s << " | run ends #{self.class} #{self.object_id} #{@exid}"
198
+ s << "\n | "; s << { took: Time.now - t0 }.inspect
199
+ s << "\n | "; s << {
200
+ thread: Thread.current.object_id,
201
+ consumed: @consumed.size,
202
+ traps: @traps.size,
203
+ }.inspect
204
+ s << "\n | "; s << {
205
+ #own_traps: @traps.reject { |t| t.texid == nil }.size, # FIXME
206
+ counters: @execution['counters'],
207
+ nodes: @execution['nodes'].size,
208
+ size: @execution['size']
209
+ }.inspect
210
+ if @unit.archive
211
+ s << "\n | "
212
+ s << {
213
+ archive_size: @unit.archive[@exid].size
214
+ }.inspect
215
+ end
216
+ s << "\n \\--- ."
217
+ s << _c.rs
218
+
219
+ puts s.string
220
+ end
221
+
222
+ def on_do_run_exc(e)
223
+
224
+ io = StringIO.new
225
+ thr = Thread.current
226
+
227
+ head, kind =
228
+ e.is_a?(StandardError) ? [ '=exe', 'error' ] : [ '!exe', 'exception' ]
229
+
230
+ t = head[0, 2] + Time.now.to_f.to_s.split('.').last
231
+ io.puts ' /' + t + ' ' + head * 17
232
+ io.puts " |#{t} + in #{self.class}#do_run"
233
+ io.puts " |#{t} #{kind}: #{e.inspect}"
234
+ io.puts " |#{t} db: #{@unit.storage.db.class} #{@unit.storage.db.hash}"
235
+ io.puts " |#{t} thread: t#{thr.object_id} #{thr.inspect}"
236
+ if @execution
237
+ io.puts " |#{t} exe:"
238
+ io.puts " |#{t} exid: #{@execution['exid'].inspect}"
239
+ io.puts " |#{t} counters: #{@execution['counters'].inspect}"
240
+ end
241
+ if @messages
242
+ io.puts " |#{t} messages:"
243
+ io.puts " |#{t} #{@messages.map { |m| [ m['mid'], m['point'] ] }.inspect}"
244
+ end
245
+ if is = Thread.current[:sto_errored_items]
246
+ io.puts " |#{t} storage errored items/models:"
247
+ is.each do |i|
248
+ io.puts " |#{t} * #{i.inspect}"
249
+ end
250
+ end
251
+ io.puts " |#{t} #{kind}: #{e.inspect}"
252
+ io.puts " |#{t} backtrace:"
253
+ e.backtrace.each { |l| io.puts "|#{t} #{l}" }
254
+ io.puts ' \\' + t + ' ' + (head * 17) + ' .'
255
+
256
+ io.string
257
+ end
258
+ end
259
+ end
260
+