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
- #eval_rule_condition ⇒ Object
-
#execute ⇒ Object
Executes the rule.
-
#find_outputs_from_space ⇒ void
Find outputs from the domain space.
-
#handle ⇒ Boolean
Handle the rule and return the outputs.
-
#initialize(param) ⇒ 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, #set_tuple_space, tuple_space_operation, #tuple_space_server, #with_process_log
Constructor Details
#initialize(param) ⇒ BasicHandler
Create a new handler for rule.
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 28 def initialize(param) ### set tuple space server set_tuple_space(param[:tuple_space]) ### set informations @plain_env = param[:env] @env = setup_env(param[:env], param[:param_set]) @package_id = param[:package_id] @rule_name = param[:rule_name] @rule_definition = param[:rule_definition] @rule_condition = eval_rule_condition() @inputs = param[:inputs] @outputs = [] @param_set = param[: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 = param[:domain_id] @domain_location = make_location("", @domain_id) @caller_id = param[:caller_id] @request_from = param[:request_from] @session_id = param[:session_id] @client_ui = param[:client_ui] 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.
207 208 209 210 211 212 213 214 215 216 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 207 def apply_touch_operation(condition, tuples) _condition = condition.eval(@env) if _condition.operation == :touch or (self.kind_of?(EmptyHandler) and _condition.operation == :write) 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
218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 218 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 |
#eval_rule_condition ⇒ Object
108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 108 def eval_rule_condition() rule_condition = @rule_definition.rule_condition_context.eval(@env) # change to touch operation if the definition is empty rule # if @rule_definition.kind_of?(Lang::EmptyRuleDefinition) # rule_condition.outputs.each do |output| # if output.operation == :write # output.set(operation: :touch) # end # end # end return rule_condition end |
#execute ⇒ Object
Executes the rule.
104 105 106 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 104 def execute raise NotImplementError end |
#find_outputs_from_space ⇒ void
This method returns an undefined value.
Find outputs from the domain space.
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 180 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 ⇒ Boolean
Handle the rule and return the outputs.
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 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 57 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) unless @domain_id == "root" # save domain log Log::DomainLog.new(self).save # save a domain dump file domain_dump_location = @working_directory ? @working_directory.location : @domain_location System::DomainDump.new(env.dumpable).write(domain_dump_location) end # execute the rule outputs = execute # publish outputs and finished begin outputs.flatten.compact.each {|output| write(output)} write(TupleSpace::FinishedTuple.new(@domain_id, Util::UUID.generate, :succeeded, outputs)) rescue Rinda::RedundantTupleError write(TupleSpace::FinishedTuple.new(@domain_id, Util::UUID.generate, :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")) return true rescue Object => e ("ERROR: " + e., 0, "info", :red) status = System::Status.error(message: e., exception: e) write(TupleSpace::CommandTuple.new(name: "terminate", args: [status])) return false end |
#make_location(name, domain_id) ⇒ BasicLocation
Make location by data name and the domain.
131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 131 def make_location(name, domain_id) if domain_id == "root" return @base_location + "./output/%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.
145 146 147 148 149 150 151 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 145 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.
154 155 156 157 158 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 154 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.
254 255 256 257 258 259 260 261 262 263 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 254 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
265 266 267 268 269 270 271 272 273 274 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 265 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.
277 278 279 280 281 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 277 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.
163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 163 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.
284 285 286 287 288 289 290 291 292 293 294 295 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 284 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
233 234 235 236 237 238 239 240 241 242 243 244 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 233 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.
247 248 249 250 251 |
# File 'lib/pione/rule-engine/basic-handler.rb', line 247 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 |