pione 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. data/.gitignore +2 -1
  2. data/History.txt +11 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +1 -1
  5. data/bin/pione-log +5 -0
  6. data/example/CountChar/CountChar.pione +1 -1
  7. data/example/SieveOfEratosthenes/SieveOfEratosthenes.pione +39 -38
  8. data/lib/pione.rb +14 -35
  9. data/lib/pione/agent/input-generator.rb +38 -40
  10. data/lib/pione/agent/logger.rb +52 -19
  11. data/lib/pione/agent/rule-provider.rb +5 -8
  12. data/lib/pione/agent/task-worker.rb +25 -32
  13. data/lib/pione/agent/tuple-space-client.rb +22 -14
  14. data/lib/pione/command.rb +21 -0
  15. data/lib/pione/command/basic-command.rb +267 -84
  16. data/lib/pione/command/child-process.rb +21 -18
  17. data/lib/pione/command/daemon-process.rb +9 -8
  18. data/lib/pione/command/front-owner-command.rb +8 -25
  19. data/lib/pione/command/pione-broker.rb +27 -24
  20. data/lib/pione/command/pione-clean.rb +6 -6
  21. data/lib/pione/command/pione-client.rb +143 -128
  22. data/lib/pione/command/pione-log.rb +61 -0
  23. data/lib/pione/command/pione-relay-account-db.rb +40 -38
  24. data/lib/pione/command/pione-relay-client-db.rb +38 -42
  25. data/lib/pione/command/pione-relay.rb +19 -20
  26. data/lib/pione/command/pione-syntax-checker.rb +70 -45
  27. data/lib/pione/command/pione-task-worker.rb +56 -66
  28. data/lib/pione/command/pione-tuple-space-provider.rb +36 -45
  29. data/lib/pione/command/pione-tuple-space-receiver.rb +34 -32
  30. data/lib/pione/command/pione-tuple-space-viewer.rb +63 -47
  31. data/lib/pione/location.rb +10 -0
  32. data/lib/pione/location/basic-location.rb +272 -0
  33. data/lib/pione/location/dropbox-location.rb +139 -0
  34. data/lib/pione/location/ftp-location.rb +156 -0
  35. data/lib/pione/location/local-location.rb +116 -0
  36. data/lib/pione/log.rb +10 -0
  37. data/lib/pione/log/domain-info.rb +72 -0
  38. data/lib/pione/log/process-log.rb +176 -0
  39. data/lib/pione/log/process-record.rb +189 -0
  40. data/lib/pione/log/xes-log.rb +105 -0
  41. data/lib/pione/model/assignment.rb +88 -80
  42. data/lib/pione/model/binary-operator.rb +74 -68
  43. data/lib/pione/model/block.rb +218 -207
  44. data/lib/pione/model/boolean.rb +123 -112
  45. data/lib/pione/model/call-rule.rb +72 -65
  46. data/lib/pione/model/data-expr.rb +596 -290
  47. data/lib/pione/model/float.rb +108 -103
  48. data/lib/pione/model/integer.rb +133 -129
  49. data/lib/pione/model/message.rb +79 -72
  50. data/lib/pione/model/package.rb +42 -38
  51. data/lib/pione/model/parameters.rb +265 -236
  52. data/lib/pione/model/rule-expr.rb +247 -242
  53. data/lib/pione/model/rule-io.rb +137 -133
  54. data/lib/pione/model/rule.rb +307 -292
  55. data/lib/pione/model/string.rb +110 -99
  56. data/lib/pione/model/variable-table.rb +300 -271
  57. data/lib/pione/model/variable.rb +88 -83
  58. data/lib/pione/option.rb +13 -0
  59. data/lib/pione/option/child-process-option.rb +19 -0
  60. data/lib/pione/{command-option → option}/common-option.rb +6 -5
  61. data/lib/pione/option/option-interface.rb +73 -0
  62. data/lib/pione/{command-option → option}/presence-notifier-option.rb +4 -3
  63. data/lib/pione/option/task-worker-owner-option.rb +24 -0
  64. data/lib/pione/{command-option → option}/tuple-space-provider-option.rb +6 -4
  65. data/lib/pione/option/tuple-space-provider-owner-option.rb +18 -0
  66. data/lib/pione/option/tuple-space-receiver-option.rb +8 -0
  67. data/lib/pione/parser/common-parser.rb +3 -2
  68. data/lib/pione/parser/expr-parser.rb +6 -1
  69. data/lib/pione/patch/em-ftpd-patch.rb +21 -0
  70. data/lib/pione/patch/rinda-patch.rb +31 -23
  71. data/lib/pione/rule-handler/action-handler.rb +35 -25
  72. data/lib/pione/rule-handler/basic-handler.rb +92 -18
  73. data/lib/pione/rule-handler/flow-handler.rb +104 -98
  74. data/lib/pione/rule-handler/root-handler.rb +11 -0
  75. data/lib/pione/system/common.rb +10 -0
  76. data/lib/pione/system/file-cache.rb +103 -84
  77. data/lib/pione/system/global.rb +67 -12
  78. data/lib/pione/system/init.rb +20 -0
  79. data/lib/pione/transformer/expr-transformer.rb +6 -1
  80. data/lib/pione/tuple-space/data-finder.rb +33 -6
  81. data/lib/pione/tuple-space/tuple-space-receiver.rb +4 -3
  82. data/lib/pione/tuple-space/tuple-space-server-interface.rb +58 -13
  83. data/lib/pione/tuple-space/tuple-space-server.rb +13 -11
  84. data/lib/pione/tuple-space/update-criteria.rb +8 -7
  85. data/lib/pione/tuple/base-location-tuple.rb +9 -0
  86. data/lib/pione/tuple/basic-tuple.rb +7 -7
  87. data/lib/pione/tuple/data-tuple.rb +5 -2
  88. data/lib/pione/tuple/lift-tuple.rb +14 -0
  89. data/lib/pione/tuple/rule-tuple.rb +1 -1
  90. data/lib/pione/tuple/task-tuple.rb +5 -1
  91. data/lib/pione/version.rb +1 -1
  92. data/pione.gemspec +5 -1
  93. data/test/location/spec_basic-location.rb +35 -0
  94. data/test/location/spec_ftp-location.rb +100 -0
  95. data/test/location/spec_local-location.rb +99 -0
  96. data/test/log/data/sample.log +1003 -0
  97. data/test/log/spec_xes-log.rb +11 -0
  98. data/test/model/spec_data-expr.rb +249 -6
  99. data/test/model/spec_data-expr.yml +45 -0
  100. data/test/parser/spec_expr-parser.yml +4 -0
  101. data/test/spec_data-finder.rb +13 -7
  102. data/test/spec_data-finder.yml +42 -13
  103. data/test/system/spec_file-cache.rb +39 -0
  104. data/test/test-util.rb +226 -1
  105. data/test/transformer/spec_expr-transformer.rb +12 -1
  106. metadata +107 -24
  107. data/bin/pione-search-log +0 -30
  108. data/lib/pione/command-option/basic-option.rb +0 -42
  109. data/lib/pione/command-option/child-process-option.rb +0 -17
  110. data/lib/pione/command-option/daemon-option.rb +0 -12
  111. data/lib/pione/command-option/task-worker-owner-option.rb +0 -17
  112. data/lib/pione/command-option/tuple-space-provider-owner-option.rb +0 -16
  113. data/lib/pione/command-option/tuple-space-receiver-option.rb +0 -12
  114. data/lib/pione/command/tuple-space-provider-owner.rb +0 -6
  115. data/lib/pione/resource/basic-resource.rb +0 -92
  116. data/lib/pione/resource/dropbox-resource.rb +0 -106
  117. data/lib/pione/resource/ftp.rb +0 -84
  118. data/lib/pione/resource/local.rb +0 -113
  119. data/lib/pione/tuple/base-uri-tuple.rb +0 -9
  120. data/lib/pione/tuple/shift-tuple.rb +0 -13
  121. data/lib/pione/util/log.rb +0 -79
  122. data/test/spec_resource.rb +0 -73
@@ -1,11 +1,11 @@
1
1
  module Pione
2
2
  module Agent
3
+ # RuleProvider is an agent for providing rules to other agents.
3
4
  class RuleProvider < TupleSpaceClient
4
-
5
5
  set_agent_type :rule_provider
6
6
 
7
- def initialize(ts_server)
8
- super(ts_server)
7
+ def initialize(tuple_space_server)
8
+ super(tuple_space_server)
9
9
  @table = {}
10
10
 
11
11
  # import system rules
@@ -44,14 +44,11 @@ module Pione
44
44
  end
45
45
 
46
46
  def transit_to_rule_loading(request)
47
- out = Tuple[:rule].new(rule_path: request.rule_path)
48
47
  if known_rule?(request.rule_path)
49
- out.status = :known
50
- out.content = @table[request.rule_path]
48
+ write(Tuple[:rule].new(rule_path: request.rule_path, content: @table[request.rule_path]))
51
49
  else
52
- out.status = :unknown
50
+ processing_error("rule '%s' is unknonw" % request.rule_path)
53
51
  end
54
- write(out)
55
52
  end
56
53
 
57
54
  def known_rule?(rule_path)
@@ -106,13 +106,11 @@ module Pione
106
106
 
107
107
  # Transition method for the state +task_waiting+. The agent takes a +task+
108
108
  # tuple and writes a +working+ tuple.
109
+ #
109
110
  # @return [Task]
110
111
  # task tuple
111
112
  def transit_to_task_waiting
112
- @task = nil
113
- @rule = nil
114
113
  task = take(Tuple[:task].new(features: @features))
115
- @task = task
116
114
  begin
117
115
  write(Tuple[:working].new(task.domain, task.digest))
118
116
  write(Tuple[:foreground].new(task.domain, task.digest))
@@ -126,23 +124,12 @@ module Pione
126
124
  # @return [Array<Task, Rule>]
127
125
  # task tuple and the rule
128
126
  def transit_to_rule_loading(task)
129
- rule =
130
- begin
131
- read0(Tuple[:rule].new(rule_path: task.rule_path))
132
- rescue Rinda::RequestExpiredError
133
- log do |msg|
134
- msg.add_record(agent_type, "action", "request_rule")
135
- msg.add_record(agent_type, "object", task.rule_path)
136
- end
137
- write(Tuple[:request_rule].new(task.rule_path))
138
- read(Tuple[:rule].new(rule_path: task.rule_path))
139
- end
140
- @rule = rule.content
141
- if rule.status == :known
142
- return task, rule.content
143
- else
144
- raise UnknownRuleError.new(task)
127
+ rule = read!(Tuple[:rule].new(rule_path: task.rule_path))
128
+ unless rule
129
+ write(Tuple[:request_rule].new(task.rule_path))
130
+ rule = read(Tuple[:rule].new(rule_path: task.rule_path))
145
131
  end
132
+ return task, rule.content
146
133
  end
147
134
 
148
135
  # Transition method for the state +task_executing+.
@@ -177,13 +164,16 @@ module Pione
177
164
  debug_message "+++ Create Sub Task worker +++"
178
165
  @child_agent = self.class.new(tuple_space_server, @features)
179
166
  @child_agent.once = true
180
- log do |msg|
181
- msg.add_record(agent_type, "action", "create_sub_task_worker")
182
- msg.add_record(agent_type, "uuid", uuid)
183
- msg.add_record(agent_type, "object", @child_agent.uuid)
167
+
168
+ Log::CreateChildTaskWorkerProcessRecord.new.tap do |record|
169
+ record.parent = uuid
170
+ record.child = @child_agent.uuid
171
+
172
+ with_process_log(record) do
173
+ take!(Tuple[:foreground].new(task.domain, nil))
174
+ @child_agent.start
175
+ end
184
176
  end
185
- take0(Tuple[:foreground].new(task.domain, nil)) rescue true
186
- @child_agent.start
187
177
  else
188
178
  tail = descendant.last
189
179
  if tail.action?
@@ -209,7 +199,7 @@ module Pione
209
199
  @action = nil
210
200
 
211
201
  # remove the working tuple
212
- take0(Tuple[:working].new(task.domain, nil)) rescue true
202
+ take!(Tuple[:working].new(task.domain, nil))
213
203
 
214
204
  debug_message_end "End Task Execution #{rule.rule_path} by worker(#{uuid})"
215
205
 
@@ -245,16 +235,19 @@ module Pione
245
235
  # the handler
246
236
  # @return [void]
247
237
  def transit_to_task_finishing(task, handler)
248
- log do |msg|
249
- msg.add_record(agent_type, "action", "finished_task")
250
- msg.add_record(agent_type, "uuid", uuid)
251
- msg.add_record(agent_type, "object", task)
252
- end
238
+ # put finished tuple
253
239
  finished = Tuple[:finished].new(
254
240
  handler.domain, :succeeded, handler.outputs, task.digest
255
241
  )
256
242
  write(finished)
257
- take0(Tuple[:foreground].new(task.domain, nil)) rescue true
243
+ # log task process
244
+ record = handler.task_process_record.merge(transition: "complete")
245
+ process_log(record)
246
+
247
+ # remove foreground
248
+ take!(Tuple[:foreground].new(task.domain, nil))
249
+
250
+ # terminate if the agent is child
258
251
  terminate if @once
259
252
  end
260
253
 
@@ -43,6 +43,10 @@ module Pione
43
43
  end
44
44
  end
45
45
 
46
+ def base_location
47
+ read(Tuple[:base_location].any).location
48
+ end
49
+
46
50
  # Protected take.
47
51
  def take(*args)
48
52
  tuple = super(*args, &method(:set_current_tuple_entry))
@@ -114,32 +118,36 @@ module Pione
114
118
 
115
119
  # Redefine hello method with logging.
116
120
  def hello
117
- log do |msg|
118
- msg.add_record(agent_type, "action", "hello")
119
- msg.add_record(agent_type, "uuid", uuid)
121
+ record = Log::AgentConnectionProcessRecord.new.tap do |record|
122
+ record.agent_type = agent_type
123
+ record.agent_uuid = uuid
124
+ record.message = "hello"
120
125
  end
121
- super
126
+ with_process_log(record) {super}
122
127
  end
123
128
 
124
129
  # Redefine bye method with logging.
125
130
  def bye
126
- log do |msg|
127
- msg.add_record(agent_type, "action", "bye")
128
- msg.add_record(agent_type, "uuid", uuid)
131
+ record = Log::AgentConnectionProcessRecord.new.tap do |record|
132
+ record.agent_type = agent_type
133
+ record.agent_uuid = uuid
134
+ record.message = "bye"
129
135
  end
130
- super
136
+ with_process_log(record) {super}
131
137
  end
132
138
 
133
- # Redefine call transition method with logging.
139
+ # Override call transition method with logging.
134
140
  def call_transition_method(*args)
135
141
  unless [:logger, :command_listener].include?(agent_type)
136
- log do |msg|
137
- msg.add_record(agent_type, "action", "transit")
138
- msg.add_record(agent_type, "state", args.first)
139
- msg.add_record(agent_type, "uuid", uuid)
142
+ record = Log::AgentActivityProcessRecord.new.tap do |rec|
143
+ rec.agent_type = agent_type
144
+ rec.agent_uuid = uuid
145
+ rec.state = args.first
140
146
  end
147
+ with_process_log(record) {super}
148
+ else
149
+ super
141
150
  end
142
- super
143
151
  end
144
152
  end
145
153
  end
@@ -0,0 +1,21 @@
1
+ module Pione
2
+ # Command is a name space for PIONE command classes.
3
+ module Command; end
4
+ end
5
+
6
+ require 'pione/command/basic-command'
7
+ require 'pione/command/front-owner-command'
8
+ require 'pione/command/daemon-process'
9
+ require 'pione/command/child-process'
10
+ require 'pione/command/pione-client'
11
+ require 'pione/command/pione-task-worker'
12
+ require 'pione/command/pione-broker'
13
+ require 'pione/command/pione-tuple-space-provider'
14
+ require 'pione/command/pione-tuple-space-receiver'
15
+ require 'pione/command/pione-tuple-space-viewer'
16
+ require 'pione/command/pione-relay'
17
+ require 'pione/command/pione-relay-client-db'
18
+ require 'pione/command/pione-relay-account-db'
19
+ require 'pione/command/pione-clean'
20
+ require 'pione/command/pione-syntax-checker'
21
+ require 'pione/command/pione-log'
@@ -1,132 +1,315 @@
1
1
  module Pione
2
2
  module Command
3
- # OptionInterface provides methods for defining options.
4
- module ClassInterface
5
- # Returns the program name.
6
- def program_name
7
- [@program_name, @program_name_block]
3
+ # CommandInfo is a strage of program informations.
4
+ class CommandInfo
5
+ attr_reader :name
6
+ attr_reader :tail
7
+ attr_reader :banner
8
+
9
+ def initialize
10
+ @name = nil
11
+ @tail = nil
12
+ @banner = banner
8
13
  end
9
14
 
10
- # Sets progaram name and visible options.
11
- def set_program_name(program_name, &b)
12
- @program_name = program_name
13
- @program_name_block = block_given? ? b : Proc.new{""}
15
+ # Set progaram name.
16
+ #
17
+ # @param name [String]
18
+ # process name
19
+ # @param b [Proc]
20
+ # process tail block
21
+ # @return [void]
22
+ def set_name(name, &b)
23
+ @name = name
14
24
  end
15
25
 
16
- # Returns the program message.
17
- def program_message
18
- @program_message
26
+ # Set program parameters.
27
+ def set_tail(&tail)
28
+ @tail = tail
19
29
  end
20
30
 
21
- # Sets program message.
22
- def set_program_message(message)
23
- @program_message = message
31
+ # Set program banner.
32
+ #
33
+ # @param banner [String]
34
+ # banner message
35
+ # @return [void]
36
+ def set_banner(banner)
37
+ @banner = banner
24
38
  end
25
- end
26
39
 
27
- module InstanceInterface
28
40
  # Setup program name. If the setup process is failed, program name is not
29
41
  # changed.
30
42
  #
43
+ # @param cmd [BasicCommand]
44
+ # command
31
45
  # @return [void]
32
- def setup_program_name
33
- begin
34
- name, b = self.class.program_name
35
- tail = self.instance_exec(&b)
36
- $PROGRAM_NAME = "%s %s" % [name, tail]
37
- rescue Exception
38
- nil
39
- end
40
- end
41
-
42
- # Returns program message.
43
- # @return [String]
44
- # program message
45
- def program_message
46
- self.class.program_message
46
+ def setup(cmd)
47
+ $PROGRAM_NAME = "%s %s" % [@name, @tail ? @tail.call(cmd) : ""]
47
48
  end
48
49
  end
49
50
 
50
- # BasicCommand is a base class for PIONE commands.
51
- class BasicCommand < PioneObject
52
- extend ClassInterface
53
- include InstanceInterface
54
- extend CommandOption::OptionInterface
55
- use_option_module CommandOption::CommonOption
51
+ # CommandOption is a class for holding option data set.
52
+ class CommandOption < PioneObject
53
+ def_delegators :@data, :[], :[]=
56
54
 
57
- # @api private
58
- def self.inherited(subclass)
59
- opts = command_options.clone
60
- subclass.instance_eval { @command_options = opts }
61
- end
62
-
63
- # Runs the command.
64
- def self.run(*args)
65
- self.new(*args).run
66
- end
67
-
68
- # Runs the command.
69
- def run
70
- parse_options
71
- validate_options
72
- prepare
73
- setup_program_name
74
- start
55
+ # Creata a command option context.
56
+ #
57
+ # @param command_info [CommandInfo]
58
+ # command informations
59
+ def initialize(command_info)
60
+ extend Option::OptionInterface
61
+ @command_info = command_info
62
+ @data = {}
75
63
  end
76
64
 
77
- private
78
-
79
- # Parses options.
65
+ # Parse the command options.
66
+ #
80
67
  # @return [void]
81
- def parse_options
82
- parser = OptionParser.new do |opt|
68
+ def parse
69
+ OptionParser.new do |opt|
70
+ # set banner
83
71
  opt.banner = "Usage: %s [options]" % opt.program_name
84
- opt.banner << "\n" + program_message if program_message
72
+ opt.banner << "\n" + @command_info.banner if @command_info.banner
85
73
 
86
- self.class.command_options.values.sort.each do |args, b|
87
- opt.on(*args, Proc.new{|*args| self.instance_exec(*args, &b)})
88
- end
74
+ # set version
89
75
  opt.version = Pione::VERSION
90
- end
91
76
 
92
- parser.parse!(ARGV)
77
+ # set default values
78
+ default_table.each do |key, value|
79
+ @data[key] = value
80
+ end
81
+
82
+ # set options
83
+ definitions.sort{|a,b| a.first <=> b.first}.each do |args, b|
84
+ opt.on(*args, Proc.new{|*args| self.instance_exec(@data, *args, &b)})
85
+ end
86
+ end.parse!(ARGV)
93
87
  rescue OptionParser::InvalidOption => e
94
- e.args.each {|arg| $stderr.puts "Unknown option: #{arg}" }
88
+ e.args.each {|arg| $stderr.puts "Unknown option: %s" % arg }
95
89
  abort
96
90
  rescue OptionParser::MissingArgument => e
97
91
  abort(e.message)
98
92
  end
99
93
 
100
- # Validates options. Override this method if subclasses should check
101
- # options.
94
+ # Check validness of the command options.
95
+ #
102
96
  # @return [void]
103
- def validate_options
104
- # do nothing
97
+ def check
98
+ validators.each do |validator|
99
+ validator.call(@data)
100
+ end
101
+ end
102
+ end
103
+
104
+ # BasicCommand is a base class for PIONE commands.
105
+ class BasicCommand < PioneObject
106
+ @info = CommandInfo.new
107
+ @option = CommandOption.new(@info).tap {|x| x.use Option::CommonOption}
108
+ @pre_preparations = []
109
+ @preparations = []
110
+ @post_preparations = []
111
+ @pre_starts = []
112
+ @starts = []
113
+ @post_starts = []
114
+ @pre_terminations = []
115
+ @terminations = []
116
+ @post_terminations =[]
117
+
118
+ class << self
119
+ attr_reader :info
120
+ attr_reader :option
121
+ attr_reader :pre_preparations
122
+ attr_reader :preparations
123
+ attr_reader :post_preparations
124
+ attr_reader :pre_starts
125
+ attr_reader :starts
126
+ attr_reader :post_starts
127
+ attr_reader :pre_terminations
128
+ attr_reader :terminations
129
+ attr_reader :post_terminations
130
+
131
+ # @api private
132
+ def inherited(subclass)
133
+ parent_option = self.option
134
+ subclass.instance_eval do
135
+ @info = CommandInfo.new
136
+ @option = CommandOption.new(@info).tap {|x| x.use parent_option}
137
+ end
138
+ setter = lambda{|name, data| subclass.instance_variable_set(name, data.clone)}
139
+ setter.call(:@pre_preparations, self.pre_preparations)
140
+ setter.call(:@preparations, self.preparations)
141
+ setter.call(:@post_preparations, self.post_preparations)
142
+ setter.call(:@pre_starts, self.pre_starts)
143
+ setter.call(:@starts, self.starts)
144
+ setter.call(:@post_starts, self.post_starts)
145
+ setter.call(:@pre_terminations, self.pre_terminations)
146
+ setter.call(:@terminations, self.terminations)
147
+ setter.call(:@post_terminations, self.post_terminations)
148
+ end
149
+
150
+ # Define command informations.
151
+ #
152
+ # @param b [Proc]
153
+ # evaluation content in the context of option definition
154
+ # @return [void]
155
+ #
156
+ # @example
157
+ # class Cmd < BasicCommand
158
+ # define_info do
159
+ # set_name "test" # set process name
160
+ # set_banner "sample" # set banner message
161
+ # end
162
+ # end
163
+ def define_info(&b)
164
+ @info.instance_eval(&b)
165
+ end
166
+
167
+ # Define command option.
168
+ #
169
+ # @param b [Proc]
170
+ # context of the option definition
171
+ #
172
+ # @example
173
+ # class Cmd < BasicCommand
174
+ # define_option do
175
+ # option("-t", "--test", "test option") do |data, arg1|
176
+ # data[:test] = true
177
+ # end
178
+ # end
179
+ # end
180
+ def define_option(&b)
181
+ @option.instance_eval(&b)
182
+ end
183
+
184
+ # Define a preparation process.
185
+ #
186
+ # @param type [Symbol]
187
+ # preparation type
188
+ # @return [void]
189
+ def prepare(type=nil, &b)
190
+ case type
191
+ when :pre
192
+ @pre_preparations << b
193
+ when :post
194
+ @post_preparations << b
195
+ else
196
+ @preparations << b
197
+ end
198
+ end
199
+
200
+ # Define a start process.
201
+ #
202
+ # @param type [Symbol]
203
+ # start type
204
+ # @return [void]
205
+ def start(type=nil, &b)
206
+ case type
207
+ when :pre
208
+ @pre_starts << b
209
+ when :post
210
+ @post_starts << b
211
+ else
212
+ @starts << b
213
+ end
214
+ end
215
+
216
+ # Define a termination process.
217
+ #
218
+ # @param type [Symbol]
219
+ # termination type
220
+ # @return [void]
221
+ def terminate(type=nil, &b)
222
+ case type
223
+ when :pre
224
+ @pre_terminations << b
225
+ when :post
226
+ @post_terminations << b
227
+ else
228
+ @terminations << b
229
+ end
230
+ end
231
+
232
+ # Run the command.
233
+ #
234
+ # @return [void]
235
+ def run(*args)
236
+ self.new(*args).run
237
+ end
238
+ end
239
+
240
+ # Return a command option.
241
+ #
242
+ # @return [CommandOption]
243
+ # command option
244
+ def option
245
+ self.class.option
105
246
  end
106
247
 
107
- # Prepares for activity. Override this method if subclass should prepare
108
- # before command activity.
248
+ # Return a command info.
249
+ #
250
+ # @return [CommandInfo]
251
+ # command info
252
+ def info
253
+ self.class.info
254
+ end
255
+
256
+ # Run the command.
257
+ #
109
258
  # @return [void]
110
- def prepare
259
+ def run
260
+ receiver = self
261
+ caller = lambda {|name| self.class.__send__(name).each{|proc| receiver.instance_eval(&proc)}}
262
+ caller.call(:pre_preparations)
263
+ caller.call(:preparations)
264
+ caller.call(:post_preparations)
265
+ caller.call(:pre_starts)
266
+ caller.call(:starts)
267
+ caller.call(:post_starts)
268
+ call_terminations
269
+ end
270
+
271
+ def call_terminations
272
+ receiver = self
273
+ caller = lambda do |name|
274
+ self.class.__send__(name).reverse.each do |proc|
275
+ puts "%s(%s):%s:%s" % [info.name, name, *proc.source_location] if Pione.debug_mode?
276
+ begin
277
+ receiver.instance_eval(&proc)
278
+ rescue Object => e
279
+ p e
280
+ end
281
+ end
282
+ end
283
+ caller.call(:pre_terminations)
284
+ caller.call(:terminations)
285
+ caller.call(:post_terminations)
286
+ end
287
+
288
+ prepare(:pre) do
289
+ # set signal trap
111
290
  Signal.trap(:INT) do
112
291
  begin
113
- terminate
292
+ call_terminations
114
293
  rescue DRb::ReplyReaderThreadError
115
294
  # ignore reply reader error
116
295
  end
117
296
  end
297
+
298
+ # parse options
299
+ option.parse
118
300
  end
119
301
 
120
- # Starts the command activity. This method should be overridden in subclasses.
121
- # @return [void]
122
- def start
123
- raise NotImplementedError
302
+ prepare do
303
+ # validate options
304
+ option.check
124
305
  end
125
306
 
126
- # Terminate the command. Exit from PIONE system.
127
- #
128
- # @return [void]
129
- def terminate
307
+ prepare(:post) do
308
+ # setup process name
309
+ info.setup(self)
310
+ end
311
+
312
+ terminate(:post) do
130
313
  Global.monitor.synchronize do
131
314
  # exit with no exception
132
315
  exit!