roby 0.7.3 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|