roby 0.7.3 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. data/History.txt +7 -5
  2. data/Manifest.txt +91 -16
  3. data/README.txt +24 -24
  4. data/Rakefile +92 -64
  5. data/app/config/app.yml +42 -43
  6. data/app/config/init.rb +26 -0
  7. data/benchmark/alloc_misc.rb +123 -0
  8. data/benchmark/discovery_latency.rb +67 -0
  9. data/benchmark/garbage_collection.rb +48 -0
  10. data/benchmark/genom.rb +31 -0
  11. data/benchmark/transactions.rb +62 -0
  12. data/bin/roby +1 -1
  13. data/bin/roby-log +16 -6
  14. data/doc/guide/.gitignore +2 -0
  15. data/doc/guide/config.yaml +34 -0
  16. data/doc/guide/ext/init.rb +14 -0
  17. data/doc/guide/ext/previous_next.rb +40 -0
  18. data/doc/guide/ext/rdoc_links.rb +33 -0
  19. data/doc/guide/index.rdoc +16 -0
  20. data/doc/guide/overview.rdoc +62 -0
  21. data/doc/guide/plan_modifications.rdoc +67 -0
  22. data/doc/guide/src/abstraction/achieve_with.page +8 -0
  23. data/doc/guide/src/abstraction/forwarding.page +8 -0
  24. data/doc/guide/src/abstraction/hierarchy.page +19 -0
  25. data/doc/guide/src/abstraction/index.page +28 -0
  26. data/doc/guide/src/abstraction/task_models.page +13 -0
  27. data/doc/guide/src/basics.template +6 -0
  28. data/doc/guide/src/basics/app.page +139 -0
  29. data/doc/guide/src/basics/code_examples.page +33 -0
  30. data/doc/guide/src/basics/dry.page +69 -0
  31. data/doc/guide/src/basics/errors.page +443 -0
  32. data/doc/guide/src/basics/events.page +179 -0
  33. data/doc/guide/src/basics/hierarchy.page +275 -0
  34. data/doc/guide/src/basics/index.page +11 -0
  35. data/doc/guide/src/basics/log_replay/goForward_1.png +0 -0
  36. data/doc/guide/src/basics/log_replay/goForward_2.png +0 -0
  37. data/doc/guide/src/basics/log_replay/goForward_3.png +0 -0
  38. data/doc/guide/src/basics/log_replay/goForward_4.png +0 -0
  39. data/doc/guide/src/basics/log_replay/goForward_5.png +0 -0
  40. data/doc/guide/src/basics/log_replay/hierarchy_error_1.png +0 -0
  41. data/doc/guide/src/basics/log_replay/hierarchy_error_2.png +0 -0
  42. data/doc/guide/src/basics/log_replay/hierarchy_error_3.png +0 -0
  43. data/doc/guide/src/basics/log_replay/plan_repair_1.png +0 -0
  44. data/doc/guide/src/basics/log_replay/plan_repair_2.png +0 -0
  45. data/doc/guide/src/basics/log_replay/plan_repair_3.png +0 -0
  46. data/doc/guide/src/basics/log_replay/plan_repair_4.png +0 -0
  47. data/doc/guide/src/basics/log_replay/roby_log_main_window.png +0 -0
  48. data/doc/guide/src/basics/log_replay/roby_log_relation_window.png +0 -0
  49. data/doc/guide/src/basics/log_replay/roby_replay_event_representation.png +0 -0
  50. data/doc/guide/src/basics/plan_objects.page +71 -0
  51. data/doc/guide/src/basics/relations_display.page +203 -0
  52. data/doc/guide/src/basics/roby_cycle_overview.png +0 -0
  53. data/doc/guide/src/basics/shell.page +102 -0
  54. data/doc/guide/src/basics/summary.page +32 -0
  55. data/doc/guide/src/basics/tasks.page +357 -0
  56. data/doc/guide/src/basics_shell_header.txt +16 -0
  57. data/doc/guide/src/cycle/cycle-overview.png +0 -0
  58. data/doc/guide/src/cycle/cycle-overview.svg +208 -0
  59. data/doc/guide/src/cycle/error_handling.page +168 -0
  60. data/doc/guide/src/cycle/error_instantaneous_repair.png +0 -0
  61. data/doc/guide/src/cycle/error_instantaneous_repair.svg +1224 -0
  62. data/doc/guide/src/cycle/garbage_collection.page +10 -0
  63. data/doc/guide/src/cycle/index.page +23 -0
  64. data/doc/guide/src/cycle/propagation.page +154 -0
  65. data/doc/guide/src/cycle/propagation_diamond.png +0 -0
  66. data/doc/guide/src/cycle/propagation_diamond.svg +1279 -0
  67. data/doc/guide/src/default.css +319 -0
  68. data/doc/guide/src/default.template +74 -0
  69. data/doc/guide/src/htmldoc.metainfo +20 -0
  70. data/doc/guide/src/htmldoc.virtual +18 -0
  71. data/doc/guide/src/images/bodybg.png +0 -0
  72. data/doc/guide/src/images/contbg.png +0 -0
  73. data/doc/guide/src/images/footerbg.png +0 -0
  74. data/doc/guide/src/images/gradient1.png +0 -0
  75. data/doc/guide/src/images/gradient2.png +0 -0
  76. data/doc/guide/src/index.page +7 -0
  77. data/doc/guide/src/introduction/index.page +29 -0
  78. data/doc/guide/src/introduction/install.page +133 -0
  79. data/doc/{papers.rdoc → guide/src/introduction/publications.page} +5 -2
  80. data/doc/{videos.rdoc → guide/src/introduction/videos.page} +4 -2
  81. data/doc/guide/src/plugins/fault_tolerance.page +44 -0
  82. data/doc/guide/src/plugins/index.page +11 -0
  83. data/doc/guide/src/plugins/subsystems.page +45 -0
  84. data/doc/guide/src/relations/dependency.page +89 -0
  85. data/doc/guide/src/relations/index.page +12 -0
  86. data/doc/misc/update_github +24 -0
  87. data/doc/tutorials/02-GoForward.rdoc +3 -3
  88. data/ext/graph/graph.cc +46 -0
  89. data/lib/roby.rb +57 -22
  90. data/lib/roby/app.rb +132 -112
  91. data/lib/roby/app/plugins/rake.rb +21 -0
  92. data/lib/roby/app/rake.rb +0 -7
  93. data/lib/roby/app/run.rb +1 -1
  94. data/lib/roby/app/scripts/distributed.rb +1 -2
  95. data/lib/roby/app/scripts/generate/bookmarks.rb +1 -1
  96. data/lib/roby/app/scripts/results.rb +2 -1
  97. data/lib/roby/app/scripts/run.rb +6 -2
  98. data/lib/roby/app/scripts/shell.rb +11 -11
  99. data/lib/roby/config.rb +1 -1
  100. data/lib/roby/decision_control.rb +62 -3
  101. data/lib/roby/distributed.rb +4 -0
  102. data/lib/roby/distributed/base.rb +8 -0
  103. data/lib/roby/distributed/communication.rb +12 -8
  104. data/lib/roby/distributed/connection_space.rb +61 -44
  105. data/lib/roby/distributed/distributed_object.rb +1 -1
  106. data/lib/roby/distributed/notifications.rb +22 -30
  107. data/lib/roby/distributed/peer.rb +13 -8
  108. data/lib/roby/distributed/proxy.rb +5 -5
  109. data/lib/roby/distributed/subscription.rb +4 -4
  110. data/lib/roby/distributed/transaction.rb +3 -3
  111. data/lib/roby/event.rb +176 -110
  112. data/lib/roby/exceptions.rb +12 -4
  113. data/lib/roby/execution_engine.rb +1604 -0
  114. data/lib/roby/external_process_task.rb +225 -0
  115. data/lib/roby/graph.rb +0 -6
  116. data/lib/roby/interface.rb +221 -137
  117. data/lib/roby/log/console.rb +5 -3
  118. data/lib/roby/log/data_stream.rb +94 -16
  119. data/lib/roby/log/dot.rb +8 -8
  120. data/lib/roby/log/event_stream.rb +13 -3
  121. data/lib/roby/log/file.rb +43 -18
  122. data/lib/roby/log/gui/basic_display_ui.rb +89 -0
  123. data/lib/roby/log/gui/chronicle_view_ui.rb +90 -0
  124. data/lib/roby/log/gui/data_displays.rb +4 -5
  125. data/lib/roby/log/gui/data_displays_ui.rb +146 -0
  126. data/lib/roby/log/gui/relations.rb +18 -18
  127. data/lib/roby/log/gui/relations_ui.rb +120 -0
  128. data/lib/roby/log/gui/relations_view_ui.rb +144 -0
  129. data/lib/roby/log/gui/replay.rb +41 -13
  130. data/lib/roby/log/gui/replay_controls.rb +3 -0
  131. data/lib/roby/log/gui/replay_controls.ui +133 -110
  132. data/lib/roby/log/gui/replay_controls_ui.rb +249 -0
  133. data/lib/roby/log/hooks.rb +19 -18
  134. data/lib/roby/log/logger.rb +7 -6
  135. data/lib/roby/log/notifications.rb +4 -4
  136. data/lib/roby/log/plan_rebuilder.rb +20 -22
  137. data/lib/roby/log/relations.rb +44 -16
  138. data/lib/roby/log/server.rb +1 -4
  139. data/lib/roby/log/timings.rb +88 -19
  140. data/lib/roby/plan-object.rb +135 -11
  141. data/lib/roby/plan.rb +408 -224
  142. data/lib/roby/planning/loops.rb +32 -25
  143. data/lib/roby/planning/model.rb +157 -51
  144. data/lib/roby/planning/task.rb +47 -20
  145. data/lib/roby/query.rb +128 -92
  146. data/lib/roby/relations.rb +254 -136
  147. data/lib/roby/relations/conflicts.rb +6 -9
  148. data/lib/roby/relations/dependency.rb +358 -0
  149. data/lib/roby/relations/ensured.rb +0 -1
  150. data/lib/roby/relations/error_handling.rb +0 -1
  151. data/lib/roby/relations/events.rb +0 -2
  152. data/lib/roby/relations/executed_by.rb +26 -11
  153. data/lib/roby/relations/planned_by.rb +14 -14
  154. data/lib/roby/robot.rb +46 -0
  155. data/lib/roby/schedulers/basic.rb +34 -0
  156. data/lib/roby/standalone.rb +4 -0
  157. data/lib/roby/standard_errors.rb +21 -15
  158. data/lib/roby/state/events.rb +5 -4
  159. data/lib/roby/support.rb +107 -6
  160. data/lib/roby/task-operations.rb +23 -19
  161. data/lib/roby/task.rb +522 -148
  162. data/lib/roby/task_index.rb +80 -0
  163. data/lib/roby/test/common.rb +283 -44
  164. data/lib/roby/test/distributed.rb +53 -37
  165. data/lib/roby/test/testcase.rb +9 -204
  166. data/lib/roby/test/tools.rb +3 -3
  167. data/lib/roby/transactions.rb +154 -111
  168. data/lib/roby/transactions/proxy.rb +40 -7
  169. data/manifest.xml +20 -0
  170. data/plugins/fault_injection/README.txt +0 -3
  171. data/plugins/fault_injection/Rakefile +2 -8
  172. data/plugins/fault_injection/app.rb +1 -1
  173. data/plugins/fault_injection/fault_injection.rb +3 -3
  174. data/plugins/fault_injection/test/test_fault_injection.rb +19 -25
  175. data/plugins/subsystems/README.txt +0 -3
  176. data/plugins/subsystems/Rakefile +2 -7
  177. data/plugins/subsystems/app.rb +27 -16
  178. data/plugins/subsystems/test/app/config/init.rb +3 -0
  179. data/plugins/subsystems/test/app/planners/main.rb +1 -1
  180. data/plugins/subsystems/test/app/tasks/services.rb +1 -1
  181. data/plugins/subsystems/test/test_subsystems.rb +23 -16
  182. data/test/distributed/test_communication.rb +32 -15
  183. data/test/distributed/test_connection.rb +28 -26
  184. data/test/distributed/test_execution.rb +59 -54
  185. data/test/distributed/test_mixed_plan.rb +34 -34
  186. data/test/distributed/test_plan_notifications.rb +26 -26
  187. data/test/distributed/test_protocol.rb +57 -48
  188. data/test/distributed/test_query.rb +11 -7
  189. data/test/distributed/test_remote_plan.rb +71 -71
  190. data/test/distributed/test_transaction.rb +50 -47
  191. data/test/mockups/external_process +28 -0
  192. data/test/planning/test_loops.rb +163 -119
  193. data/test/planning/test_model.rb +3 -3
  194. data/test/planning/test_task.rb +27 -7
  195. data/test/relations/test_conflicts.rb +3 -3
  196. data/test/relations/test_dependency.rb +324 -0
  197. data/test/relations/test_ensured.rb +2 -2
  198. data/test/relations/test_executed_by.rb +94 -19
  199. data/test/relations/test_planned_by.rb +11 -9
  200. data/test/suite_core.rb +6 -3
  201. data/test/suite_distributed.rb +1 -0
  202. data/test/suite_planning.rb +1 -0
  203. data/test/suite_relations.rb +2 -2
  204. data/test/tasks/test_external_process.rb +126 -0
  205. data/test/{test_thread_task.rb → tasks/test_thread_task.rb} +17 -20
  206. data/test/test_bgl.rb +21 -1
  207. data/test/test_event.rb +229 -155
  208. data/test/test_exceptions.rb +79 -80
  209. data/test/test_execution_engine.rb +987 -0
  210. data/test/test_gui.rb +1 -1
  211. data/test/test_interface.rb +11 -5
  212. data/test/test_log.rb +18 -7
  213. data/test/test_log_server.rb +1 -0
  214. data/test/test_plan.rb +229 -395
  215. data/test/test_query.rb +193 -35
  216. data/test/test_relations.rb +88 -8
  217. data/test/test_state.rb +55 -37
  218. data/test/test_support.rb +1 -1
  219. data/test/test_task.rb +371 -218
  220. data/test/test_testcase.rb +32 -16
  221. data/test/test_transactions.rb +211 -170
  222. data/test/test_transactions_proxy.rb +37 -19
  223. metadata +169 -71
  224. data/.gitignore +0 -29
  225. data/doc/styles/allison.css +0 -314
  226. data/doc/styles/allison.js +0 -316
  227. data/doc/styles/allison.rb +0 -276
  228. data/doc/styles/jamis.rb +0 -593
  229. data/lib/roby/control.rb +0 -746
  230. data/lib/roby/executives/simple.rb +0 -30
  231. data/lib/roby/propagation.rb +0 -562
  232. data/lib/roby/relations/hierarchy.rb +0 -239
  233. data/lib/roby/transactions/updates.rb +0 -139
  234. data/test/relations/test_hierarchy.rb +0 -158
  235. data/test/test_control.rb +0 -399
  236. data/test/test_propagation.rb +0 -210
@@ -0,0 +1,21 @@
1
+ require 'roby/app/rake'
2
+
3
+ module Roby
4
+ module Rake
5
+ ROBY_ROOT_DIR = ENV['ROBY_ROOT_DIR']
6
+
7
+ def self.plugin_doc(name)
8
+ require 'rdoc/task'
9
+
10
+ RDoc::Task.new("docs") do |rdoc|
11
+ rdoc.rdoc_dir = "#{ROBY_ROOT_DIR}/doc/html/plugins/#{name}"
12
+
13
+ yield(rdoc)
14
+ end
15
+ rescue LoadError => e
16
+ STDERR.puts "cannot generate documentation for #{name}:"
17
+ STDERR.puts " #{e.message}"
18
+ end
19
+ end
20
+ end
21
+
@@ -1,12 +1,7 @@
1
- require 'roby/support'
2
-
3
1
  module Roby
4
2
  # This module contains some tools used in the Rakefile of both Roby core
5
3
  # and plugins
6
4
  module Rake
7
- extend Logger::Hierarchy
8
- extend Logger::Forward
9
-
10
5
  # Returns the rdoc template path the documentation
11
6
  # generation should be using in Rakefile
12
7
  #
@@ -27,8 +22,6 @@ module Roby
27
22
  Roby::Rake.info "using the #{ENV['ROBY_RDOC_TEMPLATE']} template"
28
23
  ENV['ROBY_RDOC_TEMPLATE']
29
24
  end
30
- else
31
- File.expand_path('doc/styles/jamis', ROBY_ROOT_DIR)
32
25
  end
33
26
  end
34
27
 
@@ -1,4 +1,4 @@
1
- require 'roby/app'
1
+ require 'roby'
2
2
 
3
3
  app = Roby.app
4
4
  require 'optparse'
@@ -1,5 +1,4 @@
1
- require 'roby/distributed/connection_space'
2
- require 'roby/distributed/protocol'
1
+ require 'roby/distributed'
3
2
 
4
3
  config = Roby.app
5
4
  config.setup
@@ -33,7 +33,7 @@ class Roby::Log::EventMatcher
33
33
  end
34
34
 
35
35
  def event(m, sec, usec, args)
36
- if m == :discovered_tasks || m == :discovered_events
36
+ if m == :added_tasks || m == :added_events
37
37
  objects = args[1]
38
38
  for object in objects
39
39
  for remote_id in object.remote_siblings.values
@@ -1,4 +1,5 @@
1
1
  require 'roby'
2
+ require 'fileutils'
2
3
  Roby.app.setup
3
4
  app = Roby.app
4
5
 
@@ -8,7 +9,7 @@ if Dir.enum_for(:glob, File.join(app.log_dir, "*")).to_a.empty?
8
9
  exit 0
9
10
  end
10
11
 
11
- user_path = ARGV.shift
12
+ user_path = ARGV.shift || ''
12
13
  final_path = Roby::Application.unique_dirname(Roby.app.results_dir, user_path)
13
14
  puts "moving #{app.log_dir} to #{final_path}"
14
15
  FileUtils.mv app.log_dir, final_path
@@ -6,9 +6,13 @@ app.robot robot_name, (ARGV.shift || robot_name)
6
6
  app.setup
7
7
  begin
8
8
  app.run do
9
- Robot.info "loaded Roby #{Roby::VERSION}"
9
+ if defined? RUBY_DESCRIPTION
10
+ Robot.info "loaded Roby #{Roby::VERSION} on #{RUBY_DESCRIPTION}"
11
+ else
12
+ Robot.info "loaded Roby #{Roby::VERSION}"
13
+ end
14
+
10
15
  # Load the controller
11
- include Roby
12
16
  Roby.execute do
13
17
  begin
14
18
  controller_file = File.join(APP_DIR, "controllers", "#{app.robot_name}.rb")
@@ -1,7 +1,5 @@
1
1
  require 'roby'
2
- require 'roby/app'
3
2
  require 'roby/distributed'
4
- require 'roby/distributed/protocol'
5
3
  require 'optparse'
6
4
 
7
5
  require 'pp'
@@ -35,11 +33,14 @@ end
35
33
  DRb.start_service
36
34
 
37
35
  require 'irb'
36
+ require 'irb/ext/save-history'
38
37
  IRB.setup(remote_url)
39
38
  IRB.conf[:INSPECT_MODE] = false
40
39
  IRB.conf[:IRB_NAME] = remote_url
41
40
  IRB.conf[:PROMPT_MODE] = :ROBY
42
41
  IRB.conf[:AUTO_INDENT] = true
42
+ IRB.conf[:HISTORY_FILE] = File.join(APP_DIR, 'config', 'shell_history')
43
+ IRB.conf[:SAVE_HISTORY] = 1000
43
44
  IRB.conf[:PROMPT][:ROBY] = {
44
45
  :PROMPT_I => "%N > ",
45
46
  :PROMPT_N => "%N > ",
@@ -48,7 +49,12 @@ IRB.conf[:PROMPT][:ROBY] = {
48
49
  :RETURN => "=> %s\n"
49
50
  }
50
51
 
51
- control = Roby::RemoteInterface.new(DRbObject.new_with_uri("druby://#{remote_url}"))
52
+ control = begin
53
+ Roby::RemoteInterface.new(DRbObject.new_with_uri("druby://#{remote_url}"))
54
+ rescue DRb::DRbConnError
55
+ STDERR.puts "cannot connect to a Roby controller at #{remote_url}, is the controller started ?"
56
+ exit(1)
57
+ end
52
58
 
53
59
  begin
54
60
  # Make control the top-level object
@@ -57,11 +63,7 @@ begin
57
63
  irb = IRB::Irb.new(ws)
58
64
 
59
65
  context = irb.context
60
- def context.evaluate(*args, &block)
61
- Roby.execute do
62
- super
63
- end
64
- end
66
+ context.save_history = 100
65
67
  IRB.conf[:MAIN_CONTEXT] = irb.context
66
68
 
67
69
  trap("SIGINT") do
@@ -87,10 +89,8 @@ begin
87
89
  end
88
90
  end
89
91
  end
90
- rescue
92
+ rescue Exception => e
91
93
  STDERR.puts $!.full_message
92
- ensure
93
- STDERR.puts "message polling died"
94
94
  end
95
95
  end
96
96
 
@@ -8,7 +8,7 @@ try it on 1.9, checkout the 1.9 branch of the development repository on github
8
8
  end
9
9
 
10
10
  module Roby
11
- VERSION = '0.7.3'
11
+ VERSION = '0.8.0'
12
12
  ROBY_LIB_DIR = File.expand_path( File.join(File.dirname(__FILE__), '..') )
13
13
  ROBY_ROOT_DIR = File.expand_path( File.join(ROBY_LIB_DIR, '..') )
14
14
  end
@@ -1,17 +1,76 @@
1
1
  module Roby
2
2
  class DecisionControl
3
+ # Called when there is a conflict between a set of running tasks and a
4
+ # task that should have been started. The default operation is to
5
+ # postpone starting the task until all the conflicting tasks are
6
+ # finished
3
7
  def conflict(starting_task, running_tasks)
4
8
  for t in running_tasks
5
9
  starting_task.event(:start).postpone t.event(:stop)
6
10
  return
7
11
  end
8
12
  end
13
+
14
+ # Called when a transaction/execution conflict occured, where a task
15
+ # included in the transaction has been removed from the plan.
16
+ #
17
+ # +proxy+ is the transaction's representation of the task which has
18
+ # been removed and +transaction+ the transaction. The transaction has
19
+ # been invalidated prior to this call, and the task proxy has been
20
+ # removed from +transaction+.
21
+ #
22
+ # The default action is to do nothing
23
+ def finalized_plan_task(transaction, proxy)
24
+ end
25
+
26
+ # Called when a transaction/execution conflict occured, where a task
27
+ # included in the transaction has been removed from the plan.
28
+ #
29
+ # +proxy+ is the transaction representation of the event which has been
30
+ # removed and +transaction+ the transaction. The transaction has been
31
+ # invalidated prior to this call, and the event proxy has been removed
32
+ # from +transaction+.
33
+ #
34
+ # The default action is to do nothing
35
+ def finalized_plan_event(transaction, proxy)
36
+ end
37
+
38
+ # Called when a transaction/execution conflict occured, where relations
39
+ # have been added in the plan and are not present in the transaction.
40
+ #
41
+ # The new relations are of types +relations+, between +parent+ and
42
+ # +child+ and with +info+ as info object. The transaction has been
43
+ # invalidated prior to this call
44
+ #
45
+ # The default action is to do nothing
46
+ def adding_plan_relation(transaction, parent, child, relations, info)
47
+ end
48
+
49
+ # Called when a transaction/execution conflict occured, where relations
50
+ # have been removed from the plan, which were present in the
51
+ # transaction.
52
+ #
53
+ # The relations are of types +relations+, between +parent+ and +child+
54
+ # and with +info+ as info object. The transaction has been invalidated
55
+ # prior to this call
56
+ #
57
+ # The default action is to do nothing
58
+ def removing_plan_relation(transaction, parent, child, relations)
59
+ end
9
60
  end
10
61
 
11
62
  class << self
12
- attr_reader :decision_control
13
- end
63
+ attr_reader :control
14
64
 
15
- @decision_control = DecisionControl.new
65
+ def control=(new)
66
+ if control
67
+ raise ArgumentError, "cannot change the decision control object"
68
+ elsif engine && new != engine.control
69
+ raise ArgumentError, "must have Roby.control == Roby.engine.control"
70
+ end
71
+
72
+ @control = new
73
+ end
74
+ end
16
75
  end
17
76
 
@@ -1,6 +1,10 @@
1
1
  require 'roby'
2
+ require 'stringio'
3
+ require 'roby/planning'
4
+ require 'roby_marshalling'
2
5
  require 'roby/distributed/drb'
3
6
  require 'roby/distributed/protocol'
7
+ require 'roby/distributed/base'
4
8
 
5
9
  require 'roby/distributed/proxy'
6
10
  require 'roby/distributed/connection_space'
@@ -198,6 +198,14 @@ module Roby
198
198
  logger.progname = "Roby"
199
199
  end
200
200
  end
201
+
202
+ if !Roby.plan
203
+ Roby.instance_variable_set :@plan, new_state.plan
204
+ Roby.instance_variable_set :@engine, new_state.plan.engine
205
+ elsif new_state && Roby.plan != new_state.plan
206
+ raise ArgumentError, "plan mismatch between Roby.plan(#{plan}) and new_state.plan(#{new_state.plan}). Cannot set Distributed.state"
207
+ end
208
+
201
209
  @state = new_state
202
210
  end
203
211
 
@@ -46,11 +46,11 @@ module Roby
46
46
 
47
47
  # Connect to +neighbour+ and return the corresponding peer. It is a
48
48
  # blocking method, so it is an error to call it from within the control thread
49
- def self.connect(neighbour)
49
+ def self.connect(neighbour, connection_space = Distributed.state)
50
50
  Roby.condition_variable(true) do |cv, mutex|
51
51
  peer = nil
52
52
  mutex.synchronize do
53
- thread = initiate_connection(Distributed.state, neighbour) do |peer|
53
+ thread = initiate_connection(connection_space, neighbour) do |peer|
54
54
  return peer unless thread
55
55
  end
56
56
 
@@ -339,7 +339,7 @@ module Roby
339
339
  socket.close unless socket.closed?
340
340
  end
341
341
 
342
- Roby.once do
342
+ engine.once do
343
343
  task.emit(event)
344
344
  end
345
345
  end
@@ -560,7 +560,7 @@ module Roby
560
560
  return yield
561
561
  end
562
562
 
563
- Roby.execute do
563
+ peer.engine.execute do
564
564
  error = nil
565
565
  begin
566
566
  result = yield
@@ -598,7 +598,7 @@ module Roby
598
598
  def check_marshallable(object, stack = ValueSet.new)
599
599
  if !object.kind_of?(DRbObject) && object.respond_to?(:each) && !object.kind_of?(String)
600
600
  if stack.include?(object)
601
- Roby.warn "recursive marshalling of #{obj}"
601
+ Roby::Distributed.warn "recursive marshalling of #{obj}"
602
602
  raise "recursive marshalling"
603
603
  end
604
604
 
@@ -703,6 +703,7 @@ module Roby
703
703
  Distributed.debug { "#{call_spec.is_callback ? 'adding callback' : 'queueing'} [#{call_spec.message_id}]#{remote_name}.#{call_spec.method}" }
704
704
  current_cycle << [call_spec.is_callback, call_spec.method, call_spec.formatted_args, !waiting_thread, call_spec.message_id]
705
705
  if sync? || CYCLE_END_CALLS.include?(m)
706
+ Distributed.debug "transmitting #{@current_cycle.size} calls"
706
707
  send_queue << current_cycle
707
708
  @current_cycle = Array.new
708
709
  end
@@ -728,7 +729,7 @@ module Roby
728
729
  # called in the communication thread when the call succeeds, with
729
730
  # the returned value as argument.
730
731
  def transmit(m, *args, &block)
731
- is_callback = Roby.inside_control? && local_server.processing?
732
+ is_callback = engine.inside_control? && local_server.processing?
732
733
  if is_callback && local_server.processing_callback?
733
734
  raise RecursiveCallbacksError, "cannot queue callback #{m}(#{args.join(", ")}) while serving one"
734
735
  end
@@ -748,8 +749,8 @@ module Roby
748
749
  # Note that it is forbidden to use this method in control or
749
750
  # communication threads, as it would make the application deadlock
750
751
  def call(m, *args, &block)
751
- if !Roby.outside_control? || Roby::Control.taken_mutex?
752
- raise "cannot use Peer#call in control thread or while taking the Roby::Control mutex"
752
+ if !engine.outside_control? || Roby.taken_global_lock?
753
+ raise "cannot use Peer#call in control thread or while taking the Roby global lock"
753
754
  end
754
755
 
755
756
  result = nil
@@ -782,6 +783,8 @@ module Roby
782
783
  data = nil
783
784
  buffer = StringIO.new(" " * 8, 'w')
784
785
 
786
+ Roby::Distributed.debug "starting communication loop to #{self}"
787
+
785
788
  loop do
786
789
  data ||= send_queue.shift
787
790
  return if disconnected?
@@ -789,6 +792,7 @@ module Roby
789
792
  # Wait for the link to be alive before sending anything
790
793
  while !link_alive?
791
794
  return if disconnected?
795
+ Roby::Distributed.info "#{self} is out of reach. Waiting before transmitting"
792
796
  connection_space.wait_next_discovery
793
797
  end
794
798
  return if disconnected?
@@ -69,7 +69,7 @@ module Roby
69
69
  #
70
70
  # This makes Roby::Distributed behave like a Peer object
71
71
  def self.transmit(*args)
72
- Roby::Control.once do
72
+ Roby.once do
73
73
  result = Distributed.state.send(*args)
74
74
  yield(result) if block_given?
75
75
  end
@@ -140,6 +140,8 @@ module Roby
140
140
  def synchronize; mutex.synchronize { yield } end
141
141
  # The plan we are publishing, usually Roby.plan
142
142
  attr_reader :plan
143
+ # The execution engine tied to +plan+, or nil if there is none
144
+ def engine; plan.engine end
143
145
 
144
146
  # Our name on the network
145
147
  attr_reader :name
@@ -190,6 +192,7 @@ module Roby
190
192
  @start_discovery = ConditionVariable.new
191
193
  @finished_discovery = ConditionVariable.new
192
194
  @new_neighbours = Queue.new
195
+ @new_neighbours_observers = Array.new
193
196
 
194
197
  @connection_listeners = Array.new
195
198
 
@@ -222,9 +225,21 @@ module Roby
222
225
  end
223
226
  start_neighbour_discovery(true)
224
227
 
225
- receive
226
-
227
- Roby::Control.finalizers << method(:quit)
228
+ @discovery_start_handler = engine.add_propagation_handler do |plan|
229
+ start_neighbour_discovery
230
+ notify_new_neighbours
231
+ end
232
+ engine.finalizers << method(:quit)
233
+ engine.at_cycle_end do
234
+ peers.each_value do |peer|
235
+ if peer.connected?
236
+ peer.transmit(:state_update, Roby::State)
237
+ end
238
+ end
239
+ end
240
+
241
+ # Finally, start the reception thread
242
+ receive
228
243
  end
229
244
 
230
245
  # Sets up a separate thread which listens for connection
@@ -357,7 +372,7 @@ module Roby
357
372
  loop do
358
373
  return if @quit_neighbour_thread
359
374
 
360
- Control.synchronize do
375
+ Roby.synchronize do
361
376
  old_neighbours, @neighbours = @neighbours, []
362
377
  for new in discovered
363
378
  unless new.remote_id == remote_id || @neighbours.include?(new)
@@ -380,13 +395,12 @@ module Roby
380
395
  end
381
396
  return if @quit_neighbour_thread
382
397
  discovery_start = @discovery_start
383
-
384
- if ring_discovery? && (!finger || (finger.port != discovery_port))
385
- finger = Rinda::RingFinger.new(ring_broadcast, discovery_port)
386
- end
387
398
  end
388
399
 
389
400
  from = Time.now
401
+ if ring_discovery? && (!finger || (finger.port != discovery_port))
402
+ finger = Rinda::RingFinger.new(ring_broadcast, discovery_port)
403
+ end
390
404
  if central_discovery?
391
405
  discovery_tuplespace.read_all([:droby, nil, nil]).
392
406
  each do |n|
@@ -396,11 +410,11 @@ module Roby
396
410
  end
397
411
  end
398
412
 
399
- if discovery_period
400
- remaining = (@discovery_start + discovery_period) - Time.now
401
- end
402
-
403
413
  if ring_discovery?
414
+ if discovery_period
415
+ remaining = (@discovery_start + discovery_period) - Time.now
416
+ end
417
+
404
418
  finger.lookup_ring(remaining) do |cs|
405
419
  next if cs == self
406
420
 
@@ -422,7 +436,7 @@ module Roby
422
436
  # Force disconnection in case something got wrong in the normal
423
437
  # disconnection process
424
438
  Distributed.peers.values.each do |peer|
425
- peer.disconnected unless peer.disconnected?
439
+ peer.disconnected! unless peer.disconnected?
426
440
  end
427
441
 
428
442
  synchronize do
@@ -439,7 +453,7 @@ module Roby
439
453
  end
440
454
 
441
455
  @discovery_start = Time.now
442
- start_discovery.signal
456
+ start_discovery.broadcast
443
457
  end
444
458
  wait_discovery if block
445
459
  end
@@ -464,6 +478,9 @@ module Roby
464
478
  # Make the ConnectionSpace quit
465
479
  def quit
466
480
  Distributed.debug "ConnectionSpace #{self} quitting"
481
+ if @discovery_start_handler
482
+ engine.remove_propagation_handler(@discovery_start_handler)
483
+ end
467
484
 
468
485
  # Remove us from the central tuplespace
469
486
  if central_discovery?
@@ -492,7 +509,7 @@ module Roby
492
509
  end
493
510
  end
494
511
 
495
- Roby::Control.finalizers.delete(method(:quit))
512
+ plan.engine.finalizers.delete(method(:quit))
496
513
  if Distributed.state == self
497
514
  Distributed.state = nil
498
515
  end
@@ -517,6 +534,30 @@ module Roby
517
534
  def transaction_discard(trsc) # :nodoc:
518
535
  trsc.discard_transaction(false)
519
536
  end
537
+
538
+ def on_neighbour
539
+ current = neighbours.dup
540
+ engine.once { current.each { |n| yield(n) } }
541
+ new_neighbours_observers << lambda { |_, n| yield(n) }
542
+ end
543
+
544
+ # The set of proc objects which should be notified when new
545
+ # neighbours are detected.
546
+ attr_reader :new_neighbours_observers
547
+
548
+ # Called in the neighbour discovery thread to detect new
549
+ # neighbours. It fills the new_neighbours queue which is read by
550
+ # notify_new_neighbours to notify application code of new
551
+ # neighbours in the control thread
552
+ def notify_new_neighbours
553
+ while !new_neighbours.empty?
554
+ cs, neighbour = new_neighbours.pop(true)
555
+ new_neighbours_observers.each do |obs|
556
+ obs[cs, neighbour]
557
+ end
558
+ end
559
+ end
560
+
520
561
  end
521
562
 
522
563
  class << self
@@ -563,37 +604,13 @@ module Roby
563
604
  else []
564
605
  end
565
606
  end
566
- end
567
-
568
- @new_neighbours_observers = Array.new
569
- class << self
570
- # The set of proc objects which should be notified when new
571
- # neighbours are detected.
572
- attr_reader :new_neighbours_observers
573
-
574
- # Called in the neighbour discovery thread to detect new
575
- # neighbours. It fills the new_neighbours queue which is read by
576
- # notify_new_neighbours to notify application code of new
577
- # neighbours in the control thread
578
- def notify_new_neighbours
579
- return unless Distributed.state
580
- while !new_neighbours.empty?
581
- cs, neighbour = new_neighbours.pop(true)
582
- new_neighbours_observers.each do |obs|
583
- obs[cs, neighbour]
584
- end
585
- end
586
- end
587
-
607
+
588
608
  # Defines a block which should be called when a new neighbour is
589
609
  # detected
590
- def on_neighbour
591
- current = neighbours.dup
592
- Roby::Control.once { current.each { |n| yield(n) } }
593
- new_neighbours_observers << lambda { |_, n| yield(n) }
594
- end
610
+ #
611
+ # See ConnectionSpace#on_neighbour
612
+ def on_neighbour(&block); Roby::Distributed.state.on_neighbour(&block) end
595
613
  end
596
- Roby::Control.event_processing << method(:notify_new_neighbours)
597
614
  end
598
615
  end
599
616