ruote 0.9.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (291) hide show
  1. data/README.txt +24 -0
  2. data/bin/validate-workflow.rb +89 -0
  3. data/examples/about_state.rb +81 -0
  4. data/examples/bigflow.rb +19 -0
  5. data/examples/csv_weather.rb +23 -0
  6. data/examples/engine_template.rb +247 -0
  7. data/examples/flowtracing.rb +24 -0
  8. data/examples/homeworkreview.rb +68 -0
  9. data/examples/kotoba.rb +22 -0
  10. data/examples/mano_tracker.rb +172 -0
  11. data/examples/openwferu.rb +58 -0
  12. data/examples/quotereporter.rb +157 -0
  13. data/examples/scheduler_cron_usage.rb +48 -0
  14. data/examples/scheduler_usage.rb +56 -0
  15. data/lib/openwfe.rb +41 -0
  16. data/lib/openwfe/contextual.rb +111 -0
  17. data/lib/openwfe/def.rb +46 -0
  18. data/lib/openwfe/engine.rb +37 -0
  19. data/lib/openwfe/engine/engine.rb +756 -0
  20. data/lib/openwfe/engine/expool_methods.rb +172 -0
  21. data/lib/openwfe/engine/file_persisted_engine.rb +105 -0
  22. data/lib/openwfe/engine/participant_methods.rb +133 -0
  23. data/lib/openwfe/engine/status_methods.rb +353 -0
  24. data/lib/openwfe/engine/update_exp_methods.rb +112 -0
  25. data/lib/openwfe/exceptions.rb +51 -0
  26. data/lib/openwfe/expool/errorjournal.rb +476 -0
  27. data/lib/openwfe/expool/expressionpool.rb +1144 -0
  28. data/lib/openwfe/expool/expstorage.rb +403 -0
  29. data/lib/openwfe/expool/history.rb +174 -0
  30. data/lib/openwfe/expool/journal.rb +224 -0
  31. data/lib/openwfe/expool/journal_replay.rb +321 -0
  32. data/lib/openwfe/expool/parser.rb +242 -0
  33. data/lib/openwfe/expool/representation.rb +121 -0
  34. data/lib/openwfe/expool/threadedexpstorage.rb +188 -0
  35. data/lib/openwfe/expool/wfidgen.rb +388 -0
  36. data/lib/openwfe/expool/yamlexpstorage.rb +224 -0
  37. data/lib/openwfe/expressions/condition.rb +244 -0
  38. data/lib/openwfe/expressions/environment.rb +246 -0
  39. data/lib/openwfe/expressions/expressionmap.rb +258 -0
  40. data/lib/openwfe/expressions/fe_cancel.rb +109 -0
  41. data/lib/openwfe/expressions/fe_command.rb +241 -0
  42. data/lib/openwfe/expressions/fe_concurrence.rb +662 -0
  43. data/lib/openwfe/expressions/fe_cron.rb +259 -0
  44. data/lib/openwfe/expressions/fe_cursor.rb +259 -0
  45. data/lib/openwfe/expressions/fe_define.rb +192 -0
  46. data/lib/openwfe/expressions/fe_do.rb +168 -0
  47. data/lib/openwfe/expressions/fe_equals.rb +291 -0
  48. data/lib/openwfe/expressions/fe_filter.rb +129 -0
  49. data/lib/openwfe/expressions/fe_filter_definition.rb +168 -0
  50. data/lib/openwfe/expressions/fe_fqv.rb +250 -0
  51. data/lib/openwfe/expressions/fe_if.rb +303 -0
  52. data/lib/openwfe/expressions/fe_iterator.rb +145 -0
  53. data/lib/openwfe/expressions/fe_listen.rb +371 -0
  54. data/lib/openwfe/expressions/fe_losfor.rb +111 -0
  55. data/lib/openwfe/expressions/fe_misc.rb +421 -0
  56. data/lib/openwfe/expressions/fe_participant.rb +269 -0
  57. data/lib/openwfe/expressions/fe_reserve.rb +212 -0
  58. data/lib/openwfe/expressions/fe_save.rb +274 -0
  59. data/lib/openwfe/expressions/fe_sequence.rb +117 -0
  60. data/lib/openwfe/expressions/fe_set.rb +139 -0
  61. data/lib/openwfe/expressions/fe_sleep.rb +166 -0
  62. data/lib/openwfe/expressions/fe_step.rb +159 -0
  63. data/lib/openwfe/expressions/fe_subprocess.rb +168 -0
  64. data/lib/openwfe/expressions/fe_timeout.rb +127 -0
  65. data/lib/openwfe/expressions/fe_wait.rb +78 -0
  66. data/lib/openwfe/expressions/fe_when.rb +142 -0
  67. data/lib/openwfe/expressions/filter.rb +104 -0
  68. data/lib/openwfe/expressions/flowexpression.rb +847 -0
  69. data/lib/openwfe/expressions/iterator.rb +221 -0
  70. data/lib/openwfe/expressions/merge.rb +84 -0
  71. data/lib/openwfe/expressions/raw.rb +547 -0
  72. data/lib/openwfe/expressions/rprocdef.rb +375 -0
  73. data/lib/openwfe/expressions/time.rb +333 -0
  74. data/lib/openwfe/expressions/timeout.rb +178 -0
  75. data/lib/openwfe/expressions/value.rb +126 -0
  76. data/lib/openwfe/filterdef.rb +259 -0
  77. data/lib/openwfe/flowexpressionid.rb +357 -0
  78. data/lib/openwfe/listeners/listener.rb +97 -0
  79. data/lib/openwfe/listeners/listeners.rb +139 -0
  80. data/lib/openwfe/listeners/socketlisteners.rb +272 -0
  81. data/lib/openwfe/logging.rb +122 -0
  82. data/lib/openwfe/omixins.rb +95 -0
  83. data/lib/openwfe/orest/controlclient.rb +119 -0
  84. data/lib/openwfe/orest/definitions.rb +113 -0
  85. data/lib/openwfe/orest/exception.rb +60 -0
  86. data/lib/openwfe/orest/oldrestservlet.rb +279 -0
  87. data/lib/openwfe/orest/osocket.rb +148 -0
  88. data/lib/openwfe/orest/restclient.rb +176 -0
  89. data/lib/openwfe/orest/workitem.rb +206 -0
  90. data/lib/openwfe/orest/worklistclient.rb +272 -0
  91. data/lib/openwfe/orest/xmlcodec.rb +670 -0
  92. data/lib/openwfe/participants.rb +38 -0
  93. data/lib/openwfe/participants/enoparticipants.rb +230 -0
  94. data/lib/openwfe/participants/participant.rb +141 -0
  95. data/lib/openwfe/participants/participantmap.rb +249 -0
  96. data/lib/openwfe/participants/participants.rb +407 -0
  97. data/lib/openwfe/participants/soapparticipants.rb +135 -0
  98. data/lib/openwfe/participants/socketparticipants.rb +202 -0
  99. data/lib/openwfe/participants/storeparticipants.rb +254 -0
  100. data/lib/openwfe/rudefinitions.rb +130 -0
  101. data/lib/openwfe/service.rb +103 -0
  102. data/lib/openwfe/storage/yamlcustom.rb +106 -0
  103. data/lib/openwfe/storage/yamlfilestorage.rb +245 -0
  104. data/lib/openwfe/tools/flowtracer.rb +81 -0
  105. data/lib/openwfe/util/dollar.rb +217 -0
  106. data/lib/openwfe/util/irb.rb +86 -0
  107. data/lib/openwfe/util/observable.rb +144 -0
  108. data/lib/openwfe/util/ometa.rb +62 -0
  109. data/lib/openwfe/util/workqueue.rb +124 -0
  110. data/lib/openwfe/util/xml.rb +418 -0
  111. data/lib/openwfe/utils.rb +554 -0
  112. data/lib/openwfe/version.rb +37 -0
  113. data/lib/openwfe/workitem.rb +499 -0
  114. data/lib/openwfe/worklist/oldrest.rb +244 -0
  115. data/lib/openwfe/worklist/storelocks.rb +293 -0
  116. data/lib/openwfe/worklist/storeparticipant.rb +44 -0
  117. data/lib/openwfe/worklist/worklist.rb +297 -0
  118. data/test/README.txt +27 -0
  119. data/test/back_0916_test.rb +111 -0
  120. data/test/bm/bm_1_xml_vs_prog.rb +56 -0
  121. data/test/bm/bm_2_step.rb +109 -0
  122. data/test/bm/ft_0f_5ms.rb +35 -0
  123. data/test/bm/ft_26_load.rb +210 -0
  124. data/test/bm/ft_26b_load.rb +86 -0
  125. data/test/bm/ft_26c_load.rb +97 -0
  126. data/test/bm/ft_26d_load.rb +97 -0
  127. data/test/bm/ft_recu.rb +71 -0
  128. data/test/clone_test.rb +122 -0
  129. data/test/concurrence_test.rb +77 -0
  130. data/test/condition_test.rb +155 -0
  131. data/test/console_test.rb +12 -0
  132. data/test/cron_ltest.rb +15 -0
  133. data/test/description_test.rb +87 -0
  134. data/test/eno_test.rb +76 -0
  135. data/test/expmap_test.rb +54 -0
  136. data/test/expool_20031219_0916.tgz +0 -0
  137. data/test/fe_lookup_att_test.rb +62 -0
  138. data/test/fei_test.rb +181 -0
  139. data/test/file_persisted_engine_test.rb +64 -0
  140. data/test/file_persistence_test.rb +134 -0
  141. data/test/filep_cancel_test.rb +123 -0
  142. data/test/filter_test.rb +109 -0
  143. data/test/flowtestbase.rb +351 -0
  144. data/test/ft_0.rb +68 -0
  145. data/test/ft_0b_sequence.rb +36 -0
  146. data/test/ft_0c_testname.rb +33 -0
  147. data/test/ft_0d_participant.rb +30 -0
  148. data/test/ft_0e_multibody.rb +34 -0
  149. data/test/ft_10_loop.rb +134 -0
  150. data/test/ft_11_ppd.rb +415 -0
  151. data/test/ft_11b_ppd.rb +54 -0
  152. data/test/ft_12_blockparticipant.rb +97 -0
  153. data/test/ft_13_eno.rb +52 -0
  154. data/test/ft_14_subprocess.rb +88 -0
  155. data/test/ft_14b_subprocess.rb +192 -0
  156. data/test/ft_14c_subprocess.rb +68 -0
  157. data/test/ft_15_iterator.rb +216 -0
  158. data/test/ft_15b_iterator.rb +74 -0
  159. data/test/ft_16_fqv.rb +73 -0
  160. data/test/ft_17_condition.rb +84 -0
  161. data/test/ft_18_pname.rb +56 -0
  162. data/test/ft_1_unset.rb +175 -0
  163. data/test/ft_1b_unset.rb +39 -0
  164. data/test/ft_20_cron.rb +53 -0
  165. data/test/ft_21_cron.rb +87 -0
  166. data/test/ft_21b_cron_pause.rb +82 -0
  167. data/test/ft_22_history.rb +74 -0
  168. data/test/ft_23_when.rb +77 -0
  169. data/test/ft_23b_when.rb +70 -0
  170. data/test/ft_23c_wait.rb +80 -0
  171. data/test/ft_23d_cww.rb +58 -0
  172. data/test/ft_24_def.rb +44 -0
  173. data/test/ft_25_cancel.rb +89 -0
  174. data/test/ft_27_getflowpos.rb +147 -0
  175. data/test/ft_28_fileparticipant.rb +63 -0
  176. data/test/ft_29_httprb.rb +106 -0
  177. data/test/ft_2_concurrence.rb +135 -0
  178. data/test/ft_2b_concurrence.rb +188 -0
  179. data/test/ft_2c_concurrence.rb +64 -0
  180. data/test/ft_30_socketlistener.rb +203 -0
  181. data/test/ft_31_flowname.rb +40 -0
  182. data/test/ft_32_journal.rb +91 -0
  183. data/test/ft_32c_journal.rb +102 -0
  184. data/test/ft_32d_journal.rb +84 -0
  185. data/test/ft_33_description.rb +107 -0
  186. data/test/ft_34_cancelwfid.rb +80 -0
  187. data/test/ft_35_localdefs.rb +75 -0
  188. data/test/ft_36_subprocids.rb +97 -0
  189. data/test/ft_37_pnames.rb +70 -0
  190. data/test/ft_38_tag.rb +127 -0
  191. data/test/ft_38b_tag.rb +161 -0
  192. data/test/ft_38c_tag.rb +100 -0
  193. data/test/ft_39_reserve.rb +63 -0
  194. data/test/ft_39b_reserve.rb +84 -0
  195. data/test/ft_3_equals.rb +170 -0
  196. data/test/ft_3b_lookup_vf.rb +83 -0
  197. data/test/ft_40_defined.rb +61 -0
  198. data/test/ft_41_case.rb +110 -0
  199. data/test/ft_42_environments.rb +75 -0
  200. data/test/ft_43_pat10.rb +85 -0
  201. data/test/ft_44_save.rb +70 -0
  202. data/test/ft_44b_restore.rb +212 -0
  203. data/test/ft_45_citerator.rb +214 -0
  204. data/test/ft_46_pparams.rb +62 -0
  205. data/test/ft_47_filter.rb +160 -0
  206. data/test/ft_48_fe_filter.rb +88 -0
  207. data/test/ft_49_condition.rb +126 -0
  208. data/test/ft_4_misc.rb +237 -0
  209. data/test/ft_50_xml_attribute.rb +155 -0
  210. data/test/ft_51_stack.rb +55 -0
  211. data/test/ft_52_obs_participant.rb +123 -0
  212. data/test/ft_53_null_noop_participant.rb +62 -0
  213. data/test/ft_54_listen.rb +288 -0
  214. data/test/ft_54b_listen.rb +66 -0
  215. data/test/ft_54c_listen.rb +99 -0
  216. data/test/ft_55_ptimeout.rb +59 -0
  217. data/test/ft_56_timeout.rb +59 -0
  218. data/test/ft_57_a.rb +145 -0
  219. data/test/ft_58_ejournal.rb +151 -0
  220. data/test/ft_59_ps.rb +150 -0
  221. data/test/ft_59b_ps_for_pat.rb +58 -0
  222. data/test/ft_5_time.rb +118 -0
  223. data/test/ft_60_ecancel.rb +161 -0
  224. data/test/ft_61_elsub.rb +51 -0
  225. data/test/ft_62_procparticipant.rb +71 -0
  226. data/test/ft_63_pause.rb +124 -0
  227. data/test/ft_64_alias.rb +102 -0
  228. data/test/ft_64_clone.rb +69 -0
  229. data/test/ft_65_stringlaunch.rb +59 -0
  230. data/test/ft_66_subforget.rb +70 -0
  231. data/test/ft_67_schedlaunch.rb +116 -0
  232. data/test/ft_68_ifparticipant.rb +70 -0
  233. data/test/ft_69_cancelmissing.rb +51 -0
  234. data/test/ft_6_lambda.rb +64 -0
  235. data/test/ft_70_lookupvar.rb +55 -0
  236. data/test/ft_71_log.rb +60 -0
  237. data/test/ft_72_lookup_processes.rb +76 -0
  238. data/test/ft_73_cancel_sub.rb +139 -0
  239. data/test/ft_74_block_and_workitem_dup.rb +63 -0
  240. data/test/ft_75_ruby_attributes.rb +87 -0
  241. data/test/ft_76_merge_isolate.rb +88 -0
  242. data/test/ft_77_segments.rb +35 -0
  243. data/test/ft_78_eval.rb +150 -0
  244. data/test/ft_79_tticket.rb +187 -0
  245. data/test/ft_79b_tticket.rb +172 -0
  246. data/test/ft_79c_outcome.rb +56 -0
  247. data/test/ft_7_lose.rb +104 -0
  248. data/test/ft_7b_lose.rb +78 -0
  249. data/test/ft_80_spname.rb +91 -0
  250. data/test/ft_81_exp.rb +60 -0
  251. data/test/ft_82_trecu.rb +46 -0
  252. data/test/ft_83_badpause.rb +58 -0
  253. data/test/ft_84_updateexp.rb +198 -0
  254. data/test/ft_85_dolhash.rb +43 -0
  255. data/test/ft_86_dollar_fv.rb +68 -0
  256. data/test/ft_87_define.rb +74 -0
  257. data/test/ft_8_forget.rb +44 -0
  258. data/test/ft_9_cursor.rb +145 -0
  259. data/test/ft_9b_cursor.rb +105 -0
  260. data/test/ft_tests.rb +124 -0
  261. data/test/hash_test.rb +75 -0
  262. data/test/hparticipant_test.rb +164 -0
  263. data/test/lookup_att_test.rb +90 -0
  264. data/test/lookup_vf_test.rb +94 -0
  265. data/test/misc_test.rb +90 -0
  266. data/test/nut_0_irb.rb +20 -0
  267. data/test/obs_test.rb +142 -0
  268. data/test/orest_test.rb +251 -0
  269. data/test/param_test.rb +290 -0
  270. data/test/participant_test.rb +101 -0
  271. data/test/pending.rb +23 -0
  272. data/test/ps_representation.rb +133 -0
  273. data/test/rake_ltest.rb +38 -0
  274. data/test/rake_qtest.rb +68 -0
  275. data/test/raw_prog_test.rb +412 -0
  276. data/test/restart_cron_test.rb +136 -0
  277. data/test/restart_paused_test.rb +98 -0
  278. data/test/restart_sleep_test.rb +140 -0
  279. data/test/restart_tests.rb +18 -0
  280. data/test/restart_when_test.rb +112 -0
  281. data/test/ruby_procdef_test.rb +132 -0
  282. data/test/rutest_utils.rb +63 -0
  283. data/test/sec_test.rb +205 -0
  284. data/test/slock_test.rb +80 -0
  285. data/test/storage_test.rb +44 -0
  286. data/test/test.rb +3 -0
  287. data/test/timeout_test.rb +105 -0
  288. data/test/util_xml_test.rb +112 -0
  289. data/test/wfid_test.rb +175 -0
  290. data/test/wi_test.rb +75 -0
  291. metadata +433 -0
@@ -0,0 +1,662 @@
1
+ #
2
+ #--
3
+ # Copyright (c) 2006-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
+ require 'openwfe/utils'
41
+ require 'openwfe/rudefinitions'
42
+ require 'openwfe/expressions/merge'
43
+ require 'openwfe/expressions/condition'
44
+ require 'openwfe/expressions/flowexpression'
45
+ require 'openwfe/expressions/iterator'
46
+
47
+
48
+ #
49
+ # base expressions like 'sequence' and 'concurrence'
50
+ #
51
+
52
+ module OpenWFE
53
+
54
+ #
55
+ # The concurrence expression will execute each of its (direct) children
56
+ # in parallel threads.
57
+ #
58
+ # Thus,
59
+ #
60
+ # <concurrence>
61
+ # <participant ref="pa" />
62
+ # <participant ref="pb" />
63
+ # </concurrence>
64
+ #
65
+ # Participants pa and pb will be 'treated' in parallel (quasi
66
+ # simultaneously).
67
+ #
68
+ # The concurrence expressions accept many attributes, that can get
69
+ # combined. By default, the concurrence waits for all its children to
70
+ # reply and returns the workitem of the first child that replied.
71
+ # The attributes tune this behaviour.
72
+ #
73
+ # <em>count</em>
74
+ #
75
+ # <concurrence count="1">
76
+ # <participant ref="pa" />
77
+ # <participant ref="pb" />
78
+ # </concurrence>
79
+ #
80
+ # The concurrence will be over as soon as 'pa' or 'pb' replied, i.e.
81
+ # as soon as "1" child replied.
82
+ #
83
+ # <em>remaining</em>
84
+ #
85
+ # The attribute 'remaining' can take two values 'cancel' (the default) and
86
+ # 'forget'.
87
+ # Cancelled children are completely wiped away, forgotten ones continue
88
+ # to operate but their reply will simply get discarded.
89
+ #
90
+ # <em>over-if</em>
91
+ #
92
+ # 'over-if' accepts a 'boolean expression' (something replying 'true' or
93
+ # 'false'), if the expression evaluates to true, the concurrence will be
94
+ # over and the remaining children will get cancelled (the default) or
95
+ # forgotten.
96
+ #
97
+ # <em>merge</em>
98
+ #
99
+ # By default, the first child to reply to its parent 'concurrence'
100
+ # expression 'wins', i.e. its workitem is used for resuming the flow (after
101
+ # the concurrence).
102
+ #
103
+ # [first] The default : the first child to reply wins
104
+ # [last] The last child to reply wins
105
+ # [highest] The first 'defined' child (in the list of children) will win
106
+ # [lowest] The last 'defined' child (in the list of children) will win
107
+ #
108
+ # Thus, in that example
109
+ #
110
+ # <concurrence merge="lowest">
111
+ # <participant ref="pa" />
112
+ # <participant ref="pb" />
113
+ # </concurrence>
114
+ #
115
+ # when the concurrence is done, the workitem of 'pb' is used to resume the
116
+ # flow after the concurrence.
117
+ #
118
+ # <em>merge-type</em>
119
+ #
120
+ # [override] The default : no mix of values between the workitems do occur
121
+ # [mix] Priority is given to the 'winning' workitem but their values
122
+ # get mixed
123
+ # [isolate] the attributes of the workitem of each branch is placed
124
+ # in a field in the resulting workitem. For example, the
125
+ # attributes of the first branch will be stored under the
126
+ # field named '0' of the resulting workitem.
127
+ #
128
+ # The merge occurs are the top level of workitem attributes.
129
+ #
130
+ # More complex merge behaviour can be obtained by extending the
131
+ # GenericSyncExpression class. But the default sync options are already
132
+ # numerous and powerful by their combinations.
133
+ #
134
+ class ConcurrenceExpression < SequenceExpression
135
+ include ConditionMixin
136
+
137
+ names :concurrence
138
+
139
+ attr_accessor \
140
+ :sync_expression
141
+
142
+
143
+ def apply (workitem)
144
+
145
+ sync = lookup_sym_attribute(
146
+ :sync, workitem, :default => :generic)
147
+
148
+ @sync_expression =
149
+ get_expression_map.get_sync_class(sync).new(self, workitem)
150
+
151
+ @children.each do |child|
152
+ @sync_expression.add_child child
153
+ end
154
+
155
+ store_itself
156
+
157
+ #concurrence = self
158
+
159
+ @children.each_with_index do |child, index|
160
+
161
+ get_expression_pool.apply(
162
+ child,
163
+ get_workitem(workitem, index))
164
+
165
+ #Thread.new do
166
+ # begin
167
+ # #ldebug { "apply() child : #{child.to_debug_s}" }
168
+ # concurrence.synchronize do
169
+ # get_expression_pool().apply(
170
+ # child,
171
+ # #workitem.dup)
172
+ # get_workitem(workitem, index))
173
+ # end
174
+ # rescue Exception => e
175
+ # lwarn do
176
+ # "apply() " +
177
+ # "caught exception in concurrent child " +
178
+ # child.to_debug_s + "\n" +
179
+ # OpenWFE::exception_to_s(e)
180
+ # end
181
+ # end
182
+ #end
183
+ end
184
+
185
+ #@sync_expression.ready(self)
186
+ #
187
+ # this is insufficient, have to do that :
188
+
189
+ #synchronize do
190
+ #
191
+ # Making sure the freshest version of the concurrence
192
+ # expression is used.
193
+ # This is especially important when using pure persistence.
194
+ #
195
+ reloaded_self, _fei = get_expression_pool.fetch @fei
196
+ reloaded_self.sync_expression.ready reloaded_self
197
+ #end
198
+ end
199
+
200
+ def reply (workitem)
201
+ @sync_expression.reply(self, workitem)
202
+ end
203
+
204
+ protected
205
+
206
+ def get_workitem (workitem, index)
207
+ workitem.dup
208
+ end
209
+ end
210
+
211
+ #
212
+ # This expression is a mix between a 'concurrence' and an 'iterator'.
213
+ # It understands the same attributes and behaves as an interator that
214
+ # forks its children concurrently.
215
+ #
216
+ # Some examples :
217
+ #
218
+ # <concurrent-iterator on-value="sales, logistics, lob2" to-field="p">
219
+ # <participant field-ref="p" />
220
+ # </concurrent-iterator>
221
+ #
222
+ # Within a Ruby process definition :
223
+ #
224
+ # sequence do
225
+ # set :field => f, :value => %w{ Alan, Bob, Clarence }
226
+ # #...
227
+ # concurrent_iterator :on_field => "f", :to_field => "p" do
228
+ # participant "${p}"
229
+ # end
230
+ # end
231
+ #
232
+ class ConcurrentIteratorExpression < ConcurrenceExpression
233
+
234
+ names :concurrent_iterator
235
+
236
+ #attr_accessor :template
237
+
238
+ uses_template
239
+
240
+
241
+ def apply (workitem)
242
+
243
+ return reply_to_parent(workitem) \
244
+ if raw_children.length < 1
245
+
246
+ @workitems = []
247
+
248
+ iterator = Iterator.new self, workitem
249
+
250
+ return reply_to_parent(workitem) \
251
+ unless iterator.has_next?
252
+
253
+ while iterator.has_next?
254
+
255
+ wi = workitem.dup
256
+
257
+ @workitems << wi
258
+
259
+ vars = iterator.next wi
260
+
261
+ #rawexp = get_expression_pool.prepare_from_template(
262
+ # self, nil, iterator.index, template, vars)
263
+ #@children << rawexp.fei
264
+
265
+ get_expression_pool.tprepare_child(
266
+ self,
267
+ raw_children.first,
268
+ iterator.index,
269
+ true, # register child
270
+ vars)
271
+ end
272
+
273
+ super
274
+ end
275
+
276
+ protected
277
+
278
+ def get_workitem (workitem, index)
279
+
280
+ @workitems[index]
281
+ end
282
+ end
283
+
284
+ #
285
+ # A base for sync expressions, currently empty.
286
+ # That may change.
287
+ #
288
+ class SyncExpression < ObjectWithMeta
289
+
290
+ def initialize
291
+
292
+ super
293
+ end
294
+
295
+ def self.names (*exp_names)
296
+
297
+ exp_names = exp_names.collect do |n|
298
+ n.to_s
299
+ end
300
+ meta_def :expression_names do
301
+ exp_names
302
+ end
303
+ end
304
+ end
305
+
306
+ #
307
+ # The classical OpenWFE sync expression.
308
+ # Used by 'concurrence' and 'concurrent-iterator'
309
+ #
310
+ class GenericSyncExpression < SyncExpression
311
+
312
+ names :generic
313
+
314
+ attr_accessor \
315
+ :remaining_children,
316
+ :count,
317
+ :reply_count,
318
+ :cancel_remaining,
319
+ :unready_queue
320
+
321
+ def initialize (synchable, workitem)
322
+
323
+ super()
324
+
325
+ @remaining_children = []
326
+ @reply_count = 0
327
+
328
+ @count = determine_count(synchable, workitem)
329
+ @cancel_remaining = cancel_remaining?(synchable, workitem)
330
+
331
+ merge = synchable.lookup_sym_attribute(
332
+ :merge, workitem, :default => :first)
333
+
334
+ merge_type = synchable.lookup_sym_attribute(
335
+ :merge_type, workitem, :default => :mix)
336
+
337
+ synchable.ldebug { "new() merge_type is '#{merge_type}'" }
338
+
339
+ @merge_array = MergeArray.new synchable.fei, merge, merge_type
340
+
341
+ @unready_queue = []
342
+ end
343
+
344
+ #
345
+ # when all the children got applied concurrently, the concurrence
346
+ # calls this method to notify the sync expression that replies
347
+ # can be processed
348
+ #
349
+ def ready (synchable)
350
+ #synchable.synchronize do
351
+
352
+ synchable.ldebug do
353
+ "ready() called by #{synchable.fei.to_debug_s} " +
354
+ "#{@unready_queue.length} wi waiting"
355
+ end
356
+
357
+ queue = @unready_queue
358
+ @unready_queue = nil
359
+ synchable.store_itself
360
+
361
+ queue.each do |workitem|
362
+ break if do_reply(synchable, workitem)
363
+ #
364
+ # do_reply() will return 'true' as soon as the
365
+ # concurrence is over, if this is the case, the
366
+ # queue should not be treated anymore
367
+ end
368
+ #end
369
+ end
370
+
371
+ def add_child (child)
372
+ @remaining_children << child
373
+ end
374
+
375
+ def reply (synchable, workitem)
376
+ #synchable.synchronize do
377
+
378
+ if @unready_queue
379
+
380
+ @unready_queue << workitem
381
+
382
+ synchable.store_itself
383
+
384
+ synchable.ldebug do
385
+ "#{self.class}.reply() "+
386
+ "#{@unready_queue.length} wi waiting..."
387
+ end
388
+
389
+ else
390
+ do_reply synchable, workitem
391
+ end
392
+ #end
393
+ end
394
+
395
+ protected
396
+
397
+ def do_reply (synchable, workitem)
398
+
399
+ synchable.ldebug do
400
+ "#{self.class}.do_reply() from " +
401
+ "#{workitem.last_expression_id.to_debug_s}"
402
+ end
403
+
404
+ @merge_array.push(synchable, workitem)
405
+
406
+ @reply_count = @reply_count + 1
407
+
408
+ @remaining_children.delete(workitem.last_expression_id)
409
+
410
+ #synchable.ldebug do
411
+ # "#{self.class}.do_reply() "+
412
+ # "remaining children : #{@remaining_children.length}"
413
+ #end
414
+
415
+ if @remaining_children.length <= 0
416
+ reply_to_parent(synchable)
417
+ return true
418
+ end
419
+
420
+ if @count > 0 and @reply_count >= @count
421
+ treat_remaining_children(synchable)
422
+ reply_to_parent(synchable)
423
+ return true
424
+ end
425
+
426
+ #
427
+ # over-if
428
+
429
+ conditional =
430
+ synchable.eval_condition("over-if", workitem, "over-unless")
431
+
432
+ if conditional
433
+ treat_remaining_children(synchable)
434
+ reply_to_parent(synchable)
435
+ return true
436
+ end
437
+
438
+ #
439
+ # not over, resuming
440
+
441
+ synchable.store_itself()
442
+
443
+ #synchable.ldebug do
444
+ # "#{self.class}.do_reply() not replying to parent "+
445
+ # "#{workitem.last_expression_id.to_debug_s}"
446
+ #end
447
+
448
+ false
449
+ end
450
+
451
+ def reply_to_parent (synchable)
452
+
453
+ workitem = @merge_array.do_merge
454
+
455
+ synchable.reply_to_parent workitem
456
+ end
457
+
458
+ def treat_remaining_children (synchable)
459
+
460
+ expool = synchable.get_expression_pool
461
+
462
+ @remaining_children.each do |child|
463
+
464
+ synchable.ldebug do
465
+ "#{self.class}.treat_remainining_children() " +
466
+ "#{child.to_debug_s} " +
467
+ "(cancel ? #{@cancel_remaining})"
468
+ end
469
+
470
+ if @cancel_remaining
471
+ expool.cancel(child)
472
+ else
473
+ expool.forget(synchable, child)
474
+ end
475
+ end
476
+ end
477
+
478
+ def cancel_remaining? (synchable_expression, workitem)
479
+
480
+ s = synchable_expression.lookup_sym_attribute(
481
+ :remaining, workitem, :default => :cancel)
482
+
483
+ (s == :cancel)
484
+ end
485
+
486
+ def determine_count (synchable_expression, workitem)
487
+
488
+ c = synchable_expression.lookup_attribute :count, workitem
489
+ return -1 if not c
490
+ i = c.to_i
491
+ return -1 if i < 1
492
+ i
493
+ end
494
+
495
+ #
496
+ # This inner class is used to gather workitems (via push()) before
497
+ # the final merge
498
+ # This final merge is triggered by calling the do_merge() method
499
+ # which will return the resulting, merged workitem.
500
+ #
501
+ class MergeArray
502
+ include MergeMixin
503
+
504
+ attr_accessor \
505
+ :synchable_fei,
506
+ :workitem,
507
+ :workitems_by_arrival,
508
+ :workitems_by_altitude,
509
+ :merge,
510
+ :merge_type
511
+
512
+ def initialize (synchable_fei, merge, merge_type)
513
+
514
+ @synchable_fei = synchable_fei
515
+
516
+ @merge = merge
517
+ @merge_type = merge_type
518
+
519
+ ensure_merge_settings
520
+
521
+ @workitem = nil
522
+
523
+ if highest? or lowest?
524
+ @workitems_by_arrival = []
525
+ @workitems_by_altitude = []
526
+ end
527
+ end
528
+
529
+ def push (synchable, wi)
530
+
531
+ #synchable.ldebug do
532
+ # "push() isolate? #{isolate?}"
533
+ #end
534
+
535
+ if isolate?
536
+ push_in_isolation wi
537
+ elsif last? or first?
538
+ push_by_position wi
539
+ else
540
+ push_by_arrival wi
541
+ end
542
+ end
543
+
544
+ def push_by_position (wi)
545
+
546
+ source, target = if first?
547
+ [ @workitem, wi ]
548
+ else
549
+ [ wi, @workitem ]
550
+ end
551
+ @workitem = merge_workitems target, source, override?
552
+ end
553
+
554
+ def push_in_isolation (wi)
555
+
556
+ unless @workitem
557
+ @workitem = wi.dup
558
+ att = @workitem.attributes
559
+ @workitem.attributes = {}
560
+ end
561
+
562
+ #key = synchable.children.index wi.last_expression_id
563
+ #key = wi.last_expression_id.child_id
564
+ key = get_child_id wi
565
+
566
+ @workitem.attributes[key.to_s] =
567
+ OpenWFE::fulldup(wi.attributes)
568
+ end
569
+
570
+ def push_by_arrival (wi)
571
+
572
+ #index = synchable.children.index wi.last_expression_id
573
+ #index = Integer(wi.last_expression_id.child_id)
574
+ index = Integer(get_child_id(wi))
575
+
576
+ @workitems_by_arrival << wi
577
+ @workitems_by_altitude[index] = wi
578
+ end
579
+
580
+ #
581
+ # merges the workitems stored here
582
+ #
583
+ def do_merge
584
+
585
+ return @workitem if @workitem
586
+
587
+ list = if first?
588
+ @workitems_by_arrival.reverse
589
+ elsif last?
590
+ @workitems_by_arrival
591
+ elsif highest?
592
+ @workitems_by_altitude.reverse
593
+ elsif lowest?
594
+ @workitems_by_altitude
595
+ end
596
+
597
+ result = nil
598
+
599
+ list.each do |wi|
600
+ next unless wi
601
+ result = merge_workitems result, wi, override?
602
+ end
603
+
604
+ #puts "___ result :"
605
+ #puts result.to_s
606
+ #puts
607
+
608
+ result
609
+ end
610
+
611
+ protected
612
+
613
+ def first?
614
+ @merge == :first
615
+ end
616
+ def last?
617
+ @merge == :last
618
+ end
619
+ def highest?
620
+ @merge == :highest
621
+ end
622
+ def lowest?
623
+ @merge == :lowest
624
+ end
625
+
626
+ def mix?
627
+ @merge_type == :mix
628
+ end
629
+ def override?
630
+ @merge_type == :override
631
+ end
632
+ def isolate?
633
+ @merge_type == :isolate
634
+ end
635
+
636
+ #
637
+ # Returns the child id of the expression that just
638
+ # replied with the given workitem.
639
+ #
640
+ def get_child_id (workitem)
641
+
642
+ return workitem.fei.child_id \
643
+ if workitem.fei.wfid == @synchable_fei.wfid
644
+
645
+ workitem.fei.last_sub_instance_id
646
+ end
647
+
648
+ #
649
+ # Making sure @merge and @merge_type are set to
650
+ # appropriate values.
651
+ #
652
+ def ensure_merge_settings
653
+
654
+ @merge_type = :mix unless override? or isolate?
655
+ @merge = :first unless last? or highest? or lowest?
656
+ end
657
+ end
658
+
659
+ end
660
+
661
+ end
662
+