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