pione 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. data/History.txt +9 -0
  2. data/Rakefile +13 -0
  3. data/bin/pione +5 -0
  4. data/bin/pione-compiler +5 -0
  5. data/example/ScoreAggregation/ScoreAggregation.pione +2 -0
  6. data/example/ScoreAggregation/bin/apply-template.rb +1 -1
  7. data/example/ScoreAggregation/bin/mean-summary.rb +1 -1
  8. data/example/ScoreAggregation/bin/total-mean.rb +1 -1
  9. data/example/ScoreAggregation/bin/total-statistics.rb +3 -3
  10. data/example/ScoreAggregation/pione-package.json +21 -0
  11. data/example/ScoreAggregation/scenario/case1/Scenario.pione +1 -0
  12. data/example/ScoreAggregation/scenario/case1/pione-scenario.json +36 -0
  13. data/lib/pione.rb +15 -2
  14. data/lib/pione/agent/basic-agent.rb +0 -1
  15. data/lib/pione/agent/job-terminator.rb +8 -3
  16. data/lib/pione/agent/task-worker.rb +9 -2
  17. data/lib/pione/command.rb +2 -0
  18. data/lib/pione/command/basic-command.rb +4 -0
  19. data/lib/pione/command/option.rb +4 -1
  20. data/lib/pione/command/pione-clean.rb +104 -17
  21. data/lib/pione/command/pione-client.rb +16 -3
  22. data/lib/pione/command/pione-command.rb +45 -0
  23. data/lib/pione/command/pione-compiler.rb +39 -0
  24. data/lib/pione/command/pione-log.rb +1 -0
  25. data/lib/pione/command/pione-task-worker.rb +6 -2
  26. data/lib/pione/command/pione-val.rb +1 -0
  27. data/lib/pione/front.rb +1 -0
  28. data/lib/pione/front/basic-front.rb +1 -1
  29. data/lib/pione/front/front-exception.rb +5 -1
  30. data/lib/pione/global.rb +3 -118
  31. data/lib/pione/global/broker-variable.rb +21 -8
  32. data/lib/pione/global/client-variable.rb +16 -8
  33. data/lib/pione/{system → global}/config.rb +2 -2
  34. data/lib/pione/global/global-exception.rb +40 -0
  35. data/lib/pione/global/input-generator-variable.rb +4 -1
  36. data/lib/pione/global/item.rb +168 -0
  37. data/lib/pione/global/log-variable.rb +64 -13
  38. data/lib/pione/global/network-variable.rb +4 -1
  39. data/lib/pione/global/package-variable.rb +25 -10
  40. data/lib/pione/global/path-variable.rb +62 -26
  41. data/lib/pione/global/relay-variable.rb +101 -36
  42. data/lib/pione/global/system-variable.rb +26 -9
  43. data/lib/pione/global/task-worker-variable.rb +19 -7
  44. data/lib/pione/global/tuple-space-notifier-variable.rb +60 -20
  45. data/lib/pione/lang.rb +0 -2
  46. data/lib/pione/lang/data-expr.rb +8 -0
  47. data/lib/pione/package/package-exception.rb +1 -1
  48. data/lib/pione/rule-engine/action-handler.rb +14 -12
  49. data/lib/pione/rule-engine/engine-exception.rb +11 -0
  50. data/lib/pione/rule-engine/flow-handler.rb +20 -11
  51. data/lib/pione/system.rb +1 -1
  52. data/lib/pione/system/file-cache.rb +1 -1
  53. data/lib/pione/system/init.rb +13 -15
  54. data/lib/pione/system/status.rb +30 -0
  55. data/lib/pione/system/system-exception.rb +0 -24
  56. data/lib/pione/test-helper.rb +8 -1
  57. data/lib/pione/test-helper/command-helper.rb +42 -15
  58. data/lib/pione/util.rb +1 -0
  59. data/lib/pione/util/embeded-expr-expander.rb +5 -11
  60. data/lib/pione/util/pnml-compiler.rb +97 -0
  61. data/lib/pione/util/profiler.rb +107 -0
  62. data/lib/pione/version.rb +1 -1
  63. data/man/pione-clean.1 +76 -0
  64. data/pione.gemspec +5 -2
  65. data/test/agent/spec_job-terminator.rb +41 -3
  66. data/test/command/data/pione-client/ActionError.pione +5 -0
  67. data/test/command/data/pione-compiler/Sequence.pnml +137 -0
  68. data/test/command/spec_pione-clean.rb +250 -5
  69. data/test/command/spec_pione-client.rb +57 -46
  70. data/test/command/spec_pione-command.rb +18 -0
  71. data/test/command/spec_pione-compiler.rb +13 -0
  72. data/test/global/spec_item.rb +77 -0
  73. data/test/lang/data/data-expr.yml +5 -0
  74. data/test/rule-engine/{spec_action-handler.pione → data/action-handler/BasicAction.pione} +0 -0
  75. data/test/rule-engine/data/action-handler/UsePackageScript.pione +17 -0
  76. data/test/rule-engine/spec_action-handler.rb +143 -80
  77. data/test/system/spec_status.rb +13 -0
  78. data/test/{tuple → tuple-space}/spec_basic-tuple.rb +0 -0
  79. data/test/{tuple → tuple-space}/spec_data-tuple.rb +0 -0
  80. data/test/{tuple → tuple-space}/spec_finished-tuple.rb +0 -0
  81. data/test/{tuple → tuple-space}/spec_message-tuple.rb +0 -0
  82. data/test/{tuple → tuple-space}/spec_task-tuple.rb +0 -0
  83. data/test/{tuple → tuple-space}/spec_touch-tuple.rb +0 -0
  84. data/test/{tuple → tuple-space}/spec_working-tuple.rb +0 -0
  85. data/test/{tuple → tuple-space}/tuple-behavior.rb +0 -0
  86. data/test/util/data/pnml/Sequence.pnml +137 -0
  87. data/test/util/spec_pnml-compiler.rb +21 -0
  88. data/test/util/spec_profiler.rb +53 -0
  89. metadata +75 -32
  90. data/example/ScoreAggregation/package.yml +0 -5
  91. data/example/ScoreAggregation/scenario/case1/scenario.yml +0 -29
  92. data/lib/pione/lang/interpolator-parser.rb +0 -44
  93. data/lib/pione/lang/interpolator-transformer.rb +0 -13
  94. data/test/lang/spec_interpolator-parser.rb +0 -5
  95. data/test/lang/spec_interpolator-transformer.rb +0 -15
@@ -16,6 +16,17 @@ module Pione
16
16
  end
17
17
  end
18
18
 
19
+ class ActionError < StandardError
20
+ def initialize(digest, report)
21
+ @digest = digest
22
+ @report = report
23
+ end
24
+
25
+ def message
26
+ "Action rule %s has errored:\n%s" % [@digest, @report]
27
+ end
28
+ end
29
+
19
30
  class InvalidOutputError < RuleExecutionError
20
31
  def initialize(handler, outputs)
21
32
  super(handler)
@@ -171,6 +171,7 @@ module Pione
171
171
  def initialize(handler)
172
172
  super(handler)
173
173
  @data_finder = DataFinder.new(tuple_space_server, domain_id)
174
+ @finished = [] # finished tuple cache
174
175
  end
175
176
 
176
177
  # Apply input data to rules.
@@ -178,9 +179,12 @@ module Pione
178
179
  # start message
179
180
  user_message_begin("Rule Application: %s" % digest, 1)
180
181
 
181
- # rule application loop
182
- while tasks = find_tasks(rules) do
183
- distribute_tasks(tasks)
182
+ # with profile
183
+ Util::Profiler.profile(Util::RuleApplicationProfileReport.new(digest)) do
184
+ # rule application loop
185
+ while tasks = find_tasks(rules) do
186
+ distribute_tasks(tasks)
187
+ end
184
188
  end
185
189
 
186
190
  # end message
@@ -337,9 +341,9 @@ module Pione
337
341
  # setup output variables
338
342
  var_o = Lang::Variable.new("O")
339
343
  task.env.variable_set(Lang::Variable.new("OUTPUT"), var_o)
340
- o = find_output_variables(task, inputs, Lang::KeyedSequence.new)
341
- task.env.variable_set(var_o, o)
342
- param_set = param_set.set(table: param_set.table.merge({"O" => o}))
344
+ kseq = find_output_variables(task, Lang::KeyedSequence.new)
345
+ task.env.variable_set(var_o, kseq)
346
+ param_set = param_set.set(table: param_set.table.merge({"O" => kseq}))
343
347
 
344
348
  return task.set(order: order, env: env, param_set: param_set)
345
349
  else
@@ -347,17 +351,17 @@ module Pione
347
351
  end
348
352
  end
349
353
 
350
- def find_output_variables(task, inputs, o)
351
- _o = o
354
+ def find_output_variables(task, kseq)
355
+ _kseq = kseq
352
356
  task.rule_condition.outputs.each_with_index do |condition, i|
353
357
  begin
354
358
  data = condition.eval(task.env)
355
- _o = o.put(Lang::IntegerSequence.of(i+1), data)
359
+ _kseq = _kseq.put(Lang::IntegerSequence.of(i+1), data)
356
360
  rescue Lang::UnboundError
357
361
  next
358
362
  end
359
363
  end
360
- return _o
364
+ return _kseq
361
365
  end
362
366
 
363
367
  # Distribute tasks.
@@ -410,7 +414,12 @@ module Pione
410
414
  def need_to_publish_task?(task, tuple)
411
415
  # reuse task finished result if order is weak update
412
416
  if task.order == :weak
413
- if read!(TupleSpace::FinishedTuple.new(domain: task.domain_id, status: :succeeded))
417
+ template = TupleSpace::FinishedTuple.new(domain: task.domain_id, status: :succeeded)
418
+ if @finished.include?(template)
419
+ return false
420
+ end
421
+ if finished = read!(template)
422
+ @finished << finished
414
423
  return false
415
424
  end
416
425
  end
data/lib/pione/system.rb CHANGED
@@ -5,10 +5,10 @@ end
5
5
 
6
6
  require 'pione/system/object'
7
7
  require 'pione/system/common'
8
- require 'pione/system/config'
9
8
  require 'pione/system/init'
10
9
  require 'pione/system/file-cache'
11
10
  require 'pione/system/domain-info'
11
+ require 'pione/system/status'
12
12
 
13
13
  # export some classes to the name space of Pione
14
14
  Pione.module_exec {const_set(:PioneObject, Pione::System::PioneObject)}
@@ -135,7 +135,7 @@ module Pione
135
135
  def get(location)
136
136
  # cache if record doesn't exist
137
137
  unless @table.has_key?(location)
138
- cache_location = Location[Temppath.create(basedir: @tmpdir)]
138
+ cache_location = Location[Global.file_cache_path_generator.create]
139
139
  location.turn(cache_location)
140
140
  @table[location] = cache_location
141
141
  end
@@ -5,27 +5,25 @@ module Pione
5
5
  # turn on "abort on exception" mode
6
6
  Thread.abort_on_exception = true
7
7
 
8
- # load configration file
9
- System::Config.load(Global.config_path)
8
+ # load configration file for global system
9
+ Global::Config.load(Global.config_path)
10
10
 
11
11
  # make temporary directories
12
- unless Global.temporary_directory_root.exist?
13
- Global.temporary_directory_root.mkdir(0777)
14
- end
15
12
  unless Global.temporary_directory.exist?
16
- Global.temporary_directory.mkdir(0700)
17
- end
18
- unless Global.working_directory_root.exist?
19
- Global.working_directory_root.mkdir(0777)
13
+ Global.temporary_directory.mkdir(0777)
20
14
  end
21
- unless Global.working_directory.exist?
22
- Global.working_directory.mkdir(0700)
23
- end
24
- unless Global.file_cache_directory_root.exist?
25
- Global.file_cache_directory_root.mkdir(0777)
15
+
16
+ # setup default temporary path generator
17
+ Temppath.update_basedir(Global.my_temporary_directory + "others_%s" % Util::UUID.generate)
18
+
19
+ # make file cache directory
20
+ unless Global.file_cache_directory.exist?
21
+ Global.file_cache_directory.mkdir(0777)
26
22
  end
23
+
24
+ # make my file cache directory
27
25
  unless Global.file_cache_directory.exist?
28
- Global.file_cache_directory.mkdir(0700)
26
+ Global.file_cache_directory.mkdir(0777)
29
27
  end
30
28
  end
31
29
  end
@@ -0,0 +1,30 @@
1
+ module Pione
2
+ module System
3
+ class Status
4
+ class << self
5
+ def success
6
+ new(:success)
7
+ end
8
+
9
+ def error(exception)
10
+ new(:error, exception)
11
+ end
12
+ end
13
+
14
+ attr_reader :exception
15
+
16
+ def initialize(status, exception=nil)
17
+ @status = status
18
+ @exception = exception
19
+ end
20
+
21
+ def success?
22
+ @status == :success
23
+ end
24
+
25
+ def error?
26
+ @status == :error
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,29 +1,5 @@
1
1
  module Pione
2
2
  module System
3
3
  class SystemException < StandardError; end
4
-
5
- # This exception class is raised when configuration file is in invalid format.
6
- class InvalidConfigFile < SystemException
7
- # config file path
8
- attr_reader :path
9
-
10
- def initialize(path)
11
- @path = path
12
- end
13
-
14
- def message
15
- "invalid format configuration file: %s" % @path
16
- end
17
- end
18
-
19
- class UnconfigurableVariableError < SystemException
20
- def initialize(name)
21
- @name = name
22
- end
23
-
24
- def message
25
- "global variable \"%s\" is unconfigurable." % @name
26
- end
27
- end
28
4
  end
29
5
  end
@@ -15,7 +15,14 @@ module Pione
15
15
  @scope_id = (@scope_id || 0) + 1
16
16
  mod = Module.new
17
17
  const_set("MODULE%s" % @scope_id, mod)
18
- mod.instance_eval(&b)
18
+ mod.send(:define_method, :this) do
19
+ mod
20
+ end
21
+ mod.module_eval(&b)
22
+ end
23
+
24
+ def self.scope_of(mod)
25
+ eval(mod.name.split("::").reverse.drop(1).reverse.join("::"))
19
26
  end
20
27
  end
21
28
  end
@@ -1,16 +1,21 @@
1
1
  module Pione
2
2
  module TestHelper
3
+ # CommandResult is a result of command execution. This has result status,
4
+ # stdout, stdin, and etc, so you can analyze and check it.
3
5
  class CommandResult < StructX
4
6
  member :exception
5
7
  member :stdout
6
8
  member :stderr
7
9
 
10
+ # Return true if the command succeeded.
8
11
  def success?
9
12
  exception.kind_of?(SystemExit) and exception.success?
10
13
  end
11
14
 
15
+ # Print the command result report.
12
16
  def report
13
17
  unless success?
18
+ puts "[FAIL]"
14
19
  puts "ERROR: %s" % exception.message
15
20
  exception.backtrace.each do |line|
16
21
  puts "TRACE: %s" % line
@@ -23,40 +28,62 @@ module Pione
23
28
  puts "STDERR:"
24
29
  puts stderr.string[0..100]
25
30
  end
31
+ else
32
+ puts "[SUCCESS]"
26
33
  end
27
34
  end
28
35
  end
29
36
 
37
+ # This module helps tests of command execution.
30
38
  module Command
31
39
  class << self
32
- def execute(&b)
40
+ # Run the action with expectation command execution succeeds.
41
+ def succeed(*options, &b)
42
+ res = execute(options, &b)
43
+ res.should.success
44
+ return res
45
+ end
46
+
47
+ # Run the action with expectation command execution fails.
48
+ def fail(*options, &b)
49
+ res = execute(options, &b)
50
+ res.should.not.success
51
+ return res
52
+ end
53
+
54
+ private
55
+
56
+ # Run the command execution action.
57
+ def execute(options, &b)
33
58
  # initialize exit status
34
59
  Global.exit_status = true
35
60
 
36
61
  # make result
37
62
  res = CommandResult.new(stdout: StringIO.new("", "w"), stderr: StringIO.new("", "w"))
38
- $stdout = res.stdout
39
- $stderr = res.stderr
63
+
64
+ # setup stdout and stderr
65
+ $stdout = res.stdout unless options.include?(:show) or options.include?(:show_stdout)
66
+ $stderr = res.stderr unless options.include?(:show) or options.include?(:show_stderr)
67
+
68
+ # run the action
40
69
  begin
41
70
  b.call
42
71
  rescue Object => e
43
- res.exception = e
72
+ unless options.include?(:show_exception)
73
+ res.exception = e
74
+ else
75
+ raise
76
+ end
44
77
  end
78
+
79
+ # revert stdout and stderr
45
80
  $stdout = STDOUT
46
81
  $stderr = STDERR
47
- return res
48
- end
49
82
 
50
- def succeed(&b)
51
- res = execute(&b)
52
- res.report
53
- res.should.success
54
- return res
55
- end
83
+ if options.include?(:report)
84
+ res.report
85
+ end
56
86
 
57
- def fail(&b)
58
- res = execute(&b)
59
- res.should.not.success
60
87
  return res
61
88
  end
62
89
  end
data/lib/pione/util.rb CHANGED
@@ -23,4 +23,5 @@ require 'pione/util/positionable' # source position handler
23
23
  require 'pione/util/embeded-expr-expander' # expand text embeded PIONE expression
24
24
  require 'pione/util/free-thread-generator' # generate threads free from thread group
25
25
  require 'pione/util/parslet-extension' # parslet extension
26
+ require 'pione/util/pnml-compiler' # toy compiler from PNML to PIONE
26
27
 
@@ -6,17 +6,11 @@ module Pione
6
6
  return nil if str.nil?
7
7
 
8
8
  # parse and transform
9
- tree = Lang::InterpolatorParser.new.parse(str)
10
- list = Lang::InterpolatorTransformer.new.apply(tree, {package_name: nil, filename: nil})
11
-
12
- # evaluate and join
13
- list.map do |elt|
14
- if elt.is_a?(String)
15
- elt
16
- else
17
- elt.eval(env).call_pione_method(env, "textize", []).value
18
- end
19
- end.join("")
9
+ str.gsub(/\{(\$.+?)\}|\<\?\s*(.+?)\s*\?>/) do
10
+ tree = Lang::DocumentParser.new.expr.parse($1 || $2)
11
+ expr = Lang::DocumentTransformer.new.apply(tree, {package_name: nil, filename: nil})
12
+ expr.eval(env).call_pione_method(env, "textize", []).value
13
+ end
20
14
  end
21
15
  end
22
16
  end
@@ -0,0 +1,97 @@
1
+ module Pione
2
+ module Util
3
+ class PNMLCompiler
4
+ def initialize(src)
5
+ @src = src
6
+ end
7
+
8
+ # Compile PNML file into PIONE document as a string.
9
+ def compile
10
+ doc = REXML::Document.new(@src.read)
11
+ rule_table = make_rule_table(doc)
12
+ io_table = make_io_table(doc)
13
+ input_table = make_input_table(doc, rule_table, io_table)
14
+ output_table = make_output_table(doc, rule_table, io_table)
15
+ rules = make_flow_rules(rule_table, input_table, output_table)
16
+ return textize_flow_rules(rules)
17
+ end
18
+
19
+ private
20
+
21
+ # Make rule mapping table by collecting transitions and associating with its id and name.
22
+ def make_rule_table(doc)
23
+ rule_table = Hash.new
24
+ REXML::XPath.each(doc, "/pnml/net/transition") do |elt|
25
+ id = elt.attribute("id").value
26
+ name = REXML::XPath.first(elt, "name/text").texts.map{|text| text.value}.join("")
27
+ rule_table[id] = name
28
+ end
29
+ return rule_table
30
+ end
31
+
32
+ # Make input and output mapping table by collecting places and associating its id and name.
33
+ def make_io_table(doc)
34
+ io_table = Hash.new {|h, k| h[k] = []}
35
+ REXML::XPath.each(doc, "/pnml/net/place") do |elt|
36
+ id = elt.attribute("id").value
37
+ name = REXML::XPath.first(elt, "name/text").texts.map{|text| text.value}.join("")
38
+ io_table[id] << name
39
+ end
40
+ return io_table
41
+ end
42
+
43
+ # Make rule's input table by collecting arcs and associating its source and target.
44
+ def make_input_table(doc, rule_table, io_table)
45
+ input_table = Hash.new {|h, k| h[k] = []}
46
+ REXML::XPath.each(doc, "/pnml/net/arc") do |elt|
47
+ source = elt.attribute("source").value
48
+ target = elt.attribute("target").value
49
+ name = REXML::XPath.first(elt, "inscription/text").texts.map{|text| text.value}.join("")
50
+ input_table[rule_table[target]] << io_table[source]
51
+ end
52
+ return input_table
53
+ end
54
+
55
+ # Make rule's output table by collecting arcs and associating its source and target.
56
+ def make_output_table(doc, rule_table, io_table)
57
+ output_table = Hash.new {|h, k| h[k] = []}
58
+ REXML::XPath.each(doc, "/pnml/net/arc") do |elt|
59
+ source = elt.attribute("source").value
60
+ target = elt.attribute("target").value
61
+ name = REXML::XPath.first(elt, "inscription/text").texts.map{|text| text.value}.join("")
62
+ output_table[rule_table[source]] << io_table[target]
63
+ end
64
+ return output_table
65
+ end
66
+
67
+ # Make flow rules from rule table, input table, and output table.
68
+ def make_flow_rules(rule_table, input_table, output_table)
69
+ rules = Array.new
70
+ rule_table.each do |key, rule_name|
71
+ inputs = input_table[rule_name]
72
+ outputs = output_table[rule_name]
73
+ rules << [rule_name, inputs, outputs]
74
+ end
75
+ return rules.sort {|a, b| a.first <=> b.first}
76
+ end
77
+
78
+ FLOW_RULE_TEMPLATE = <<-RULE
79
+ Rule %s
80
+ %s
81
+ %s
82
+ Action
83
+ cp {$I[1]} {$O[1]}
84
+ End
85
+ RULE
86
+
87
+ # Textize flow rules.
88
+ def textize_flow_rules(rules)
89
+ rules.map do |rule|
90
+ inputs = rule[1].map {|name| "input '%s'" % name}.join("\n ")
91
+ outputs = rule[2].map {|name| "output '%s'" % name}.join("\n ")
92
+ Indentation.cut(FLOW_RULE_TEMPLATE) % [rule[0], inputs, outputs]
93
+ end.join("\n\n")
94
+ end
95
+ end
96
+ end
97
+ end