sfpagent 0.2.5 → 0.2.6

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sfpagent might be problematic. Click here for more details.

data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.5
1
+ 0.2.6
@@ -262,7 +262,11 @@ module Sfp
262
262
  f.flock(File::LOCK_EX)
263
263
  Sfp::Agent.logger.info "Setting the BSig model [Wait]"
264
264
  f.rewind
265
- data = (bsig.nil? ? '' : JSON.generate(bsig))
265
+ data = ''
266
+ if !bsig.nil?
267
+ bsig['operators'].each_index { |i| bsig['operators'][i]['id'] = i }
268
+ data = JSON.generate(bsig)
269
+ end
266
270
  f.write(data)
267
271
  f.flush
268
272
  f.truncate(f.pos)
data/lib/sfpagent/bsig.rb CHANGED
@@ -63,6 +63,7 @@ class Sfp::BSig
63
63
  exec_status = :no_bsig
64
64
  sleep SleepTime
65
65
  else
66
+ bsig['operators'].sort! { |op1,op2| op1['pi'] <=> op2['pi'] }
66
67
  exec_status = achieve_local_goal(bsig['id'], bsig['goal'], bsig['operators'], 1, :main)
67
68
  if exec_status == :failure
68
69
  Sfp::Agent.logger.error "[main] Executing BSig model [Failed]"
@@ -92,13 +93,19 @@ class Sfp::BSig
92
93
  end
93
94
  end
94
95
 
95
- # returns
96
+ # @param id BSig's id
97
+ # @param goal goal state
98
+ # @param operators an array of sorted (by 'pi') operators
99
+ # @param pi current priority index value
100
+ # @param mode 'main' thread or 'satisfier' thread
101
+ #
102
+ # @return
96
103
  # :no_flaw => there is no goal-flaw
97
104
  # :failure => there is a failure on achieving the goal
98
105
  # :ongoing => the selected operator is being executed
99
106
  # :repaired => some goal-flaws have been repaired, but the goal may have other flaws
100
107
  #
101
- def achieve_local_goal(id, goal, operators, pi, mode)
108
+ def sequential_achieve_local_goal(id, goal, operators, pi, mode)
102
109
  operator = nil
103
110
 
104
111
  current = get_current_state
@@ -107,13 +114,61 @@ class Sfp::BSig
107
114
 
108
115
  operator = select_operator(flaws, operators, pi)
109
116
  return :failure if operator.nil?
117
+
118
+ execute_operator(operator, id, operators, mode)
119
+ end
110
120
 
111
- # debugging
112
- #Sfp::Agent.logger.info "[#{mode}] Flaws: #{JSON.generate(flaws)}"
121
+ # @param id BSig's id
122
+ # @param goal goal state
123
+ # @param operators an array of sorted (by 'pi') operators
124
+ # @param pi current priority index value
125
+ # @param mode 'main' thread or 'satisfier' thread
126
+ #
127
+ # @return
128
+ # :no_flaw => there is no goal-flaw
129
+ # :failure => there is a failure on achieving the goal
130
+ # :ongoing => the selected operator is being executed
131
+ # :repaired => some goal-flaws have been repaired, but the goal may have other flaws
132
+ #
133
+ def achieve_local_goal(id, goal, operators, pi, mode)
134
+ current = get_current_state
135
+ flaws = compute_flaws(goal, current)
136
+ return :no_flaw if flaws.length <= 0
137
+
138
+ operators = select_operators(flaws, operators, pi)
139
+ return :failure if operators == :failure
140
+
141
+ Sfp::Agent.logger.info "total operators: #{operators.length}"
142
+
143
+ total = operators.length
144
+ status = []
145
+ operators_lock = Mutex.new
146
+ operators.each do |operator|
147
+ Thread.new {
148
+ stat = execute_operator(operator, id, operators, mode)
149
+ Sfp::Agent.logger.info "#{operator['name']}{#{JSON.generate(operator['parameters'])}} => #{stat}"
150
+ operators_lock.synchronize { status << stat }
151
+ }
152
+ end
153
+ wait? { status.length >= operators.length }
154
+ Sfp::Agent.logger.info "exec status: #{status.inspect}"
155
+ status.each { |stat|
156
+ return :failure if stat == :failure
157
+ return :ongoing if stat == :ongoing
158
+ }
159
+ :repaired
160
+ end
113
161
 
162
+ def wait?
163
+ until yield do
164
+ sleep 1
165
+ end
166
+ end
167
+
168
+ def execute_operator(operator, id, operators, mode)
114
169
  return :ongoing if not lock_operator(operator)
115
170
 
116
- Sfp::Agent.logger.info "[#{mode}] Selected operator: #{operator['name']}"
171
+ Sfp::Agent.logger.info "[#{mode}] Selected operator: #{operator['id']}:#{operator['name']}{#{JSON.generate(operator['parameters'])}}"
117
172
 
118
173
  next_pi = operator['pi'] + 1
119
174
  pre_local, pre_remote = split_preconditions(operator)
@@ -151,16 +206,29 @@ class Sfp::BSig
151
206
  def achieve_remote_goal(id, goal, pi, mode)
152
207
  if goal.length > 0
153
208
  agents = Sfp::Agent.get_agents
154
- split_goal_by_agent(goal).each do |agent_name,agent_goal|
155
- if agents.has_key?(agent_name)
156
- return false if agents[agent_name]['sfpAddress'].to_s == ''
157
- return false if not send_goal_to_agent(agents[agent_name], id, agent_goal, pi, agent_name, mode)
158
- else
159
- return false if not verify_state_of_not_exist_agent(agent_name, agent_goal)
160
- end
209
+ status = []
210
+ lock = Mutex.new
211
+ agents_goal = split_goal_by_agent(goal)
212
+ agents_goal.each do |agent_name,agent_goal|
213
+ Thread.new {
214
+ stat = achieve_remote_agent_goal(agents, agent_name, agent_goal, id, pi, mode)
215
+ lock.synchronize { status << stat }
216
+ }
161
217
  end
218
+ wait? { status.length >= agents_goal.length }
219
+ Sfp::Agent.logger.info "achieve_remote_goal: #{status}"
220
+ status.each { |stat| return false if !stat }
162
221
  end
222
+ true
223
+ end
163
224
 
225
+ def achieve_remote_agent_goal(agents, name, goal, id, pi, mode)
226
+ if agents.has_key?(name)
227
+ return false if agents[name]['sfpAddress'].to_s == ''
228
+ return false if not send_goal_to_agent(agents[name], id, goal, pi, name, mode)
229
+ else
230
+ return false if not verify_state_of_not_exist_agent(name, goal)
231
+ end
164
232
  true
165
233
  end
166
234
 
@@ -180,6 +248,7 @@ class Sfp::BSig
180
248
  bsig = Sfp::Agent.get_bsig
181
249
  return false if bsig.nil? or id < bsig['id']
182
250
 
251
+ bsig['operators'].sort! { |op1,op2| op1['pi'] <=> op2['pi'] }
183
252
  status = nil
184
253
  tries = MaxTries
185
254
  begin
@@ -226,7 +295,7 @@ class Sfp::BSig
226
295
 
227
296
  def lock_operator(operator)
228
297
  @lock.synchronize {
229
- operator_lock_file = "#{CacheDir}/operator.#{operator['name']}.lock"
298
+ operator_lock_file = "#{CacheDir}/operator.#{operator['id']}.#{operator['name']}.lock"
230
299
  return false if File.exist?(operator_lock_file)
231
300
  File.open(operator_lock_file, 'w') { |f| f.write('1') }
232
301
  return true
@@ -235,7 +304,7 @@ class Sfp::BSig
235
304
 
236
305
  def unlock_operator(operator)
237
306
  @lock.synchronize {
238
- operator_lock_file = "#{CacheDir}/operator.#{operator['name']}.lock"
307
+ operator_lock_file = "#{CacheDir}/operator.#{operator['id']}.#{operator['name']}.lock"
239
308
  File.delete(operator_lock_file) if File.exist?(operator_lock_file)
240
309
  }
241
310
  end
@@ -327,20 +396,35 @@ class Sfp::BSig
327
396
  flaws
328
397
  end
329
398
 
330
- def select_operator(flaws, operators, pi)
331
- selected_operator = nil
332
- operators.each { |op|
399
+ # @param flaws a map of flaws (variable-value) that should be repaired
400
+ # @param operators a sorted-list of operators (sorted by 'pi')
401
+ # @param pi minimum priority-index value
402
+ #
403
+ # @return a list of applicable operators, or symbol :failure if all flaws
404
+ # cannot be repaired by available operators
405
+ #
406
+ def select_operators(flaws, operators, pi)
407
+ selected_operator = []
408
+ repaired = {}
409
+ operators.each do |op|
333
410
  next if op['pi'] < pi
334
411
  if can_repair?(op, flaws)
335
- if selected_operator.nil?
336
- selected_operator = op
337
- elsif selected_operator['pi'] > op['pi']
338
- selected_operator = op
339
- end
412
+ selected_operator << op
413
+ op['effect'].each { |var,val| repaired[var] = val if flaws[var] == val }
340
414
  end
341
- }
415
+ break if repaired.length >= flaws.length
416
+ end
417
+ return :failure if repaired.length < flaws.length
342
418
  selected_operator
343
419
  end
420
+
421
+ def select_operator(flaws, operators, pi)
422
+ operators.each do |op|
423
+ next if op['pi'] < pi
424
+ return op if can_repair?(op, flaws)
425
+ end
426
+ nil
427
+ end
344
428
 
345
429
  def can_repair?(operator, flaws)
346
430
  operator['effect'].each { |variable,value| return true if flaws[variable] == value }
@@ -365,7 +449,7 @@ class Sfp::BSig
365
449
  end
366
450
 
367
451
  def invoke(operator, mode)
368
- Sfp::Agent.logger.info "[#{mode}] Invoking #{operator['name']}"
452
+ Sfp::Agent.logger.info "[#{mode}] Invoking #{operator['name']}{#{operator['parameters']}}"
369
453
 
370
454
  begin
371
455
  status = Sfp::Agent.execute_action(operator)
@@ -377,7 +461,7 @@ class Sfp::BSig
377
461
  end
378
462
  end
379
463
  rescue Exception => e
380
- Sfp::Agent.logger.error "Error in invoking operator #{operator['name']}\n#{e}\n#{e.backtrace.join("\n")}"
464
+ Sfp::Agent.logger.error "Error in invoking operator #{operator['name']}{#{operator['parameters']}}\n#{e}\n#{e.backtrace.join("\n")}"
381
465
  return false
382
466
  end
383
467
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sfpagent
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.5
4
+ version: 0.2.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2013-08-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sfp
16
- requirement: &12203820 !ruby/object:Gem::Requirement
16
+ requirement: &15974100 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: 0.3.12
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *12203820
24
+ version_requirements: *15974100
25
25
  description: A Ruby implementation of SFP agent.
26
26
  email: herry13@gmail.com
27
27
  executables: