openwferu 0.9.16 → 0.9.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (184) hide show
  1. data/examples/about_state.rb +81 -0
  2. data/examples/engine_template.rb +7 -0
  3. data/lib/openwfe/contextual.rb +2 -2
  4. data/lib/openwfe/def.rb +2 -3
  5. data/lib/openwfe/{util/schedulers.rb → engine.rb} +3 -39
  6. data/lib/openwfe/engine/engine.rb +202 -251
  7. data/lib/openwfe/engine/process_status.rb +359 -0
  8. data/lib/openwfe/expool/errorjournal.rb +6 -6
  9. data/lib/openwfe/expool/expressionpool.rb +161 -239
  10. data/lib/openwfe/expool/expstorage.rb +185 -55
  11. data/lib/openwfe/expool/journal.rb +1 -2
  12. data/lib/openwfe/expool/parser.rb +233 -0
  13. data/lib/openwfe/expool/threadedexpstorage.rb +6 -18
  14. data/lib/openwfe/expool/wfidgen.rb +25 -7
  15. data/lib/openwfe/expool/yamlexpstorage.rb +60 -37
  16. data/lib/openwfe/expressions/condition.rb +49 -12
  17. data/lib/openwfe/expressions/environment.rb +45 -15
  18. data/lib/openwfe/expressions/expressionmap.rb +39 -19
  19. data/lib/openwfe/expressions/fe_concurrence.rb +24 -13
  20. data/lib/openwfe/expressions/fe_cron.rb +19 -18
  21. data/lib/openwfe/expressions/fe_cursor.rb +69 -28
  22. data/lib/openwfe/expressions/fe_define.rb +4 -1
  23. data/lib/openwfe/expressions/fe_do.rb +1 -3
  24. data/lib/openwfe/expressions/fe_equals.rb +131 -20
  25. data/lib/openwfe/expressions/fe_fqv.rb +27 -3
  26. data/lib/openwfe/expressions/fe_iterator.rb +14 -7
  27. data/lib/openwfe/expressions/fe_listen.rb +7 -2
  28. data/lib/openwfe/expressions/fe_misc.rb +187 -20
  29. data/lib/openwfe/expressions/fe_participant.rb +8 -7
  30. data/lib/openwfe/expressions/fe_reserve.rb +105 -33
  31. data/lib/openwfe/expressions/fe_save.rb +55 -5
  32. data/lib/openwfe/expressions/{fe_value.rb → fe_set.rb} +6 -82
  33. data/lib/openwfe/expressions/fe_sleep.rb +25 -15
  34. data/lib/openwfe/expressions/fe_subprocess.rb +2 -2
  35. data/lib/openwfe/expressions/fe_wait.rb +3 -2
  36. data/lib/openwfe/expressions/fe_when.rb +7 -15
  37. data/lib/openwfe/expressions/flowexpression.rb +90 -49
  38. data/lib/openwfe/expressions/merge.rb +7 -1
  39. data/lib/openwfe/expressions/raw.rb +261 -63
  40. data/lib/openwfe/expressions/{raw_prog.rb → rprocdef.rb} +94 -179
  41. data/lib/openwfe/expressions/time.rb +36 -12
  42. data/lib/openwfe/expressions/timeout.rb +9 -7
  43. data/lib/openwfe/expressions/value.rb +126 -0
  44. data/lib/openwfe/flowexpressionid.rb +52 -22
  45. data/lib/openwfe/listeners/listeners.rb +3 -3
  46. data/lib/openwfe/listeners/socketlisteners.rb +8 -5
  47. data/lib/openwfe/logging.rb +6 -3
  48. data/lib/openwfe/omixins.rb +8 -6
  49. data/lib/openwfe/orest/xmlcodec.rb +16 -12
  50. data/lib/openwfe/participants.rb +38 -0
  51. data/lib/openwfe/participants/participant.rb +1 -1
  52. data/lib/openwfe/participants/participantmap.rb +24 -10
  53. data/lib/openwfe/participants/participants.rb +4 -3
  54. data/lib/openwfe/participants/soapparticipants.rb +1 -1
  55. data/lib/openwfe/participants/socketparticipants.rb +1 -1
  56. data/lib/openwfe/rudefinitions.rb +7 -5
  57. data/lib/openwfe/storage/yamlcustom.rb +10 -10
  58. data/lib/openwfe/storage/yamlfilestorage.rb +12 -12
  59. data/lib/openwfe/tools/flowtracer.rb +6 -5
  60. data/lib/openwfe/util/dollar.rb +42 -85
  61. data/lib/openwfe/util/ometa.rb +1 -3
  62. data/lib/openwfe/util/workqueue.rb +1 -1
  63. data/lib/openwfe/utils.rb +33 -11
  64. data/lib/openwfe/version.rb +2 -2
  65. data/lib/openwfe/workitem.rb +76 -14
  66. data/lib/openwfe/worklist/storelocks.rb +9 -4
  67. data/lib/openwfe/worklist/storeparticipant.rb +1 -1
  68. data/test/back_0916_test.rb +101 -0
  69. data/test/bm/ft_26_load.rb +1 -1
  70. data/test/bm/ft_26b_load.rb +1 -1
  71. data/test/bm/ft_26c_load.rb +3 -2
  72. data/test/bm/ft_26d_load.rb +97 -0
  73. data/test/bm/ft_recu.rb +71 -0
  74. data/test/concurrence_test.rb +1 -1
  75. data/test/condition_test.rb +152 -0
  76. data/test/description_test.rb +12 -7
  77. data/test/eno_test.rb +1 -1
  78. data/test/expool_20031219_0916.tgz +0 -0
  79. data/test/fe_lookup_att_test.rb +1 -1
  80. data/test/fei_test.rb +16 -0
  81. data/test/file_persistence_test.rb +8 -12
  82. data/test/filep_cancel_test.rb +116 -0
  83. data/test/flowtestbase.rb +47 -25
  84. data/test/ft_0.rb +1 -1
  85. data/test/ft_10_loop.rb +29 -14
  86. data/test/{ft_10b_loop2.rb → ft_10b_loop.rb} +2 -11
  87. data/test/ft_11_ppd.rb +6 -17
  88. data/test/ft_11b_ppd.rb +1 -4
  89. data/test/ft_12_blockparticipant.rb +1 -1
  90. data/test/ft_13_eno.rb +1 -1
  91. data/test/ft_15_iterator.rb +1 -1
  92. data/test/ft_15b_iterator.rb +1 -1
  93. data/test/ft_17_condition.rb +6 -6
  94. data/test/ft_18_pname.rb +1 -1
  95. data/test/ft_20_cron.rb +1 -1
  96. data/test/ft_21_cron.rb +6 -4
  97. data/test/ft_22_history.rb +1 -1
  98. data/test/ft_23_when.rb +1 -1
  99. data/test/ft_23b_when.rb +18 -6
  100. data/test/ft_23c_wait.rb +8 -6
  101. data/test/ft_25_cancel.rb +7 -5
  102. data/test/ft_27_getflowpos.rb +22 -17
  103. data/test/ft_28_fileparticipant.rb +1 -2
  104. data/test/ft_2_concurrence.rb +1 -1
  105. data/test/ft_2b_concurrence.rb +25 -20
  106. data/test/ft_30_socketlistener.rb +0 -3
  107. data/test/ft_34_cancelwfid.rb +9 -9
  108. data/test/ft_35_localdefs.rb +0 -1
  109. data/test/ft_36_subprocids.rb +6 -6
  110. data/test/ft_38_tag.rb +3 -2
  111. data/test/ft_38b_tag.rb +229 -0
  112. data/test/ft_39_reserve.rb +3 -18
  113. data/test/ft_39b_reserve.rb +34 -5
  114. data/test/ft_3b_lookup_vf.rb +83 -0
  115. data/test/ft_40_defined.rb +2 -11
  116. data/test/ft_42_environments.rb +4 -6
  117. data/test/ft_44b_restore.rb +88 -22
  118. data/test/ft_45_citerator.rb +57 -11
  119. data/test/ft_49_condition.rb +4 -2
  120. data/test/ft_4_misc.rb +24 -3
  121. data/test/ft_50_xml_attribute.rb +17 -20
  122. data/test/ft_54_listen.rb +1 -1
  123. data/test/ft_54b_listen.rb +2 -2
  124. data/test/ft_56_timeout.rb +8 -1
  125. data/test/ft_57_a.rb +10 -10
  126. data/test/ft_59_ps.rb +49 -16
  127. data/test/ft_60_ecancel.rb +52 -10
  128. data/test/ft_63_pause.rb +8 -8
  129. data/test/ft_65_stringlaunch.rb +4 -6
  130. data/test/ft_67_schedlaunch.rb +4 -4
  131. data/test/ft_69_cancelmissing.rb +4 -2
  132. data/test/ft_70_lookupvar.rb +2 -2
  133. data/test/ft_72_lookup_processes.rb +2 -2
  134. data/test/ft_73_cancel_sub.rb +8 -8
  135. data/test/ft_77_segments.rb +38 -0
  136. data/test/ft_78_eval.rb +154 -0
  137. data/test/ft_79_tticket.rb +185 -0
  138. data/test/ft_80_spname.rb +95 -0
  139. data/test/ft_81_exp.rb +64 -0
  140. data/test/ft_82_trecu.rb +48 -0
  141. data/test/ft_83_badpause.rb +62 -0
  142. data/test/ft_84_updateexp.rb +125 -0
  143. data/test/ft_9b_cursor.rb +105 -0
  144. data/test/ft_tests.rb +14 -1
  145. data/test/hash_test.rb +7 -7
  146. data/test/hparticipant_test.rb +4 -4
  147. data/test/lookup_vf_test.rb +94 -0
  148. data/test/misc_test.rb +5 -3
  149. data/test/orest_test.rb +4 -3
  150. data/test/param_test.rb +12 -16
  151. data/test/participant_test.rb +36 -0
  152. data/test/pending.rb +10 -10
  153. data/test/rake_ltest.rb +1 -10
  154. data/test/rake_qtest.rb +7 -6
  155. data/test/raw_prog_test.rb +89 -121
  156. data/test/restart_cron_test.rb +84 -36
  157. data/test/restart_paused_test.rb +100 -0
  158. data/test/restart_sleep_test.rb +1 -1
  159. data/test/restart_tests.rb +1 -0
  160. data/test/restart_when_test.rb +33 -22
  161. data/test/ruby_procdef_test.rb +19 -18
  162. data/test/sec_test.rb +74 -35
  163. data/test/storage_test.rb +44 -0
  164. data/test/test.rb +3 -0
  165. data/test/timeout_test.rb +7 -18
  166. data/test/wfid_test.rb +2 -1
  167. data/test/wi_test.rb +29 -18
  168. metadata +121 -57
  169. data/lib/openwfe/expressions/raw_xml.rb +0 -176
  170. data/lib/openwfe/expressions/simplerep.rb +0 -266
  171. data/lib/openwfe/util/kotoba.rb +0 -236
  172. data/lib/openwfe/util/lru.rb +0 -171
  173. data/lib/openwfe/util/otime.rb +0 -246
  174. data/lib/openwfe/util/safe.rb +0 -160
  175. data/lib/openwfe/util/scheduler.rb +0 -1158
  176. data/test/cron_test.rb +0 -113
  177. data/test/cronline_test.rb +0 -60
  178. data/test/dollar_test.rb +0 -90
  179. data/test/kotoba_test.rb +0 -72
  180. data/test/lru_test.rb +0 -79
  181. data/test/safely_test.rb +0 -84
  182. data/test/scheduler_1_test.rb +0 -88
  183. data/test/scheduler_test.rb +0 -363
  184. data/test/time_test.rb +0 -84
@@ -0,0 +1,359 @@
1
+ #
2
+ #--
3
+ # Copyright (c) 2007-2008, John Mettraux, OpenWFE.org
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions are met:
8
+ #
9
+ # . Redistributions of source code must retain the above copyright notice, this
10
+ # list of conditions and the following disclaimer.
11
+ #
12
+ # . Redistributions in binary form must reproduce the above copyright notice,
13
+ # this list of conditions and the following disclaimer in the documentation
14
+ # and/or other materials provided with the distribution.
15
+ #
16
+ # . Neither the name of the "OpenWFE" nor the names of its contributors may be
17
+ # used to endorse or promote products derived from this software without
18
+ # specific prior written permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
+ # POSSIBILITY OF SUCH DAMAGE.
31
+ #++
32
+ #
33
+
34
+ #
35
+ # "made in Japan"
36
+ #
37
+ # John Mettraux at openwfe.org
38
+ #
39
+
40
+ module OpenWFE
41
+
42
+ #
43
+ # ProcessStatus represents information about the status of a workflow
44
+ # process instance.
45
+ #
46
+ # The status is mainly a list of expressions and a hash of errors.
47
+ #
48
+ # Instances of this class are obtained via Engine.process_status().
49
+ #
50
+ class ProcessStatus
51
+
52
+ #
53
+ # the String workflow instance id of the Process.
54
+ #
55
+ attr_reader :wfid
56
+
57
+ #
58
+ # The list of the expressions currently active in the process instance.
59
+ #
60
+ # For instance, if your process definition is currently in a
61
+ # concurrence, more than one expressions may be listed here.
62
+ #
63
+ attr_reader :expressions
64
+
65
+ #
66
+ # A hash whose values are ProcessError instances, the keys
67
+ # are FlowExpressionId instances (fei) (identifying the expressions
68
+ # that are concerned with the error)
69
+ #
70
+ attr_reader :errors
71
+
72
+ #
73
+ # The time at which the process got launched.
74
+ #
75
+ attr_reader :launch_time
76
+
77
+ #
78
+ # The variables hash as set in the process environment (the process
79
+ # scope).
80
+ #
81
+ attr_reader :variables
82
+
83
+ #
84
+ # Is the process currently in pause ?
85
+ #
86
+ attr_accessor :paused
87
+
88
+ #
89
+ # Builds an empty ProcessStatus instance.
90
+ #
91
+ def initialize
92
+
93
+ @wfid = nil
94
+ @expressions = []
95
+ @errors = {}
96
+ @launch_time = nil
97
+ @variables = nil
98
+ end
99
+
100
+ #
101
+ # Returns the workflow definition name for this process.
102
+ #
103
+ def wfname
104
+
105
+ @expressions.first.fei.wfname
106
+ end
107
+
108
+ alias :workflow_definition_name :wfname
109
+
110
+ #
111
+ # Returns the workflow definition revision for this process.
112
+ #
113
+ def wfrevision
114
+
115
+ @expressions.first.fei.wfrevision
116
+ end
117
+
118
+ alias :workflow_definition_revision :wfrevision
119
+
120
+ #
121
+ # Returns the count of concurrent branches currently active for
122
+ # this process. The typical 'sequential only' process will
123
+ # have a return value of 1 here.
124
+ #
125
+ def branches
126
+
127
+ @expressions.size
128
+ end
129
+
130
+ #
131
+ # Returns the tags currently set in this process.
132
+ #
133
+ def tags
134
+
135
+ return [] unless @variables
136
+
137
+ @variables.keys.select do |k|
138
+ @variables[k].is_a?(OpenWFE::RawExpression::Tag)
139
+ end
140
+ end
141
+
142
+ #
143
+ # Returns true if the process is in pause.
144
+ #
145
+ def paused?
146
+
147
+ #@expressions.first.paused?
148
+ @paused
149
+ end
150
+
151
+ #
152
+ # this method is used by Engine.get_process_status() when
153
+ # it prepares its results.
154
+ #
155
+ def << (item)
156
+
157
+ if item.kind_of?(FlowExpression)
158
+ add_expression item
159
+ else
160
+ add_error item
161
+ end
162
+ end
163
+
164
+ #
165
+ # A String representation, handy for debugging, quick viewing.
166
+ #
167
+ def to_s
168
+
169
+ s = []
170
+
171
+ s << "-- #{self.class.name} --"
172
+ s << " wfid : #{@wfid}"
173
+ s << " launch_time : #{launch_time}"
174
+ s << " tags : #{tags.join(", ")}"
175
+ s << " errors : #{@errors.size}"
176
+ s << " paused : #{paused?}"
177
+
178
+ s << " expressions :"
179
+ @expressions.each do |fexp|
180
+ s << " #{fexp.fei.to_s}"
181
+ end
182
+
183
+ s.join "\n"
184
+ end
185
+
186
+ protected
187
+
188
+ def add_expression (fexp)
189
+
190
+ if fexp.is_a?(Environment)
191
+ @variables = fexp.variables if fexp.fei.expid == "0"
192
+ return
193
+ end
194
+
195
+ set_wfid fexp.fei.parent_wfid
196
+
197
+ @launch_time = fexp.apply_time if fexp.fei.expid == '0'
198
+
199
+ exps = @expressions
200
+ @expressions = []
201
+
202
+ added = false
203
+ @expressions = exps.collect do |fe|
204
+ if added or fe.fei.wfid != fexp.fei.wfid
205
+ fe
206
+ else
207
+ if OpenWFE::starts_with(fexp.fei.expid, fe.fei.expid)
208
+ added = true
209
+ fexp
210
+ elsif OpenWFE::starts_with(fe.fei.expid, fexp.fei.expid)
211
+ added = true
212
+ fe
213
+ else
214
+ fe
215
+ end
216
+ end
217
+ end
218
+ @expressions << fexp unless added
219
+ end
220
+
221
+ def add_error (error)
222
+
223
+ @errors[error.fei] = error
224
+ end
225
+
226
+ def set_wfid (wfid)
227
+
228
+ return if @wfid
229
+ @wfid = wfid
230
+ end
231
+ end
232
+
233
+ #
234
+ # Renders a nice, terminal oriented, representation of an
235
+ # Engine.get_process_status() result.
236
+ #
237
+ # You usually directly benefit from this when doing
238
+ #
239
+ # puts engine.get_process_status.to_s
240
+ #
241
+ def OpenWFE.pretty_print_process_status (ps)
242
+
243
+ # TODO : include launch_time and why is process_id so long ?
244
+
245
+ s = ""
246
+ s << "process_id | name | rev | brn | err | paused? \n"
247
+ s << "--------------------+-------------------+---------+-----+-----+---------\n"
248
+
249
+ ps.keys.sort.each do |wfid|
250
+
251
+ status = ps[wfid]
252
+ fexp = status.expressions.first
253
+ ffei = fexp.fei
254
+
255
+ s << "%-19s" % wfid[0, 19]
256
+ s << " | "
257
+ s << "%-17s" % ffei.workflow_definition_name[0, 17]
258
+ s << " | "
259
+ s << "%-7s" % ffei.workflow_definition_revision[0, 7]
260
+ s << " | "
261
+ s << "%3s" % status.expressions.size.to_s[0, 3]
262
+ s << " | "
263
+ s << "%3s" % status.errors.size.to_s[0, 3]
264
+ s << " | "
265
+ s << "%5s" % status.paused?.to_s
266
+ s << "\n"
267
+ end
268
+ s
269
+ end
270
+
271
+ #
272
+ # This mixin is only included by the Engine class. It contains all
273
+ # the methods about ProcessStatus.
274
+ #
275
+ module StatusMixin
276
+
277
+ #
278
+ # Returns a hash of ProcessStatus instances. The keys of the hash
279
+ # are workflow instance ids.
280
+ #
281
+ # A ProcessStatus is a description of the state of a process instance.
282
+ # It enumerates the expressions where the process is currently
283
+ # located (waiting certainly) and the errors the process currently
284
+ # has (hopefully none).
285
+ #
286
+ def process_statuses (options={})
287
+
288
+ options = { :wfid_prefix => options } if options.is_a?(String)
289
+
290
+ result = {}
291
+
292
+ expressions = get_expression_storage.find_expressions options
293
+
294
+ expressions.each do |fexp|
295
+
296
+ next unless (fexp.apply_time or fexp.is_a?(Environment))
297
+
298
+ next if fexp.fei.wfid == "0" # skip the engine env
299
+
300
+ #(result[fexp.fei.parent_wfid] ||= ProcessStatus.new) << fexp
301
+
302
+ parent_wfid = fexp.fei.parent_wfid
303
+
304
+ ps = result[parent_wfid]
305
+
306
+ if not ps
307
+
308
+ ps = ProcessStatus.new
309
+
310
+ ps.paused =
311
+ (get_expool.paused_instances[parent_wfid] != nil)
312
+
313
+ result[parent_wfid] = ps
314
+ end
315
+
316
+ ps << fexp
317
+ end
318
+
319
+ result.values.each do |ps|
320
+ get_error_journal.get_error_log(ps.wfid).each do |error|
321
+ ps << error
322
+ end
323
+ end
324
+
325
+ class << result
326
+ def to_s
327
+ OpenWFE::pretty_print_process_status(self)
328
+ end
329
+ end
330
+
331
+ result
332
+ end
333
+
334
+ #
335
+ # list_process_status() will be deprecated at release 1.0.0
336
+ #
337
+ alias :list_process_status :process_statuses
338
+
339
+ #
340
+ # Returns the process status of one given process instance.
341
+ #
342
+ def process_status (wfid)
343
+
344
+ wfid = extract_wfid wfid, true
345
+
346
+ process_statuses(:wfid => wfid).values[0]
347
+ end
348
+
349
+ #
350
+ # Returns true if the process is in pause.
351
+ #
352
+ def is_paused? (wfid)
353
+
354
+ (get_expression_pool.paused_instances[wfid] != nil)
355
+ end
356
+ end
357
+
358
+ end
359
+
@@ -1,6 +1,6 @@
1
1
  #
2
2
  #--
3
- # Copyright (c) 2007, John Mettraux, OpenWFE.org
3
+ # Copyright (c) 2007-2008, John Mettraux, OpenWFE.org
4
4
  # All rights reserved.
5
5
  #
6
6
  # Redistribution and use in source and binary forms, with or without
@@ -200,7 +200,7 @@ module OpenWFE
200
200
  # Will replay a given process instance at its 1 to last error.
201
201
  #
202
202
  #def replay_at_last_error (wfid, offset=0)
203
- # wfid = to_wfid(wfid)
203
+ # wfid = extract_wfid(wfid)
204
204
  # log = get_error_log(wfid)
205
205
  # index = (-1 - offset)
206
206
  # error = log[index]
@@ -272,7 +272,7 @@ module OpenWFE
272
272
  #
273
273
  def get_error_log (wfid)
274
274
 
275
- wfid = to_wfid(wfid)
275
+ wfid = extract_wfid wfid, true
276
276
  @per_processes[wfid] or []
277
277
  end
278
278
 
@@ -281,7 +281,7 @@ module OpenWFE
281
281
  #
282
282
  def remove_error_log (wfid)
283
283
 
284
- wfid = to_wfid(wfid)
284
+ wfid = extract_wfid wfid, true
285
285
  @per_processes.delete(wfid)
286
286
  end
287
287
 
@@ -349,7 +349,7 @@ module OpenWFE
349
349
  #
350
350
  def get_error_log (wfid)
351
351
 
352
- path = get_path(wfid)
352
+ path = get_path wfid
353
353
 
354
354
  return [] unless File.exist?(path)
355
355
 
@@ -470,7 +470,7 @@ module OpenWFE
470
470
  #
471
471
  def get_path (fei_or_wfid)
472
472
 
473
- @workdir + "/" + to_wfid(fei_or_wfid) + ".ejournal"
473
+ @workdir + "/" + extract_wfid(fei_or_wfid, true) + ".ejournal"
474
474
  end
475
475
  end
476
476
  end
@@ -1,6 +1,6 @@
1
1
  #
2
2
  #--
3
- # Copyright (c) 2006-2007, John Mettraux, OpenWFE.org
3
+ # Copyright (c) 2006-2008, John Mettraux, OpenWFE.org
4
4
  # All rights reserved.
5
5
  #
6
6
  # Redistribution and use in source and binary forms, with or without
@@ -39,8 +39,6 @@
39
39
 
40
40
  require 'uri'
41
41
  require 'monitor'
42
- require 'open-uri'
43
- require 'rexml/document'
44
42
 
45
43
  require 'openwfe/utils'
46
44
  require 'openwfe/service'
@@ -48,16 +46,14 @@ require 'openwfe/logging'
48
46
  require 'openwfe/omixins'
49
47
  require 'openwfe/rudefinitions'
50
48
  require 'openwfe/flowexpressionid'
51
- require 'openwfe/util/lru'
52
- require 'openwfe/util/safe'
53
49
  require 'openwfe/util/workqueue'
54
50
  require 'openwfe/util/observable'
51
+ require 'openwfe/expool/parser'
55
52
  require 'openwfe/expressions/environment'
56
- require 'openwfe/expressions/raw_xml'
57
- require 'openwfe/expressions/raw_prog'
58
- require 'openwfe/expressions/simplerep'
53
+ require 'openwfe/expressions/raw'
59
54
 
60
- include OpenWFE
55
+ require 'rufus/lru' # gem 'rufus-lru'
56
+ require 'rufus/verbs' # gem 'rufus-lru'
61
57
 
62
58
 
63
59
  module OpenWFE
@@ -97,17 +93,22 @@ module OpenWFE
97
93
 
98
94
 
99
95
  #
100
- # code loaded from a remote URI will get evaluated with
101
- # that security level
96
+ # The hash containing the wfid of the process instances currently
97
+ # paused.
102
98
  #
103
- SAFETY_LEVEL = 2
99
+ attr_reader :paused_instances
104
100
 
101
+ #
102
+ # The constructor for the expression pool.
103
+ #
105
104
  def initialize (service_name, application_context)
106
105
 
107
106
  super()
108
-
107
+
109
108
  service_init(service_name, application_context)
110
109
 
110
+ @paused_instances = {}
111
+
111
112
  @monitors = MonitorProvider.new(application_context)
112
113
 
113
114
  @observers = {}
@@ -162,10 +163,12 @@ module OpenWFE
162
163
  unless wfdurl
163
164
 
164
165
  definition = if wfdurl.match "^field:"
166
+
165
167
  wfdfield = wfdurl[6..-1]
166
168
  launchitem.attributes.delete wfdfield
167
169
  else
168
- read_uri(wfdurl)
170
+
171
+ read_uri wfdurl
169
172
  end
170
173
 
171
174
  raise "didn't find process definition at '#{wfdurl}'" \
@@ -200,7 +203,7 @@ module OpenWFE
200
203
  # will raise an exception if there are requirements
201
204
  # and one of them is not met
202
205
 
203
- raw_expression.new_environment()
206
+ raw_expression.new_environment
204
207
  #
205
208
  # as this expression is the root of a new process instance,
206
209
  # it has to have an environment for all the variables of
@@ -231,7 +234,7 @@ module OpenWFE
231
234
  # and of course used by the launch_template() method.
232
235
  #
233
236
  def prepare_from_template (
234
- requesting_expression, sub_id, template, params=nil)
237
+ requesting_expression, env_id, sub_id, template, params=nil)
235
238
 
236
239
  rawexp = if template.is_a?(RawExpression)
237
240
 
@@ -282,9 +285,15 @@ module OpenWFE
282
285
  # "#{rawexp.fei.workflow_instance_id.to_s}"
283
286
  #end
284
287
 
285
- env = rawexp.new_environment params
288
+ if env_id
289
+
290
+ rawexp.environment_id = env_id
291
+ else
286
292
  #
287
293
  # the new scope gets its own environment
294
+ #
295
+ rawexp.new_environment params
296
+ end
288
297
 
289
298
  rawexp.store_itself
290
299
 
@@ -295,10 +304,15 @@ module OpenWFE
295
304
  # launches a subprocess
296
305
  #
297
306
  def launch_template (
298
- requesting_expression, sub_id, template, workitem, params=nil)
307
+ requesting_expression,
308
+ env_id,
309
+ sub_id,
310
+ template,
311
+ workitem,
312
+ params=nil)
299
313
 
300
314
  rawexp = prepare_from_template(
301
- requesting_expression, sub_id, template, params)
315
+ requesting_expression, env_id, sub_id, template, params)
302
316
 
303
317
  workitem.flow_expression_id = rawexp.fei
304
318
 
@@ -332,6 +346,7 @@ module OpenWFE
332
346
  def apply (exp, workitem)
333
347
 
334
348
  queue_work :do_apply, exp, workitem
349
+ #do_apply exp, workitem
335
350
  end
336
351
 
337
352
  #
@@ -340,6 +355,7 @@ module OpenWFE
340
355
  def reply (exp, workitem)
341
356
 
342
357
  queue_work :do_reply, exp, workitem
358
+ #do_reply exp, workitem
343
359
  end
344
360
 
345
361
  #
@@ -349,7 +365,7 @@ module OpenWFE
349
365
  #
350
366
  def cancel (exp)
351
367
 
352
- exp, fei = fetch(exp)
368
+ exp, fei = fetch exp
353
369
 
354
370
  unless exp
355
371
  ldebug { "cancel() cannot cancel missing #{fei.to_debug_s}" }
@@ -361,7 +377,7 @@ module OpenWFE
361
377
  onotify :cancel, exp
362
378
 
363
379
  inflowitem = exp.cancel()
364
- remove(exp)
380
+ remove exp
365
381
 
366
382
  inflowitem
367
383
  end
@@ -381,9 +397,9 @@ module OpenWFE
381
397
  wi = cancel exp
382
398
 
383
399
  if wi
384
- reply_to_parent(exp, wi, false)
400
+ reply_to_parent exp, wi, false
385
401
  else
386
- parent_exp = fetch_expression(exp.parent_id)
402
+ parent_exp = fetch_expression exp.parent_id
387
403
  parent_exp.remove_child(exp.fei) if parent_exp
388
404
  end
389
405
  end
@@ -394,10 +410,15 @@ module OpenWFE
394
410
  #
395
411
  def cancel_process (exp_or_wfid)
396
412
 
397
- ldebug { "cancel_process() from #{exp_or_wfid}" }
413
+ wfid = extract_wfid exp_or_wfid, false
414
+
415
+ ldebug { "cancel_process() '#{wfid}'" }
416
+
417
+ root = fetch_root wfid
418
+
419
+ raise "no process to cancel '#{wfid}'" unless root
398
420
 
399
- root = fetch_root(exp_or_wfid)
400
- cancel(root)
421
+ cancel root
401
422
  end
402
423
  alias :cancel_flow :cancel_process
403
424
 
@@ -407,7 +428,7 @@ module OpenWFE
407
428
  #
408
429
  def forget (parent_exp, exp)
409
430
 
410
- exp, fei = fetch(exp)
431
+ exp, fei = fetch exp
411
432
 
412
433
  #ldebug { "forget() forgetting #{fei}" }
413
434
 
@@ -518,11 +539,11 @@ module OpenWFE
518
539
 
519
540
  #ldebug { "fetch() exp is of kind #{exp.class}" }
520
541
 
521
- fei = if exp.kind_of?(FlowExpression)
542
+ fei = if exp.is_a?(FlowExpression)
522
543
 
523
544
  exp.fei
524
545
 
525
- elsif not exp.kind_of?(FlowExpressionId)
546
+ elsif not exp.is_a?(FlowExpressionId)
526
547
 
527
548
  raise \
528
549
  "Cannot fetch expression with key : "+
@@ -547,51 +568,40 @@ module OpenWFE
547
568
  #
548
569
  def fetch_expression (exp)
549
570
 
550
- exp, fei = fetch(exp)
571
+ exp, fei = fetch exp
551
572
  exp
552
573
  end
553
574
 
554
- #
555
- # Fetches the root expression of a process (given any of its
556
- # expressions or its wfid).
557
- #
558
- def fetch_root (exp_or_wfid)
559
-
560
- ldebug { "fetch_root() '#{exp_or_wfid.to_s}'" }
561
-
562
- return fetch_expression_with_wfid(exp_or_wfid) \
563
- if exp_or_wfid.is_a?(String)
564
-
565
- exp = fetch_expression(exp_or_wfid)
566
-
567
- raise "did not find root for expression #{exp_or_wfid}" unless exp
568
-
569
- return exp unless exp.parent_id
570
-
571
- fetch_root(fetch_expression(exp.parent_id))
572
- end
573
-
574
575
  #
575
576
  # Returns the engine environment (the top level environment)
576
577
  #
577
- def fetch_engine_environment ()
578
+ def fetch_engine_environment
578
579
  synchronize do
579
580
  #
580
581
  # synchronize to ensure that there's 1! engine env
581
582
 
582
583
  eei = engine_environment_id
583
- ee, fei = fetch(eei)
584
+ ee, fei = fetch eei
584
585
 
585
- if not ee
586
- ee = Environment\
587
- .new(eei, nil, nil, @application_context, nil)
588
- ee.store_itself()
589
- end
586
+ return ee if ee
587
+
588
+ ee = Environment.new_env(
589
+ eei, nil, nil, @application_context, nil)
590
+
591
+ ee.store_itself
590
592
 
591
593
  ee
592
594
  end
593
595
  end
594
596
 
597
+ #
598
+ # Fetches the root expression of a process (or a subprocess).
599
+ #
600
+ def fetch_root (wfid)
601
+
602
+ get_expression_storage.fetch_root wfid
603
+ end
604
+
595
605
  #
596
606
  # Removes a flow expression from the pool
597
607
  # (This method is mainly called from the pool itself)
@@ -631,14 +641,15 @@ module OpenWFE
631
641
 
632
642
  linfo { "reschedule() initiating..." }
633
643
 
634
- get_expression_storage.each_of_kind(Schedulable) do |fei, fe|
644
+ options = { :include_classes => Rufus::Schedulable }
645
+
646
+ get_expression_storage.find_expressions(options).each do |fexp|
635
647
 
636
- #linfo { "reschedule() for #{fei.to_debug_s}..." }
637
- linfo { "reschedule() for #{fei.to_s}..." }
648
+ linfo { "reschedule() for #{fexp.fei.to_s}..." }
638
649
 
639
- onotify :reschedule, fei
650
+ onotify :reschedule, fexp.fei
640
651
 
641
- fe.reschedule(get_scheduler)
652
+ fexp.reschedule get_scheduler
642
653
  end
643
654
 
644
655
  linfo { "reschedule() done. (took #{t.duration} ms)" }
@@ -673,84 +684,42 @@ module OpenWFE
673
684
  # Returns the list of applied expressions belonging to a given
674
685
  # workflow instance.
675
686
  #
676
- def get_process_stack (wfid)
677
-
678
- raise "please provide a non-nil workflow instance id" \
679
- unless wfid
680
-
681
- wfid = to_wfid wfid
682
-
683
- result = []
687
+ # If the unapplied optional parameter is set to true, all the
688
+ # expressions (even those not yet applied) that compose the process
689
+ # instance will be returned. Environments will be returned as well.
690
+ #
691
+ def process_stack (wfid, unapplied=false)
684
692
 
685
- get_expression_storage.real_each do |fei, fexp|
693
+ #raise "please provide a non-nil workflow instance id" \
694
+ # unless wfid
686
695
 
687
- next if fexp.kind_of?(Environment)
688
- next if fexp.kind_of?(RawExpression)
689
- next unless fexp.apply_time
696
+ wfid = extract_wfid wfid, true
690
697
 
691
- next if fei.parent_wfid != wfid
698
+ params = {
699
+ #:exclude_classes => [ Environment, RawExpression ],
700
+ #:exclude_classes => [ Environment ],
701
+ :parent_wfid => wfid
702
+ }
703
+ params[:applied] = true if (not unapplied)
692
704
 
693
- result << fexp
694
- end
695
-
696
- ldebug do
697
- "process_stack() " +
698
- "found #{result.size} exps for flow #{wfid}"
699
- end
700
-
701
- result
705
+ get_expression_storage.find_expressions params
702
706
  end
703
707
 
704
- alias :get_flow_stack :get_process_stack
705
-
706
708
  #
707
709
  # Lists all workflows (processes) currently in the expool (in
708
710
  # the engine).
709
711
  # This method will return a list of "process-definition" expressions
710
712
  # (root of flows).
711
713
  #
712
- # If consider_subprocesses is set to true, "process-definition"
713
- # expressions of subprocesses will be returned as well.
714
- #
715
- # "wfid_prefix" allows your to query for specific workflow instance
716
- # id prefixes.
717
- #
718
- def list_processes (consider_subprocesses=false, wfid_prefix=nil)
719
-
720
- result = []
721
-
722
- # collect() would look better
723
-
724
- get_expression_storage.real_each(wfid_prefix) do |fei, fexp|
725
-
726
- #ldebug { "list_processes() class is #{fexp.class.name}" }
727
-
728
- next unless fexp.is_a?(DefineExpression)
729
-
730
- next if not consider_subprocesses and fei.wfid.index(".")
731
-
732
- #next unless fei.wfid.match("^#{wfid_prefix}") if wfid_prefix
733
-
734
- result << fexp
735
- end
736
-
737
- result
738
- end
739
-
740
- #
741
- # Returns the first expression found with the given wfid.
742
- #
743
- def fetch_expression_with_wfid (wfid)
744
-
745
- #list_processes(false, wfid)[0]
714
+ def list_processes (options={})
746
715
 
747
- ps = list_processes(false, wfid)
748
-
749
- ldebug do
750
- "fetch_expression_with_wfid() '#{wfid}' found #{ps.size} items"
751
- end
716
+ options[:include_classes] = DefineExpression
717
+ #
718
+ # Maybe it would be better to list root expressions instead
719
+ # so that expressions like 'sequence' can be used
720
+ # as root expressions. Later...
752
721
 
753
- ps[0]
722
+ get_expression_storage.find_expressions options
754
723
  end
755
724
 
756
725
  #
@@ -765,7 +734,7 @@ module OpenWFE
765
734
  fei = extract_fei fei
766
735
  # densha requires that... :(
767
736
 
768
- se = OpenWFE::exception_to_s(error)
737
+ se = OpenWFE::exception_to_s error
769
738
 
770
739
  onotify :error, fei, message, workitem, error.class.name, se
771
740
 
@@ -786,18 +755,41 @@ module OpenWFE
786
755
  end
787
756
  end
788
757
 
758
+ #
759
+ # Gets the process definition (if necessary) and turns into
760
+ # into an expression tree (for storing into a RawExpression).
761
+ #
762
+ def determine_rep (param)
763
+
764
+ param = read_uri(param) if param.is_a?(URI)
765
+
766
+ DefParser.parse param
767
+ end
768
+
789
769
  protected
790
770
 
791
- #--
792
- # Returns true if it's the fei of a participant
793
- # (or of a subprocess ref)
794
771
  #
795
- #def is_participant? (fei)
796
- # exp_name = fei.expression_name
797
- # return true if exp_name == "participant"
798
- # (get_expression_map.get_class(exp_name) == nil)
799
- #end
800
- #++
772
+ # This is the only point in the expression pool where an URI
773
+ # is read, so this is where the :remote_definitions_allowed
774
+ # security check is enforced.
775
+ #
776
+ def read_uri (uri)
777
+
778
+ uri = URI.parse uri.to_s
779
+
780
+ raise "loading remote definitions is not allowed" \
781
+ if (ac[:remote_definitions_allowed] != true and
782
+ uri.scheme and
783
+ uri.scheme != 'file')
784
+
785
+ #open(uri.to_s).read
786
+
787
+ f = Rufus::Verbs.fopen uri
788
+ result = f.read
789
+ f.close if f.respond_to?(:close)
790
+
791
+ result
792
+ end
801
793
 
802
794
  #
803
795
  # This method is called by the workqueue when processing
@@ -813,7 +805,7 @@ module OpenWFE
813
805
 
814
806
  rescue Exception => e
815
807
 
816
- notify_error(e, fei, message, workitem)
808
+ notify_error e, fei, message, workitem
817
809
  end
818
810
  end
819
811
 
@@ -824,22 +816,21 @@ module OpenWFE
824
816
 
825
817
  exp, _fei = fetch(exp) if exp.is_a?(FlowExpressionId)
826
818
 
827
- check_if_paused exp
828
-
829
819
  #ldebug { "apply() '#{_fei}'" }
830
820
 
831
821
  if not exp
832
822
 
823
+ #raise "apply() cannot apply missing #{_fei.to_debug_s}"
824
+ # not very helpful anyway
825
+
833
826
  lwarn do
834
827
  "do_apply() cannot apply missing #{_fei.to_debug_s}"
835
828
  end
836
-
837
829
  return
838
-
839
- #raise "apply() cannot apply missing #{_fei.to_debug_s}"
840
- # not very helpful anyway
841
830
  end
842
831
 
832
+ check_if_paused exp
833
+
843
834
  workitem.flow_expression_id = exp.fei
844
835
 
845
836
  onotify :apply, exp, workitem
@@ -857,14 +848,18 @@ module OpenWFE
857
848
  ldebug { "reply() to #{fei.to_debug_s}" }
858
849
  ldebug { "reply() from #{workitem.last_expression_id.to_debug_s}" }
859
850
 
860
- check_if_paused exp
861
-
862
851
  if not exp
852
+
863
853
  #raise "cannot reply to missing #{fei.to_debug_s}"
864
- lwarn { "reply() cannot reply to missing #{fei.to_debug_s}" }
854
+
855
+ lwarn do
856
+ "reply() cannot reply to missing #{fei.to_debug_s}"
857
+ end
865
858
  return
866
859
  end
867
860
 
861
+ check_if_paused exp
862
+
868
863
  onotify :reply, exp, workitem
869
864
 
870
865
  exp.reply(workitem)
@@ -876,10 +871,9 @@ module OpenWFE
876
871
  #
877
872
  def check_if_paused (expression)
878
873
 
879
- return unless expression
874
+ wfid = expression.fei.parent_wfid
880
875
 
881
- raise PausedError.new(expression.fei.wfid) \
882
- if expression.paused?
876
+ raise PausedError.new(wfid) if @paused_instances[wfid]
883
877
  end
884
878
 
885
879
  #
@@ -894,7 +888,7 @@ module OpenWFE
894
888
  ocron = options[:cron]
895
889
  oevery = options[:every]
896
890
 
897
- fei = new_fei(nil, "schedlaunch", "0", "sequence")
891
+ fei = new_fei nil, "schedlaunch", "0", "sequence"
898
892
 
899
893
  # not very happy with this code, it builds custom
900
894
  # wrapping processes manually, maybe there is
@@ -902,8 +896,8 @@ module OpenWFE
902
896
 
903
897
  if oat or oin
904
898
 
905
- seq = get_expression_map.get_class(:sequence)
906
- seq = seq.new(fei, nil, nil, application_context, nil)
899
+ seq = get_expression_map.get_class :sequence
900
+ seq = seq.new_exp fei, nil, nil, application_context, nil
907
901
 
908
902
  att = if oat
909
903
  { "until" => oat }
@@ -912,10 +906,14 @@ module OpenWFE
912
906
  end
913
907
  att["scheduler-tags"] = "scheduled-launch"
914
908
 
915
- sle = get_expression_map.get_class(:sleep)
916
- sle = sle.new(fei.dup, fei, nil, application_context, att)
909
+ sle = get_expression_map.get_class :sleep
910
+
911
+ sle = sle.new_exp(
912
+ fei.dup, fei, nil, application_context, att)
913
+
917
914
  sle.fei.expression_id = "0.0"
918
915
  sle.fei.expression_name = "sleep"
916
+
919
917
  seq.children << sle.fei
920
918
  seq.children << raw_expression.fei
921
919
 
@@ -940,8 +938,8 @@ module OpenWFE
940
938
  att["name"] = "//cron_launch__#{fei.wfid}"
941
939
  att["scheduler-tags"] = "scheduled-launch"
942
940
 
943
- cro = get_expression_map.get_class(:cron)
944
- cro = cro.new(fei, nil, nil, application_context, att)
941
+ cro = get_expression_map.get_class :cron
942
+ cro = cro.new_exp fei, nil, nil, application_context, att
945
943
 
946
944
  cro.children << raw_expression.fei
947
945
 
@@ -991,78 +989,6 @@ module OpenWFE
991
989
  wi
992
990
  end
993
991
 
994
- #
995
- # This is the only point in the expression pool where an URI
996
- # is read, so this is where the :remote_definitions_allowed
997
- # security check is enforced.
998
- #
999
- def read_uri (uri)
1000
-
1001
- uri = uri.to_s
1002
- uri = uri[5..-1] if uri.match("^file:")
1003
- uri = URI.parse(uri)
1004
-
1005
- if uri.scheme
1006
- raise "loading remote definitions is not allowed" \
1007
- if ac[:remote_definitions_allowed] != true
1008
- end
1009
-
1010
- open(uri.to_s).read
1011
- end
1012
-
1013
- #
1014
- # The parameter to this method might be either a process
1015
- # definition (in any form) or a LaunchItem.
1016
- #
1017
- # Will return a 'representation' (what is used to build
1018
- # a RawExpression instance).
1019
- #
1020
- def determine_representation (param)
1021
-
1022
- #ldebug do
1023
- # "determine_representation() from class #{param.class.name}"
1024
- #end
1025
-
1026
- param = read_uri(param) if param.is_a?(URI)
1027
-
1028
- #ldebug do
1029
- # "determine_representation() " +
1030
- # "param of class #{param.class.name}"
1031
- #end
1032
-
1033
- return param \
1034
- if param.is_a?(SimpleExpRepresentation)
1035
-
1036
- return param.do_make \
1037
- if param.is_a?(ProcessDefinition) or param.is_a?(Class)
1038
-
1039
- raise "cannot handle definition of class #{param.class.name}" \
1040
- unless param.is_a? String
1041
-
1042
- if param[0, 1] == "<"
1043
- #
1044
- # XML definition
1045
-
1046
- xmlRoot = REXML::Document.new(param).root
1047
- class << xmlRoot
1048
- def raw_expression_class
1049
- XmlRawExpression
1050
- end
1051
- end
1052
- return xmlRoot
1053
- end
1054
-
1055
- return YAML.load(s) if param.match("^--- .")
1056
- #
1057
- # something that was dumped via YAML
1058
-
1059
- #
1060
- # else it's some ruby code to eval
1061
-
1062
- ProcessDefinition::eval_ruby_process_definition(
1063
- param, SAFETY_LEVEL)
1064
- end
1065
-
1066
992
  #
1067
993
  # Builds a FlowExpressionId instance for a process being
1068
994
  # launched.
@@ -1099,20 +1025,16 @@ module OpenWFE
1099
1025
  #
1100
1026
  def build_raw_expression (launchitem, param)
1101
1027
 
1102
- procdef = determine_representation param
1103
-
1104
- #return procdef if procdef.is_a? RawExpression
1105
-
1106
- flow_name = procdef.attributes['name']
1107
- flow_revision = procdef.attributes['revision']
1108
- exp_name = procdef.name
1028
+ procdef = determine_rep param
1109
1029
 
1110
- fei = new_fei(launchitem, flow_name, flow_revision, exp_name)
1030
+ atts = procdef[1]
1031
+ flow_name = atts['name'] || "noname"
1032
+ flow_revision = atts['revision'] || "0"
1033
+ exp_name = procdef.first
1111
1034
 
1112
- #puts procdef.raw_expression_class
1113
- #puts procdef.raw_expression_class.public_methods
1035
+ fei = new_fei launchitem, flow_name, flow_revision, exp_name
1114
1036
 
1115
- procdef.raw_expression_class.new(
1037
+ RawExpression.new_raw(
1116
1038
  fei, nil, nil, @application_context, procdef)
1117
1039
  end
1118
1040
  end