roby 0.8.0 → 3.0.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 (644) hide show
  1. checksums.yaml +7 -0
  2. data/.deep-cover.rb +3 -0
  3. data/.gitattributes +1 -0
  4. data/.gitignore +24 -0
  5. data/.simplecov +10 -0
  6. data/.travis.yml +17 -0
  7. data/.yardopts +4 -0
  8. data/Gemfile +15 -0
  9. data/README.md +11 -0
  10. data/Rakefile +47 -177
  11. data/benchmark/{alloc_misc.rb → attic/alloc_misc.rb} +2 -2
  12. data/benchmark/{discovery_latency.rb → attic/discovery_latency.rb} +19 -19
  13. data/benchmark/{garbage_collection.rb → attic/garbage_collection.rb} +9 -9
  14. data/benchmark/{genom.rb → attic/genom.rb} +0 -0
  15. data/benchmark/attic/transactions.rb +62 -0
  16. data/benchmark/plan_basic_operations.rb +28 -0
  17. data/benchmark/relations/graph.rb +63 -0
  18. data/benchmark/ruby/identity.rb +18 -0
  19. data/benchmark/ruby/set_intersect_vs_hash_merge.rb +39 -0
  20. data/benchmark/ruby/yield_vs_block.rb +35 -0
  21. data/benchmark/run +5 -0
  22. data/benchmark/synthetic_plan_modifications_with_transactions.rb +79 -0
  23. data/benchmark/transactions.rb +99 -51
  24. data/bin/roby +38 -197
  25. data/bin/roby-display +14 -0
  26. data/bin/roby-log +3 -176
  27. data/doc/guide/{src → attic}/abstraction/achieve_with.page +1 -1
  28. data/doc/guide/{src → attic}/abstraction/forwarding.page +1 -1
  29. data/doc/guide/{src → attic}/abstraction/hierarchy.page +1 -1
  30. data/doc/guide/{src → attic}/abstraction/index.page +1 -1
  31. data/doc/guide/{src → attic}/abstraction/task_models.page +1 -1
  32. data/doc/guide/{overview.rdoc → attic/cycle/api_overview.rdoc} +6 -1
  33. data/doc/guide/{src → attic}/cycle/cycle-overview.png +0 -0
  34. data/doc/guide/{src → attic}/cycle/cycle-overview.svg +0 -0
  35. data/doc/guide/attic/cycle/error_handling.page +98 -0
  36. data/doc/guide/{src → attic}/cycle/error_instantaneous_repair.png +0 -0
  37. data/doc/guide/{src → attic}/cycle/error_instantaneous_repair.svg +0 -0
  38. data/doc/guide/{src/cycle/error_handling.page → attic/cycle/error_sources.page} +46 -89
  39. data/doc/guide/{src → attic}/cycle/garbage_collection.page +1 -1
  40. data/doc/guide/{src → attic}/cycle/index.page +1 -1
  41. data/doc/guide/{src → attic}/cycle/propagation.page +11 -1
  42. data/doc/guide/{src → attic}/cycle/propagation_diamond.png +0 -0
  43. data/doc/guide/{src → attic}/cycle/propagation_diamond.svg +0 -0
  44. data/doc/guide/attic/plans/building_plans.page +89 -0
  45. data/doc/guide/attic/plans/code.page +192 -0
  46. data/doc/guide/{src/basics → attic/plans}/events.page +3 -4
  47. data/doc/guide/attic/plans/index.page +7 -0
  48. data/doc/guide/{plan_modifications.rdoc → attic/plans/plan_modifications.rdoc} +5 -3
  49. data/doc/guide/{src/basics → attic/plans}/plan_objects.page +2 -1
  50. data/doc/guide/attic/plans/querying_plans.page +5 -0
  51. data/doc/guide/{src/basics → attic/plans}/tasks.page +20 -20
  52. data/doc/guide/config.yaml +7 -4
  53. data/doc/guide/ext/extended_menu.rb +29 -0
  54. data/doc/guide/ext/init.rb +6 -0
  55. data/doc/guide/ext/rdoc_links.rb +7 -6
  56. data/doc/guide/src/advanced_concepts/history.page +5 -0
  57. data/doc/guide/src/advanced_concepts/index.page +11 -0
  58. data/doc/guide/src/advanced_concepts/recognizing_patterns.page +83 -0
  59. data/doc/guide/src/advanced_concepts/scheduling.page +87 -0
  60. data/doc/guide/src/advanced_concepts/transactions.page +5 -0
  61. data/doc/guide/src/advanced_concepts/unreachability.page +42 -0
  62. data/doc/guide/src/base.template +96 -0
  63. data/doc/guide/src/basics_shell_header.txt +5 -7
  64. data/doc/guide/src/building/action_coordination.page +96 -0
  65. data/doc/guide/src/building/actions.page +124 -0
  66. data/doc/guide/src/building/file_layout.page +71 -0
  67. data/doc/guide/src/building/index.page +50 -0
  68. data/doc/guide/src/building/patterns.page +86 -0
  69. data/doc/guide/src/building/patterns_forwarding.png +0 -0
  70. data/doc/guide/src/building/patterns_forwarding.svg +277 -0
  71. data/doc/guide/src/building/runtime.page +95 -0
  72. data/doc/guide/src/building/task_models.page +94 -0
  73. data/doc/guide/src/building/tasks.page +284 -0
  74. data/doc/guide/src/concepts/error_handling.page +100 -0
  75. data/doc/guide/src/concepts/exception_propagation.png +0 -0
  76. data/doc/guide/src/concepts/exception_propagation.svg +445 -0
  77. data/doc/guide/src/concepts/execution.page +85 -0
  78. data/doc/guide/src/concepts/execution.png +0 -0
  79. data/doc/guide/src/concepts/execution.svg +573 -0
  80. data/doc/guide/src/concepts/execution_cycle.png +0 -0
  81. data/doc/guide/src/concepts/garbage_collection.page +57 -0
  82. data/doc/guide/src/concepts/index.page +27 -0
  83. data/doc/guide/src/concepts/plans.page +101 -0
  84. data/doc/guide/src/concepts/policy.page +31 -0
  85. data/doc/guide/src/concepts/reactor.page +61 -0
  86. data/doc/guide/src/concepts/simple_plan_example.png +0 -0
  87. data/doc/guide/src/concepts/simple_plan_example.svg +376 -0
  88. data/doc/guide/src/default.template +9 -74
  89. data/doc/guide/src/event_relations/forward.page +71 -0
  90. data/doc/guide/src/event_relations/index.page +12 -0
  91. data/doc/guide/src/event_relations/scheduling_constraints.page +43 -0
  92. data/doc/guide/src/event_relations/signal.page +55 -0
  93. data/doc/guide/src/event_relations/temporal_constraints.page +77 -0
  94. data/doc/guide/src/htmldoc.metainfo +21 -8
  95. data/doc/guide/src/index.page +8 -3
  96. data/doc/guide/src/{introduction/install.page → installation/index.page} +37 -25
  97. data/doc/guide/src/installation/publications.page +14 -0
  98. data/doc/guide/src/{introduction → installation}/videos.page +14 -7
  99. data/doc/guide/src/interacting/index.page +16 -0
  100. data/doc/guide/src/interacting/run.page +33 -0
  101. data/doc/guide/src/interacting/shell.page +95 -0
  102. data/doc/guide/src/plugins/creating_plugins.page +72 -0
  103. data/doc/guide/src/plugins/index.page +27 -5
  104. data/doc/guide/src/plugins/{fault_tolerance.page → standard_plugins/fault_tolerance.page} +2 -2
  105. data/doc/guide/src/plugins/standard_plugins/index.page +11 -0
  106. data/doc/guide/src/plugins/{subsystems.page → standard_plugins/subsystems.page} +2 -2
  107. data/doc/guide/src/style_screen.css +687 -0
  108. data/doc/guide/src/task_relations/dependency.page +107 -0
  109. data/doc/guide/src/task_relations/executed_by.page +77 -0
  110. data/doc/guide/src/task_relations/index.page +12 -0
  111. data/doc/guide/src/task_relations/new_relations.page +119 -0
  112. data/doc/guide/src/task_relations/planned_by.page +46 -0
  113. data/doc/guide/src/tutorial/app.page +117 -0
  114. data/doc/guide/src/{basics → tutorial}/code_examples.page +6 -5
  115. data/doc/guide/src/{basics → tutorial}/dry.page +15 -15
  116. data/doc/guide/src/{basics → tutorial}/errors.page +43 -68
  117. data/doc/guide/src/tutorial/events.page +195 -0
  118. data/doc/guide/src/{basics → tutorial}/hierarchy.page +53 -52
  119. data/doc/guide/src/tutorial/index.page +13 -0
  120. data/doc/guide/src/tutorial/log_replay/goForward_1.png +0 -0
  121. data/doc/guide/src/tutorial/log_replay/goForward_2.png +0 -0
  122. data/doc/guide/src/tutorial/log_replay/goForward_3.png +0 -0
  123. data/doc/guide/src/{basics → tutorial}/log_replay/goForward_4.png +0 -0
  124. data/doc/guide/src/tutorial/log_replay/goForward_5.png +0 -0
  125. data/doc/guide/src/{basics → tutorial}/log_replay/hierarchy_error_1.png +0 -0
  126. data/doc/guide/src/{basics → tutorial}/log_replay/hierarchy_error_2.png +0 -0
  127. data/doc/guide/src/{basics → tutorial}/log_replay/hierarchy_error_3.png +0 -0
  128. data/doc/guide/src/tutorial/log_replay/moveto_code_error.png +0 -0
  129. data/doc/guide/src/{basics → tutorial}/log_replay/plan_repair_1.png +0 -0
  130. data/doc/guide/src/{basics → tutorial}/log_replay/plan_repair_2.png +0 -0
  131. data/doc/guide/src/{basics → tutorial}/log_replay/plan_repair_3.png +0 -0
  132. data/doc/guide/src/tutorial/log_replay/plan_repair_4.png +0 -0
  133. data/doc/guide/src/tutorial/log_replay/roby_log_main_window.png +0 -0
  134. data/doc/guide/src/{basics → tutorial}/log_replay/roby_log_relation_window.png +0 -0
  135. data/doc/guide/src/{basics → tutorial}/log_replay/roby_replay_event_representation.png +0 -0
  136. data/doc/guide/src/tutorial/relations_display.page +153 -0
  137. data/doc/guide/src/{basics → tutorial}/roby_cycle_overview.png +0 -0
  138. data/doc/guide/src/tutorial/shell.page +121 -0
  139. data/doc/guide/src/{basics → tutorial}/summary.page +1 -1
  140. data/doc/guide/src/tutorial/tasks.page +374 -0
  141. data/lib/roby.rb +102 -47
  142. data/lib/roby/actions.rb +17 -0
  143. data/lib/roby/actions/action.rb +80 -0
  144. data/lib/roby/actions/interface.rb +45 -0
  145. data/lib/roby/actions/library.rb +23 -0
  146. data/lib/roby/actions/models/action.rb +224 -0
  147. data/lib/roby/actions/models/coordination_action.rb +58 -0
  148. data/lib/roby/actions/models/interface.rb +22 -0
  149. data/lib/roby/actions/models/interface_base.rb +294 -0
  150. data/lib/roby/actions/models/library.rb +12 -0
  151. data/lib/roby/actions/models/method_action.rb +90 -0
  152. data/lib/roby/actions/task.rb +114 -0
  153. data/lib/roby/and_generator.rb +125 -0
  154. data/lib/roby/app.rb +2795 -829
  155. data/lib/roby/app/autotest_console_reporter.rb +138 -0
  156. data/lib/roby/app/base.rb +21 -0
  157. data/lib/roby/app/cucumber.rb +2 -0
  158. data/lib/roby/app/cucumber/controller.rb +439 -0
  159. data/lib/roby/app/cucumber/helpers.rb +280 -0
  160. data/lib/roby/app/cucumber/world.rb +32 -0
  161. data/lib/roby/app/debug.rb +136 -0
  162. data/lib/roby/app/gen.rb +2 -0
  163. data/lib/roby/app/rake.rb +178 -38
  164. data/lib/roby/app/robot_config.rb +9 -0
  165. data/lib/roby/app/robot_names.rb +115 -0
  166. data/lib/roby/app/run.rb +3 -2
  167. data/lib/roby/app/scripts.rb +72 -0
  168. data/lib/roby/app/scripts/autotest.rb +173 -0
  169. data/lib/roby/app/scripts/display.rb +2 -0
  170. data/lib/roby/app/scripts/restart.rb +52 -0
  171. data/lib/roby/app/scripts/results.rb +17 -8
  172. data/lib/roby/app/scripts/run.rb +155 -24
  173. data/lib/roby/app/scripts/shell.rb +147 -62
  174. data/lib/roby/app/scripts/test.rb +107 -22
  175. data/lib/roby/app/test_reporter.rb +74 -0
  176. data/lib/roby/app/test_server.rb +159 -0
  177. data/lib/roby/app/vagrant.rb +47 -0
  178. data/lib/roby/backports.rb +16 -0
  179. data/lib/roby/cli/display.rb +190 -0
  180. data/lib/roby/cli/exceptions.rb +17 -0
  181. data/lib/roby/cli/gen/actions/class.rb +5 -0
  182. data/lib/roby/cli/gen/actions/test.rb +6 -0
  183. data/lib/roby/cli/gen/app/.yardopts +6 -0
  184. data/lib/roby/cli/gen/app/README.md +28 -0
  185. data/lib/roby/cli/gen/app/Rakefile +15 -0
  186. data/{app → lib/roby/cli/gen/app}/config/app.yml +29 -39
  187. data/lib/roby/cli/gen/app/models/.gitattributes +1 -0
  188. data/{app → lib/roby/cli/gen/app/scripts}/controllers/.gitattributes +0 -0
  189. data/{app/data/.gitattributes → lib/roby/cli/gen/app/test/.gitignore} +0 -0
  190. data/lib/roby/cli/gen/class/class.rb +6 -0
  191. data/lib/roby/cli/gen/class/test.rb +7 -0
  192. data/lib/roby/cli/gen/helpers.rb +203 -0
  193. data/lib/roby/cli/gen/module/module.rb +5 -0
  194. data/lib/roby/cli/gen/module/test.rb +6 -0
  195. data/lib/roby/cli/gen/roby_app/config/init.rb +17 -0
  196. data/lib/roby/cli/gen/roby_app/config/robots/robot.rb +40 -0
  197. data/lib/roby/cli/gen/task/class.rb +44 -0
  198. data/lib/roby/cli/gen/task/test.rb +6 -0
  199. data/lib/roby/cli/gen_main.rb +120 -0
  200. data/lib/roby/cli/log.rb +276 -0
  201. data/lib/roby/cli/log/flamegraph.html +499 -0
  202. data/lib/roby/cli/log/flamegraph_renderer.rb +88 -0
  203. data/lib/roby/cli/main.rb +153 -0
  204. data/lib/roby/coordination.rb +60 -0
  205. data/lib/roby/coordination/action_script.rb +25 -0
  206. data/lib/roby/coordination/action_state_machine.rb +125 -0
  207. data/lib/roby/coordination/actions.rb +106 -0
  208. data/lib/roby/coordination/base.rb +145 -0
  209. data/lib/roby/coordination/calculus.rb +40 -0
  210. data/lib/roby/coordination/child.rb +28 -0
  211. data/lib/roby/coordination/event.rb +29 -0
  212. data/lib/roby/coordination/fault_handler.rb +25 -0
  213. data/lib/roby/coordination/fault_handling_task.rb +13 -0
  214. data/lib/roby/coordination/fault_response_table.rb +110 -0
  215. data/lib/roby/coordination/models/action_script.rb +64 -0
  216. data/lib/roby/coordination/models/action_state_machine.rb +224 -0
  217. data/lib/roby/coordination/models/actions.rb +191 -0
  218. data/lib/roby/coordination/models/arguments.rb +55 -0
  219. data/lib/roby/coordination/models/base.rb +176 -0
  220. data/lib/roby/coordination/models/capture.rb +86 -0
  221. data/lib/roby/coordination/models/child.rb +35 -0
  222. data/lib/roby/coordination/models/event.rb +41 -0
  223. data/lib/roby/coordination/models/exceptions.rb +42 -0
  224. data/lib/roby/coordination/models/fault_handler.rb +219 -0
  225. data/lib/roby/coordination/models/fault_response_table.rb +77 -0
  226. data/lib/roby/coordination/models/root.rb +22 -0
  227. data/lib/roby/coordination/models/script.rb +283 -0
  228. data/lib/roby/coordination/models/task.rb +184 -0
  229. data/lib/roby/coordination/models/task_from_action.rb +50 -0
  230. data/lib/roby/coordination/models/task_from_as_plan.rb +33 -0
  231. data/lib/roby/coordination/models/task_from_instanciation_object.rb +31 -0
  232. data/lib/roby/coordination/models/task_from_variable.rb +27 -0
  233. data/lib/roby/coordination/models/task_with_dependencies.rb +48 -0
  234. data/lib/roby/coordination/models/variable.rb +32 -0
  235. data/lib/roby/coordination/script.rb +200 -0
  236. data/lib/roby/coordination/script_instruction.rb +12 -0
  237. data/lib/roby/coordination/task.rb +45 -0
  238. data/lib/roby/coordination/task_base.rb +69 -0
  239. data/lib/roby/coordination/task_script.rb +293 -0
  240. data/lib/roby/coordination/task_state_machine.rb +308 -0
  241. data/lib/roby/decision_control.rb +33 -21
  242. data/lib/roby/distributed_object.rb +76 -0
  243. data/lib/roby/droby.rb +17 -0
  244. data/lib/roby/droby/droby_id.rb +6 -0
  245. data/lib/roby/droby/enable.rb +153 -0
  246. data/lib/roby/droby/event_logger.rb +189 -0
  247. data/lib/roby/droby/event_logging.rb +57 -0
  248. data/lib/roby/droby/exceptions.rb +14 -0
  249. data/lib/roby/droby/identifiable.rb +22 -0
  250. data/lib/roby/droby/logfile.rb +141 -0
  251. data/lib/roby/droby/logfile/client.rb +176 -0
  252. data/lib/roby/droby/logfile/file_format.md +97 -0
  253. data/lib/roby/droby/logfile/index.rb +117 -0
  254. data/lib/roby/droby/logfile/reader.rb +139 -0
  255. data/lib/roby/droby/logfile/server.rb +199 -0
  256. data/lib/roby/droby/logfile/writer.rb +114 -0
  257. data/lib/roby/droby/marshal.rb +264 -0
  258. data/lib/roby/droby/marshallable.rb +12 -0
  259. data/lib/roby/droby/null_event_logger.rb +25 -0
  260. data/lib/roby/droby/object_manager.rb +205 -0
  261. data/lib/roby/droby/peer_id.rb +6 -0
  262. data/lib/roby/droby/plan_rebuilder.rb +373 -0
  263. data/lib/roby/droby/rebuilt_plan.rb +160 -0
  264. data/lib/roby/droby/remote_droby_id.rb +6 -0
  265. data/lib/roby/droby/timepoints.rb +205 -0
  266. data/lib/roby/droby/timepoints_ctf.metadata.erb +101 -0
  267. data/lib/roby/droby/timepoints_ctf.rb +125 -0
  268. data/lib/roby/droby/v5.rb +14 -0
  269. data/lib/roby/droby/v5/builtin.rb +120 -0
  270. data/lib/roby/droby/v5/droby_class.rb +45 -0
  271. data/lib/roby/droby/v5/droby_constant.rb +81 -0
  272. data/lib/roby/droby/v5/droby_dump.rb +1026 -0
  273. data/lib/roby/droby/v5/droby_id.rb +44 -0
  274. data/lib/roby/droby/v5/droby_model.rb +82 -0
  275. data/lib/roby/droby/v5/peer_id.rb +10 -0
  276. data/lib/roby/droby/v5/remote_droby_id.rb +42 -0
  277. data/lib/roby/event.rb +79 -957
  278. data/lib/roby/event_constraints.rb +835 -0
  279. data/lib/roby/event_generator.rb +1047 -0
  280. data/lib/roby/event_structure/causal_link.rb +6 -0
  281. data/lib/roby/event_structure/forwarding.rb +6 -0
  282. data/lib/roby/event_structure/precedence.rb +7 -0
  283. data/lib/roby/event_structure/signal.rb +8 -0
  284. data/lib/roby/event_structure/temporal_constraints.rb +640 -0
  285. data/lib/roby/exceptions.rb +446 -152
  286. data/lib/roby/executable_plan.rb +549 -0
  287. data/lib/roby/execution_engine.rb +1997 -950
  288. data/lib/roby/filter_generator.rb +26 -0
  289. data/lib/roby/gui/chronicle_view.rb +225 -0
  290. data/lib/roby/gui/chronicle_widget.rb +925 -0
  291. data/lib/roby/gui/dot_id.rb +11 -0
  292. data/lib/roby/gui/exception_view.rb +44 -0
  293. data/lib/roby/gui/log_display.rb +273 -0
  294. data/lib/roby/gui/model_views.rb +2 -0
  295. data/lib/roby/gui/model_views/action_interface.rb +53 -0
  296. data/lib/roby/gui/model_views/task.rb +47 -0
  297. data/lib/roby/gui/model_views/task.rhtml +41 -0
  298. data/lib/roby/gui/object_info_view.rb +89 -0
  299. data/lib/roby/gui/plan_dot_layout.rb +427 -0
  300. data/lib/roby/gui/plan_rebuilder_widget.rb +357 -0
  301. data/lib/roby/gui/qt4_toMSecsSinceEpoch.rb +8 -0
  302. data/lib/roby/gui/relations_view.rb +278 -0
  303. data/lib/roby/gui/relations_view/relations.ui +139 -0
  304. data/lib/roby/gui/relations_view/relations_canvas.rb +1088 -0
  305. data/lib/roby/gui/relations_view/relations_config.rb +292 -0
  306. data/lib/roby/gui/relations_view/relations_view.ui +53 -0
  307. data/lib/roby/gui/scheduler_view.css +24 -0
  308. data/lib/roby/gui/scheduler_view.rb +46 -0
  309. data/lib/roby/gui/scheduler_view.rhtml +53 -0
  310. data/lib/roby/gui/stepping.rb +93 -0
  311. data/lib/roby/gui/stepping.ui +181 -0
  312. data/lib/roby/gui/styles.rb +81 -0
  313. data/lib/roby/gui/task_display_configuration.rb +42 -0
  314. data/lib/roby/gui/task_state_at.rb +38 -0
  315. data/lib/roby/hooks.rb +26 -0
  316. data/lib/roby/interface.rb +136 -469
  317. data/lib/roby/interface/async.rb +20 -0
  318. data/lib/roby/interface/async/action_monitor.rb +188 -0
  319. data/lib/roby/interface/async/interface.rb +498 -0
  320. data/lib/roby/interface/async/job_monitor.rb +213 -0
  321. data/lib/roby/interface/async/log.rb +238 -0
  322. data/lib/roby/interface/async/new_job_listener.rb +79 -0
  323. data/lib/roby/interface/async/ui_connector.rb +183 -0
  324. data/lib/roby/interface/client.rb +553 -0
  325. data/lib/roby/interface/command.rb +24 -0
  326. data/lib/roby/interface/command_argument.rb +16 -0
  327. data/lib/roby/interface/command_library.rb +92 -0
  328. data/lib/roby/interface/droby_channel.rb +174 -0
  329. data/lib/roby/interface/exceptions.rb +22 -0
  330. data/lib/roby/interface/interface.rb +655 -0
  331. data/lib/roby/interface/job.rb +47 -0
  332. data/lib/roby/interface/rest.rb +10 -0
  333. data/lib/roby/interface/rest/api.rb +29 -0
  334. data/lib/roby/interface/rest/helpers.rb +24 -0
  335. data/lib/roby/interface/rest/server.rb +212 -0
  336. data/lib/roby/interface/server.rb +154 -0
  337. data/lib/roby/interface/shell_client.rb +468 -0
  338. data/lib/roby/interface/shell_subcommand.rb +24 -0
  339. data/lib/roby/interface/subcommand_client.rb +35 -0
  340. data/lib/roby/interface/tcp.rb +168 -0
  341. data/lib/roby/models/arguments.rb +112 -0
  342. data/lib/roby/models/plan_object.rb +83 -0
  343. data/lib/roby/models/task.rb +835 -0
  344. data/lib/roby/models/task_event.rb +62 -0
  345. data/lib/roby/models/task_service.rb +78 -0
  346. data/lib/roby/or_generator.rb +88 -0
  347. data/lib/roby/plan.rb +1751 -864
  348. data/lib/roby/plan_object.rb +611 -0
  349. data/lib/roby/plan_service.rb +200 -0
  350. data/lib/roby/promise.rb +332 -0
  351. data/lib/roby/queries.rb +23 -0
  352. data/lib/roby/queries/and_matcher.rb +32 -0
  353. data/lib/roby/queries/any.rb +27 -0
  354. data/lib/roby/queries/code_error_matcher.rb +58 -0
  355. data/lib/roby/queries/event_generator_matcher.rb +9 -0
  356. data/lib/roby/queries/execution_exception_matcher.rb +165 -0
  357. data/lib/roby/queries/index.rb +165 -0
  358. data/lib/roby/queries/localized_error_matcher.rb +149 -0
  359. data/lib/roby/queries/matcher_base.rb +107 -0
  360. data/lib/roby/queries/none.rb +27 -0
  361. data/lib/roby/queries/not_matcher.rb +30 -0
  362. data/lib/roby/queries/op_matcher.rb +8 -0
  363. data/lib/roby/queries/or_matcher.rb +30 -0
  364. data/lib/roby/queries/plan_object_matcher.rb +363 -0
  365. data/lib/roby/queries/query.rb +188 -0
  366. data/lib/roby/queries/task_event_generator_matcher.rb +86 -0
  367. data/lib/roby/queries/task_matcher.rb +344 -0
  368. data/lib/roby/relations.rb +42 -678
  369. data/lib/roby/relations/bidirectional_directed_adjacency_graph.rb +492 -0
  370. data/lib/roby/relations/directed_relation_support.rb +268 -0
  371. data/lib/roby/relations/event_relation_graph.rb +19 -0
  372. data/lib/roby/relations/fork_merge_visitor.rb +154 -0
  373. data/lib/roby/relations/graph.rb +533 -0
  374. data/lib/roby/relations/models/directed_relation_support.rb +11 -0
  375. data/lib/roby/relations/models/graph.rb +75 -0
  376. data/lib/roby/relations/models/task_relation_graph.rb +18 -0
  377. data/lib/roby/relations/space.rb +380 -0
  378. data/lib/roby/relations/task_relation_graph.rb +20 -0
  379. data/lib/roby/robot.rb +85 -38
  380. data/lib/roby/schedulers/basic.rb +155 -25
  381. data/lib/roby/schedulers/null.rb +20 -0
  382. data/lib/roby/schedulers/reporting.rb +31 -0
  383. data/lib/roby/schedulers/state.rb +129 -0
  384. data/lib/roby/schedulers/temporal.rb +91 -0
  385. data/lib/roby/singletons.rb +87 -0
  386. data/lib/roby/standalone.rb +4 -2
  387. data/lib/roby/standard_errors.rb +405 -82
  388. data/lib/roby/state.rb +6 -3
  389. data/lib/roby/state/conf_model.rb +5 -0
  390. data/lib/roby/state/events.rb +181 -95
  391. data/lib/roby/state/goal_model.rb +77 -0
  392. data/lib/roby/state/open_struct.rb +591 -0
  393. data/lib/roby/state/open_struct_model.rb +68 -0
  394. data/lib/roby/state/pos.rb +45 -45
  395. data/lib/roby/state/shapes.rb +11 -11
  396. data/lib/roby/state/state_model.rb +303 -0
  397. data/lib/roby/state/task.rb +43 -0
  398. data/lib/roby/support.rb +88 -148
  399. data/lib/roby/task.rb +1361 -1750
  400. data/lib/roby/task_arguments.rb +428 -0
  401. data/lib/roby/task_event.rb +127 -0
  402. data/lib/roby/task_event_generator.rb +337 -0
  403. data/lib/roby/task_service.rb +6 -0
  404. data/lib/roby/task_structure/conflicts.rb +104 -0
  405. data/lib/roby/task_structure/dependency.rb +932 -0
  406. data/lib/roby/task_structure/error_handling.rb +118 -0
  407. data/lib/roby/task_structure/executed_by.rb +234 -0
  408. data/lib/roby/task_structure/planned_by.rb +90 -0
  409. data/lib/roby/tasks/aggregator.rb +37 -0
  410. data/lib/roby/tasks/external_process.rb +275 -0
  411. data/lib/roby/tasks/group.rb +27 -0
  412. data/lib/roby/tasks/null.rb +19 -0
  413. data/lib/roby/tasks/parallel.rb +43 -0
  414. data/lib/roby/tasks/sequence.rb +88 -0
  415. data/lib/roby/tasks/simple.rb +21 -0
  416. data/lib/roby/{thread_task.rb → tasks/thread.rb} +50 -24
  417. data/lib/roby/tasks/timeout.rb +17 -0
  418. data/lib/roby/tasks/virtual.rb +55 -0
  419. data/lib/roby/template_plan.rb +7 -0
  420. data/lib/roby/test/aruba_minitest.rb +74 -0
  421. data/lib/roby/test/assertion.rb +16 -0
  422. data/lib/roby/test/assertions.rb +490 -0
  423. data/lib/roby/test/common.rb +368 -591
  424. data/lib/roby/test/dsl.rb +149 -0
  425. data/lib/roby/test/error.rb +18 -0
  426. data/lib/roby/test/event_reporter.rb +83 -0
  427. data/lib/roby/test/execution_expectations.rb +1134 -0
  428. data/lib/roby/test/expect_execution.rb +151 -0
  429. data/lib/roby/test/minitest_helpers.rb +166 -0
  430. data/lib/roby/test/roby_app_helpers.rb +200 -0
  431. data/lib/roby/test/run_planners.rb +155 -0
  432. data/lib/roby/test/self.rb +112 -0
  433. data/lib/roby/test/spec.rb +198 -0
  434. data/lib/roby/test/tasks/empty_task.rb +4 -4
  435. data/lib/roby/test/tasks/goto.rb +28 -27
  436. data/lib/roby/test/teardown_plans.rb +100 -0
  437. data/lib/roby/test/testcase.rb +239 -307
  438. data/lib/roby/test/tools.rb +159 -155
  439. data/lib/roby/test/validate_state_machine.rb +75 -0
  440. data/lib/roby/transaction.rb +1125 -0
  441. data/lib/roby/transaction/event_generator_proxy.rb +63 -0
  442. data/lib/roby/transaction/plan_object_proxy.rb +99 -0
  443. data/lib/roby/transaction/plan_service_proxy.rb +43 -0
  444. data/lib/roby/transaction/proxying.rb +120 -0
  445. data/lib/roby/transaction/task_event_generator_proxy.rb +19 -0
  446. data/lib/roby/transaction/task_proxy.rb +135 -0
  447. data/lib/roby/until_generator.rb +30 -0
  448. data/lib/roby/version.rb +5 -0
  449. data/lib/roby/yard.rb +169 -0
  450. data/lib/yard-roby.rb +1 -0
  451. data/manifest.xml +32 -6
  452. data/roby.gemspec +59 -0
  453. metadata +788 -587
  454. data/Manifest.txt +0 -321
  455. data/NOTES +0 -4
  456. data/README.txt +0 -166
  457. data/TODO.txt +0 -146
  458. data/app/README.txt +0 -24
  459. data/app/Rakefile +0 -8
  460. data/app/config/ROBOT.rb +0 -5
  461. data/app/config/init.rb +0 -33
  462. data/app/config/roby.yml +0 -3
  463. data/app/controllers/ROBOT.rb +0 -2
  464. data/app/planners/ROBOT/main.rb +0 -6
  465. data/app/planners/main.rb +0 -5
  466. data/app/scripts/distributed +0 -3
  467. data/app/scripts/generate/bookmarks +0 -3
  468. data/app/scripts/replay +0 -3
  469. data/app/scripts/results +0 -3
  470. data/app/scripts/run +0 -3
  471. data/app/scripts/server +0 -3
  472. data/app/scripts/shell +0 -3
  473. data/app/scripts/test +0 -3
  474. data/app/tasks/.gitattributes +0 -0
  475. data/app/tasks/ROBOT/.gitattributes +0 -0
  476. data/bin/roby-shell +0 -25
  477. data/doc/guide/src/basics/app.page +0 -139
  478. data/doc/guide/src/basics/index.page +0 -11
  479. data/doc/guide/src/basics/log_replay/goForward_1.png +0 -0
  480. data/doc/guide/src/basics/log_replay/goForward_2.png +0 -0
  481. data/doc/guide/src/basics/log_replay/goForward_3.png +0 -0
  482. data/doc/guide/src/basics/log_replay/goForward_5.png +0 -0
  483. data/doc/guide/src/basics/log_replay/plan_repair_4.png +0 -0
  484. data/doc/guide/src/basics/log_replay/roby_log_main_window.png +0 -0
  485. data/doc/guide/src/basics/relations_display.page +0 -203
  486. data/doc/guide/src/basics/shell.page +0 -102
  487. data/doc/guide/src/default.css +0 -319
  488. data/doc/guide/src/introduction/index.page +0 -29
  489. data/doc/guide/src/introduction/publications.page +0 -14
  490. data/doc/guide/src/relations/dependency.page +0 -89
  491. data/doc/guide/src/relations/index.page +0 -12
  492. data/ext/droby/dump.cc +0 -175
  493. data/ext/droby/extconf.rb +0 -3
  494. data/ext/graph/algorithm.cc +0 -746
  495. data/ext/graph/extconf.rb +0 -7
  496. data/ext/graph/graph.cc +0 -575
  497. data/ext/graph/graph.hh +0 -183
  498. data/ext/graph/iterator_sequence.hh +0 -102
  499. data/ext/graph/undirected_dfs.hh +0 -226
  500. data/ext/graph/undirected_graph.hh +0 -421
  501. data/lib/roby/app/scripts/generate/bookmarks.rb +0 -162
  502. data/lib/roby/app/scripts/replay.rb +0 -31
  503. data/lib/roby/app/scripts/server.rb +0 -18
  504. data/lib/roby/basic_object.rb +0 -151
  505. data/lib/roby/config.rb +0 -14
  506. data/lib/roby/distributed.rb +0 -36
  507. data/lib/roby/distributed/base.rb +0 -448
  508. data/lib/roby/distributed/communication.rb +0 -875
  509. data/lib/roby/distributed/connection_space.rb +0 -616
  510. data/lib/roby/distributed/distributed_object.rb +0 -206
  511. data/lib/roby/distributed/drb.rb +0 -62
  512. data/lib/roby/distributed/notifications.rb +0 -531
  513. data/lib/roby/distributed/peer.rb +0 -555
  514. data/lib/roby/distributed/protocol.rb +0 -529
  515. data/lib/roby/distributed/proxy.rb +0 -343
  516. data/lib/roby/distributed/subscription.rb +0 -311
  517. data/lib/roby/distributed/transaction.rb +0 -498
  518. data/lib/roby/external_process_task.rb +0 -225
  519. data/lib/roby/graph.rb +0 -160
  520. data/lib/roby/log.rb +0 -3
  521. data/lib/roby/log/chronicle.rb +0 -303
  522. data/lib/roby/log/console.rb +0 -74
  523. data/lib/roby/log/data_stream.rb +0 -275
  524. data/lib/roby/log/dot.rb +0 -279
  525. data/lib/roby/log/event_stream.rb +0 -161
  526. data/lib/roby/log/file.rb +0 -396
  527. data/lib/roby/log/gui/basic_display.ui +0 -83
  528. data/lib/roby/log/gui/basic_display_ui.rb +0 -89
  529. data/lib/roby/log/gui/chronicle.rb +0 -26
  530. data/lib/roby/log/gui/chronicle_view.rb +0 -40
  531. data/lib/roby/log/gui/chronicle_view.ui +0 -70
  532. data/lib/roby/log/gui/chronicle_view_ui.rb +0 -90
  533. data/lib/roby/log/gui/data_displays.rb +0 -171
  534. data/lib/roby/log/gui/data_displays.ui +0 -155
  535. data/lib/roby/log/gui/data_displays_ui.rb +0 -146
  536. data/lib/roby/log/gui/notifications.rb +0 -26
  537. data/lib/roby/log/gui/relations.rb +0 -269
  538. data/lib/roby/log/gui/relations.ui +0 -123
  539. data/lib/roby/log/gui/relations_ui.rb +0 -120
  540. data/lib/roby/log/gui/relations_view.rb +0 -185
  541. data/lib/roby/log/gui/relations_view.ui +0 -149
  542. data/lib/roby/log/gui/relations_view_ui.rb +0 -144
  543. data/lib/roby/log/gui/replay.rb +0 -366
  544. data/lib/roby/log/gui/replay_controls.rb +0 -206
  545. data/lib/roby/log/gui/replay_controls.ui +0 -282
  546. data/lib/roby/log/gui/replay_controls_ui.rb +0 -249
  547. data/lib/roby/log/gui/runtime.rb +0 -130
  548. data/lib/roby/log/hooks.rb +0 -186
  549. data/lib/roby/log/logger.rb +0 -203
  550. data/lib/roby/log/notifications.rb +0 -244
  551. data/lib/roby/log/plan_rebuilder.rb +0 -468
  552. data/lib/roby/log/relations.rb +0 -1084
  553. data/lib/roby/log/server.rb +0 -547
  554. data/lib/roby/log/sqlite.rb +0 -47
  555. data/lib/roby/log/timings.rb +0 -233
  556. data/lib/roby/plan-object.rb +0 -371
  557. data/lib/roby/planning.rb +0 -13
  558. data/lib/roby/planning/loops.rb +0 -309
  559. data/lib/roby/planning/model.rb +0 -1012
  560. data/lib/roby/planning/task.rb +0 -180
  561. data/lib/roby/query.rb +0 -655
  562. data/lib/roby/relations/conflicts.rb +0 -67
  563. data/lib/roby/relations/dependency.rb +0 -358
  564. data/lib/roby/relations/ensured.rb +0 -19
  565. data/lib/roby/relations/error_handling.rb +0 -22
  566. data/lib/roby/relations/events.rb +0 -7
  567. data/lib/roby/relations/executed_by.rb +0 -208
  568. data/lib/roby/relations/influence.rb +0 -10
  569. data/lib/roby/relations/planned_by.rb +0 -63
  570. data/lib/roby/state/information.rb +0 -55
  571. data/lib/roby/state/state.rb +0 -367
  572. data/lib/roby/task-operations.rb +0 -186
  573. data/lib/roby/task_index.rb +0 -80
  574. data/lib/roby/test/distributed.rb +0 -230
  575. data/lib/roby/test/tasks/simple_task.rb +0 -23
  576. data/lib/roby/transactions.rb +0 -507
  577. data/lib/roby/transactions/proxy.rb +0 -325
  578. data/plugins/fault_injection/History.txt +0 -4
  579. data/plugins/fault_injection/README.txt +0 -34
  580. data/plugins/fault_injection/Rakefile +0 -12
  581. data/plugins/fault_injection/TODO.txt +0 -0
  582. data/plugins/fault_injection/app.rb +0 -52
  583. data/plugins/fault_injection/fault_injection.rb +0 -89
  584. data/plugins/fault_injection/test/test_fault_injection.rb +0 -78
  585. data/plugins/subsystems/README.txt +0 -37
  586. data/plugins/subsystems/Rakefile +0 -13
  587. data/plugins/subsystems/app.rb +0 -182
  588. data/plugins/subsystems/test/app/README +0 -24
  589. data/plugins/subsystems/test/app/Rakefile +0 -8
  590. data/plugins/subsystems/test/app/config/app.yml +0 -71
  591. data/plugins/subsystems/test/app/config/init.rb +0 -12
  592. data/plugins/subsystems/test/app/config/roby.yml +0 -3
  593. data/plugins/subsystems/test/app/planners/main.rb +0 -20
  594. data/plugins/subsystems/test/app/scripts/distributed +0 -3
  595. data/plugins/subsystems/test/app/scripts/replay +0 -3
  596. data/plugins/subsystems/test/app/scripts/results +0 -3
  597. data/plugins/subsystems/test/app/scripts/run +0 -3
  598. data/plugins/subsystems/test/app/scripts/server +0 -3
  599. data/plugins/subsystems/test/app/scripts/shell +0 -3
  600. data/plugins/subsystems/test/app/scripts/test +0 -3
  601. data/plugins/subsystems/test/app/tasks/services.rb +0 -15
  602. data/plugins/subsystems/test/test_subsystems.rb +0 -78
  603. data/test/distributed/test_communication.rb +0 -195
  604. data/test/distributed/test_connection.rb +0 -284
  605. data/test/distributed/test_execution.rb +0 -378
  606. data/test/distributed/test_mixed_plan.rb +0 -341
  607. data/test/distributed/test_plan_notifications.rb +0 -238
  608. data/test/distributed/test_protocol.rb +0 -525
  609. data/test/distributed/test_query.rb +0 -106
  610. data/test/distributed/test_remote_plan.rb +0 -491
  611. data/test/distributed/test_transaction.rb +0 -466
  612. data/test/mockups/external_process +0 -28
  613. data/test/mockups/tasks.rb +0 -27
  614. data/test/planning/test_loops.rb +0 -432
  615. data/test/planning/test_model.rb +0 -427
  616. data/test/planning/test_task.rb +0 -126
  617. data/test/relations/test_conflicts.rb +0 -42
  618. data/test/relations/test_dependency.rb +0 -324
  619. data/test/relations/test_ensured.rb +0 -38
  620. data/test/relations/test_executed_by.rb +0 -224
  621. data/test/relations/test_planned_by.rb +0 -56
  622. data/test/suite_core.rb +0 -29
  623. data/test/suite_distributed.rb +0 -10
  624. data/test/suite_planning.rb +0 -4
  625. data/test/suite_relations.rb +0 -8
  626. data/test/tasks/test_external_process.rb +0 -126
  627. data/test/tasks/test_thread_task.rb +0 -70
  628. data/test/test_bgl.rb +0 -528
  629. data/test/test_event.rb +0 -969
  630. data/test/test_exceptions.rb +0 -591
  631. data/test/test_execution_engine.rb +0 -987
  632. data/test/test_gui.rb +0 -20
  633. data/test/test_interface.rb +0 -43
  634. data/test/test_log.rb +0 -125
  635. data/test/test_log_server.rb +0 -133
  636. data/test/test_plan.rb +0 -418
  637. data/test/test_query.rb +0 -424
  638. data/test/test_relations.rb +0 -260
  639. data/test/test_state.rb +0 -432
  640. data/test/test_support.rb +0 -16
  641. data/test/test_task.rb +0 -1181
  642. data/test/test_testcase.rb +0 -138
  643. data/test/test_transactions.rb +0 -610
  644. data/test/test_transactions_proxy.rb +0 -216
@@ -0,0 +1,20 @@
1
+ require 'roby'
2
+ require 'roby/interface'
3
+ require 'hooks'
4
+ require 'roby/hooks'
5
+ require 'concurrent'
6
+
7
+ require 'roby/interface/async/job_monitor'
8
+ require 'roby/interface/async/new_job_listener'
9
+ require 'roby/interface/async/interface'
10
+ require 'roby/interface/async/action_monitor'
11
+ require 'roby/interface/async/ui_connector'
12
+
13
+ module Roby
14
+ module Interface
15
+ module Async
16
+ extend Logger::Hierarchy
17
+ end
18
+ end
19
+ end
20
+
@@ -0,0 +1,188 @@
1
+ module Roby
2
+ module Interface
3
+ module Async
4
+ # An action definition
5
+ #
6
+ # While {JobMonitor} represents a running / instanciated job, this
7
+ # represents just an action with a set of argument. It binds
8
+ # automatically to a matching running job if there is one.
9
+ class ActionMonitor
10
+ # The underlying Async::Interface
11
+ attr_reader :interface
12
+ # The action name
13
+ attr_reader :action_name
14
+ # The arguments that are part of the job definition itself
15
+ attr_reader :static_arguments
16
+ # The arguments that have been set to override the static
17
+ # arguments, or set arguments not yet set in {#static_arguments}
18
+ attr_reader :arguments
19
+ # The underlying {JobMonitor} object if we're tracking a job
20
+ attr_reader :async
21
+
22
+ include Hooks
23
+ include Hooks::InstanceHooks
24
+
25
+ # @!method on_progress
26
+ #
27
+ # Hooks called when self got updated
28
+ #
29
+ # @return [void]
30
+ define_hooks :on_progress
31
+
32
+ # Whether there is a job matching this action monitor running
33
+ def exists?
34
+ !!async
35
+ end
36
+
37
+ # If at least one job ran and is terminated
38
+ def terminated?
39
+ async && async.terminated?
40
+ end
41
+
42
+ # The job ID of the last job that ran
43
+ def job_id
44
+ async && async.job_id
45
+ end
46
+
47
+ # The set of arguments that should be passed to the action
48
+ #
49
+ # It is basically the merged {#static_arguments} and
50
+ # {#arguments}
51
+ def action_arguments
52
+ static_arguments.merge(arguments)
53
+ end
54
+
55
+ # @api private
56
+ #
57
+ # Helper to handle the batch argument in e.g. {#kill} and
58
+ # {#restart}
59
+ def handle_batch_argument(batch)
60
+ if batch
61
+ yield(batch)
62
+ else
63
+ yield(batch = interface.create_batch)
64
+ batch.__process
65
+ end
66
+ end
67
+
68
+ # Drop this job
69
+ #
70
+ # @param [Client::BatchContext] batch if given, the restart
71
+ # commands will be added to this batch. Otherwise, a new batch
72
+ # is created and {Client::BatchContext#__process} is called.
73
+ def drop(batch: nil)
74
+ handle_batch_argument(batch) do |b|
75
+ b.drop_job(async.job_id)
76
+ end
77
+ end
78
+
79
+ # Kill this job
80
+ #
81
+ # @param [Client::BatchContext] batch if given, the restart
82
+ # commands will be added to this batch. Otherwise, a new batch
83
+ # is created and {Client::BatchContext#__process} is called.
84
+ def kill(batch: nil)
85
+ if !running?
86
+ raise InvalidState, "cannot kill a non-running action"
87
+ end
88
+
89
+ handle_batch_argument(batch) do |b|
90
+ b.kill_job(async.job_id)
91
+ end
92
+ end
93
+
94
+ # Start or restart a job based on this action
95
+ #
96
+ # @param [Hash] arguments the arguments that should be used
97
+ # instead of {#action_arguments}
98
+ # @param [Client::BatchContext] batch if given, the restart
99
+ # commands will be added to this batch. Otherwise, a new batch
100
+ # is created and {Client::BatchContext#__process} is called.
101
+ def restart(arguments = self.action_arguments, batch: nil, lazy: false)
102
+ if lazy && running? && (arguments == async.action_arguments)
103
+ return
104
+ end
105
+
106
+ handle_batch_argument(batch) do |b|
107
+ if running?
108
+ kill(batch: b)
109
+ end
110
+ b.start_job(action_name, arguments)
111
+ end
112
+ end
113
+
114
+ def initialize(interface, action_name, static_arguments = Hash.new)
115
+ @interface, @action_name, @static_arguments =
116
+ interface, action_name, static_arguments
117
+ @arguments = Hash.new
118
+
119
+ interface.on_reachable do
120
+ run_hook :on_progress
121
+ end
122
+ interface.on_unreachable do
123
+ unreachable!
124
+ end
125
+ interface.on_job(action_name: action_name) do |job|
126
+ if !self.async || self.job_id != job.job_id || terminated?
127
+ matching = static_arguments.all? do |arg_name, arg_val|
128
+ job.action_arguments[arg_name.to_sym] == arg_val
129
+ end
130
+ if matching
131
+ self.async = job
132
+ job.start
133
+ end
134
+ end
135
+ end
136
+ end
137
+
138
+ def running?
139
+ async && async.running?
140
+ end
141
+
142
+ def success?
143
+ async && async.success?
144
+ end
145
+
146
+ def failed?
147
+ async && async.failed?
148
+ end
149
+
150
+ def finished?
151
+ async && async.finished?
152
+ end
153
+
154
+ def terminated?
155
+ async && async.terminated?
156
+ end
157
+
158
+ def state
159
+ if interface.reachable?
160
+ if !async
161
+ :reachable
162
+ else
163
+ async.state
164
+ end
165
+ else
166
+ :unreachable
167
+ end
168
+ end
169
+
170
+ def unreachable!
171
+ @async = nil
172
+ run_hook :on_progress
173
+ end
174
+
175
+ def async=(async)
176
+ @async = async
177
+ async.on_progress do
178
+ if self.async == async
179
+ run_hook :on_progress
180
+ end
181
+ end
182
+ run_hook :on_progress
183
+ end
184
+ end
185
+ end
186
+ end
187
+ end
188
+
@@ -0,0 +1,498 @@
1
+ module Roby
2
+ module Interface
3
+ module Async
4
+ # An event-based client to for the Roby interface
5
+ #
6
+ # This class provides an asynchronous (event-based) API to the Roby
7
+ # interface, it allows for job and task discovery and tracking, and
8
+ # is robust to disconnections and reconnections.
9
+ #
10
+ # It is meant for the implementations of GUIs that interface with a
11
+ # Roby system. The {#poll} method must be called regularly from a
12
+ # main event loop (e.g. from a Qt timer)
13
+ #
14
+ # Notification callbacks can be registered with one of the on_
15
+ # methods (on_job, ...). A Qt-oriented declarative approach to
16
+ # binding jobs to a UI can be found in {UIConnector}
17
+ class Interface
18
+ extend Logger::Hierarchy
19
+ extend Logger::Forward
20
+
21
+ include Hooks
22
+ include Hooks::InstanceHooks
23
+
24
+ # @return [String] a string that describes the remote host
25
+ attr_reader :remote_name
26
+ # @return [#call] an object that can create a Client instance
27
+ attr_reader :connection_method
28
+ # @return [Client,nil] the socket used to communicate to the server,
29
+ # or nil if we have not managed to connect yet
30
+ attr_reader :client
31
+ # The future used to connect to the remote process without blocking
32
+ # the main event loop
33
+ attr_reader :connection_future
34
+
35
+ # @!group Hooks
36
+
37
+ # @!method on_reachable()
38
+ # Hooks called when we successfully connected
39
+ #
40
+ # @param [Array<JobMonitor>] list of currently active jobs, as
41
+ # returned by {#jobs}. These monitors are inactive: if you
42
+ # want to track one of them, you must call
43
+ # {JobMonitor#start}.
44
+ # @return [void]
45
+ define_hooks :on_reachable
46
+ # @!method on_unreachable()
47
+ # Hooks called when the connection to the Roby app has been
48
+ # lost.
49
+ # @return [void]
50
+ define_hooks :on_unreachable
51
+ # @!method on_notification
52
+ # Hooks called for generic notifications messages, usually
53
+ # queued through {Application#notify}. Note that all log
54
+ # messages sent through {Robot} are forwarded this way.
55
+ #
56
+ # @yieldparam [Symbol] level message level
57
+ # @yieldparam [String] message a text message explaining the
58
+ # notification
59
+ # @return [void]
60
+ define_hooks :on_notification
61
+ # @!method on_ui_event
62
+ # Hooks called for UI events, that is notifications that are
63
+ # meant for user interaction (but are mostly meaningless to
64
+ # the user). These are arbitrary, and defined by Roby or
65
+ # its plugins.
66
+ #
67
+ # @yieldparam [String] event_name the event name
68
+ # @yieldparam args the event arguments, which are
69
+ # event-specific
70
+ # @return [void]
71
+ define_hooks :on_ui_event
72
+ # @!method on_job_progress
73
+ #
74
+ # Hooks called for job progress notifications
75
+ #
76
+ # @yieldparam [Symbol] state the new job state, as one of the
77
+ # JOB constants defined on {Roby::Interface}
78
+ # @yieldparam [Integer] job_id the job ID
79
+ # @yieldparam [String] job_name the job name
80
+ # @yieldparam [Array<Object>] args additional information
81
+ # specific to this progress message. See
82
+ # {Interface::Interface#on_job_notification} for details.
83
+ # @return [void]
84
+ define_hooks :on_job_progress
85
+ # @!method on_exception
86
+ #
87
+ # Hooks called for exceptions
88
+ #
89
+ # @yieldparam (see Roby::Interface::Interface#on_exception)
90
+ # @return [void]
91
+ define_hooks :on_exception
92
+
93
+ # Registers a callback that should be called for each new job
94
+ #
95
+ # The callback gets called, on registration, with all the
96
+ # existing jobs. It is then called with new jobs as they get
97
+ # created.
98
+ #
99
+ # @param [String,nil] action_name limit notifications to actions
100
+ # with this name. No filtering is performed if nil.
101
+ # @yieldparam [JobMonitor] job_monitor a monitor for a job that is just
102
+ # created. It is not monitoring the job yet, call
103
+ # {JobMonitor#start} to get it to start monitoring.
104
+ # @return [NewJobListener]
105
+ def on_job(action_name: nil, jobs: self.jobs, &block)
106
+ listener = NewJobListener.new(self, action_name, block)
107
+ listener.start
108
+ if reachable?
109
+ run_initial_new_job_hooks_events(listener, jobs)
110
+ end
111
+ listener
112
+ end
113
+
114
+ # @!endgroup Hooks
115
+
116
+ # The set of JobMonitor objects currently registered on self
117
+ #
118
+ # @return [Hash<Integer,Set<JobMonitor>>]
119
+ attr_reader :job_monitors
120
+
121
+ # The set of NewJobListener objects currently registered on self
122
+ #
123
+ # @return [Array<NewJobListener>]
124
+ attr_reader :new_job_listeners
125
+
126
+ DEFAULT_REMOTE_NAME = "localhost"
127
+
128
+ def initialize(remote_name = DEFAULT_REMOTE_NAME, port: Roby::Interface::DEFAULT_PORT, connect: true, &connection_method)
129
+ @connection_method = connection_method || lambda {
130
+ Roby::Interface.connect_with_tcp_to(remote_name, port)
131
+ }
132
+
133
+ @remote_name = remote_name
134
+ @first_connection_attempt = true
135
+ if connect
136
+ attempt_connection
137
+ end
138
+
139
+ @job_monitors = Hash.new
140
+ @new_job_listeners = Array.new
141
+ end
142
+
143
+ # Schedules an async call on the client
144
+ #
145
+ # @see Client#async_call
146
+ def async_call(path, m, *args, &block)
147
+ raise 'client not connected' unless connected?
148
+ client.async_call(path, m, *args, &block)
149
+ end
150
+
151
+ # Checks whether an async call is still pending
152
+ #
153
+ # @see Client#async_call_pending?
154
+ def async_call_pending?(call)
155
+ connected? && client.async_call_pending?(call)
156
+ end
157
+
158
+ # Start a connection attempt
159
+ def attempt_connection
160
+ @connection_future = Concurrent::Future.new do
161
+ client = connection_method.call
162
+ [client, client.jobs]
163
+ end
164
+ connection_future.execute
165
+ end
166
+
167
+ # The set of known actions
168
+ #
169
+ # This is available only after we got a successful connection to
170
+ # the remote side
171
+ def actions
172
+ client.actions
173
+ end
174
+
175
+ # Verify the state of the last connection attempt
176
+ #
177
+ # It checks on the last connection attempt, and sets {#client}
178
+ # if it was successful, as well as call the callbacks registered
179
+ # with {#on_reachable}
180
+ def poll_connection_attempt
181
+ return if client
182
+ return if !connection_future.complete?
183
+
184
+ case e = connection_future.reason
185
+ when ConnectionError, ComError, ProtocolError
186
+ Interface.info "failed connection attempt: #{e}"
187
+ attempt_connection
188
+ if @first_connection_attempt
189
+ @first_connection_attempt = false
190
+ run_hook :on_unreachable
191
+ end
192
+ nil
193
+ when NilClass
194
+ Interface.info "successfully connected"
195
+ @client, jobs = connection_future.value
196
+ @client.io.reset_thread_guard
197
+ @connection_future = nil
198
+ jobs = jobs.map do |job_id, (job_state, placeholder_task, job_task)|
199
+ JobMonitor.new(self, job_id, state: job_state, placeholder_task: placeholder_task, task: job_task)
200
+ end
201
+ run_hook :on_reachable, jobs
202
+ new_job_listeners.each do |listener|
203
+ listener.reset
204
+ run_initial_new_job_hooks_events(listener, jobs)
205
+ end
206
+ else
207
+ future, @connection_future = @connection_future, nil
208
+ raise future.reason
209
+ end
210
+ end
211
+
212
+ # @private
213
+ #
214
+ # Process the message queues from {#client}
215
+ def process_message_queues
216
+ client.notification_queue.each do |id, level, message|
217
+ run_hook :on_notification, level, message
218
+ end
219
+ client.notification_queue.clear
220
+ client.ui_event_queue.each do |id, event_name, *args|
221
+ run_hook :on_ui_event, event_name, *args
222
+ end
223
+ client.ui_event_queue.clear
224
+
225
+ client.job_progress_queue.each do |id, (job_state, job_id, job_name, *args)|
226
+ new_job_listeners.each do |listener|
227
+ next if listener.seen_job_with_id?(job_id)
228
+
229
+ job =
230
+ if job_state == JOB_MONITORED
231
+ JobMonitor.new(
232
+ self, job_id,
233
+ state: job_state,
234
+ placeholder_task: args[0],
235
+ task: args[1])
236
+ else
237
+ monitor_job(job_id, start: false)
238
+ end
239
+ if listener.matches?(job)
240
+ listener.call(job)
241
+ else
242
+ listener.ignored(job)
243
+ end
244
+ end
245
+
246
+ if monitors = job_monitors[job_id]
247
+ monitors.delete_if do |m|
248
+ m.update_state(job_state)
249
+ if job_state == JOB_REPLACED
250
+ m.replaced(args.first)
251
+ end
252
+ m.finalized?
253
+ end
254
+ if monitors.empty?
255
+ job_monitors.delete(job_id)
256
+ end
257
+ end
258
+ run_hook :on_job_progress, job_state, job_id, job_name, args
259
+ end
260
+ client.job_progress_queue.clear
261
+
262
+ client.exception_queue.each do |id, (kind, exception, tasks, job_ids)|
263
+ job_ids.each do |job_id|
264
+ if monitors = job_monitors[job_id]
265
+ monitors.dup.each do |m|
266
+ m.notify_exception(kind, exception)
267
+ end
268
+ end
269
+ end
270
+
271
+ run_hook :on_exception, kind, exception, tasks, job_ids
272
+ end
273
+ client.exception_queue.clear
274
+ end
275
+
276
+ def connecting?
277
+ connection_future
278
+ end
279
+
280
+ def connected?
281
+ !!client
282
+ end
283
+
284
+ def cycle_start_time
285
+ client.cycle_start_time
286
+ end
287
+
288
+ def cycle_index
289
+ client.cycle_index
290
+ end
291
+
292
+ def poll_messages
293
+ has_cycle_end = true
294
+ while has_cycle_end
295
+ cleanup_dead_monitors
296
+ _, has_cycle_end = client.poll
297
+ process_message_queues
298
+ end
299
+ rescue ComError
300
+ Interface.info "link closed, trying to reconnect"
301
+ unreachable!
302
+ attempt_connection
303
+ false
304
+ rescue Exception => e
305
+ Interface.warn "error while polling connection, trying to reconnect"
306
+ Roby.log_exception_with_backtrace(e, Interface, :warn)
307
+ unreachable!
308
+ attempt_connection
309
+ false
310
+ end
311
+
312
+ # Blocking call that waits until calling #poll would do something
313
+ #
314
+ # @param [Numeric,nil] timeout a timeout after which the method
315
+ # will return. Use nil for no timeout
316
+ # @return [Boolean] falsy if the timeout was reached, true
317
+ # otherwise
318
+ def wait(timeout: nil)
319
+ if connected?
320
+ client.wait(timeout: timeout)
321
+ else
322
+ wait_connection_attempt_result(timeout: timeout)
323
+ end
324
+ end
325
+
326
+ # Wait for the current connection attempt to finish
327
+ #
328
+ # @param [Numeric,nil] timeout a timeout after which the method
329
+ # will return. Use nil for no timeout
330
+ # @return [Boolean] falsy if the timeout was reached, true
331
+ # otherwise
332
+ def wait_connection_attempt_result(timeout: nil)
333
+ connection_future.wait(timeout)
334
+ connection_future.complete?
335
+ end
336
+
337
+
338
+ # Active part of the async. This has to be called regularly within
339
+ # the system's main event loop (e.g. Roby's, Vizkit's or Qt's)
340
+ #
341
+ # @return [Boolean] true if we are connected to the remote server
342
+ # and false otherwise
343
+ def poll
344
+ if connected?
345
+ poll_messages
346
+ true
347
+ elsif connecting?
348
+ poll_connection_attempt
349
+ !!client
350
+ end
351
+ end
352
+
353
+ def unreachable!
354
+ job_monitors.each_value do |monitors|
355
+ monitors.each do |j|
356
+ j.update_state(:unreachable)
357
+ end
358
+ end
359
+ job_monitors.clear
360
+
361
+ if client
362
+ client.close if !client.closed?
363
+ @client = nil
364
+ run_hook :on_unreachable
365
+ end
366
+ end
367
+
368
+ # Close the connection to the Roby interface
369
+ #
370
+ # @param [Boolean] reconnect if true, attempt to reconnect right
371
+ # away. If false, the caller will be responsible to call
372
+ # {#attempt_connection} before any future call to {#poll}
373
+ def close(reconnect: false)
374
+ unreachable!
375
+ if reconnect
376
+ attempt_connection
377
+ end
378
+ end
379
+
380
+ # True if we are connected to a client
381
+ def reachable?
382
+ !!client
383
+ end
384
+
385
+ # Asks the remote app to quit (synchronous)
386
+ def quit
387
+ client.quit
388
+ end
389
+
390
+ # Asks the remote app to restart (synchronous)
391
+ def restart
392
+ client.restart
393
+ end
394
+
395
+ # Returns all the existing jobs on this interface
396
+ #
397
+ # The returned monitors are not started, you have to call
398
+ # {JobMonitor#start} explicitely on them before you use them
399
+ #
400
+ # @return [Array<JobMonitor>]
401
+ def jobs
402
+ return Array.new if !reachable?
403
+
404
+ client.jobs.map do |job_id, (job_state, placeholder_task, job_task)|
405
+ JobMonitor.new(self, job_id, placeholder_task: placeholder_task, task: job_task, state: job_state)
406
+ end
407
+ end
408
+
409
+ # Find the jobs that have been created from a given action
410
+ #
411
+ # The returned monitors are not started, you have to call
412
+ # {JobMonitor#start} explicitely on them before you use them
413
+ #
414
+ # @param [String] action_name the action name
415
+ # @return [Array<JobMonitor>] the matching jobs
416
+ def find_all_jobs(action_name, jobs: self.jobs)
417
+ jobs.find_all do |job|
418
+ job.task.action_model.name == action_name
419
+ end
420
+ end
421
+
422
+ # Create a monitor on a job based on its ID
423
+ #
424
+ # The monitor is already started
425
+ def monitor_job(job_id, start: true)
426
+ job_state, placeholder_task, job_task = client.find_job_info_by_id(job_id)
427
+ job = JobMonitor.new(self, job_id, state: job_state, placeholder_task: placeholder_task, task: job_task)
428
+ if start
429
+ job.start
430
+ end
431
+ job
432
+ end
433
+
434
+ # @api private
435
+ #
436
+ # Helper to call a job listener for all matching jobs in a job
437
+ # set. This is called when the new job listener is created and
438
+ # when we get connected to a roby interface
439
+ #
440
+ # @param [NewJobListener] listener
441
+ # @param [Array<JobMonitor>] jobs
442
+ def run_initial_new_job_hooks_events(listener, jobs = self.jobs)
443
+ jobs.each do |job|
444
+ if listener.matches?(job)
445
+ listener.call(job)
446
+ end
447
+ end
448
+ end
449
+
450
+ def create_batch
451
+ client.create_batch
452
+ end
453
+
454
+ def add_new_job_listener(job)
455
+ new_job_listeners << job
456
+ end
457
+
458
+ def remove_new_job_listener(job)
459
+ new_job_listeners.delete(job)
460
+ end
461
+
462
+ def add_job_monitor(job)
463
+ set = (job_monitors[job.job_id] ||= Set.new)
464
+ job_monitors[job.job_id] << job
465
+ end
466
+
467
+ def cleanup_dead_monitors
468
+ job_monitors.delete_if do |job_id, monitors|
469
+ monitors.delete_if do |job|
470
+ job.finalized?
471
+ end
472
+ monitors.empty?
473
+ end
474
+ end
475
+
476
+ def remove_job_monitor(job)
477
+ if set = job_monitors[job.job_id]
478
+ set.delete(job)
479
+ if set.empty?
480
+ job_monitors.delete(job.job_id)
481
+ end
482
+ end
483
+ end
484
+
485
+ def active_job_monitor?(job)
486
+ if set = job_monitors[job.job_id]
487
+ set.include?(job)
488
+ end
489
+ end
490
+
491
+ def connect_to_ui(widget, &block)
492
+ UIConnector.new(self, widget).instance_eval(&block)
493
+ end
494
+ end
495
+ end
496
+ end
497
+ end
498
+