Class: Pione::RuleEngine::BasicHandler
- Inherits:
-
Object
- Object
- Pione::RuleEngine::BasicHandler
- Includes:
- Log::MessageLog, TupleSpace::TupleSpaceInterface
- Defined in:
- lib/pione/rule-engine/basic-handler.rb
Overview
BasicHandler is a base class for rule handlers.
Direct Known Subclasses
Constant Summary
Constants included from Log::MessageLog
Log::MessageLog::MESSAGE_QUEUE
Instance Attribute Summary collapse
-
#base_location ⇒ Object
readonly
base location.
-
#caller_id ⇒ Object
readonly
from domain.
-
#digest ⇒ Object
readonly
handler’s digest string.
-
#domain_id ⇒ Object
readonly
domain id.
-
#domain_location ⇒ Object
readonly
domain location.
-
#dry_run ⇒ Object
readonly
flag of dry run mode.
-
#env ⇒ Object
readonly
handler’s environement.
-
#inputs ⇒ Object
readonly
input tuples.
-
#outputs ⇒ Object
readonly
output tuples.
-
#package_id ⇒ Object
readonly
package id.
-
#param_set ⇒ Object
readonly
parameter set.
-
#plain_env ⇒ Object
readonly
plain environment.
-
#rule_condition ⇒ Object
readonly
rule condtions.
-
#rule_definition ⇒ Object
readonly
definition of the handling rule.
-
#rule_name ⇒ Object
readonly
rule name.
Instance Method Summary collapse
-
#apply_touch_operation(condition, tuples) ⇒ Object
Apply touch operation.
- #create_data_by_touch_operation(condition) ⇒ Object
-
#execute ⇒ Object
Executes the rule.
-
#find_outputs_from_space ⇒ void
Find outputs from the domain space.
-
#handle ⇒ Object
Handle the rule and return the outputs.
-
#initialize(space, env, package_id, rule_name, rule_definition, inputs, param_set, domain_id, caller_id) ⇒ BasicHandler
constructor
Create a new handler for rule.
-
#make_location(name, domain_id) ⇒ BasicLocation
Make location by data name and the domain.
-
#make_output_location(name) ⇒ Object
Make output data location by the name.
-
#make_output_tuple(data_expr) ⇒ Object
Make output tuple by the name.
-
#make_rule_process_record ⇒ Object
Build rule process record.
- #make_task_process_record ⇒ Object
-
#publish_outputs(outputs) ⇒ Object
Publish output data tuples.
-
#setup_env(env, param_set) ⇒ Object
Setup handler’s environment.
-
#show_outputs(outputs) ⇒ Object
Show output tuples as message.
- #update_time_by_touch_operation(tuples) ⇒ Object
-
#write_data_null(output, tuples, i) ⇒ Object
Write a data null tuple if the output condition accepts nonexistence.
Methods included from Log::MessageLog
#debug_message, #debug_message_begin, #debug_message_end, debug_mode, debug_mode=, debug_mode?, message, quiet_mode, quiet_mode=, quiet_mode?, #show, #user_message, #user_message_begin, #user_message_end
Methods included from TupleSpace::TupleSpaceInterface
#process_log, #processing_error, #read!, #set_tuple_space, #take!, #take_all!, tuple_space_operation, #tuple_space_server, #with_process_log
Constructor Details
#initialize(space, env, package_id, rule_name, rule_definition, inputs, param_set, domain_id, caller_id) ⇒ BasicHandler
Create a new handler for rule.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 25 def initialize(space, env, package_id, rule_name, rule_definition, inputs, param_set, domain_id, caller_id) ### set tuple space server set_tuple_space(space) ### set informations @plain_env = env @env = setup_env(env, param_set) @package_id = package_id @rule_name = rule_name @rule_definition = rule_definition @rule_condition = rule_definition.rule_condition_context.eval(@env) @inputs = inputs @outputs = [] @param_set = param_set @digest = Util::TaskDigest.generate(package_id, rule_name, inputs, param_set) @base_location = read!(TupleSpace::BaseLocationTuple.any).location @dry_run = begin read!(TupleSpace::DryRunTuple.any).availability rescue false end @domain_id = domain_id @domain_location = make_location("", @domain_id) @caller_id = caller_id end |
Instance Attribute Details
#base_location ⇒ Object (readonly)
base location
18 19 20 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 18 def base_location @base_location end |
#caller_id ⇒ Object (readonly)
from domain
22 23 24 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 22 def caller_id @caller_id end |
#digest ⇒ Object (readonly)
handler’s digest string
17 18 19 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 17 def digest @digest end |
#domain_id ⇒ Object (readonly)
domain id
20 21 22 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 20 def domain_id @domain_id end |
#domain_location ⇒ Object (readonly)
domain location
21 22 23 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 21 def domain_location @domain_location end |
#dry_run ⇒ Object (readonly)
flag of dry run mode
19 20 21 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 19 def dry_run @dry_run end |
#env ⇒ Object (readonly)
handler’s environement
9 10 11 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 9 def env @env end |
#inputs ⇒ Object (readonly)
input tuples
14 15 16 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 14 def inputs @inputs end |
#outputs ⇒ Object (readonly)
output tuples
15 16 17 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 15 def outputs @outputs end |
#package_id ⇒ Object (readonly)
package id
10 11 12 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 10 def package_id @package_id end |
#param_set ⇒ Object (readonly)
parameter set
16 17 18 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 16 def param_set @param_set end |
#plain_env ⇒ Object (readonly)
plain environment
8 9 10 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 8 def plain_env @plain_env end |
#rule_condition ⇒ Object (readonly)
rule condtions
13 14 15 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 13 def rule_condition @rule_condition end |
#rule_definition ⇒ Object (readonly)
definition of the handling rule
12 13 14 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 12 def rule_definition @rule_definition end |
#rule_name ⇒ Object (readonly)
rule name
11 12 13 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 11 def rule_name @rule_name end |
Instance Method Details
#apply_touch_operation(condition, tuples) ⇒ Object
Apply touch operation.
173 174 175 176 177 178 179 180 181 182 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 173 def apply_touch_operation(condition, tuples) _condition = condition.eval(@env) if _condition.operation == :touch if tuples.empty? create_data_by_touch_operation(_condition) else update_time_by_touch_operation(tuples) end end end |
#create_data_by_touch_operation(condition) ⇒ Object
184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 184 def create_data_by_touch_operation(condition) # NOTE: touch operation applies first piece of data sequence now name = condition.pieces.first.pattern location = @domain_location + name # create a empty file location.create("") unless location.exist? # FIXME: write a touch tuple time = Time.now write(TupleSpace::TouchTuple.new(name: name, domain: @domain_id, time: time)) # FIXME: create an output data tuple data_tuple = TupleSpace::DataTuple.new(name: name, domain: @domain_id, location: location, time: time) write(data_tuple) [data_tuple] end |
#execute ⇒ Object
Executes the rule.
85 86 87 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 85 def execute raise NotImplementError end |
#find_outputs_from_space ⇒ void
This method returns an undefined value.
Find outputs from the domain space.
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 146 def find_outputs_from_space tuples = read_all(TupleSpace::DataTuple.new(domain: @domain_id)) outputs = [] @rule_condition.outputs.each_with_index do |condition, i| _condition = condition.eval(@env) case _condition.distribution when :all outputs[i] = tuples.find_all {|t| _condition.match(t.name)} when :each # FIXME outputs[i] = tuples.find_all {|t| _condition.match(t.name)} end # apply touch operation and push the result if new_tuples = apply_touch_operation(_condition, outputs[i]) outputs[i] = new_tuples end # write data null if needed write_data_null(_condition, outputs[i], i) end return outputs end |
#handle ⇒ Object
Handle the rule and return the outputs.
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 48 def handle # make rule and task process log process_log(make_task_process_record.merge(transition: "start")) process_log(make_rule_process_record.merge(transition: "start")) # show begin messages (@digest, 0, "==>") ("caller: %s" % @caller_id) # save domain log Log::DomainLog.new(self).save # save domain info domain_info_location = @working_directory ? @working_directory :@domain_location System::DomainInfo.new(env.dumpable).write(domain_info_location) # execute the rule outputs = execute # publish outputs and finished begin outputs.flatten.compact.each {|output| write(output)} write(TupleSpace::FinishedTuple.new(@domain_id, :succeeded, outputs)) rescue Rinda::RedundantTupleError write(TupleSpace::FinishedTuple.new(@domain_id, :error, outputs)) end # show end message show_outputs(outputs) (@digest, 0, "<==") # put rule and task process log process_log(make_rule_process_record.merge(transition: "complete")) process_log(make_task_process_record.merge(transition: "complete")) end |
#make_location(name, domain_id) ⇒ BasicLocation
Make location by data name and the domain.
97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 97 def make_location(name, domain_id) if domain_id == "root" return @base_location + "./%s" % name else # make relative path pakcage_id, rule_name, task_id = domain_id.split(":") path = "./.%s/%s/%s/%s" % [package_id, rule_name, task_id, name] # make location return @base_location + path end end |
#make_output_location(name) ⇒ Object
Make output data location by the name.
111 112 113 114 115 116 117 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 111 def make_output_location(name) # FIXME: maybe we should not lift output here return if @caller_id.nil? # get parent domain or root domain make_location(name, @caller_id) end |
#make_output_tuple(data_expr) ⇒ Object
Make output tuple by the name.
120 121 122 123 124 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 120 def make_output_tuple(data_expr) name = data_expr.first.name location = make_output_location(name) TupleSpace::DataTuple.new(name: name, domain: @domain_id, location: location, time: nil) end |
#make_rule_process_record ⇒ Object
Build rule process record.
220 221 222 223 224 225 226 227 228 229 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 220 def make_rule_process_record Log::RuleProcessRecord.new.tap do |record| record.name = "&%s:%s" % [@package_id, @rule_name] record.rule_type = @rule_definition.rule_type if @caller caller_package_id, caller_rule_name, caller_task_id = @caller.split(":") record.caller = "&%s:%s" % [caller_package_id, caller_rule_name] end end end |
#make_task_process_record ⇒ Object
231 232 233 234 235 236 237 238 239 240 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 231 def make_task_process_record Log::TaskProcessRecord.new.tap do |record| record.name = @digest record.package_id = @package_id record.rule_name = @rule_name record.rule_type = @rule_definition.rule_type record.inputs = @inputs.flatten.map{|input| input.name}.join(",") record.parameters = @param_set.textize end end |
#publish_outputs(outputs) ⇒ Object
Publish output data tuples.
243 244 245 246 247 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 243 def publish_outputs(outputs) # output data rescue Rinda::RedundantTupleError write("finished") end |
#setup_env(env, param_set) ⇒ Object
Setup handler’s environment. We make a new environment that is introduced a new layer in top of the plain package environment, so we can do any operations safety.
129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 129 def setup_env(env, param_set) # put new layer _env = env.layer # set current package id _env.set(current_package_id: package_id) # merge parameter set _env.merge_param_set(param_set) ### system environment # ENV.each do |key, value| # @variable_table.set(Variable.new("ENV_" + key), PioneString.new(value)) # end end |
#show_outputs(outputs) ⇒ Object
Show output tuples as message. This method is used for debugging only.
250 251 252 253 254 255 256 257 258 259 260 261 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 250 def show_outputs(outputs) ("Result of %s:" % @digest) if outputs outputs.each_with_index do |output, i| output.each_with_index do |t, ii| ("[%s,%s] %s" % [i, ii, t.name], 1) end end else ("no outputs", 1) end end |
#update_time_by_touch_operation(tuples) ⇒ Object
199 200 201 202 203 204 205 206 207 208 209 210 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 199 def update_time_by_touch_operation(tuples) fun = lambda do |tuple| time = Time.now new_data = TupleSpace::DataTuple.new(name: tuple.name, domain: @domain_id, location: tuple.location, time: time) write(TupleSpace::TouchTuple.new(name: tuple.name, domain: @domain_id, time: time)) write(new_data) new_data end tuples.map do |tuple| take!(TupleSpace::DataTuple.new(name: tuple.name, domain: @domain_id)) ? fun.call(tuple) : tuple end end |
#write_data_null(output, tuples, i) ⇒ Object
Write a data null tuple if the output condition accepts nonexistence.
213 214 215 216 217 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 213 def write_data_null(output, tuples, i) if output.accept_nonexistence? and tuples.nil? write(TupleSpace::DataNullTuple.new(domain: @domain_id, position: i)) end end |