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.
- checksums.yaml +7 -0
- data/.deep-cover.rb +3 -0
- data/.gitattributes +1 -0
- data/.gitignore +24 -0
- data/.simplecov +10 -0
- data/.travis.yml +17 -0
- data/.yardopts +4 -0
- data/Gemfile +15 -0
- data/README.md +11 -0
- data/Rakefile +47 -177
- data/benchmark/{alloc_misc.rb → attic/alloc_misc.rb} +2 -2
- data/benchmark/{discovery_latency.rb → attic/discovery_latency.rb} +19 -19
- data/benchmark/{garbage_collection.rb → attic/garbage_collection.rb} +9 -9
- data/benchmark/{genom.rb → attic/genom.rb} +0 -0
- data/benchmark/attic/transactions.rb +62 -0
- data/benchmark/plan_basic_operations.rb +28 -0
- data/benchmark/relations/graph.rb +63 -0
- data/benchmark/ruby/identity.rb +18 -0
- data/benchmark/ruby/set_intersect_vs_hash_merge.rb +39 -0
- data/benchmark/ruby/yield_vs_block.rb +35 -0
- data/benchmark/run +5 -0
- data/benchmark/synthetic_plan_modifications_with_transactions.rb +79 -0
- data/benchmark/transactions.rb +99 -51
- data/bin/roby +38 -197
- data/bin/roby-display +14 -0
- data/bin/roby-log +3 -176
- data/doc/guide/{src → attic}/abstraction/achieve_with.page +1 -1
- data/doc/guide/{src → attic}/abstraction/forwarding.page +1 -1
- data/doc/guide/{src → attic}/abstraction/hierarchy.page +1 -1
- data/doc/guide/{src → attic}/abstraction/index.page +1 -1
- data/doc/guide/{src → attic}/abstraction/task_models.page +1 -1
- data/doc/guide/{overview.rdoc → attic/cycle/api_overview.rdoc} +6 -1
- data/doc/guide/{src → attic}/cycle/cycle-overview.png +0 -0
- data/doc/guide/{src → attic}/cycle/cycle-overview.svg +0 -0
- data/doc/guide/attic/cycle/error_handling.page +98 -0
- data/doc/guide/{src → attic}/cycle/error_instantaneous_repair.png +0 -0
- data/doc/guide/{src → attic}/cycle/error_instantaneous_repair.svg +0 -0
- data/doc/guide/{src/cycle/error_handling.page → attic/cycle/error_sources.page} +46 -89
- data/doc/guide/{src → attic}/cycle/garbage_collection.page +1 -1
- data/doc/guide/{src → attic}/cycle/index.page +1 -1
- data/doc/guide/{src → attic}/cycle/propagation.page +11 -1
- data/doc/guide/{src → attic}/cycle/propagation_diamond.png +0 -0
- data/doc/guide/{src → attic}/cycle/propagation_diamond.svg +0 -0
- data/doc/guide/attic/plans/building_plans.page +89 -0
- data/doc/guide/attic/plans/code.page +192 -0
- data/doc/guide/{src/basics → attic/plans}/events.page +3 -4
- data/doc/guide/attic/plans/index.page +7 -0
- data/doc/guide/{plan_modifications.rdoc → attic/plans/plan_modifications.rdoc} +5 -3
- data/doc/guide/{src/basics → attic/plans}/plan_objects.page +2 -1
- data/doc/guide/attic/plans/querying_plans.page +5 -0
- data/doc/guide/{src/basics → attic/plans}/tasks.page +20 -20
- data/doc/guide/config.yaml +7 -4
- data/doc/guide/ext/extended_menu.rb +29 -0
- data/doc/guide/ext/init.rb +6 -0
- data/doc/guide/ext/rdoc_links.rb +7 -6
- data/doc/guide/src/advanced_concepts/history.page +5 -0
- data/doc/guide/src/advanced_concepts/index.page +11 -0
- data/doc/guide/src/advanced_concepts/recognizing_patterns.page +83 -0
- data/doc/guide/src/advanced_concepts/scheduling.page +87 -0
- data/doc/guide/src/advanced_concepts/transactions.page +5 -0
- data/doc/guide/src/advanced_concepts/unreachability.page +42 -0
- data/doc/guide/src/base.template +96 -0
- data/doc/guide/src/basics_shell_header.txt +5 -7
- data/doc/guide/src/building/action_coordination.page +96 -0
- data/doc/guide/src/building/actions.page +124 -0
- data/doc/guide/src/building/file_layout.page +71 -0
- data/doc/guide/src/building/index.page +50 -0
- data/doc/guide/src/building/patterns.page +86 -0
- data/doc/guide/src/building/patterns_forwarding.png +0 -0
- data/doc/guide/src/building/patterns_forwarding.svg +277 -0
- data/doc/guide/src/building/runtime.page +95 -0
- data/doc/guide/src/building/task_models.page +94 -0
- data/doc/guide/src/building/tasks.page +284 -0
- data/doc/guide/src/concepts/error_handling.page +100 -0
- data/doc/guide/src/concepts/exception_propagation.png +0 -0
- data/doc/guide/src/concepts/exception_propagation.svg +445 -0
- data/doc/guide/src/concepts/execution.page +85 -0
- data/doc/guide/src/concepts/execution.png +0 -0
- data/doc/guide/src/concepts/execution.svg +573 -0
- data/doc/guide/src/concepts/execution_cycle.png +0 -0
- data/doc/guide/src/concepts/garbage_collection.page +57 -0
- data/doc/guide/src/concepts/index.page +27 -0
- data/doc/guide/src/concepts/plans.page +101 -0
- data/doc/guide/src/concepts/policy.page +31 -0
- data/doc/guide/src/concepts/reactor.page +61 -0
- data/doc/guide/src/concepts/simple_plan_example.png +0 -0
- data/doc/guide/src/concepts/simple_plan_example.svg +376 -0
- data/doc/guide/src/default.template +9 -74
- data/doc/guide/src/event_relations/forward.page +71 -0
- data/doc/guide/src/event_relations/index.page +12 -0
- data/doc/guide/src/event_relations/scheduling_constraints.page +43 -0
- data/doc/guide/src/event_relations/signal.page +55 -0
- data/doc/guide/src/event_relations/temporal_constraints.page +77 -0
- data/doc/guide/src/htmldoc.metainfo +21 -8
- data/doc/guide/src/index.page +8 -3
- data/doc/guide/src/{introduction/install.page → installation/index.page} +37 -25
- data/doc/guide/src/installation/publications.page +14 -0
- data/doc/guide/src/{introduction → installation}/videos.page +14 -7
- data/doc/guide/src/interacting/index.page +16 -0
- data/doc/guide/src/interacting/run.page +33 -0
- data/doc/guide/src/interacting/shell.page +95 -0
- data/doc/guide/src/plugins/creating_plugins.page +72 -0
- data/doc/guide/src/plugins/index.page +27 -5
- data/doc/guide/src/plugins/{fault_tolerance.page → standard_plugins/fault_tolerance.page} +2 -2
- data/doc/guide/src/plugins/standard_plugins/index.page +11 -0
- data/doc/guide/src/plugins/{subsystems.page → standard_plugins/subsystems.page} +2 -2
- data/doc/guide/src/style_screen.css +687 -0
- data/doc/guide/src/task_relations/dependency.page +107 -0
- data/doc/guide/src/task_relations/executed_by.page +77 -0
- data/doc/guide/src/task_relations/index.page +12 -0
- data/doc/guide/src/task_relations/new_relations.page +119 -0
- data/doc/guide/src/task_relations/planned_by.page +46 -0
- data/doc/guide/src/tutorial/app.page +117 -0
- data/doc/guide/src/{basics → tutorial}/code_examples.page +6 -5
- data/doc/guide/src/{basics → tutorial}/dry.page +15 -15
- data/doc/guide/src/{basics → tutorial}/errors.page +43 -68
- data/doc/guide/src/tutorial/events.page +195 -0
- data/doc/guide/src/{basics → tutorial}/hierarchy.page +53 -52
- data/doc/guide/src/tutorial/index.page +13 -0
- data/doc/guide/src/tutorial/log_replay/goForward_1.png +0 -0
- data/doc/guide/src/tutorial/log_replay/goForward_2.png +0 -0
- data/doc/guide/src/tutorial/log_replay/goForward_3.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/goForward_4.png +0 -0
- data/doc/guide/src/tutorial/log_replay/goForward_5.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/hierarchy_error_1.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/hierarchy_error_2.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/hierarchy_error_3.png +0 -0
- data/doc/guide/src/tutorial/log_replay/moveto_code_error.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/plan_repair_1.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/plan_repair_2.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/plan_repair_3.png +0 -0
- data/doc/guide/src/tutorial/log_replay/plan_repair_4.png +0 -0
- data/doc/guide/src/tutorial/log_replay/roby_log_main_window.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/roby_log_relation_window.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/roby_replay_event_representation.png +0 -0
- data/doc/guide/src/tutorial/relations_display.page +153 -0
- data/doc/guide/src/{basics → tutorial}/roby_cycle_overview.png +0 -0
- data/doc/guide/src/tutorial/shell.page +121 -0
- data/doc/guide/src/{basics → tutorial}/summary.page +1 -1
- data/doc/guide/src/tutorial/tasks.page +374 -0
- data/lib/roby.rb +102 -47
- data/lib/roby/actions.rb +17 -0
- data/lib/roby/actions/action.rb +80 -0
- data/lib/roby/actions/interface.rb +45 -0
- data/lib/roby/actions/library.rb +23 -0
- data/lib/roby/actions/models/action.rb +224 -0
- data/lib/roby/actions/models/coordination_action.rb +58 -0
- data/lib/roby/actions/models/interface.rb +22 -0
- data/lib/roby/actions/models/interface_base.rb +294 -0
- data/lib/roby/actions/models/library.rb +12 -0
- data/lib/roby/actions/models/method_action.rb +90 -0
- data/lib/roby/actions/task.rb +114 -0
- data/lib/roby/and_generator.rb +125 -0
- data/lib/roby/app.rb +2795 -829
- data/lib/roby/app/autotest_console_reporter.rb +138 -0
- data/lib/roby/app/base.rb +21 -0
- data/lib/roby/app/cucumber.rb +2 -0
- data/lib/roby/app/cucumber/controller.rb +439 -0
- data/lib/roby/app/cucumber/helpers.rb +280 -0
- data/lib/roby/app/cucumber/world.rb +32 -0
- data/lib/roby/app/debug.rb +136 -0
- data/lib/roby/app/gen.rb +2 -0
- data/lib/roby/app/rake.rb +178 -38
- data/lib/roby/app/robot_config.rb +9 -0
- data/lib/roby/app/robot_names.rb +115 -0
- data/lib/roby/app/run.rb +3 -2
- data/lib/roby/app/scripts.rb +72 -0
- data/lib/roby/app/scripts/autotest.rb +173 -0
- data/lib/roby/app/scripts/display.rb +2 -0
- data/lib/roby/app/scripts/restart.rb +52 -0
- data/lib/roby/app/scripts/results.rb +17 -8
- data/lib/roby/app/scripts/run.rb +155 -24
- data/lib/roby/app/scripts/shell.rb +147 -62
- data/lib/roby/app/scripts/test.rb +107 -22
- data/lib/roby/app/test_reporter.rb +74 -0
- data/lib/roby/app/test_server.rb +159 -0
- data/lib/roby/app/vagrant.rb +47 -0
- data/lib/roby/backports.rb +16 -0
- data/lib/roby/cli/display.rb +190 -0
- data/lib/roby/cli/exceptions.rb +17 -0
- data/lib/roby/cli/gen/actions/class.rb +5 -0
- data/lib/roby/cli/gen/actions/test.rb +6 -0
- data/lib/roby/cli/gen/app/.yardopts +6 -0
- data/lib/roby/cli/gen/app/README.md +28 -0
- data/lib/roby/cli/gen/app/Rakefile +15 -0
- data/{app → lib/roby/cli/gen/app}/config/app.yml +29 -39
- data/lib/roby/cli/gen/app/models/.gitattributes +1 -0
- data/{app → lib/roby/cli/gen/app/scripts}/controllers/.gitattributes +0 -0
- data/{app/data/.gitattributes → lib/roby/cli/gen/app/test/.gitignore} +0 -0
- data/lib/roby/cli/gen/class/class.rb +6 -0
- data/lib/roby/cli/gen/class/test.rb +7 -0
- data/lib/roby/cli/gen/helpers.rb +203 -0
- data/lib/roby/cli/gen/module/module.rb +5 -0
- data/lib/roby/cli/gen/module/test.rb +6 -0
- data/lib/roby/cli/gen/roby_app/config/init.rb +17 -0
- data/lib/roby/cli/gen/roby_app/config/robots/robot.rb +40 -0
- data/lib/roby/cli/gen/task/class.rb +44 -0
- data/lib/roby/cli/gen/task/test.rb +6 -0
- data/lib/roby/cli/gen_main.rb +120 -0
- data/lib/roby/cli/log.rb +276 -0
- data/lib/roby/cli/log/flamegraph.html +499 -0
- data/lib/roby/cli/log/flamegraph_renderer.rb +88 -0
- data/lib/roby/cli/main.rb +153 -0
- data/lib/roby/coordination.rb +60 -0
- data/lib/roby/coordination/action_script.rb +25 -0
- data/lib/roby/coordination/action_state_machine.rb +125 -0
- data/lib/roby/coordination/actions.rb +106 -0
- data/lib/roby/coordination/base.rb +145 -0
- data/lib/roby/coordination/calculus.rb +40 -0
- data/lib/roby/coordination/child.rb +28 -0
- data/lib/roby/coordination/event.rb +29 -0
- data/lib/roby/coordination/fault_handler.rb +25 -0
- data/lib/roby/coordination/fault_handling_task.rb +13 -0
- data/lib/roby/coordination/fault_response_table.rb +110 -0
- data/lib/roby/coordination/models/action_script.rb +64 -0
- data/lib/roby/coordination/models/action_state_machine.rb +224 -0
- data/lib/roby/coordination/models/actions.rb +191 -0
- data/lib/roby/coordination/models/arguments.rb +55 -0
- data/lib/roby/coordination/models/base.rb +176 -0
- data/lib/roby/coordination/models/capture.rb +86 -0
- data/lib/roby/coordination/models/child.rb +35 -0
- data/lib/roby/coordination/models/event.rb +41 -0
- data/lib/roby/coordination/models/exceptions.rb +42 -0
- data/lib/roby/coordination/models/fault_handler.rb +219 -0
- data/lib/roby/coordination/models/fault_response_table.rb +77 -0
- data/lib/roby/coordination/models/root.rb +22 -0
- data/lib/roby/coordination/models/script.rb +283 -0
- data/lib/roby/coordination/models/task.rb +184 -0
- data/lib/roby/coordination/models/task_from_action.rb +50 -0
- data/lib/roby/coordination/models/task_from_as_plan.rb +33 -0
- data/lib/roby/coordination/models/task_from_instanciation_object.rb +31 -0
- data/lib/roby/coordination/models/task_from_variable.rb +27 -0
- data/lib/roby/coordination/models/task_with_dependencies.rb +48 -0
- data/lib/roby/coordination/models/variable.rb +32 -0
- data/lib/roby/coordination/script.rb +200 -0
- data/lib/roby/coordination/script_instruction.rb +12 -0
- data/lib/roby/coordination/task.rb +45 -0
- data/lib/roby/coordination/task_base.rb +69 -0
- data/lib/roby/coordination/task_script.rb +293 -0
- data/lib/roby/coordination/task_state_machine.rb +308 -0
- data/lib/roby/decision_control.rb +33 -21
- data/lib/roby/distributed_object.rb +76 -0
- data/lib/roby/droby.rb +17 -0
- data/lib/roby/droby/droby_id.rb +6 -0
- data/lib/roby/droby/enable.rb +153 -0
- data/lib/roby/droby/event_logger.rb +189 -0
- data/lib/roby/droby/event_logging.rb +57 -0
- data/lib/roby/droby/exceptions.rb +14 -0
- data/lib/roby/droby/identifiable.rb +22 -0
- data/lib/roby/droby/logfile.rb +141 -0
- data/lib/roby/droby/logfile/client.rb +176 -0
- data/lib/roby/droby/logfile/file_format.md +97 -0
- data/lib/roby/droby/logfile/index.rb +117 -0
- data/lib/roby/droby/logfile/reader.rb +139 -0
- data/lib/roby/droby/logfile/server.rb +199 -0
- data/lib/roby/droby/logfile/writer.rb +114 -0
- data/lib/roby/droby/marshal.rb +264 -0
- data/lib/roby/droby/marshallable.rb +12 -0
- data/lib/roby/droby/null_event_logger.rb +25 -0
- data/lib/roby/droby/object_manager.rb +205 -0
- data/lib/roby/droby/peer_id.rb +6 -0
- data/lib/roby/droby/plan_rebuilder.rb +373 -0
- data/lib/roby/droby/rebuilt_plan.rb +160 -0
- data/lib/roby/droby/remote_droby_id.rb +6 -0
- data/lib/roby/droby/timepoints.rb +205 -0
- data/lib/roby/droby/timepoints_ctf.metadata.erb +101 -0
- data/lib/roby/droby/timepoints_ctf.rb +125 -0
- data/lib/roby/droby/v5.rb +14 -0
- data/lib/roby/droby/v5/builtin.rb +120 -0
- data/lib/roby/droby/v5/droby_class.rb +45 -0
- data/lib/roby/droby/v5/droby_constant.rb +81 -0
- data/lib/roby/droby/v5/droby_dump.rb +1026 -0
- data/lib/roby/droby/v5/droby_id.rb +44 -0
- data/lib/roby/droby/v5/droby_model.rb +82 -0
- data/lib/roby/droby/v5/peer_id.rb +10 -0
- data/lib/roby/droby/v5/remote_droby_id.rb +42 -0
- data/lib/roby/event.rb +79 -957
- data/lib/roby/event_constraints.rb +835 -0
- data/lib/roby/event_generator.rb +1047 -0
- data/lib/roby/event_structure/causal_link.rb +6 -0
- data/lib/roby/event_structure/forwarding.rb +6 -0
- data/lib/roby/event_structure/precedence.rb +7 -0
- data/lib/roby/event_structure/signal.rb +8 -0
- data/lib/roby/event_structure/temporal_constraints.rb +640 -0
- data/lib/roby/exceptions.rb +446 -152
- data/lib/roby/executable_plan.rb +549 -0
- data/lib/roby/execution_engine.rb +1997 -950
- data/lib/roby/filter_generator.rb +26 -0
- data/lib/roby/gui/chronicle_view.rb +225 -0
- data/lib/roby/gui/chronicle_widget.rb +925 -0
- data/lib/roby/gui/dot_id.rb +11 -0
- data/lib/roby/gui/exception_view.rb +44 -0
- data/lib/roby/gui/log_display.rb +273 -0
- data/lib/roby/gui/model_views.rb +2 -0
- data/lib/roby/gui/model_views/action_interface.rb +53 -0
- data/lib/roby/gui/model_views/task.rb +47 -0
- data/lib/roby/gui/model_views/task.rhtml +41 -0
- data/lib/roby/gui/object_info_view.rb +89 -0
- data/lib/roby/gui/plan_dot_layout.rb +427 -0
- data/lib/roby/gui/plan_rebuilder_widget.rb +357 -0
- data/lib/roby/gui/qt4_toMSecsSinceEpoch.rb +8 -0
- data/lib/roby/gui/relations_view.rb +278 -0
- data/lib/roby/gui/relations_view/relations.ui +139 -0
- data/lib/roby/gui/relations_view/relations_canvas.rb +1088 -0
- data/lib/roby/gui/relations_view/relations_config.rb +292 -0
- data/lib/roby/gui/relations_view/relations_view.ui +53 -0
- data/lib/roby/gui/scheduler_view.css +24 -0
- data/lib/roby/gui/scheduler_view.rb +46 -0
- data/lib/roby/gui/scheduler_view.rhtml +53 -0
- data/lib/roby/gui/stepping.rb +93 -0
- data/lib/roby/gui/stepping.ui +181 -0
- data/lib/roby/gui/styles.rb +81 -0
- data/lib/roby/gui/task_display_configuration.rb +42 -0
- data/lib/roby/gui/task_state_at.rb +38 -0
- data/lib/roby/hooks.rb +26 -0
- data/lib/roby/interface.rb +136 -469
- data/lib/roby/interface/async.rb +20 -0
- data/lib/roby/interface/async/action_monitor.rb +188 -0
- data/lib/roby/interface/async/interface.rb +498 -0
- data/lib/roby/interface/async/job_monitor.rb +213 -0
- data/lib/roby/interface/async/log.rb +238 -0
- data/lib/roby/interface/async/new_job_listener.rb +79 -0
- data/lib/roby/interface/async/ui_connector.rb +183 -0
- data/lib/roby/interface/client.rb +553 -0
- data/lib/roby/interface/command.rb +24 -0
- data/lib/roby/interface/command_argument.rb +16 -0
- data/lib/roby/interface/command_library.rb +92 -0
- data/lib/roby/interface/droby_channel.rb +174 -0
- data/lib/roby/interface/exceptions.rb +22 -0
- data/lib/roby/interface/interface.rb +655 -0
- data/lib/roby/interface/job.rb +47 -0
- data/lib/roby/interface/rest.rb +10 -0
- data/lib/roby/interface/rest/api.rb +29 -0
- data/lib/roby/interface/rest/helpers.rb +24 -0
- data/lib/roby/interface/rest/server.rb +212 -0
- data/lib/roby/interface/server.rb +154 -0
- data/lib/roby/interface/shell_client.rb +468 -0
- data/lib/roby/interface/shell_subcommand.rb +24 -0
- data/lib/roby/interface/subcommand_client.rb +35 -0
- data/lib/roby/interface/tcp.rb +168 -0
- data/lib/roby/models/arguments.rb +112 -0
- data/lib/roby/models/plan_object.rb +83 -0
- data/lib/roby/models/task.rb +835 -0
- data/lib/roby/models/task_event.rb +62 -0
- data/lib/roby/models/task_service.rb +78 -0
- data/lib/roby/or_generator.rb +88 -0
- data/lib/roby/plan.rb +1751 -864
- data/lib/roby/plan_object.rb +611 -0
- data/lib/roby/plan_service.rb +200 -0
- data/lib/roby/promise.rb +332 -0
- data/lib/roby/queries.rb +23 -0
- data/lib/roby/queries/and_matcher.rb +32 -0
- data/lib/roby/queries/any.rb +27 -0
- data/lib/roby/queries/code_error_matcher.rb +58 -0
- data/lib/roby/queries/event_generator_matcher.rb +9 -0
- data/lib/roby/queries/execution_exception_matcher.rb +165 -0
- data/lib/roby/queries/index.rb +165 -0
- data/lib/roby/queries/localized_error_matcher.rb +149 -0
- data/lib/roby/queries/matcher_base.rb +107 -0
- data/lib/roby/queries/none.rb +27 -0
- data/lib/roby/queries/not_matcher.rb +30 -0
- data/lib/roby/queries/op_matcher.rb +8 -0
- data/lib/roby/queries/or_matcher.rb +30 -0
- data/lib/roby/queries/plan_object_matcher.rb +363 -0
- data/lib/roby/queries/query.rb +188 -0
- data/lib/roby/queries/task_event_generator_matcher.rb +86 -0
- data/lib/roby/queries/task_matcher.rb +344 -0
- data/lib/roby/relations.rb +42 -678
- data/lib/roby/relations/bidirectional_directed_adjacency_graph.rb +492 -0
- data/lib/roby/relations/directed_relation_support.rb +268 -0
- data/lib/roby/relations/event_relation_graph.rb +19 -0
- data/lib/roby/relations/fork_merge_visitor.rb +154 -0
- data/lib/roby/relations/graph.rb +533 -0
- data/lib/roby/relations/models/directed_relation_support.rb +11 -0
- data/lib/roby/relations/models/graph.rb +75 -0
- data/lib/roby/relations/models/task_relation_graph.rb +18 -0
- data/lib/roby/relations/space.rb +380 -0
- data/lib/roby/relations/task_relation_graph.rb +20 -0
- data/lib/roby/robot.rb +85 -38
- data/lib/roby/schedulers/basic.rb +155 -25
- data/lib/roby/schedulers/null.rb +20 -0
- data/lib/roby/schedulers/reporting.rb +31 -0
- data/lib/roby/schedulers/state.rb +129 -0
- data/lib/roby/schedulers/temporal.rb +91 -0
- data/lib/roby/singletons.rb +87 -0
- data/lib/roby/standalone.rb +4 -2
- data/lib/roby/standard_errors.rb +405 -82
- data/lib/roby/state.rb +6 -3
- data/lib/roby/state/conf_model.rb +5 -0
- data/lib/roby/state/events.rb +181 -95
- data/lib/roby/state/goal_model.rb +77 -0
- data/lib/roby/state/open_struct.rb +591 -0
- data/lib/roby/state/open_struct_model.rb +68 -0
- data/lib/roby/state/pos.rb +45 -45
- data/lib/roby/state/shapes.rb +11 -11
- data/lib/roby/state/state_model.rb +303 -0
- data/lib/roby/state/task.rb +43 -0
- data/lib/roby/support.rb +88 -148
- data/lib/roby/task.rb +1361 -1750
- data/lib/roby/task_arguments.rb +428 -0
- data/lib/roby/task_event.rb +127 -0
- data/lib/roby/task_event_generator.rb +337 -0
- data/lib/roby/task_service.rb +6 -0
- data/lib/roby/task_structure/conflicts.rb +104 -0
- data/lib/roby/task_structure/dependency.rb +932 -0
- data/lib/roby/task_structure/error_handling.rb +118 -0
- data/lib/roby/task_structure/executed_by.rb +234 -0
- data/lib/roby/task_structure/planned_by.rb +90 -0
- data/lib/roby/tasks/aggregator.rb +37 -0
- data/lib/roby/tasks/external_process.rb +275 -0
- data/lib/roby/tasks/group.rb +27 -0
- data/lib/roby/tasks/null.rb +19 -0
- data/lib/roby/tasks/parallel.rb +43 -0
- data/lib/roby/tasks/sequence.rb +88 -0
- data/lib/roby/tasks/simple.rb +21 -0
- data/lib/roby/{thread_task.rb → tasks/thread.rb} +50 -24
- data/lib/roby/tasks/timeout.rb +17 -0
- data/lib/roby/tasks/virtual.rb +55 -0
- data/lib/roby/template_plan.rb +7 -0
- data/lib/roby/test/aruba_minitest.rb +74 -0
- data/lib/roby/test/assertion.rb +16 -0
- data/lib/roby/test/assertions.rb +490 -0
- data/lib/roby/test/common.rb +368 -591
- data/lib/roby/test/dsl.rb +149 -0
- data/lib/roby/test/error.rb +18 -0
- data/lib/roby/test/event_reporter.rb +83 -0
- data/lib/roby/test/execution_expectations.rb +1134 -0
- data/lib/roby/test/expect_execution.rb +151 -0
- data/lib/roby/test/minitest_helpers.rb +166 -0
- data/lib/roby/test/roby_app_helpers.rb +200 -0
- data/lib/roby/test/run_planners.rb +155 -0
- data/lib/roby/test/self.rb +112 -0
- data/lib/roby/test/spec.rb +198 -0
- data/lib/roby/test/tasks/empty_task.rb +4 -4
- data/lib/roby/test/tasks/goto.rb +28 -27
- data/lib/roby/test/teardown_plans.rb +100 -0
- data/lib/roby/test/testcase.rb +239 -307
- data/lib/roby/test/tools.rb +159 -155
- data/lib/roby/test/validate_state_machine.rb +75 -0
- data/lib/roby/transaction.rb +1125 -0
- data/lib/roby/transaction/event_generator_proxy.rb +63 -0
- data/lib/roby/transaction/plan_object_proxy.rb +99 -0
- data/lib/roby/transaction/plan_service_proxy.rb +43 -0
- data/lib/roby/transaction/proxying.rb +120 -0
- data/lib/roby/transaction/task_event_generator_proxy.rb +19 -0
- data/lib/roby/transaction/task_proxy.rb +135 -0
- data/lib/roby/until_generator.rb +30 -0
- data/lib/roby/version.rb +5 -0
- data/lib/roby/yard.rb +169 -0
- data/lib/yard-roby.rb +1 -0
- data/manifest.xml +32 -6
- data/roby.gemspec +59 -0
- metadata +788 -587
- data/Manifest.txt +0 -321
- data/NOTES +0 -4
- data/README.txt +0 -166
- data/TODO.txt +0 -146
- data/app/README.txt +0 -24
- data/app/Rakefile +0 -8
- data/app/config/ROBOT.rb +0 -5
- data/app/config/init.rb +0 -33
- data/app/config/roby.yml +0 -3
- data/app/controllers/ROBOT.rb +0 -2
- data/app/planners/ROBOT/main.rb +0 -6
- data/app/planners/main.rb +0 -5
- data/app/scripts/distributed +0 -3
- data/app/scripts/generate/bookmarks +0 -3
- data/app/scripts/replay +0 -3
- data/app/scripts/results +0 -3
- data/app/scripts/run +0 -3
- data/app/scripts/server +0 -3
- data/app/scripts/shell +0 -3
- data/app/scripts/test +0 -3
- data/app/tasks/.gitattributes +0 -0
- data/app/tasks/ROBOT/.gitattributes +0 -0
- data/bin/roby-shell +0 -25
- data/doc/guide/src/basics/app.page +0 -139
- data/doc/guide/src/basics/index.page +0 -11
- data/doc/guide/src/basics/log_replay/goForward_1.png +0 -0
- data/doc/guide/src/basics/log_replay/goForward_2.png +0 -0
- data/doc/guide/src/basics/log_replay/goForward_3.png +0 -0
- data/doc/guide/src/basics/log_replay/goForward_5.png +0 -0
- data/doc/guide/src/basics/log_replay/plan_repair_4.png +0 -0
- data/doc/guide/src/basics/log_replay/roby_log_main_window.png +0 -0
- data/doc/guide/src/basics/relations_display.page +0 -203
- data/doc/guide/src/basics/shell.page +0 -102
- data/doc/guide/src/default.css +0 -319
- data/doc/guide/src/introduction/index.page +0 -29
- data/doc/guide/src/introduction/publications.page +0 -14
- data/doc/guide/src/relations/dependency.page +0 -89
- data/doc/guide/src/relations/index.page +0 -12
- data/ext/droby/dump.cc +0 -175
- data/ext/droby/extconf.rb +0 -3
- data/ext/graph/algorithm.cc +0 -746
- data/ext/graph/extconf.rb +0 -7
- data/ext/graph/graph.cc +0 -575
- data/ext/graph/graph.hh +0 -183
- data/ext/graph/iterator_sequence.hh +0 -102
- data/ext/graph/undirected_dfs.hh +0 -226
- data/ext/graph/undirected_graph.hh +0 -421
- data/lib/roby/app/scripts/generate/bookmarks.rb +0 -162
- data/lib/roby/app/scripts/replay.rb +0 -31
- data/lib/roby/app/scripts/server.rb +0 -18
- data/lib/roby/basic_object.rb +0 -151
- data/lib/roby/config.rb +0 -14
- data/lib/roby/distributed.rb +0 -36
- data/lib/roby/distributed/base.rb +0 -448
- data/lib/roby/distributed/communication.rb +0 -875
- data/lib/roby/distributed/connection_space.rb +0 -616
- data/lib/roby/distributed/distributed_object.rb +0 -206
- data/lib/roby/distributed/drb.rb +0 -62
- data/lib/roby/distributed/notifications.rb +0 -531
- data/lib/roby/distributed/peer.rb +0 -555
- data/lib/roby/distributed/protocol.rb +0 -529
- data/lib/roby/distributed/proxy.rb +0 -343
- data/lib/roby/distributed/subscription.rb +0 -311
- data/lib/roby/distributed/transaction.rb +0 -498
- data/lib/roby/external_process_task.rb +0 -225
- data/lib/roby/graph.rb +0 -160
- data/lib/roby/log.rb +0 -3
- data/lib/roby/log/chronicle.rb +0 -303
- data/lib/roby/log/console.rb +0 -74
- data/lib/roby/log/data_stream.rb +0 -275
- data/lib/roby/log/dot.rb +0 -279
- data/lib/roby/log/event_stream.rb +0 -161
- data/lib/roby/log/file.rb +0 -396
- data/lib/roby/log/gui/basic_display.ui +0 -83
- data/lib/roby/log/gui/basic_display_ui.rb +0 -89
- data/lib/roby/log/gui/chronicle.rb +0 -26
- data/lib/roby/log/gui/chronicle_view.rb +0 -40
- data/lib/roby/log/gui/chronicle_view.ui +0 -70
- data/lib/roby/log/gui/chronicle_view_ui.rb +0 -90
- data/lib/roby/log/gui/data_displays.rb +0 -171
- data/lib/roby/log/gui/data_displays.ui +0 -155
- data/lib/roby/log/gui/data_displays_ui.rb +0 -146
- data/lib/roby/log/gui/notifications.rb +0 -26
- data/lib/roby/log/gui/relations.rb +0 -269
- data/lib/roby/log/gui/relations.ui +0 -123
- data/lib/roby/log/gui/relations_ui.rb +0 -120
- data/lib/roby/log/gui/relations_view.rb +0 -185
- data/lib/roby/log/gui/relations_view.ui +0 -149
- data/lib/roby/log/gui/relations_view_ui.rb +0 -144
- data/lib/roby/log/gui/replay.rb +0 -366
- data/lib/roby/log/gui/replay_controls.rb +0 -206
- data/lib/roby/log/gui/replay_controls.ui +0 -282
- data/lib/roby/log/gui/replay_controls_ui.rb +0 -249
- data/lib/roby/log/gui/runtime.rb +0 -130
- data/lib/roby/log/hooks.rb +0 -186
- data/lib/roby/log/logger.rb +0 -203
- data/lib/roby/log/notifications.rb +0 -244
- data/lib/roby/log/plan_rebuilder.rb +0 -468
- data/lib/roby/log/relations.rb +0 -1084
- data/lib/roby/log/server.rb +0 -547
- data/lib/roby/log/sqlite.rb +0 -47
- data/lib/roby/log/timings.rb +0 -233
- data/lib/roby/plan-object.rb +0 -371
- data/lib/roby/planning.rb +0 -13
- data/lib/roby/planning/loops.rb +0 -309
- data/lib/roby/planning/model.rb +0 -1012
- data/lib/roby/planning/task.rb +0 -180
- data/lib/roby/query.rb +0 -655
- data/lib/roby/relations/conflicts.rb +0 -67
- data/lib/roby/relations/dependency.rb +0 -358
- data/lib/roby/relations/ensured.rb +0 -19
- data/lib/roby/relations/error_handling.rb +0 -22
- data/lib/roby/relations/events.rb +0 -7
- data/lib/roby/relations/executed_by.rb +0 -208
- data/lib/roby/relations/influence.rb +0 -10
- data/lib/roby/relations/planned_by.rb +0 -63
- data/lib/roby/state/information.rb +0 -55
- data/lib/roby/state/state.rb +0 -367
- data/lib/roby/task-operations.rb +0 -186
- data/lib/roby/task_index.rb +0 -80
- data/lib/roby/test/distributed.rb +0 -230
- data/lib/roby/test/tasks/simple_task.rb +0 -23
- data/lib/roby/transactions.rb +0 -507
- data/lib/roby/transactions/proxy.rb +0 -325
- data/plugins/fault_injection/History.txt +0 -4
- data/plugins/fault_injection/README.txt +0 -34
- data/plugins/fault_injection/Rakefile +0 -12
- data/plugins/fault_injection/TODO.txt +0 -0
- data/plugins/fault_injection/app.rb +0 -52
- data/plugins/fault_injection/fault_injection.rb +0 -89
- data/plugins/fault_injection/test/test_fault_injection.rb +0 -78
- data/plugins/subsystems/README.txt +0 -37
- data/plugins/subsystems/Rakefile +0 -13
- data/plugins/subsystems/app.rb +0 -182
- data/plugins/subsystems/test/app/README +0 -24
- data/plugins/subsystems/test/app/Rakefile +0 -8
- data/plugins/subsystems/test/app/config/app.yml +0 -71
- data/plugins/subsystems/test/app/config/init.rb +0 -12
- data/plugins/subsystems/test/app/config/roby.yml +0 -3
- data/plugins/subsystems/test/app/planners/main.rb +0 -20
- data/plugins/subsystems/test/app/scripts/distributed +0 -3
- data/plugins/subsystems/test/app/scripts/replay +0 -3
- data/plugins/subsystems/test/app/scripts/results +0 -3
- data/plugins/subsystems/test/app/scripts/run +0 -3
- data/plugins/subsystems/test/app/scripts/server +0 -3
- data/plugins/subsystems/test/app/scripts/shell +0 -3
- data/plugins/subsystems/test/app/scripts/test +0 -3
- data/plugins/subsystems/test/app/tasks/services.rb +0 -15
- data/plugins/subsystems/test/test_subsystems.rb +0 -78
- data/test/distributed/test_communication.rb +0 -195
- data/test/distributed/test_connection.rb +0 -284
- data/test/distributed/test_execution.rb +0 -378
- data/test/distributed/test_mixed_plan.rb +0 -341
- data/test/distributed/test_plan_notifications.rb +0 -238
- data/test/distributed/test_protocol.rb +0 -525
- data/test/distributed/test_query.rb +0 -106
- data/test/distributed/test_remote_plan.rb +0 -491
- data/test/distributed/test_transaction.rb +0 -466
- data/test/mockups/external_process +0 -28
- data/test/mockups/tasks.rb +0 -27
- data/test/planning/test_loops.rb +0 -432
- data/test/planning/test_model.rb +0 -427
- data/test/planning/test_task.rb +0 -126
- data/test/relations/test_conflicts.rb +0 -42
- data/test/relations/test_dependency.rb +0 -324
- data/test/relations/test_ensured.rb +0 -38
- data/test/relations/test_executed_by.rb +0 -224
- data/test/relations/test_planned_by.rb +0 -56
- data/test/suite_core.rb +0 -29
- data/test/suite_distributed.rb +0 -10
- data/test/suite_planning.rb +0 -4
- data/test/suite_relations.rb +0 -8
- data/test/tasks/test_external_process.rb +0 -126
- data/test/tasks/test_thread_task.rb +0 -70
- data/test/test_bgl.rb +0 -528
- data/test/test_event.rb +0 -969
- data/test/test_exceptions.rb +0 -591
- data/test/test_execution_engine.rb +0 -987
- data/test/test_gui.rb +0 -20
- data/test/test_interface.rb +0 -43
- data/test/test_log.rb +0 -125
- data/test/test_log_server.rb +0 -133
- data/test/test_plan.rb +0 -418
- data/test/test_query.rb +0 -424
- data/test/test_relations.rb +0 -260
- data/test/test_state.rb +0 -432
- data/test/test_support.rb +0 -16
- data/test/test_task.rb +0 -1181
- data/test/test_testcase.rb +0 -138
- data/test/test_transactions.rb +0 -610
- 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
|
+
|