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
@@ -42,6 +42,7 @@
42
42
 
43
43
  require 'find'
44
44
  require 'yaml'
45
+ require 'monitor'
45
46
  require 'fileutils'
46
47
 
47
48
  require 'openwfe/utils'
@@ -58,19 +59,25 @@ require 'openwfe/expressions/raw_xml'
58
59
 
59
60
  module OpenWFE
60
61
 
61
-
62
62
  #
63
63
  # Stores OpenWFEru related objects into yaml encoded files.
64
64
  # This storage is meant to look and feel like a Hash.
65
65
  #
66
66
  class YamlFileStorage
67
- include ServiceMixin
67
+ include MonitorMixin, ServiceMixin
68
68
 
69
69
  attr_accessor :basepath
70
70
 
71
71
  def initialize (service_name, application_context, path)
72
+
73
+ super()
74
+
72
75
  service_init(service_name, application_context)
76
+
73
77
  @basepath = path
78
+ #@basepath = OpenWFE::clean_path(@basepath)
79
+ @basepath += "/" unless @basepath[-1, 1] == "/"
80
+
74
81
  FileUtils.makedirs @basepath
75
82
  end
76
83
 
@@ -78,27 +85,31 @@ module OpenWFE
78
85
  # Stores an object with its FlowExpressionId instance as its key.
79
86
  #
80
87
  def []= (fei, object)
81
-
82
- fei_path = compute_file_path(fei)
83
- fei_parent_path = File.dirname(fei_path)
84
-
85
- FileUtils.makedirs(fei_parent_path) \
86
- if not File.exist?(fei_parent_path)
88
+ synchronize do
89
+ fei_path = compute_file_path(fei)
90
+
91
+ fei_parent_path = File.dirname(fei_path)
87
92
 
88
- fd = IO.sysopen(fei_path , "w+")
89
- io = IO.open(fd , "w+")
90
-
91
- data = YAML.dump(object)
92
-
93
- io.write(data)
94
- io.close
93
+ FileUtils.makedirs(fei_parent_path) \
94
+ if not File.exist?(fei_parent_path)
95
+
96
+ fd = IO.sysopen(fei_path , "w+")
97
+ io = IO.open(fd , "w+")
98
+
99
+ data = YAML.dump(object)
100
+
101
+ io.write(data)
102
+ io.close
103
+ end
95
104
  end
96
105
 
97
106
  #
98
107
  # Deletes the whole storage directory... beware...
99
108
  #
100
109
  def purge
101
- FileUtils.remove_dir @basepath
110
+ synchronize do
111
+ FileUtils.remove_dir @basepath
112
+ end
102
113
  end
103
114
 
104
115
  #
@@ -114,13 +125,15 @@ module OpenWFE
114
125
  # instance.
115
126
  #
116
127
  def delete (fei)
128
+ synchronize do
117
129
 
118
- fei_path = compute_file_path(fei)
119
-
120
- if File.exist?(fei_path)
130
+ fei_path = compute_file_path(fei)
131
+
132
+ #ldebug do
133
+ # "delete()\n for #{fei.to_debug_s}\n at #{fei_path}"
134
+ #end
135
+
121
136
  File.delete(fei_path)
122
- else
123
- raise "Object not found at #{fei_path}"
124
137
  end
125
138
  end
126
139
 
@@ -141,7 +154,8 @@ module OpenWFE
141
154
  # Returns the count of objects currently stored in this instance.
142
155
  #
143
156
  def length
144
- return count_objects(0, @basepath)
157
+ #return count_objects(0, @basepath)
158
+ count_objects()
145
159
  end
146
160
 
147
161
  alias :size :length
@@ -159,38 +173,51 @@ module OpenWFE
159
173
  return object
160
174
  end
161
175
 
162
- def count_objects (count, item)
163
-
164
- # TODO #8346 : use "find" to do that job
165
- # measure perf before and after change !
166
-
167
- return count + 1 if OpenWFE::ends_with(item, ".yaml")
168
-
169
- if File.stat(item).directory?
170
-
171
- d = Dir.new(item)
172
- d.each do |i|
173
- next if i == "." or i == ".."
174
- i = item + "/" + i
175
- count = count_objects(count, i)
176
- end
177
- d.close()
176
+ def count_objects
177
+ count = 0
178
+ Find.find(@basepath) do |path|
179
+ next if File.stat(path).directory?
180
+ count += 1 if OpenWFE::ends_with(path, ".yaml")
178
181
  end
179
-
180
182
  return count
181
183
  end
182
184
 
185
+ #
186
+ # Passes each object path to the given block
187
+ #
183
188
  def each_object_path (&block)
184
189
  return unless block
185
- Find.find(@basepath) do |path|
186
- block.call path \
187
- unless File.stat(path).directory?
190
+ synchronize do
191
+ Find.find(@basepath) do |path|
192
+ next if File.stat(path).directory?
193
+ next unless OpenWFE::ends_with(path, ".yaml")
194
+ ldebug { "each_object_path() considering #{path}" }
195
+ block.call path
196
+ end
188
197
  end
189
198
  end
190
-
191
- def compute_file_path (fei)
192
- raise NotImplementedError.new
199
+
200
+ #
201
+ # Passes each object to the given block
202
+ #
203
+ def each_object (&block)
204
+ return unless block
205
+ each_object_path do |path|
206
+ block.call load_object(path)
207
+ end
193
208
  end
209
+
210
+ #
211
+ # each_value() is a method from Hash, by providing it here
212
+ # it's easier to disguise a YamlFileStorage as a hash.
213
+ #
214
+ alias :each_value :each_object
215
+
216
+ protected
217
+
218
+ def compute_file_path (object)
219
+ raise NotImplementedError.new
220
+ end
194
221
 
195
222
  end
196
223
 
@@ -173,10 +173,23 @@ module OpenWFE
173
173
 
174
174
  def call_ruby (ruby_code)
175
175
 
176
- binding = nil
177
- binding = @flow_expression.get_binding if @flow_expression
178
-
179
- eval(ruby_code, binding).to_s
176
+ #binding = nil
177
+ #binding = @flow_expression.get_binding if @flow_expression
178
+ #eval(ruby_code, binding).to_s
179
+
180
+ wi = @workitem
181
+ workitem = @workitem
182
+ if @flow_expression
183
+ fexp = @flow_expression
184
+ flow_expression = @flow_expression
185
+ fei = @flow_expression.fei
186
+ end
187
+ #
188
+ # some simple notations made available to ${ruby:...}
189
+ # notations
190
+
191
+ #eval(ruby_code, binding).to_s
192
+ eval(ruby_code).to_s
180
193
  end
181
194
  end
182
195
 
@@ -0,0 +1,154 @@
1
+ #
2
+ #--
3
+ # Copyright (c) 2007, 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$
34
+ #
35
+
36
+ #
37
+ # "made in Japan"
38
+ #
39
+ # John Mettraux at openwfe.org
40
+ #
41
+
42
+ #require 'monitor'
43
+
44
+
45
+ module OpenWFE
46
+
47
+ #
48
+ # A Hash that has a max size. After the maxsize has been reached, the
49
+ # least recently used entries (LRU hence), will be discared to make
50
+ # room for the new entries.
51
+ #
52
+ class LruHash
53
+ #include MonitorMixin
54
+ #
55
+ # seems not necessary for now, and it collides with expool's
56
+ # @monitors own sync
57
+
58
+ def initialize (maxsize)
59
+
60
+ super()
61
+
62
+ @maxsize = maxsize
63
+
64
+ @hash = {}
65
+ @lru_keys = []
66
+ end
67
+
68
+ def maxsize= (newsize)
69
+ remove_lru() while @hash.size > newsize
70
+ @maxsize = newsize
71
+ end
72
+
73
+ def maxsize
74
+ return @maxsize
75
+ end
76
+
77
+ def size
78
+ return @lru_keys.size
79
+ end
80
+ alias :length :size
81
+
82
+ def keys
83
+ return @hash.keys
84
+ end
85
+ def values
86
+ return @values
87
+ end
88
+
89
+ def clear
90
+ @hash.clear
91
+ @lru_keys.clear
92
+ end
93
+
94
+ def each (&block)
95
+ return unless block
96
+ @hash.each do |k, v|
97
+ block.call(k, v)
98
+ end
99
+ end
100
+
101
+ #
102
+ # Returns the keys with the lru in front.
103
+ #
104
+ def ordered_keys
105
+ return @lru_keys
106
+ end
107
+
108
+ def [] (key)
109
+ value = @hash[key]
110
+ return nil unless value
111
+ touch(key)
112
+ return value
113
+ end
114
+
115
+ def []= (key, value)
116
+ remove_lru() while @hash.size >= @maxsize
117
+ @hash[key] = value
118
+ touch(key)
119
+ return value
120
+ end
121
+
122
+ def delete (key)
123
+ value = @hash.delete(key)
124
+ @lru_keys.delete(key)
125
+ return value
126
+ end
127
+
128
+ def include? (key)
129
+ return @hash.include?(key)
130
+ end
131
+
132
+ protected
133
+
134
+ #
135
+ # Puts the key on top of the lru 'stack'.
136
+ # The bottom being the lru place.
137
+ #
138
+ def touch (key)
139
+ @lru_keys.delete(key)
140
+ @lru_keys << key
141
+ end
142
+
143
+ #
144
+ # Removes the lru value and returns it.
145
+ # Returns nil if the cache is currently empty.
146
+ #
147
+ def remove_lru ()
148
+ return nil if @lru_keys.size < 1
149
+ key = @lru_keys.delete_at(0)
150
+ return @hash.delete(key)
151
+ end
152
+ end
153
+ end
154
+
@@ -184,13 +184,34 @@ module OpenWFE
184
184
  o = Rational(time.utc_offset, 3600 * 24)
185
185
 
186
186
  begin
187
+
187
188
  return DateTime.new(
188
- time.year, time.month, time.day, time.hour, time.min, s, o)
189
+ time.year,
190
+ time.month,
191
+ time.day,
192
+ time.hour,
193
+ time.min,
194
+ s,
195
+ o)
196
+
189
197
  rescue Exception => e
190
- puts \
191
- "\n Date.new() problem. Params :"+
192
- "\n....y:#{time.year} M:#{time.month} d:#{time.day} "+
193
- "h:#{time.hour} m:#{time.min} s:#{s} o:#{o}"
198
+
199
+ #puts
200
+ #puts OpenWFE::exception_to_s(e)
201
+ #puts
202
+ #puts \
203
+ # "\n Date.new() problem. Params :"+
204
+ # "\n....y:#{time.year} M:#{time.month} d:#{time.day} "+
205
+ # "h:#{time.hour} m:#{time.min} s:#{s} o:#{o}"
206
+
207
+ return DateTime.new(
208
+ time.year,
209
+ time.month,
210
+ time.day,
211
+ time.hour,
212
+ time.min,
213
+ time.sec,
214
+ time.utc_offset)
194
215
  end
195
216
  end
196
217
 
@@ -41,9 +41,7 @@
41
41
 
42
42
  require 'monitor'
43
43
 
44
- #require 'openwfe/utils'
45
44
  require 'openwfe/util/otime'
46
- require 'openwfe/util/stoppable'
47
45
 
48
46
 
49
47
  module OpenWFE
@@ -88,7 +86,7 @@ module OpenWFE
88
86
  # # will regenerate the monthly report in four days
89
87
  #
90
88
  class Scheduler
91
- include MonitorMixin, Stoppable
89
+ include MonitorMixin
92
90
 
93
91
  attr_accessor \
94
92
  :precision
@@ -107,35 +105,34 @@ module OpenWFE
107
105
  # every 250ms, the scheduler wakes up
108
106
 
109
107
  @last_cron_minute = -1
108
+
109
+ @stopped = false
110
110
  end
111
111
 
112
112
  #
113
113
  # Starts this scheduler (or restart it if it was previously stopped)
114
114
  #
115
- def start
116
-
117
- #if @scheduler_thread
118
- # @scheduler_thread.wakeup
119
- # return
120
- #end
115
+ def sstart
121
116
 
122
117
  @scheduler_thread = Thread.new do
123
118
  while true
124
- break if self.is_stopped?
125
- #print "."
126
- #$stdout.flush
119
+ break if @stopped
120
+ #print "."; $stdout.flush
127
121
  step
128
122
  sleep(@precision)
129
123
  end
130
124
  end
131
-
132
- do_restart
133
125
  end
134
126
 
135
127
  #
136
- # The scheduler is stoppable via stop() or do_stop()
128
+ # The scheduler is stoppable via sstop()
137
129
  #
138
- alias :stop :do_stop
130
+ def sstop
131
+ @stopped = true
132
+ end
133
+
134
+ alias :start :sstart
135
+ alias :stop :sstop
139
136
 
140
137
  #
141
138
  # Joins on the scheduler thread
@@ -171,7 +168,7 @@ module OpenWFE
171
168
  job.trigger()
172
169
  return nil
173
170
  end
174
-
171
+
175
172
  return push(job) \
176
173
  if @pending_jobs.length < 1
177
174
 
@@ -262,8 +259,8 @@ module OpenWFE
262
259
  # Returns the job id attributed to this 'cron job', this id can
263
260
  # be used to unschedule the job.
264
261
  #
265
- def schedule \
266
- (cron_line, cron_id=nil, schedulable=nil, params=nil, &block)
262
+ def schedule (
263
+ cron_line, cron_id=nil, schedulable=nil, params=nil, &block)
267
264
 
268
265
  synchronize do
269
266
 
@@ -368,24 +365,17 @@ module OpenWFE
368
365
  #
369
366
  # cron entries
370
367
 
371
- begin
372
- if now.sec == 0 and minute > @last_cron_minute
373
- #
374
- # only consider cron entries at the second 0 of a
375
- # minute
368
+ if now.sec == 0 and minute > @last_cron_minute
369
+ #
370
+ # only consider cron entries at the second 0 of a
371
+ # minute
376
372
 
377
- @last_cron_minute = minute
373
+ @last_cron_minute = minute
378
374
 
379
- @cron_entries.each do |cron_id, cron_entry|
380
- #puts "step() cron_id : #{cron_id}"
381
- cron_entry.trigger \
382
- if cron_entry.matches? now
383
- end
375
+ @cron_entries.each do |cron_id, cron_entry|
376
+ #puts "step() cron_id : #{cron_id}"
377
+ trigger(cron_entry) if cron_entry.matches? now
384
378
  end
385
- rescue Exception => e
386
- #puts \
387
- # "step() caught exception\n" +
388
- # OpenWFE::exception_to_s(e)
389
379
  end
390
380
 
391
381
  #
@@ -412,11 +402,29 @@ module OpenWFE
412
402
  #
413
403
  # obviously
414
404
 
415
- job.trigger()
405
+ trigger(job)
406
+
416
407
  @pending_jobs.delete_at(0)
417
408
  end
418
409
  end
419
- end
410
+ end
411
+
412
+ def trigger (entry)
413
+ Thread.new do
414
+ begin
415
+ entry.trigger
416
+ rescue Exception => e
417
+ message =
418
+ "trigger() caught exception\n" +
419
+ OpenWFE::exception_to_s(e)
420
+ if self.respond_to? :lwarn
421
+ lwarn { message }
422
+ else
423
+ puts message
424
+ end
425
+ end
426
+ end
427
+ end
420
428
  end
421
429
 
422
430
  #
@@ -60,12 +60,14 @@ module OpenWFE
60
60
 
61
61
  ldebug { "initialize() SchedulerService #{self.object_id}" }
62
62
 
63
- start()
63
+ sstart()
64
64
  end
65
65
 
66
66
  def stop
67
+
67
68
  linfo { "stop() for scheduler #{self.object_id}" }
68
- do_stop
69
+
70
+ sstop()
69
71
  end
70
72
  end
71
73
 
data/lib/openwfe/utils.rb CHANGED
@@ -99,6 +99,7 @@ module OpenWFE
99
99
 
100
100
  return nil if object == nil
101
101
 
102
+ return object if object.kind_of? Float
102
103
  return object if object.kind_of? Fixnum
103
104
  return object if object.kind_of? TrueClass
104
105
  return object if object.kind_of? FalseClass
@@ -196,9 +197,43 @@ module OpenWFE
196
197
  return s
197
198
  end
198
199
 
200
+ #
201
+ # Some code for writing thinks like :
202
+ #
203
+ # if async
204
+ # OpenWFE::call_in_thread "launch()", self do
205
+ # raw_expression.apply(wi)
206
+ # end
207
+ # else
208
+ # raw_expression.apply(wi)
209
+ # end
210
+ #
211
+ def OpenWFE.call_in_thread (caller_name, caller_object=nil, &block)
212
+ return unless block
213
+ Thread.new do
214
+ begin
215
+ block.call
216
+ rescue Exception => e
217
+ msg = "#{caller_name} caught an exception\n" + exception_to_s(e)
218
+ if caller_object and caller_object.respond_to? :lwarn
219
+ caller_object.lwarn { msg }
220
+ else
221
+ puts msg
222
+ end
223
+ end
224
+ end
225
+ # implicitely return the thread
226
+ end
227
+
199
228
  #
200
229
  # A small Timer class for debug purposes.
201
230
  #
231
+ # t = Time.new
232
+ #
233
+ # # ... do something
234
+ #
235
+ # puts "that something took #{t.duration} ms"
236
+ #
202
237
  class Timer
203
238
 
204
239
  attr_reader :start
@@ -207,11 +242,38 @@ module OpenWFE
207
242
  @start = Time.now.to_f
208
243
  end
209
244
 
245
+ #
246
+ # Returns the number of milliseconds since this Timer was
247
+ # instantiated.
248
+ #
210
249
  def duration
211
250
  return (Time.now.to_f - @start) * 1000
212
251
  end
213
252
  end
214
253
 
254
+ #
255
+ # Returns a version of s that is usable as or within a filename
256
+ # (removes for examples things like '/' or '\'...)
257
+ #
258
+ def OpenWFE.ensure_for_filename (s)
259
+ s = s.gsub(" ", "_")
260
+ s = s.gsub("/", "_")
261
+ s = s.gsub(":", "_")
262
+ s = s.gsub(";", "_")
263
+ s = s.gsub("\*", "_")
264
+ s = s.gsub("\\", "_")
265
+ s = s.gsub("\+", "_")
266
+ s = s.gsub("\?", "_")
267
+ return s
268
+ end
269
+
270
+ #
271
+ # "my//path" -> "my/path"
272
+ #
273
+ def OpenWFE.clean_path (s)
274
+ s.gsub(/\/+/, "/")
275
+ end
276
+
215
277
  #
216
278
  # This method is used within the InFlowWorkItem and the CsvTable classes.
217
279
  #
@@ -34,5 +34,5 @@
34
34
  #
35
35
 
36
36
  module OpenWFE
37
- OPENWFERU_VERSION = '0.9.4'
37
+ OPENWFERU_VERSION = '0.9.5'
38
38
  end