openwferu 0.9.4 → 0.9.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. data/examples/mano_tracker.rb +13 -6
  2. data/examples/quotereporter.rb +3 -2
  3. data/lib/openwfe/engine/engine.rb +31 -4
  4. data/lib/openwfe/engine/file_persisted_engine.rb +35 -9
  5. data/lib/openwfe/expool/expressionpool.rb +116 -67
  6. data/lib/openwfe/expool/expstorage.rb +142 -101
  7. data/lib/openwfe/expool/history.rb +7 -2
  8. data/lib/openwfe/expool/yamlexpstorage.rb +150 -6
  9. data/lib/openwfe/expressions/{fe_condition.rb → condition.rb} +4 -6
  10. data/lib/openwfe/expressions/expressionmap.rb +8 -0
  11. data/lib/openwfe/expressions/fe_cancel.rb +109 -0
  12. data/lib/openwfe/expressions/fe_concurrence.rb +252 -16
  13. data/lib/openwfe/expressions/fe_cursor.rb +8 -3
  14. data/lib/openwfe/{util/stoppable.rb → expressions/fe_do.rb} +42 -11
  15. data/lib/openwfe/expressions/fe_iterator.rb +4 -3
  16. data/lib/openwfe/expressions/fe_misc.rb +3 -2
  17. data/lib/openwfe/expressions/fe_participant.rb +5 -0
  18. data/lib/openwfe/expressions/fe_raw.rb +10 -2
  19. data/lib/openwfe/expressions/fe_subprocess.rb +1 -1
  20. data/lib/openwfe/expressions/fe_time.rb +43 -23
  21. data/lib/openwfe/expressions/fe_value.rb +1 -1
  22. data/lib/openwfe/expressions/flowexpression.rb +22 -22
  23. data/lib/openwfe/expressions/raw_prog.rb +20 -39
  24. data/lib/openwfe/expressions/raw_xml.rb +6 -6
  25. data/lib/openwfe/expressions/timeout.rb +8 -3
  26. data/lib/openwfe/expressions/wtemplate.rb +67 -0
  27. data/lib/openwfe/flowexpressionid.rb +4 -1
  28. data/lib/openwfe/participants/atomparticipants.rb +13 -1
  29. data/lib/openwfe/participants/enoparticipant.rb +66 -5
  30. data/lib/openwfe/participants/participantmap.rb +12 -0
  31. data/lib/openwfe/rudefinitions.rb +15 -3
  32. data/lib/openwfe/service.rb +4 -5
  33. data/lib/openwfe/storage/yamlfilestorage.rb +72 -45
  34. data/lib/openwfe/util/dollar.rb +17 -4
  35. data/lib/openwfe/util/lru.rb +154 -0
  36. data/lib/openwfe/util/otime.rb +26 -5
  37. data/lib/openwfe/util/scheduler.rb +44 -36
  38. data/lib/openwfe/util/schedulers.rb +4 -2
  39. data/lib/openwfe/utils.rb +62 -0
  40. data/lib/openwfe/version.rb +1 -1
  41. data/lib/openwfe/worklist/storeparticipant.rb +34 -5
  42. data/test/eno_test.rb +69 -0
  43. data/test/file_persistence_test.rb +13 -11
  44. data/test/flowtestbase.rb +29 -15
  45. data/test/ft_0.rb +2 -1
  46. data/test/ft_0b_sequence.rb +2 -1
  47. data/test/ft_0c_testname.rb +6 -5
  48. data/test/ft_0d_participant.rb +2 -1
  49. data/test/ft_10_loop.rb +11 -6
  50. data/test/ft_10b_loop2.rb +63 -0
  51. data/test/ft_11_ppd.rb +39 -13
  52. data/test/ft_12_blockparticipant.rb +2 -1
  53. data/test/ft_13_eno.rb +3 -2
  54. data/test/ft_14_subprocess.rb +2 -1
  55. data/test/ft_14b_subprocess.rb +2 -1
  56. data/test/ft_15_iterator.rb +2 -1
  57. data/test/ft_16_fqv.rb +2 -1
  58. data/test/ft_17_condition.rb +2 -1
  59. data/test/ft_18_pname.rb +2 -1
  60. data/test/ft_19_csv.rb +2 -1
  61. data/test/ft_1_unset.rb +14 -18
  62. data/test/ft_1b_unset.rb +39 -0
  63. data/test/ft_20_cron.rb +2 -1
  64. data/test/ft_21_cron.rb +2 -1
  65. data/test/ft_22_history.rb +7 -5
  66. data/test/ft_23_when.rb +2 -1
  67. data/test/ft_23b_when.rb +2 -1
  68. data/test/ft_24_def.rb +2 -1
  69. data/test/ft_25_cancel.rb +79 -0
  70. data/test/ft_26_load.rb +197 -0
  71. data/test/ft_2_concurrence.rb +89 -15
  72. data/test/ft_2b_concurrence.rb +152 -0
  73. data/test/ft_2c_concurrence.rb +39 -0
  74. data/test/ft_3_equals.rb +4 -3
  75. data/test/ft_4_misc.rb +4 -3
  76. data/test/ft_5_time.rb +2 -1
  77. data/test/ft_6_lambda.rb +2 -1
  78. data/test/ft_7_lose.rb +53 -17
  79. data/test/ft_8_forget.rb +7 -6
  80. data/test/ft_9_cursor.rb +8 -7
  81. data/test/hparticipant_test.rb +37 -14
  82. data/test/lru_test.rb +79 -0
  83. data/test/misc_test.rb +16 -0
  84. data/test/rake_qtest.rb +7 -0
  85. data/test/raw_prog_test.rb +0 -13
  86. data/test/rutest_utils.rb +15 -2
  87. data/test/scheduler_test.rb +31 -4
  88. data/test/timeout_test.rb +6 -2
  89. data/test/wfid_test.rb +68 -0
  90. metadata +169 -158
  91. data/lib/openwfe/expool/journalexpstorage.rb +0 -312
  92. data/lib/openwfe/util/lru_cache.rb +0 -149
@@ -1,312 +0,0 @@
1
- #
2
- #--
3
- # Copyright (c) 2006-2007, Nicolas Modryzk and 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
- # $Id: definitions.rb 2725 2006-06-02 13:26:32Z jmettraux $
34
- #
35
-
36
- #
37
- # "made in Japan"
38
- #
39
- # Nicolas Modrzyk at openwfe.org
40
- # John Mettraux at openwfe.org
41
- #
42
-
43
- require 'fileutils'
44
- require 'base64'
45
-
46
- require 'openwfe/service'
47
- require 'openwfe/workitem'
48
- require 'openwfe/flowexpressionid'
49
- require 'openwfe/expressions/expressionmap'
50
-
51
-
52
- module OpenWFE
53
-
54
- #
55
- # by default the journals are stored into "work/journal"
56
- #
57
- DEFAULT_STORAGE_PATH = "work/"
58
-
59
- #
60
- # this is the container class for storing entries in the the journal
61
- #
62
- class JournalEntry
63
-
64
- # reused for
65
- ENTRY_DELIM = ' -- '
66
-
67
- attr_reader :fei, :action, :fe, :time
68
-
69
-
70
- def initialize (action, fei, fe, stime=nil)
71
- @action = action
72
- @fei = fei
73
- @fe = fe
74
- @time = if stime
75
- stime
76
- else
77
- Time.new
78
- end
79
- end
80
-
81
- #
82
- # parse the entry from a line read from a log file
83
- def JournalEntry.parse_from_string (line)
84
- # offset includes iso formatting and delim
85
- time_offset = line.index(ENTRY_DELIM)
86
-
87
- time = Time.iso8601(line.slice(0..time_offset))
88
-
89
- line = line.slice(time_offset+ ENTRY_DELIM.length..line.length)
90
- action = line[0..2]
91
-
92
- index = line.index(ENTRY_DELIM,7)
93
- fei = OpenWFE::FlowExpressionId.to_fei(line[8..index-1])
94
-
95
- if action == :put.to_s
96
- fe_64_yaml = line[index+ENTRY_DELIM.length,line.length].rstrip
97
- fe_yaml = Base64.decode64(fe_64_yaml.gsub("**","\n"))
98
- fe = YAML.load(fe_yaml)
99
- return JournalEntry.new(:put, fei, fe, time)
100
- else
101
- return JournalEntry.new(action, fei, nil, time)
102
- end
103
- end
104
-
105
- #
106
- # this is directly used to store the entry in the journal.
107
- # This is using base64 encoding to wrap the encoded object, and is not readable. Use to_human_s to decrypt
108
- def to_s
109
- if @action == :put
110
- base64 = Base64.encode64(YAML.dump(@fe)).gsub("\n","**") + "\n"
111
- @time.iso8601 + ENTRY_DELIM + @action.to_s + ENTRY_DELIM + @fei.to_s + ENTRY_DELIM + base64
112
- else
113
- @time.iso8601 + ENTRY_DELIM + @action.to_s + ENTRY_DELIM + @fei.to_s + ENTRY_DELIM + "\n"
114
- end
115
- end
116
-
117
- #
118
- # same as above,except the encoded object is fully expanded. The return value cannot be processed.
119
- def to_human_s
120
- if @action == :put
121
- @time.iso8601 + ENTRY_DELIM + @action.to_s + ENTRY_DELIM + @fei.to_s + ENTRY_DELIM + "\n" + YAML.dump(@fe).to_s + "---\n"
122
- else
123
- to_s
124
- end
125
- end
126
- end
127
-
128
- #
129
- # the class responsible for handling replay of a log file
130
- class JournalReplay
131
-
132
- def initialize(storage=nil)
133
- if not storage
134
- @storage = @application_context[S_EXPRESSION_STORAGE]
135
- else
136
- @storage = storage
137
- end
138
- end
139
-
140
- #
141
- # from the content of path_to_journal, will replay all the entries one by one on the given storage
142
- def replay(path_to_journal)
143
- datalines = IO.readlines(path_to_journal)
144
- datalines.each {
145
- |line_read|
146
- entry = (JournalEntry.parse_from_string(line_read))
147
- if(entry.action == :put)
148
- @storage[entry.fei]=entry.fe
149
- else
150
- #TODO: implement delete
151
- #@storage.delete(entry.fei)
152
- @storage.remove(entry.fei)
153
- end
154
- }
155
- end
156
-
157
- end
158
-
159
- #
160
- # this is the main class for journalized storage
161
- class JournalizedExpressionStorage
162
- include ServiceMixin
163
-
164
- attr_accessor :basepath
165
-
166
- def initialize (serviceName, applicationContext)
167
- service_init(serviceName, applicationContext)
168
- path = if (@application_context)
169
- @application_context[:file_expression_storage_path]
170
- else
171
- DEFAULT_STORAGE_PATH
172
- end
173
- @basepath = path + "/journal"
174
- FileUtils.makedirs @basepath
175
- end
176
-
177
- #
178
- # remove the file corresponding to the journal of this workflow instance
179
- def clean (workflow_id)
180
- fei_path = compute_file_path_id(workflow_id)
181
- if (File.exist?(fei_path))
182
- File.delete(fei_path)
183
- end
184
- end
185
-
186
- #
187
- # backup the journal file corresponding to the give workflow instance
188
- # by default, deletes the original journal file.
189
- def backup (workflow_id, delete_original = true, backup_path = nil)
190
- path_to_journal = compute_file_path_id(workflow_id)
191
- temporary_journal = if not backup_path
192
- path_to_journal+".0"
193
- else
194
- backup_path
195
- end
196
- FileUtils.copy_file(path_to_journal, temporary_journal)
197
- File.delete(path_to_journal) if delete_original
198
- return temporary_journal
199
- end
200
-
201
- #
202
- # truncate the content of the log file:
203
- # - number of lines
204
- # - before a given date
205
- def truncate! (workflow_id, number_of_lines=nil, after_date=nil)
206
- return 0 if not number_of_lines and not after_date
207
-
208
- fei_path = compute_file_path_id(workflow_id)
209
- datalines = IO.readlines(fei_path)
210
- entries = Array.new
211
-
212
- datalines.each { |line_read|
213
- entry = JournalEntry.parse_from_string(line_read)
214
- break if after_date and entry.time >= after_date
215
- break if number_of_lines and entries.length >= number_of_lines
216
- entries.push entry
217
- }
218
-
219
- backup(workflow_id)
220
-
221
- fd = IO.sysopen(fei_path, File::WRONLY|File::CREAT, 0666)
222
- io = IO.open(fd , "w")
223
-
224
- entries.each{ |entry|
225
- io.write(entry.to_s)
226
- }
227
- io.close
228
-
229
- return entries.length
230
- end
231
-
232
- #
233
- # create a human readable log file for the given workflow instance.
234
- # Note that this will override any existing previously created file
235
- def to_human_s(workflow_id)
236
- fei_path = compute_file_path_id(workflow_id)
237
- if (File.exist?(fei_path))
238
- fei_new_path = fei_path[0,fei_path.length-5] + ".txt"
239
- File.delete(fei_new_path) if (File.exist?(fei_new_path))
240
-
241
- fd = IO.sysopen(fei_new_path, File::WRONLY|File::CREAT, 0666)
242
- io = IO.open(fd , "w")
243
-
244
- datalines = IO.readlines(fei_path)
245
- datalines.each { |line_read| human = (JournalEntry.parse_from_string(line_read)).to_human_s ; io.write(human) }
246
-
247
- io.close
248
- else
249
- raise "workflow journal does not exist for given id:"+workflow_id
250
- end
251
- end
252
-
253
- #
254
- # interface method for the persistence. add a flow expression to the storage
255
- def []= (fei, flow_expression)
256
- write_to_journal(JournalEntry.new(:put, fei, flow_expression))
257
- end
258
-
259
- #
260
- # interface method: remove the expressionid and persist the related workitem
261
- def remove (fei)
262
- write_to_journal(JournalEntry.new(:del, fei, nil))
263
- end
264
-
265
- #
266
- # compute the size of the journal (number of entries) in the journal for the
267
- # given workflow id
268
- def size (workflow_instance_id)
269
- fei_path = compute_file_path_id(workflow_instance_id)
270
- return 0 if not File.exist?(fei_path)
271
-
272
- datalines = IO.readlines(fei_path)
273
- return datalines.length
274
- end
275
-
276
- #
277
- # alias for the protected compute_file_path with a better name.
278
- # Return the path of the log for the given workflow instance
279
- def where_is_journal_for (workflow_instance_id)
280
- compute_file_path(workflow_instance_id)
281
- end
282
-
283
- #
284
- # write an entry to the journal. This call the to_s method of the entry
285
- # and append the resulting line to the log file
286
- def write_to_journal (journal_entry)
287
- fei_path = compute_file_path(journal_entry.fei)
288
- fei_parent_path = File.dirname(fei_path)
289
-
290
- FileUtils.makedirs fei_parent_path if not (File.exist?(fei_parent_path))
291
-
292
- fd = IO.sysopen(fei_path, File::WRONLY|File::APPEND|File::CREAT, 0666)
293
- io = IO.open(fd , "w")
294
-
295
- io.write(journal_entry.to_s)
296
-
297
- io.close
298
- end
299
-
300
- protected
301
-
302
- def compute_file_path (fei)
303
- compute_file_path_id(fei.parent_workflow_instance_id)
304
- end
305
-
306
- def compute_file_path_id (parent_workflow_instance_id)
307
- @basepath + "/" + parent_workflow_instance_id.to_s + ".yaml"
308
- end
309
-
310
- end
311
-
312
- end
@@ -1,149 +0,0 @@
1
- #
2
- #--
3
- # Copyright (c) 2006-2007, Nicolas Modryzk, 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
- # $Id: definitions.rb 2725 2006-06-02 13:26:32Z jmettraux $
34
- #
35
-
36
- #
37
- # "made in Japan"
38
- #
39
- # Nicolas Modrzyk at openwfe.org
40
- #
41
-
42
- module OpenWFE
43
-
44
- # Simple LRU cache based on
45
-
46
- class LRUCache
47
-
48
- # initialize the LRU.
49
- # cache contains the mapping key,value
50
- # queue contains the list of keys, according to the LRU
51
- # max is the maximum number of items to keep in the cache
52
- def initialize(max=20, maxttl=nil)
53
- @cache = {}
54
- @queue = []
55
- @ttl_cache = {}
56
- @max = max
57
- @maxttl = maxttl
58
- @finalizers = []
59
- end
60
-
61
- # Check to see if the cache contains the given key.
62
- def include?(key)
63
- @cache.include?(key)
64
- end
65
-
66
- # Return the element identified by the given key.
67
- def [](key)
68
- r = nil
69
- if @cache.has_key? key
70
- r = @cache[key]
71
- @queue.push @queue.delete(key)
72
- @ttl_cache[key] = Time.now.to_i
73
- end
74
- r
75
- end
76
-
77
- # Set the element of the cache identified by the given key.
78
- def []=(key, val)
79
- if @queue.length == @max
80
- d = @queue.shift
81
- @cache.delete d
82
- end
83
- if @queue.first and @maxttl
84
- now = Time.now.to_i
85
- while ((@ttl_cache[@queue.first] + @maxttl) < now)
86
- d = @queue.shift
87
- do_finalization(d,@cache[d])
88
- @cache.delete d
89
- end
90
- end
91
- @cache[key] = val
92
- @ttl_cache[key] = Time.now.to_i
93
- @queue.push key
94
- end
95
-
96
- # delete the key.
97
- # TODO: check this is working
98
- def delete(key)
99
- d = @queue.delete(key)
100
- do_finalization(d,@cache[d])
101
- @cache.delete key
102
- end
103
-
104
- # Allows one to set the maximum size of the cache queue. If the queue
105
- # is currently larger than the size that it is being set to, elements
106
- # will be expired until the queue is at the maximum size.
107
-
108
- def size=(max)
109
- @max = max
110
- while @queue.length > @max
111
- d = @queue.shift
112
- do_finalization(d,@cache[d])
113
- @cache.delete d
114
- end
115
- @max
116
- end
117
- alias maxsize= size=
118
-
119
- # Return the maximum size of the cache.
120
- def maxsize
121
- @max
122
- end
123
-
124
- # Return the current size of the cache.
125
- def size
126
- @queue.length
127
- end
128
-
129
- # Return a copy of current set of keys to cache elements.
130
- def queue
131
- @queue.dup
132
- end
133
-
134
- def add_finalizer(*args,&block)
135
- @finalizers.push [block,args]
136
- end
137
-
138
- def do_finalization(key,obj)
139
- begin
140
- @finalizers.each do |f|
141
- f[0].call(key,obj,*f[1])
142
- end
143
- rescue Exception => e
144
- puts e, e.backtrace
145
- raise e
146
- end
147
- end
148
- end
149
- end