openwferu 0.9.1 → 0.9.2
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.
- data/{README → README.txt} +16 -13
- data/bin/validate-workflow.rb +46 -22
- data/examples/README.txt +8 -0
- data/examples/homeworkreview.rb +66 -0
- data/examples/quotereporter.rb +154 -0
- data/lib/{openwferu.rb → openwfe.rb} +6 -8
- data/lib/{ru → openwfe}/contextual.rb +11 -3
- data/lib/{ru → openwfe/engine}/engine.rb +50 -36
- data/lib/{ru/participant.rb → openwfe/engine/file_persisted_engine.rb} +21 -22
- data/lib/openwfe/expool/expressionpool.rb +534 -0
- data/lib/openwfe/expool/expstorage.rb +184 -0
- data/lib/openwfe/expool/journalexpstorage.rb +312 -0
- data/lib/openwfe/expool/yamlexpstorage.rb +127 -0
- data/lib/{ru → openwfe/expressions}/environment.rb +19 -14
- data/lib/{ru → openwfe/expressions}/expressionmap.rb +48 -21
- data/lib/{ru → openwfe/expressions}/fe_concurrence.rb +111 -35
- data/lib/openwfe/expressions/fe_cursor.rb +236 -0
- data/lib/{ru → openwfe/expressions}/fe_define.rb +5 -5
- data/lib/openwfe/expressions/fe_fqv.rb +99 -0
- data/lib/openwfe/expressions/fe_iterator.rb +182 -0
- data/lib/{ru/fe_misc.rb → openwfe/expressions/fe_losfor.rb} +14 -56
- data/lib/openwfe/expressions/fe_misc.rb +102 -0
- data/lib/{ru → openwfe/expressions}/fe_participant.rb +25 -14
- data/lib/{ru → openwfe/expressions}/fe_raw.rb +39 -75
- data/lib/{ru/fe_base.rb → openwfe/expressions/fe_sequence.rb} +40 -35
- data/lib/{ru → openwfe/expressions}/fe_subprocess.rb +30 -14
- data/lib/{ru → openwfe/expressions}/fe_time.rb +59 -31
- data/lib/{ru → openwfe/expressions}/fe_utils.rb +42 -26
- data/lib/{ru → openwfe/expressions}/fe_value.rb +20 -14
- data/lib/openwfe/expressions/flowexpression.rb +434 -0
- data/lib/openwfe/expressions/raw_prog.rb +391 -0
- data/lib/openwfe/expressions/raw_xml.rb +128 -0
- data/lib/openwfe/flowexpressionid.rb +148 -0
- data/lib/{ru → openwfe}/logging.rb +10 -6
- data/lib/{osocket.rb → openwfe/osocket.rb} +36 -35
- data/lib/{otime.rb → openwfe/otime.rb} +71 -21
- data/lib/openwfe/participants/atomparticipants.rb +144 -0
- data/lib/openwfe/participants/enoparticipant.rb +73 -0
- data/lib/openwfe/participants/participant.rb +85 -0
- data/lib/{ru → openwfe/participants}/participantmap.rb +40 -12
- data/lib/{ru → openwfe/participants}/participants.rb +41 -12
- data/lib/openwfe/participants/soapparticipants.rb +96 -0
- data/lib/{controlclient.rb → openwfe/rest/controlclient.rb} +12 -13
- data/lib/{definitions.rb → openwfe/rest/definitions.rb} +3 -3
- data/lib/{exception.rb → openwfe/rest/exception.rb} +3 -3
- data/lib/{restclient.rb → openwfe/rest/restclient.rb} +13 -22
- data/lib/{worklistclient.rb → openwfe/rest/worklistclient.rb} +33 -46
- data/lib/openwfe/rest/xmlcodec.rb +575 -0
- data/lib/{ru → openwfe}/rudefinitions.rb +32 -4
- data/lib/{ru → openwfe}/service.rb +20 -8
- data/lib/openwfe/storage/yamlfilestorage.rb +159 -0
- data/lib/{ru → openwfe/util}/dollar.rb +10 -8
- data/lib/openwfe/util/lru_cache.rb +149 -0
- data/lib/{ru → openwfe/util}/scheduler.rb +18 -10
- data/lib/{ru → openwfe/util}/schedulers.rb +7 -7
- data/lib/{utils.rb → openwfe/utils.rb} +93 -9
- data/lib/openwfe/workitem.rb +366 -0
- data/lib/openwfe/worklist/worklists.rb +175 -0
- data/test/README.txt +27 -0
- data/test/atomtest.rb +99 -0
- data/test/crontest.rb +58 -0
- data/test/dollartest.rb +3 -3
- data/test/feitest.rb +42 -14
- data/test/file_persistence_test.rb +93 -0
- data/test/flowtestbase.rb +72 -26
- data/test/ft_0.rb +1 -97
- data/test/ft_0b_sequence.rb +33 -0
- data/test/ft_0c_testname.rb +29 -0
- data/test/ft_10_loop.rb +48 -0
- data/test/ft_11_ppd.rb +292 -0
- data/test/ft_12_blockparticipant.rb +45 -0
- data/test/ft_13_eno.rb +51 -0
- data/test/ft_14_subprocess.rb +90 -0
- data/test/ft_14b_subprocess.rb +40 -0
- data/test/ft_15_iterator.rb +70 -0
- data/test/ft_16_fqv.rb +57 -0
- data/test/ft_1_unset.rb +25 -1
- data/test/ft_2_concurrence.rb +10 -5
- data/test/ft_3_equals.rb +35 -1
- data/test/ft_4_misc.rb +16 -1
- data/test/ft_5_time.rb +26 -1
- data/test/ft_6_lambda.rb +2 -1
- data/test/{ft_7_losfor.rb → ft_7_lose.rb} +41 -35
- data/test/ft_8_forget.rb +46 -0
- data/test/ft_9_cursor.rb +94 -0
- data/test/journal_persistence_test.rb +147 -0
- data/test/misctest.rb +13 -9
- data/test/rake_ptest.rb +18 -0
- data/test/rake_qtest.rb +43 -0
- data/test/{fulltest.rb → rake_test.rb} +2 -2
- data/test/raw_prog_test.rb +236 -0
- data/test/rest_test.rb +189 -0
- data/test/rutest_utils.rb +1 -1
- data/test/timetest.rb +42 -34
- metadata +125 -82
- data/lib/codec.rb +0 -573
- data/lib/flowexpressionid.rb +0 -139
- data/lib/ru/expressionpool.rb +0 -382
- data/lib/ru/expressionstorage.rb +0 -99
- data/lib/ru/flowexpression.rb +0 -272
- data/lib/ru/ruutils.rb +0 -70
- data/lib/test.rb +0 -222
- data/lib/workitem.rb +0 -249
- data/test/quicktest.rb +0 -21
|
@@ -0,0 +1,184 @@
|
|
|
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
|
+
|
|
45
|
+
require 'openwfe/service'
|
|
46
|
+
require 'openwfe/util/lru_cache'
|
|
47
|
+
require 'openwfe/flowexpressionid'
|
|
48
|
+
|
|
49
|
+
module OpenWFE
|
|
50
|
+
|
|
51
|
+
#
|
|
52
|
+
# Create a composite expression storage.
|
|
53
|
+
# This will take parameters from the application context to create
|
|
54
|
+
# the resulting composite storage
|
|
55
|
+
class CompositeExpressionStorage
|
|
56
|
+
include ServiceMixin
|
|
57
|
+
|
|
58
|
+
attr_accessor \
|
|
59
|
+
:persistence, \
|
|
60
|
+
:cache, \
|
|
61
|
+
:journal
|
|
62
|
+
|
|
63
|
+
def initialize (serviceName, applicationContext)
|
|
64
|
+
|
|
65
|
+
service_init(serviceName, applicationContext)
|
|
66
|
+
|
|
67
|
+
@cache = @application_context[:cached_expression_storage]
|
|
68
|
+
@journal = @application_context[:journalized_expression_storage]
|
|
69
|
+
@persistence = @application_context[:file_expression_storage]
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
#
|
|
73
|
+
# call the add method for each registered storage
|
|
74
|
+
def []= (fei, flowExpression)
|
|
75
|
+
@journal[fei] = flowExpression if @journal
|
|
76
|
+
@cache[fei] = flowExpression if @cache
|
|
77
|
+
@persistence[fei] = flowExpression
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
#
|
|
81
|
+
# remove the expressionid from each registered storage
|
|
82
|
+
def remove (fei, workitem)
|
|
83
|
+
@journal.remove(fei, workitem) if @journal
|
|
84
|
+
@cache.remove(fei, workitem) if @cache
|
|
85
|
+
@persistence.remove(fei,workitem)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
#
|
|
89
|
+
# slightly different method. Try to get the value from the cache storage if one
|
|
90
|
+
# if not retrieve it, and then add it to the cache.
|
|
91
|
+
def [] (fei)
|
|
92
|
+
return @cache[fei] if @cache
|
|
93
|
+
flow_expression = @persistence[fei]
|
|
94
|
+
@cache[fei] = flow_expression if @cache
|
|
95
|
+
return flow_expression
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
#
|
|
100
|
+
# implementation of a LRU caching storage.
|
|
101
|
+
class LruCachedExpressionStorage
|
|
102
|
+
include ServiceMixin
|
|
103
|
+
|
|
104
|
+
DEFAULT_LRU_SIZE = 10
|
|
105
|
+
|
|
106
|
+
def initialize (service_name, application_context)
|
|
107
|
+
service_init(service_name, application_context)
|
|
108
|
+
size = if (@application_context)
|
|
109
|
+
@application_context[:lru_storage_size]
|
|
110
|
+
else
|
|
111
|
+
DEFAULT_LRU_SIZE
|
|
112
|
+
end
|
|
113
|
+
@cache = LRUCache.new(size)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def []= (fei, flowExpression)
|
|
117
|
+
@cache[fei]=flowExpression
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
#
|
|
121
|
+
# interface method to remove an entry for the given expression_id
|
|
122
|
+
def remove (fei, workitem)
|
|
123
|
+
@cache.delete(fei)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
#
|
|
127
|
+
# check if the value is in the cache
|
|
128
|
+
def is_in_cache?(fei)
|
|
129
|
+
@cache.include?(fei)
|
|
130
|
+
end
|
|
131
|
+
alias has_key? is_in_cache?
|
|
132
|
+
|
|
133
|
+
#
|
|
134
|
+
# interface method, return the value associated with the given id,
|
|
135
|
+
# or nil if not in cache.
|
|
136
|
+
def [] (fei)
|
|
137
|
+
if(@cache.include?(fei))
|
|
138
|
+
return @cache[fei]
|
|
139
|
+
else
|
|
140
|
+
return nil
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
#
|
|
147
|
+
# Memory consuming in-memory storage.
|
|
148
|
+
# No memory limit, puts everything in a Hash
|
|
149
|
+
#
|
|
150
|
+
class InMemoryExpressionStorage < Hash
|
|
151
|
+
include ServiceMixin
|
|
152
|
+
|
|
153
|
+
def initialize (service_name, application_context)
|
|
154
|
+
@service_name = service_name
|
|
155
|
+
@application_context = application_context
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def remove (fei, workitem)
|
|
159
|
+
delete(fei)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def purge
|
|
163
|
+
self.clear
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def to_s
|
|
167
|
+
s = "\n\n==== #{self.class} ===="
|
|
168
|
+
each do |k, v|
|
|
169
|
+
s << "\n"
|
|
170
|
+
if v.kind_of?(RawExpression)
|
|
171
|
+
s << "*raw"
|
|
172
|
+
else
|
|
173
|
+
s << " "
|
|
174
|
+
end
|
|
175
|
+
s << v.to_s
|
|
176
|
+
s << " key/value mismatch !" if k != v.fei
|
|
177
|
+
end
|
|
178
|
+
s << "\n==== . ====\n"
|
|
179
|
+
return s
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
end
|
|
@@ -0,0 +1,312 @@
|
|
|
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, workitem=nil)
|
|
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
|