ruote 0.9.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,269 @@
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/filter'
43
+ require 'openwfe/expressions/timeout'
44
+
45
+
46
+ #
47
+ # The participant expression, in its own file
48
+ #
49
+
50
+ module OpenWFE
51
+
52
+ #
53
+ # Participants sit at the edge between the engine and the external
54
+ # world. The participant expression transmit the workitem applied
55
+ # to it to the Participant instance it looks up in the participant map
56
+ # tied to the engine.
57
+ #
58
+ # direct reference to participant alpha :
59
+ #
60
+ # <participant ref="alpha" />
61
+ #
62
+ # the name of the participant is the value found in
63
+ # the field 'target' :
64
+ #
65
+ # <participant field-ref="target" />
66
+ # <participant ref="${f:target}" />
67
+ #
68
+ # the name of the participant is the value found in
69
+ # the variable 'target' :
70
+ #
71
+ # <participant variable-ref="target" />
72
+ # <participant ref="${target}" />
73
+ #
74
+ # direct reference to participant 'alpha'
75
+ # if a subprocess named 'alpha' has been defined, the
76
+ # subprocess will be called instead :
77
+ #
78
+ # <alpha />
79
+ #
80
+ # The Participant expressions includes the FilterMixin and thus
81
+ # understands and applies the "filter" attribute.
82
+ #
83
+ # Since OpenWFEru 0.9.9, the attributes of the participant expression are
84
+ # set inside a hash field named 'params' just available to the participant.
85
+ # Thus in
86
+ #
87
+ # <participant ref="toto" task="play golf" location="Minami Center" />
88
+ #
89
+ # participant 'toto' will receive a workitem with a field named 'params'
90
+ # containing the hash
91
+ # { "ref"=>"toto", "task"=>"play golf", "location"=>"Minami Center" }.
92
+ #
93
+ # When the workitem gets back from the participant, the field 'params' is
94
+ # deleted.
95
+ #
96
+ # The participant expressions include the TimeoutMixin, it means that
97
+ # a timeout can be stated :
98
+ #
99
+ # <participant ref="toto" timeout="2w1d" />
100
+ #
101
+ # If after 2 weeks and 1 day (15 days), participant "toto" hasn't replied,
102
+ # the workitem will get cancelled and the flow will resume (behind the
103
+ # scene, participant "toto", will receive a CancelItem instance bearing
104
+ # the same FlowExpressionId as the initial workitem and the participant
105
+ # implementation is responsible for the cancel application).
106
+ #
107
+ # The participant expression accepts an optional 'if' (or 'unless')
108
+ # attribute. It's used for conditional execution of the participant :
109
+ #
110
+ # participant :ref => "toto", :if => "${weather} == raining"
111
+ # # the participant toto will receive a workitem only if
112
+ # # it's raining
113
+ #
114
+ # boss :unless => "#{f:matter} == 'very trivial'"
115
+ # # the boss will not participate in the proces if the matter
116
+ # # is 'very trivial'
117
+ #
118
+ class ParticipantExpression < FlowExpression
119
+ include FilterMixin
120
+ include TimeoutMixin
121
+ include ConditionMixin
122
+
123
+ names :participant
124
+
125
+ attr_accessor :participant_name
126
+ attr_accessor :applied_workitem
127
+
128
+
129
+ def apply (workitem)
130
+
131
+ conditional = eval_condition :if, workitem, :unless
132
+
133
+ return super_reply_to_parent(workitem) \
134
+ if conditional == false
135
+ #
136
+ # skip expression
137
+ # <participant ref="x" if="y" /> (where y evals to false)
138
+
139
+ @participant_name = lookup_ref workitem
140
+
141
+ @participant_name = fetch_text_content workitem \
142
+ unless @participant_name
143
+
144
+ participant =
145
+ get_participant_map.lookup_participant @participant_name
146
+
147
+ raise "No participant named '#{@participant_name}'" \
148
+ unless participant
149
+
150
+ remove_timedout_flag workitem
151
+
152
+ @applied_workitem = workitem.dup
153
+
154
+ schedule_timeout
155
+
156
+ filter_in workitem
157
+
158
+ store_itself
159
+
160
+ workitem.params = lookup_attributes workitem
161
+
162
+ #
163
+ # threading AFTER the store_itself()
164
+ #
165
+ Thread.new do
166
+ begin
167
+
168
+ # these two pmap calls were combined, but with the :reply
169
+ # notification in reply_to_parent() it feels more
170
+ # elegant like that
171
+
172
+ get_participant_map.dispatch(
173
+ participant, @participant_name, workitem)
174
+
175
+ get_participant_map.onotify(
176
+ @participant_name, :apply, workitem)
177
+
178
+ rescue Exception => e
179
+
180
+ get_expression_pool.notify_error(
181
+ e, fei, :do_apply, workitem)
182
+ end
183
+ end
184
+ end
185
+
186
+ alias :super_reply_to_parent :reply_to_parent
187
+
188
+ def reply_to_parent (workitem)
189
+
190
+ get_participant_map.onotify @participant_name, :reply, workitem
191
+ #
192
+ # for 'listen' expressions waiting for replies
193
+
194
+ unschedule_timeout()
195
+
196
+ workitem.attributes.delete "params"
197
+
198
+ filter_out workitem
199
+
200
+ super workitem
201
+ end
202
+
203
+ #
204
+ # The cancel() method of a ParticipantExpression is particular : it
205
+ # will emit a CancelItem instance towards the participant itself
206
+ # to notify it of the cancellation.
207
+ #
208
+ def cancel
209
+
210
+ unschedule_timeout
211
+
212
+ cancel_participant
213
+
214
+ @applied_workitem
215
+ end
216
+
217
+ #
218
+ # Upon timeout, the ParticipantExpression will cancel itself and
219
+ # the flow will resume.
220
+ #
221
+ def trigger (scheduler)
222
+
223
+ linfo { "trigger() timeout requested for #{@fei.to_debug_s}" }
224
+
225
+ begin
226
+
227
+ #@scheduler_job_id = nil
228
+ #
229
+ # so that cancel won't unschedule without need
230
+
231
+ cancel_participant
232
+
233
+ set_timedout_flag @applied_workitem
234
+
235
+ reply_to_parent @applied_workitem
236
+
237
+ rescue
238
+
239
+ lerror do
240
+ "trigger() problem while timing out\n"+
241
+ OpenWFE::exception_to_s($!)
242
+ end
243
+ end
244
+ end
245
+
246
+ protected
247
+
248
+ #
249
+ # Have to cancel the workitem on the participant side
250
+ #
251
+ def cancel_participant
252
+
253
+ return unless @applied_workitem
254
+ #
255
+ # if there is an applied workitem, it means there
256
+ # is a participant to cancel...
257
+
258
+ participant = \
259
+ get_participant_map.lookup_participant(@participant_name)
260
+
261
+ cancelitem = CancelItem.new(@applied_workitem)
262
+
263
+ get_participant_map.dispatch(
264
+ participant, @participant_name, cancelitem)
265
+ end
266
+ end
267
+
268
+ end
269
+
@@ -0,0 +1,212 @@
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
+ #require 'thread'
41
+
42
+
43
+ module OpenWFE
44
+
45
+ #
46
+ # The 'reserve' expression ensures that its nested child expression
47
+ # executes while a reserved mutex is set.
48
+ #
49
+ # Thus
50
+ #
51
+ # concurrence do
52
+ # reserve :mutex => :m0 do
53
+ # sequence do
54
+ # participant :alpha
55
+ # participant :bravo
56
+ # end
57
+ # end
58
+ # reserve :mutex => :m0 do
59
+ # participant :charly
60
+ # end
61
+ # participant :delta
62
+ # end
63
+ #
64
+ # The sequence will not but run while the participant charly is active
65
+ # and vice versa. The participant delta is not concerned.
66
+ #
67
+ # The mutex is a regular variable name, thus a mutex named "//toto" could
68
+ # be used to prevent segments of totally different process instances from
69
+ # running.
70
+ #
71
+ class ReserveExpression < FlowExpression
72
+
73
+ #
74
+ # A mutex for the whole class, it's meant to prevent 'reserve'
75
+ # from reserving a workflow mutex simultaneaously.
76
+ #
77
+ #@@mutex = Mutex.new
78
+
79
+ names :reserve
80
+
81
+ #
82
+ # The name of the mutex this expressions uses.
83
+ # It's a variable name, that means it can be prefixed with
84
+ # {nothing} (local scope), '/' (process scope) and '//' (engine /
85
+ # global scope).
86
+ #
87
+ attr_accessor :mutex_name
88
+
89
+ #
90
+ # An instance variable for storing the applied workitem if the 'reserve'
91
+ # cannot be entered immediately.
92
+ #
93
+ attr_accessor :applied_workitem
94
+
95
+
96
+ def apply (workitem)
97
+
98
+ return reply_to_parent(workitem) \
99
+ if @children.size < 1
100
+
101
+ @mutex_name = lookup_string_attribute :mutex, workitem
102
+
103
+ #FlowMutex.synchronize do
104
+
105
+ mutex = lookup_variable(@mutex_name) || FlowMutex.new(@mutex_name)
106
+
107
+ mutex.register self, workitem
108
+ #end
109
+ end
110
+
111
+ def reply (workitem)
112
+
113
+ lookup_variable(@mutex_name).release self
114
+
115
+ reply_to_parent workitem
116
+ end
117
+
118
+ #
119
+ # Called by the FlowMutex to enter the 'reserved/critical' section.
120
+ #
121
+ def enter (workitem=nil)
122
+
123
+ get_expression_pool.apply(
124
+ @children[0], workitem || @applied_workitem)
125
+ end
126
+ end
127
+
128
+ #
129
+ # A FlowMutex is a process variable (thus serializable) that keeps
130
+ # track of the expressions in a critical section (1!) or waiting for
131
+ # entering it.
132
+ #
133
+ #--
134
+ # The current syncrhonization scheme is 1 thread mutex for all the
135
+ # FlowMutex. Shouldn't be too costly and the operations under sync are
136
+ # quite tiny.
137
+ #++
138
+ #
139
+ class FlowMutex
140
+
141
+ #--
142
+ # Granularity level ? "big rock". Only one FlowMutex operation
143
+ # a a time for the whole business process engine...
144
+ #
145
+ #@@class_mutex = Mutex.new
146
+ #++
147
+
148
+ attr_accessor :mutex_name
149
+ attr_accessor :feis
150
+
151
+ def initialize (mutex_name)
152
+
153
+ @mutex_name = mutex_name
154
+ @feis = []
155
+ end
156
+
157
+ def register (fexp, workitem)
158
+
159
+ @feis << fexp.fei
160
+
161
+ fexp.set_variable @mutex_name, self
162
+
163
+ if @feis.size == 1
164
+ #
165
+ # immediately let the expression enter the critical section
166
+ #
167
+ fexp.store_itself
168
+ fexp.enter workitem
169
+ else
170
+ #
171
+ # later...
172
+ #
173
+ fexp.applied_workitem = workitem
174
+ fexp.store_itself
175
+ end
176
+ end
177
+
178
+ def release (releaser)
179
+
180
+ next_fei = nil
181
+
182
+ #@@class_mutex.synchronize do
183
+
184
+ current_fei = @feis.delete_at 0
185
+
186
+ releaser.set_variable @mutex_name, self
187
+
188
+ log.warn "release() BAD! c:#{current_fei} r:#{releaser.fei}" \
189
+ if releaser.fei != current_fei
190
+
191
+ next_fei = @feis.first
192
+ #end
193
+
194
+ return unless next_fei
195
+
196
+ releaser.get_expression_pool.fetch_expression(next_fei).enter
197
+ end
198
+
199
+ #--
200
+ # Used by the ReserveExpression when looking up for a FlowMutex
201
+ # and registering into it.
202
+ #
203
+ #def self.synchronize (&block)
204
+ # @@class_mutex.synchronize do
205
+ # block.call
206
+ # end
207
+ #end
208
+ #++
209
+ end
210
+
211
+ end
212
+