flor 0.18.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (165) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +29 -0
  3. data/CREDITS.md +1 -0
  4. data/LICENSE.txt +1 -1
  5. data/Makefile +1 -1
  6. data/README.md +16 -2
  7. data/flor.gemspec +1 -2
  8. data/lib/flor.rb +3 -2
  9. data/lib/flor/colours.rb +5 -3
  10. data/lib/flor/conf.rb +1 -0
  11. data/lib/flor/core.rb +9 -8
  12. data/lib/flor/core/executor.rb +20 -16
  13. data/lib/flor/core/node.rb +1 -13
  14. data/lib/flor/core/procedure.rb +10 -1
  15. data/lib/flor/core/texecutor.rb +35 -3
  16. data/lib/flor/djan.rb +1 -0
  17. data/lib/flor/errors.rb +1 -0
  18. data/lib/flor/flor.rb +172 -26
  19. data/lib/flor/id.rb +5 -1
  20. data/lib/flor/log.rb +14 -8
  21. data/lib/flor/migrations/0001_tables.rb +1 -0
  22. data/lib/flor/migrations/0002_cunit_and_munit.rb +1 -0
  23. data/lib/flor/migrations/0003_timer_onid_bnid.rb +1 -0
  24. data/lib/flor/migrations/0004_trap_bnid.rb +1 -0
  25. data/lib/flor/migrations/0005_pointer_content.rb +1 -0
  26. data/lib/flor/parser.rb +19 -11
  27. data/lib/flor/pcore/_apply.rb +1 -0
  28. data/lib/flor/pcore/_arr.rb +1 -0
  29. data/lib/flor/pcore/_atom.rb +1 -0
  30. data/lib/flor/pcore/_att.rb +1 -0
  31. data/lib/flor/pcore/_coll.rb +1 -0
  32. data/lib/flor/pcore/_dmute.rb +1 -0
  33. data/lib/flor/pcore/_dol.rb +1 -0
  34. data/lib/flor/pcore/_dqs.rb +1 -0
  35. data/lib/flor/pcore/_dump.rb +1 -0
  36. data/lib/flor/pcore/_err.rb +1 -0
  37. data/lib/flor/pcore/_head.rb +1 -0
  38. data/lib/flor/pcore/_obj.rb +1 -0
  39. data/lib/flor/pcore/_pat_.rb +1 -0
  40. data/lib/flor/pcore/_pat_arr.rb +1 -0
  41. data/lib/flor/pcore/_pat_guard.rb +1 -0
  42. data/lib/flor/pcore/_pat_obj.rb +1 -0
  43. data/lib/flor/pcore/_pat_or.rb +1 -0
  44. data/lib/flor/pcore/_pat_regex.rb +1 -0
  45. data/lib/flor/pcore/_ref.rb +1 -0
  46. data/lib/flor/pcore/_rxs.rb +1 -0
  47. data/lib/flor/pcore/_skip.rb +1 -0
  48. data/lib/flor/pcore/_val.rb +1 -0
  49. data/lib/flor/pcore/all.rb +1 -0
  50. data/lib/flor/pcore/andor.rb +1 -0
  51. data/lib/flor/pcore/any.rb +1 -0
  52. data/lib/flor/pcore/apply.rb +1 -0
  53. data/lib/flor/pcore/arith.rb +1 -0
  54. data/lib/flor/pcore/array_qmark.rb +1 -0
  55. data/lib/flor/pcore/break.rb +1 -0
  56. data/lib/flor/pcore/case.rb +1 -0
  57. data/lib/flor/pcore/cmp.rb +1 -0
  58. data/lib/flor/pcore/collect.rb +2 -1
  59. data/lib/flor/pcore/cond.rb +1 -0
  60. data/lib/flor/pcore/cursor.rb +45 -3
  61. data/lib/flor/pcore/define.rb +1 -0
  62. data/lib/flor/pcore/detect.rb +1 -0
  63. data/lib/flor/pcore/do_return.rb +1 -0
  64. data/lib/flor/pcore/each.rb +1 -0
  65. data/lib/flor/pcore/echo.rb +1 -0
  66. data/lib/flor/pcore/empty.rb +1 -0
  67. data/lib/flor/pcore/fail.rb +1 -0
  68. data/lib/flor/pcore/filter.rb +1 -0
  69. data/lib/flor/pcore/find.rb +1 -0
  70. data/lib/flor/pcore/flatten.rb +1 -0
  71. data/lib/flor/pcore/for_each.rb +1 -0
  72. data/lib/flor/pcore/if.rb +1 -0
  73. data/lib/flor/pcore/includes.rb +1 -0
  74. data/lib/flor/pcore/inject.rb +1 -0
  75. data/lib/flor/pcore/iterator.rb +1 -0
  76. data/lib/flor/pcore/keys.rb +1 -0
  77. data/lib/flor/pcore/length.rb +1 -0
  78. data/lib/flor/pcore/loop.rb +1 -0
  79. data/lib/flor/pcore/map.rb +1 -0
  80. data/lib/flor/pcore/match.rb +1 -0
  81. data/lib/flor/pcore/matchr.rb +1 -0
  82. data/lib/flor/pcore/max.rb +1 -0
  83. data/lib/flor/pcore/merge.rb +1 -0
  84. data/lib/flor/pcore/move.rb +1 -0
  85. data/lib/flor/pcore/noeval.rb +1 -0
  86. data/lib/flor/pcore/noret.rb +1 -0
  87. data/lib/flor/pcore/not.rb +1 -0
  88. data/lib/flor/pcore/on.rb +4 -3
  89. data/lib/flor/pcore/on_cancel.rb +1 -0
  90. data/lib/flor/pcore/on_error.rb +1 -0
  91. data/lib/flor/pcore/push.rb +1 -0
  92. data/lib/flor/pcore/rand.rb +1 -0
  93. data/lib/flor/pcore/range.rb +1 -0
  94. data/lib/flor/pcore/reduce.rb +1 -0
  95. data/lib/flor/pcore/return.rb +1 -0
  96. data/lib/flor/pcore/reverse.rb +1 -0
  97. data/lib/flor/pcore/select.rb +1 -0
  98. data/lib/flor/pcore/sequence.rb +1 -0
  99. data/lib/flor/pcore/set.rb +1 -0
  100. data/lib/flor/pcore/shuffle.rb +1 -0
  101. data/lib/flor/pcore/slice.rb +1 -0
  102. data/lib/flor/pcore/sort.rb +1 -0
  103. data/lib/flor/pcore/sort_by.rb +1 -0
  104. data/lib/flor/pcore/split.rb +1 -0
  105. data/lib/flor/pcore/stall.rb +1 -0
  106. data/lib/flor/pcore/strings.rb +1 -0
  107. data/lib/flor/pcore/timestamp.rb +1 -0
  108. data/lib/flor/pcore/to_array.rb +1 -0
  109. data/lib/flor/pcore/twig.rb +1 -0
  110. data/lib/flor/pcore/type_of.rb +1 -0
  111. data/lib/flor/pcore/until.rb +1 -0
  112. data/lib/flor/punit/abort.rb +50 -0
  113. data/lib/flor/punit/c_collect.rb +1 -0
  114. data/lib/flor/punit/c_each.rb +19 -0
  115. data/lib/flor/punit/c_for_each.rb +2 -1
  116. data/lib/flor/punit/c_iterator.rb +2 -1
  117. data/lib/flor/punit/c_map.rb +1 -0
  118. data/lib/flor/punit/cancel.rb +1 -0
  119. data/lib/flor/punit/concurrence.rb +7 -5
  120. data/lib/flor/punit/cron.rb +1 -0
  121. data/lib/flor/punit/do_trap.rb +1 -0
  122. data/lib/flor/punit/every.rb +1 -0
  123. data/lib/flor/punit/graft.rb +1 -0
  124. data/lib/flor/punit/{m_ram.rb → m_receive_and_merge.rb} +5 -4
  125. data/lib/flor/punit/on_timeout.rb +1 -0
  126. data/lib/flor/punit/part.rb +1 -0
  127. data/lib/flor/punit/schedule.rb +1 -0
  128. data/lib/flor/punit/signal.rb +1 -0
  129. data/lib/flor/punit/sleep.rb +1 -0
  130. data/lib/flor/punit/task.rb +1 -0
  131. data/lib/flor/punit/trace.rb +1 -0
  132. data/lib/flor/punit/trap.rb +10 -1
  133. data/lib/flor/to_string.rb +1 -0
  134. data/lib/flor/tools/env.rb +1 -0
  135. data/lib/flor/tools/firb.rb +33 -0
  136. data/lib/flor/tools/shell.rb +13 -3
  137. data/lib/flor/tools/shell_out.rb +1 -0
  138. data/lib/flor/tt.rb +98 -0
  139. data/lib/flor/unit.rb +3 -0
  140. data/lib/flor/unit/caller.rb +158 -23
  141. data/lib/flor/unit/caller_jruby.rb +133 -0
  142. data/lib/flor/unit/dump.rb +36 -0
  143. data/lib/flor/unit/executor.rb +19 -13
  144. data/lib/flor/unit/ganger.rb +9 -12
  145. data/lib/flor/unit/gangers.rb +125 -0
  146. data/lib/flor/unit/hloader.rb +34 -7
  147. data/lib/flor/unit/hook.rb +3 -0
  148. data/lib/flor/unit/hooker.rb +32 -15
  149. data/lib/flor/unit/journal.rb +23 -0
  150. data/lib/flor/unit/loader.rb +142 -15
  151. data/lib/flor/unit/logger.rb +35 -7
  152. data/lib/flor/unit/models.rb +8 -1
  153. data/lib/flor/unit/models/execution.rb +51 -0
  154. data/lib/flor/unit/models/message.rb +6 -0
  155. data/lib/flor/unit/models/pointer.rb +21 -1
  156. data/lib/flor/unit/models/timer.rb +1 -0
  157. data/lib/flor/unit/models/trace.rb +1 -0
  158. data/lib/flor/unit/models/trap.rb +3 -2
  159. data/lib/flor/unit/scheduler.rb +51 -36
  160. data/lib/flor/unit/spooler.rb +1 -0
  161. data/lib/flor/unit/storage.rb +113 -84
  162. data/lib/flor/unit/taskers.rb +70 -1
  163. data/lib/flor/unit/waiter.rb +22 -17
  164. data/lib/flor/unit/wlist.rb +19 -8
  165. metadata +16 -11
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module Flor
3
4
 
@@ -14,6 +15,8 @@ module Flor
14
15
 
15
16
  def to_hook
16
17
 
18
+ @unit.loader.require(@h)
19
+
17
20
  if @h['class']
18
21
  class_to_hook
19
22
  elsif @h['instance']
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module Flor
3
4
 
@@ -5,6 +6,22 @@ module Flor
5
6
 
6
7
  # NB: logger configuration entries start with "hok_"
7
8
 
9
+ attr_reader :hooks
10
+
11
+ KEYS = {
12
+ consumed: [:consumed, :c].freeze,
13
+ point: [:point, :p].freeze,
14
+ nid: [:nid].freeze,
15
+ exid: [:exid].freeze,
16
+ domain: [:domain, :d].freeze,
17
+ subdomain: [:subdomain, :sd].freeze,
18
+ tag: [:tag, :t].freeze,
19
+ name: [:name, :n].freeze,
20
+ subnid: [:subnid].freeze,
21
+ heap: [:heap, :hp].freeze,
22
+ heat: [:heat, :ht].freeze
23
+ }.freeze
24
+
8
25
  def initialize(unit)
9
26
 
10
27
  @unit = unit
@@ -54,7 +71,11 @@ module Flor
54
71
  end
55
72
  end
56
73
 
57
- hook = Flor::Hook.instantiate(@unit, hook) if hook.is_a?(Class)
74
+ hook = Flor::Hook.instantiate(@unit, hook) \
75
+ if hook.is_a?(Class)
76
+
77
+ name ||= hook.name \
78
+ if hook.respond_to?(:name) && hook.method(:name).arity < 1
58
79
 
59
80
  @hooks << [ name, opts, hook, block ]
60
81
  end
@@ -81,13 +102,10 @@ module Flor
81
102
 
82
103
  protected
83
104
 
84
- def o(opts, *keys)
85
-
86
- array = false
87
- array = keys.pop if keys.last == []
105
+ def o(opts, key, array: false)
88
106
 
89
107
  r = nil
90
- keys.each { |k| break r = opts[k] if opts.has_key?(k) }
108
+ KEYS[key].each { |k| break r = opts[k] if opts.has_key?(k) }
91
109
 
92
110
  return nil if r == nil
93
111
  array ? Array(r) : r
@@ -103,7 +121,7 @@ module Flor
103
121
 
104
122
  opts = hook.opts if hook.respond_to?(:opts) && opts.empty?
105
123
 
106
- c = o(opts, :consumed, :c)
124
+ c = o(opts, :consumed)
107
125
  return false if c == true && ! message['consumed']
108
126
  return false if c == false && message['consumed']
109
127
 
@@ -112,7 +130,7 @@ module Flor
112
130
  return false if hook.within_itself?(executor, message)
113
131
  end
114
132
 
115
- ps = o(opts, :point, :p, [])
133
+ ps = o(opts, :point, array: true)
116
134
  return false if ps && ! ps.include?(message['point'])
117
135
 
118
136
  if nid = o(opts, :nid)
@@ -127,24 +145,24 @@ module Flor
127
145
 
128
146
  dm = Flor.domain(message['exid'])
129
147
 
130
- if dm && ds = o(opts, :domain, :d, [])
148
+ if dm && ds = o(opts, :domain, array: true)
131
149
  return false \
132
150
  unless ds.find { |d| d.is_a?(Regexp) ? (!! d.match(dm)) : (d == dm) }
133
151
  end
134
152
 
135
- if dm && sds = o(opts, :subdomain, :sd, [])
153
+ if dm && sds = o(opts, :subdomain, array: true)
136
154
  return false \
137
155
  unless sds.find do |sd|
138
156
  dm[0, sd.length] == sd
139
157
  end
140
158
  end
141
159
 
142
- if ts = o(opts, :tag, :t, [])
160
+ if ts = o(opts, :tag, array: true)
143
161
  return false unless %w[ entered left ].include?(message['point'])
144
162
  return false unless includes?(ts, message['tags'])
145
163
  end
146
164
 
147
- if ns = o(opts, :name, :n)
165
+ if ns = o(opts, :name)
148
166
  name = message['name']
149
167
  return false \
150
168
  unless ns.find { |n|
@@ -166,12 +184,12 @@ module Flor
166
184
  end
167
185
  end
168
186
 
169
- if hps = o(opts, :heap, :hp, [])
187
+ if hps = o(opts, :heap, array: true)
170
188
  return false unless node ||= executor.node(message['nid'])
171
189
  return false unless includes?(hps, node['heap'])
172
190
  end
173
191
 
174
- if hts = o(opts, :heat, :ht, [])
192
+ if hts = o(opts, :heat, array: true)
175
193
  return false unless node ||= executor.node(message['nid'])
176
194
  return false unless includes?(hts, node['heat0'])
177
195
  end
@@ -180,4 +198,3 @@ module Flor
180
198
  end
181
199
  end
182
200
  end
183
-
@@ -1,13 +1,24 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module Flor
3
4
 
5
+ # A Journal hook, receives only "consumed" messages and
6
+ # keeps a copy of all of them.
7
+ #
8
+ # Used in specs, do not uses as-is in production, since it simply
9
+ # grows in memory...
10
+ #
4
11
  class Journal
5
12
 
6
13
  attr_reader :messages
7
14
 
8
15
  def initialize(unit)
9
16
 
17
+ # Add a #journal method to the flor unit so that
18
+ # `unit.journal` yields the message list.
19
+ #
10
20
  unit.singleton_class.instance_eval do
21
+
11
22
  define_method(:journal) do
12
23
  @hooker['journal'].messages
13
24
  end
@@ -16,11 +27,23 @@ module Flor
16
27
  @messages = []
17
28
  end
18
29
 
30
+ # Tells the hooker that this hook is only interested in message that
31
+ # have been "consumed", remember, the hooker passes messages to
32
+ # hooks before consumption and after consumption. In this case only
33
+ # consumed messages are passed.
34
+ #
35
+ # Other hooks may declare they are only interested in messages
36
+ # belonging to a certain domain or having a certain tag.
37
+ # See spec/unit/unit_hooks_spec.rb for more filtering examples.
38
+ #
19
39
  def opts; { consumed: true }; end
20
40
 
41
+ # The method used by the hooker to give consumed messages to this journal
42
+ #
21
43
  def notify(executor, message)
22
44
 
23
45
  @messages << Flor.dup(message)
46
+ # stores a deep clone of each consumed message
24
47
 
25
48
  [] # no new messages
26
49
  end
@@ -1,7 +1,30 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module Flor
3
4
 
4
- class Loader
5
+ class CoreLoader
6
+
7
+ def shutdown
8
+ end
9
+
10
+ # Called to interpret require: confs from hooks and friends
11
+ #
12
+ def require(conf)
13
+
14
+ re = conf['require']
15
+
16
+ return unless re
17
+
18
+ ::Kernel.require(
19
+ if path = conf['_path']
20
+ File.join(File.dirname(path), re)
21
+ else
22
+ re
23
+ end)
24
+ end
25
+ end
26
+
27
+ class Loader < CoreLoader
5
28
 
6
29
  # NB: tasker configuration entries start with "loa_"
7
30
 
@@ -12,10 +35,8 @@ module Flor
12
35
  @cache = {}
13
36
  @mutex = Mutex.new
14
37
 
15
- @root = File.absolute_path(@unit.conf['lod_path'] || @unit.conf['root'])
16
- end
17
-
18
- def shutdown
38
+ @root = File.absolute_path(
39
+ @unit.conf['lod_path'] || @unit.conf['root'] || '.')
19
40
  end
20
41
 
21
42
  def variables(domain)
@@ -25,7 +46,7 @@ module Flor
25
46
  .collect { |pa| [ pa, expose_d(pa, {}) ] }
26
47
  .select { |pa, d| Flor.sub_domain?(d, domain) }
27
48
  .sort_by { |pa, d| d.count('.') }
28
- .inject({}) { |vars, (pa, _)| vars.merge!(eval(pa, {})) }
49
+ .inject({}) { |vars, (pa, _)| vars.merge!(eval_variables(pa, {})) }
29
50
  end
30
51
 
31
52
  #def procedures(path)
@@ -66,25 +87,28 @@ module Flor
66
87
  .select { |pa| pa.index('/lib/taskers/') }
67
88
  .collect { |pa| [ pa, *expose_dn(pa, {}) ] }
68
89
  .select { |pa, d, n|
69
- Flor.sub_domain?([ d, n ].join('.'), domain) ||
90
+ Flor.sub_domain?([ d, n ], domain) ||
70
91
  (n == name && Flor.sub_domain?(d, domain)) }
71
92
  .sort_by { |pa, d, n| d.count('.') }
72
93
  .last
73
94
 
74
95
  return nil unless pat
75
96
 
76
- conf = eval(pat, message)
97
+ conf = eval_tasker_conf(pat, message)
77
98
 
78
99
  return conf if nam == name
79
100
 
80
- conf = conf[name]
101
+ cnf = conf[name]
102
+
103
+ return nil unless cnf
81
104
 
82
- return nil unless conf
105
+ extras = conf.select { |_, v| ! v.is_a?(Hash) }
106
+ extras['_path'] = pat
83
107
 
84
- (conf.is_a?(Array) ? conf : [ conf ])
85
- .each { |h| h['_path'] = pat }
108
+ (cnf.is_a?(Array) ? cnf : [ cnf ])
109
+ .each { |h| h.merge!(extras) }
86
110
 
87
- conf
111
+ cnf
88
112
  end
89
113
 
90
114
  def hooks(domain)
@@ -98,8 +122,8 @@ module Flor
98
122
  .select { |pa, d| Flor.sub_domain?(d, domain) }
99
123
  .sort_by { |pa, d| d.count('.') }
100
124
  .collect { |pa, d|
101
- eval(pa, {}).each_with_index { |h, i|
102
- h['_path'] = pa + ":#{i}" } }
125
+ eval_hook_conf(pa, {})
126
+ .each_with_index { |h, i| h['_path'] = "#{pa}:#{i}" } }
103
127
  .flatten(1)
104
128
  end
105
129
 
@@ -109,8 +133,82 @@ module Flor
109
133
  .collect { |h| Flor::Hook.new(@unit, exid, h) }
110
134
  end
111
135
 
136
+ def domains(start=nil)
137
+
138
+ start ||= ''
139
+
140
+ Dir[File.join(@root, '**/*.{json,flo,flor,rb}')]
141
+ .collect { |pa| pa[@root.length..-1] }
142
+ .sort
143
+ .collect { |pa|
144
+ pa = pa[4..-1] if pa.match(/^\/usr\//)
145
+ case pa
146
+ when /\.flor?$/ then extract_flow_domain(pa)
147
+ when /\/lib\/hooks\// then extract_hook_domain(pa)
148
+ when /\/lib\/taskers\// then extract_tasker_domain(pa)
149
+ when /\/etc\/variables\// then extract_variable_domain(pa)
150
+ else nil
151
+ end }
152
+ .compact
153
+ .select { |pa| pa.length > 1 }
154
+ .collect { |pa|
155
+ pa = pa[1..-1] if pa[0, 1] == '/'
156
+ pa = pa[0..-2] if pa.match(/\/$/)
157
+ pa.gsub('/', '.') }
158
+ .sort
159
+ .uniq
160
+ .select { |dm| Flor.sub_domain?(start, dm) }
161
+ end
162
+
163
+ def definitions(start=nil)
164
+
165
+ start ||= ''
166
+
167
+ Dir[File.join(@root, '**/*.{flo,flor}')]
168
+ .collect { |pa| pa[@root.length..-1] }
169
+ .collect { |pa| pa.gsub(/\A\/usr\//, '/') }
170
+ .collect { |pa| pa.gsub(/\/lib\/(sub)?flows\//, '/') }
171
+ .collect { |pa| pa.gsub(/\.flor?\z/, '') }
172
+ .collect { |pa| pa.gsub(/\//, '.') }
173
+ .collect { |pa| pa.gsub(/\A\./, '') }
174
+ .sort
175
+ .select { |pa| Flor.sub_domain?(start, pa) }
176
+ end
177
+
112
178
  protected
113
179
 
180
+ def extract_flow_domain(pa)
181
+ #o = pa
182
+ pa
183
+ .gsub(/\/lib\/(sub)?flows\//, '/')
184
+ .split('/')[0..-2].join('/')
185
+ #.tap { |x| p 'flow:' + o + ':' + x }
186
+ end
187
+ def extract_hook_domain(pa)
188
+ #o = pa
189
+ pa
190
+ .gsub(/\/lib\/hooks\//, '/')
191
+ .gsub(/\/(dot|hooks)\.(json|rb)$/, '/')
192
+ .gsub(/\.(json|rb)$/, '')
193
+ #.tap { |x| p 'hook:' + o + ':' + x }
194
+ end
195
+ def extract_tasker_domain(pa)
196
+ #o = pa
197
+ pa
198
+ .gsub(/\/lib\/taskers\//, '/')
199
+ .gsub(/\/[^\/]+\/(dot|flor|tasker)\.(json|rb)$/, '/')
200
+ .gsub(/\.(json|rb)$/, '')
201
+ #.tap { |x| p 'tasker: ' + o + ': ' + x }
202
+ end
203
+ def extract_variable_domain(pa)
204
+ #o = pa
205
+ pa
206
+ .gsub(/\/etc\/variables\//, '/')
207
+ .gsub(/\/(dot|flor)\.(json|rb)$/, '/')
208
+ .gsub(/\.(json|rb)$/, '')
209
+ #.tap { |x| p 'variable: ' + o + ': ' + x }
210
+ end
211
+
114
212
  def split_dn(domain, name)
115
213
 
116
214
  if name
@@ -152,6 +250,35 @@ module Flor
152
250
  end
153
251
  end
154
252
 
253
+ def eval_variables(path, context)
254
+ eval(path, context)
255
+ end
256
+ def eval_tasker_conf(path, context)
257
+ eval(path, context)
258
+ end
259
+ # TODO like in eval_hook_conf, reject fautly tasker confs...
260
+ # TODO like in eval_hook_conf, reject fautly variables...
261
+
262
+ def eval_hook_conf(path, context)
263
+
264
+ a = eval(path, context)
265
+
266
+ fail ArgumentError.new(
267
+ "hook conf at #{path} must be an array of hashes"
268
+ ) unless a.is_a?(Array)
269
+
270
+ a.each do |e|
271
+ fail ArgumentError.new(
272
+ "hook conf at #{path} has non-hash entry #{e.inspect}"
273
+ ) unless e.is_a?(Hash)
274
+ fail ArgumentError.new(
275
+ "hook conf at #{path} has incorrect point #{e['point'].inspect}"
276
+ ) unless e['point'].is_a?(String)
277
+ end
278
+
279
+ a
280
+ end
281
+
155
282
  def eval(path, context)
156
283
 
157
284
  ext =
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module Flor
3
4
 
@@ -62,17 +63,25 @@ module Flor
62
63
  n = Time.now.utc
63
64
  stp = Flor.tstamp(n)
64
65
 
66
+ dbi =
67
+ case @unit.storage.db.to_s
68
+ when /SQLite/ then @unit.storage.db.uri
69
+ else ''
70
+ end
71
+ dbi = ' ' + dbi if dbi.length > 0
72
+
65
73
  txt = elts.collect(&:to_s).join(' ')
66
- err = elts.find { |e| e.is_a?(Exception) }
67
74
 
68
- line = "#{stp} #{@uni} #{lvl} #{txt}"
75
+ err = find_err(elts)
76
+
77
+ head = "#{stp} #{@uni}#{dbi} #{lvl} "
69
78
 
70
79
  if err
71
- dig = lvl[0, 1] + Digest::MD5.hexdigest(line)[0, 4]
72
- @out.puts("#{stp} #{@uni} #{lvl} #{dig} #{txt}")
80
+ dig = lvl[0, 1] + Digest::MD5.hexdigest(head + txt)[0, 4]
81
+ @out.puts(head + dig + ' ' + txt)
73
82
  err.backtrace.each { |lin| @out.puts(" #{dig} #{@uni} #{lin}") }
74
83
  else
75
- @out.puts(line)
84
+ @out.puts(head + txt)
76
85
  end
77
86
  end
78
87
 
@@ -113,7 +122,18 @@ module Flor
113
122
  #
114
123
  msg = summarize_blob(msg)
115
124
 
116
- @out.puts "#{_c.blg}sto#{_c.rs} t#{Thread.current.object_id} #{level.upcase} #{msg}"
125
+ msg = "#{_c.dg}#{msg}"
126
+ msg = msg.gsub(/\b(INSERT|UPDATE)\b/) { |m| "#{_c.rs}#{m}#{_c.dg}" }
127
+
128
+ tim = Time.now.utc.strftime('%T.%L') # HH:MM:SS.123
129
+ dbi = @unit.storage.db.object_id.to_s(16)
130
+ tid = Thread.current.object_id.to_s(16)
131
+ lvl = level.upcase
132
+
133
+ @out.puts(
134
+ "#{_c.blg}sto#{_c.rs} " +
135
+ "#{tim} #{_c.dg}db#{dbi} th#{tid} " +
136
+ "#{_c.rs}#{lvl}#{_c.rs} #{msg}#{_c.rs}")
117
137
  end
118
138
 
119
139
  def size_to_s(s)
@@ -179,7 +199,8 @@ module Flor
179
199
 
180
200
  return unless @unit.conf['log_err']
181
201
 
182
- @out.puts(Flor.msg_to_detail_s(executor, message, opts.merge(flag: true)))
202
+ s = Flor.msg_to_detail_s(executor, message, opts.merge(flag: true))
203
+ @out.puts(s) if s
183
204
  end
184
205
 
185
206
  def log_src(source, opts, log_opts={})
@@ -226,6 +247,13 @@ module Flor
226
247
  message[0..k + 2 + 4] + "(...len#{i - (k + 2 + 1)})" + message[i..-1]
227
248
  end
228
249
 
250
+ def find_err(elts)
251
+
252
+ elts.find { |e| e.is_a?(Exception) } ||
253
+ (defined?(Java) &&
254
+ elts.find { |e| e.class.ancestors.include?(Java::JavaLang::Error) })
255
+ end
256
+
229
257
  class Out
230
258
 
231
259
  attr_reader :unit