roby 0.7
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/.gitignore +29 -0
- data/History.txt +4 -0
- data/License-fr.txt +519 -0
- data/License.txt +515 -0
- data/Manifest.txt +245 -0
- data/NOTES +4 -0
- data/README.txt +163 -0
- data/Rakefile +161 -0
- data/TODO.txt +146 -0
- data/app/README.txt +24 -0
- data/app/Rakefile +8 -0
- data/app/config/ROBOT.rb +5 -0
- data/app/config/app.yml +91 -0
- data/app/config/init.rb +7 -0
- data/app/config/roby.yml +3 -0
- data/app/controllers/.gitattributes +0 -0
- data/app/controllers/ROBOT.rb +2 -0
- data/app/data/.gitattributes +0 -0
- data/app/planners/ROBOT/main.rb +6 -0
- data/app/planners/main.rb +5 -0
- data/app/scripts/distributed +3 -0
- data/app/scripts/generate/bookmarks +3 -0
- data/app/scripts/replay +3 -0
- data/app/scripts/results +3 -0
- data/app/scripts/run +3 -0
- data/app/scripts/server +3 -0
- data/app/scripts/shell +3 -0
- data/app/scripts/test +3 -0
- data/app/tasks/.gitattributes +0 -0
- data/app/tasks/ROBOT/.gitattributes +0 -0
- data/bin/roby +210 -0
- data/bin/roby-log +168 -0
- data/bin/roby-shell +25 -0
- data/doc/images/event_generalization.png +0 -0
- data/doc/images/exception_propagation_1.png +0 -0
- data/doc/images/exception_propagation_2.png +0 -0
- data/doc/images/exception_propagation_3.png +0 -0
- data/doc/images/exception_propagation_4.png +0 -0
- data/doc/images/exception_propagation_5.png +0 -0
- data/doc/images/replay_handler_error.png +0 -0
- data/doc/images/replay_handler_error_0.png +0 -0
- data/doc/images/replay_handler_error_1.png +0 -0
- data/doc/images/roby_cycle_overview.png +0 -0
- data/doc/images/roby_replay_02.png +0 -0
- data/doc/images/roby_replay_03.png +0 -0
- data/doc/images/roby_replay_04.png +0 -0
- data/doc/images/roby_replay_event_representation.png +0 -0
- data/doc/images/roby_replay_first_state.png +0 -0
- data/doc/images/roby_replay_relations.png +0 -0
- data/doc/images/roby_replay_startup.png +0 -0
- data/doc/images/task_event_generalization.png +0 -0
- data/doc/papers.rdoc +11 -0
- data/doc/styles/allison.css +314 -0
- data/doc/styles/allison.js +316 -0
- data/doc/styles/allison.rb +276 -0
- data/doc/styles/jamis.rb +593 -0
- data/doc/tutorials/01-GettingStarted.rdoc +86 -0
- data/doc/tutorials/02-GoForward.rdoc +220 -0
- data/doc/tutorials/03-PlannedPath.rdoc +268 -0
- data/doc/tutorials/04-EventPropagation.rdoc +236 -0
- data/doc/tutorials/05-ErrorHandling.rdoc +319 -0
- data/doc/tutorials/06-Overview.rdoc +40 -0
- data/doc/videos.rdoc +69 -0
- data/ext/droby/dump.cc +175 -0
- data/ext/droby/extconf.rb +3 -0
- data/ext/graph/algorithm.cc +746 -0
- data/ext/graph/extconf.rb +7 -0
- data/ext/graph/graph.cc +529 -0
- data/ext/graph/graph.hh +183 -0
- data/ext/graph/iterator_sequence.hh +102 -0
- data/ext/graph/undirected_dfs.hh +226 -0
- data/ext/graph/undirected_graph.hh +421 -0
- data/lib/roby.rb +41 -0
- data/lib/roby/app.rb +870 -0
- data/lib/roby/app/rake.rb +56 -0
- data/lib/roby/app/run.rb +14 -0
- data/lib/roby/app/scripts/distributed.rb +13 -0
- data/lib/roby/app/scripts/generate/bookmarks.rb +162 -0
- data/lib/roby/app/scripts/replay.rb +31 -0
- data/lib/roby/app/scripts/results.rb +15 -0
- data/lib/roby/app/scripts/run.rb +26 -0
- data/lib/roby/app/scripts/server.rb +18 -0
- data/lib/roby/app/scripts/shell.rb +88 -0
- data/lib/roby/app/scripts/test.rb +40 -0
- data/lib/roby/basic_object.rb +151 -0
- data/lib/roby/config.rb +5 -0
- data/lib/roby/control.rb +747 -0
- data/lib/roby/decision_control.rb +17 -0
- data/lib/roby/distributed.rb +32 -0
- data/lib/roby/distributed/base.rb +440 -0
- data/lib/roby/distributed/communication.rb +871 -0
- data/lib/roby/distributed/connection_space.rb +592 -0
- data/lib/roby/distributed/distributed_object.rb +206 -0
- data/lib/roby/distributed/drb.rb +62 -0
- data/lib/roby/distributed/notifications.rb +539 -0
- data/lib/roby/distributed/peer.rb +550 -0
- data/lib/roby/distributed/protocol.rb +529 -0
- data/lib/roby/distributed/proxy.rb +343 -0
- data/lib/roby/distributed/subscription.rb +311 -0
- data/lib/roby/distributed/transaction.rb +498 -0
- data/lib/roby/event.rb +897 -0
- data/lib/roby/exceptions.rb +234 -0
- data/lib/roby/executives/simple.rb +30 -0
- data/lib/roby/graph.rb +166 -0
- data/lib/roby/interface.rb +390 -0
- data/lib/roby/log.rb +3 -0
- data/lib/roby/log/chronicle.rb +303 -0
- data/lib/roby/log/console.rb +72 -0
- data/lib/roby/log/data_stream.rb +197 -0
- data/lib/roby/log/dot.rb +279 -0
- data/lib/roby/log/event_stream.rb +151 -0
- data/lib/roby/log/file.rb +340 -0
- data/lib/roby/log/gui/basic_display.ui +83 -0
- data/lib/roby/log/gui/chronicle.rb +26 -0
- data/lib/roby/log/gui/chronicle_view.rb +40 -0
- data/lib/roby/log/gui/chronicle_view.ui +70 -0
- data/lib/roby/log/gui/data_displays.rb +172 -0
- data/lib/roby/log/gui/data_displays.ui +155 -0
- data/lib/roby/log/gui/notifications.rb +26 -0
- data/lib/roby/log/gui/relations.rb +248 -0
- data/lib/roby/log/gui/relations.ui +123 -0
- data/lib/roby/log/gui/relations_view.rb +185 -0
- data/lib/roby/log/gui/relations_view.ui +149 -0
- data/lib/roby/log/gui/replay.rb +327 -0
- data/lib/roby/log/gui/replay_controls.rb +200 -0
- data/lib/roby/log/gui/replay_controls.ui +259 -0
- data/lib/roby/log/gui/runtime.rb +130 -0
- data/lib/roby/log/hooks.rb +185 -0
- data/lib/roby/log/logger.rb +202 -0
- data/lib/roby/log/notifications.rb +244 -0
- data/lib/roby/log/plan_rebuilder.rb +470 -0
- data/lib/roby/log/relations.rb +1056 -0
- data/lib/roby/log/server.rb +550 -0
- data/lib/roby/log/sqlite.rb +47 -0
- data/lib/roby/log/timings.rb +164 -0
- data/lib/roby/plan-object.rb +247 -0
- data/lib/roby/plan.rb +762 -0
- data/lib/roby/planning.rb +13 -0
- data/lib/roby/planning/loops.rb +302 -0
- data/lib/roby/planning/model.rb +906 -0
- data/lib/roby/planning/task.rb +151 -0
- data/lib/roby/propagation.rb +562 -0
- data/lib/roby/query.rb +619 -0
- data/lib/roby/relations.rb +583 -0
- data/lib/roby/relations/conflicts.rb +70 -0
- data/lib/roby/relations/ensured.rb +20 -0
- data/lib/roby/relations/error_handling.rb +23 -0
- data/lib/roby/relations/events.rb +9 -0
- data/lib/roby/relations/executed_by.rb +193 -0
- data/lib/roby/relations/hierarchy.rb +239 -0
- data/lib/roby/relations/influence.rb +10 -0
- data/lib/roby/relations/planned_by.rb +63 -0
- data/lib/roby/robot.rb +7 -0
- data/lib/roby/standard_errors.rb +218 -0
- data/lib/roby/state.rb +5 -0
- data/lib/roby/state/events.rb +221 -0
- data/lib/roby/state/information.rb +55 -0
- data/lib/roby/state/pos.rb +110 -0
- data/lib/roby/state/shapes.rb +32 -0
- data/lib/roby/state/state.rb +353 -0
- data/lib/roby/support.rb +92 -0
- data/lib/roby/task-operations.rb +182 -0
- data/lib/roby/task.rb +1618 -0
- data/lib/roby/test/common.rb +399 -0
- data/lib/roby/test/distributed.rb +214 -0
- data/lib/roby/test/tasks/empty_task.rb +9 -0
- data/lib/roby/test/tasks/goto.rb +36 -0
- data/lib/roby/test/tasks/simple_task.rb +23 -0
- data/lib/roby/test/testcase.rb +519 -0
- data/lib/roby/test/tools.rb +160 -0
- data/lib/roby/thread_task.rb +87 -0
- data/lib/roby/transactions.rb +462 -0
- data/lib/roby/transactions/proxy.rb +292 -0
- data/lib/roby/transactions/updates.rb +139 -0
- data/plugins/fault_injection/History.txt +4 -0
- data/plugins/fault_injection/README.txt +37 -0
- data/plugins/fault_injection/Rakefile +18 -0
- data/plugins/fault_injection/TODO.txt +0 -0
- data/plugins/fault_injection/app.rb +52 -0
- data/plugins/fault_injection/fault_injection.rb +89 -0
- data/plugins/fault_injection/test/test_fault_injection.rb +84 -0
- data/plugins/subsystems/README.txt +40 -0
- data/plugins/subsystems/Rakefile +18 -0
- data/plugins/subsystems/app.rb +171 -0
- data/plugins/subsystems/test/app/README +24 -0
- data/plugins/subsystems/test/app/Rakefile +8 -0
- data/plugins/subsystems/test/app/config/app.yml +71 -0
- data/plugins/subsystems/test/app/config/init.rb +9 -0
- data/plugins/subsystems/test/app/config/roby.yml +3 -0
- data/plugins/subsystems/test/app/planners/main.rb +20 -0
- data/plugins/subsystems/test/app/scripts/distributed +3 -0
- data/plugins/subsystems/test/app/scripts/replay +3 -0
- data/plugins/subsystems/test/app/scripts/results +3 -0
- data/plugins/subsystems/test/app/scripts/run +3 -0
- data/plugins/subsystems/test/app/scripts/server +3 -0
- data/plugins/subsystems/test/app/scripts/shell +3 -0
- data/plugins/subsystems/test/app/scripts/test +3 -0
- data/plugins/subsystems/test/app/tasks/services.rb +15 -0
- data/plugins/subsystems/test/test_subsystems.rb +71 -0
- data/test/distributed/test_communication.rb +178 -0
- data/test/distributed/test_connection.rb +282 -0
- data/test/distributed/test_execution.rb +373 -0
- data/test/distributed/test_mixed_plan.rb +341 -0
- data/test/distributed/test_plan_notifications.rb +238 -0
- data/test/distributed/test_protocol.rb +516 -0
- data/test/distributed/test_query.rb +102 -0
- data/test/distributed/test_remote_plan.rb +491 -0
- data/test/distributed/test_transaction.rb +463 -0
- data/test/mockups/tasks.rb +27 -0
- data/test/planning/test_loops.rb +380 -0
- data/test/planning/test_model.rb +427 -0
- data/test/planning/test_task.rb +106 -0
- data/test/relations/test_conflicts.rb +42 -0
- data/test/relations/test_ensured.rb +38 -0
- data/test/relations/test_executed_by.rb +149 -0
- data/test/relations/test_hierarchy.rb +158 -0
- data/test/relations/test_planned_by.rb +54 -0
- data/test/suite_core.rb +24 -0
- data/test/suite_distributed.rb +9 -0
- data/test/suite_planning.rb +3 -0
- data/test/suite_relations.rb +8 -0
- data/test/test_bgl.rb +508 -0
- data/test/test_control.rb +399 -0
- data/test/test_event.rb +894 -0
- data/test/test_exceptions.rb +592 -0
- data/test/test_interface.rb +37 -0
- data/test/test_log.rb +114 -0
- data/test/test_log_server.rb +132 -0
- data/test/test_plan.rb +584 -0
- data/test/test_propagation.rb +210 -0
- data/test/test_query.rb +266 -0
- data/test/test_relations.rb +180 -0
- data/test/test_state.rb +414 -0
- data/test/test_support.rb +16 -0
- data/test/test_task.rb +938 -0
- data/test/test_testcase.rb +122 -0
- data/test/test_thread_task.rb +73 -0
- data/test/test_transactions.rb +569 -0
- data/test/test_transactions_proxy.rb +198 -0
- metadata +570 -0
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
require 'roby/log/data_stream'
|
|
2
|
+
|
|
3
|
+
class Roby::Task::DRoby
|
|
4
|
+
attr_accessor :mission
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
module Roby
|
|
8
|
+
module Log
|
|
9
|
+
class Notifications < Roby::Log::DataDecoder
|
|
10
|
+
GENERATOR_CALL_LIMIT = 0.1
|
|
11
|
+
|
|
12
|
+
attr_reader :tasks
|
|
13
|
+
|
|
14
|
+
attr_reader :histories
|
|
15
|
+
def initialize(name)
|
|
16
|
+
@tasks = Hash.new
|
|
17
|
+
@histories = Hash.new { |h, k| h[k] = Array.new }
|
|
18
|
+
super(name)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def added_task(task)
|
|
22
|
+
task.remote_siblings.each_value do |id|
|
|
23
|
+
tasks[id] = task
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
def removed_task(remote_id)
|
|
27
|
+
task = tasks.delete(remote_id)
|
|
28
|
+
task.remote_siblings.each_value do |id|
|
|
29
|
+
tasks.delete(id)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def clear
|
|
34
|
+
super
|
|
35
|
+
|
|
36
|
+
@tasks.clear
|
|
37
|
+
@histories.clear
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def process(data)
|
|
42
|
+
data.each_slice(4) do |m, sec, usec, args|
|
|
43
|
+
time = Time.at(sec, usec)
|
|
44
|
+
case m.to_s
|
|
45
|
+
when /inserted/
|
|
46
|
+
task = tasks[args[1]]
|
|
47
|
+
task.mission = true
|
|
48
|
+
event :added_mission, args[0], task
|
|
49
|
+
|
|
50
|
+
when /discarded/
|
|
51
|
+
task = tasks[args[1]]
|
|
52
|
+
task.mission = false
|
|
53
|
+
event :discarded_mission, args[0], task
|
|
54
|
+
|
|
55
|
+
when /discovered_tasks/
|
|
56
|
+
args[1].each { |t| added_task(t) }
|
|
57
|
+
|
|
58
|
+
when /finalized_task/
|
|
59
|
+
id = args[1]
|
|
60
|
+
task = tasks[id]
|
|
61
|
+
if histories[id].empty?
|
|
62
|
+
event :finalized_pending, time, task
|
|
63
|
+
end
|
|
64
|
+
histories.delete(task)
|
|
65
|
+
removed_task(args[1])
|
|
66
|
+
|
|
67
|
+
when /generator_calling/
|
|
68
|
+
@current_call = [time, args[0]]
|
|
69
|
+
|
|
70
|
+
when /generator_called/
|
|
71
|
+
if @current_call[1] == args[0]
|
|
72
|
+
duration = time - @current_call[0]
|
|
73
|
+
if duration > GENERATOR_CALL_LIMIT
|
|
74
|
+
event :overly_long_call, time, duration, tasks[args[0].task], args[0].symbol, args[1]
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
when /exception/
|
|
79
|
+
error, involved_tasks = *args
|
|
80
|
+
involved_tasks = involved_tasks.map { |id| tasks[id] }
|
|
81
|
+
event m, time, error, involved_tasks
|
|
82
|
+
when /generator_fired/
|
|
83
|
+
generator = args[0]
|
|
84
|
+
if generator.respond_to?(:task)
|
|
85
|
+
histories[generator.task] << args
|
|
86
|
+
if generator.symbol == :failed
|
|
87
|
+
event :failed_task, time, tasks[generator.task], histories[generator.task]
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def event(name, *args)
|
|
95
|
+
displays.each do |display|
|
|
96
|
+
if display.respond_to?(name)
|
|
97
|
+
display.send(name, *args)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
class NotificationsDisplay < Qt::TextBrowser
|
|
104
|
+
include DataDisplay
|
|
105
|
+
decoder Notifications
|
|
106
|
+
|
|
107
|
+
attr_reader :document
|
|
108
|
+
attr_reader :text
|
|
109
|
+
|
|
110
|
+
STYLESHEET = <<-EOS
|
|
111
|
+
h1 { font-size: large; }
|
|
112
|
+
h1 { margin-bottom: 3px; }
|
|
113
|
+
h2 { font-size: medium; }
|
|
114
|
+
.time {
|
|
115
|
+
margin-right: 10px;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
div.info {
|
|
119
|
+
color: black;
|
|
120
|
+
margin-top: 20px;
|
|
121
|
+
border-top: thin solid black;
|
|
122
|
+
}
|
|
123
|
+
div.info h1 { margin-top: 0; background-color: #5FB86A; }
|
|
124
|
+
div.warn {
|
|
125
|
+
color: black;
|
|
126
|
+
margin-top: 20px;
|
|
127
|
+
border-top: thin solid black;
|
|
128
|
+
}
|
|
129
|
+
div.warn h1 { margin-top: 0; background-color: #B8AC5F; }
|
|
130
|
+
div.error {
|
|
131
|
+
color: black;
|
|
132
|
+
margin-top: 20px;
|
|
133
|
+
border-top: thin solid black;
|
|
134
|
+
}
|
|
135
|
+
div.error h1 { margin-top: 0; background-color: #B8937D; }
|
|
136
|
+
EOS
|
|
137
|
+
|
|
138
|
+
def initialize
|
|
139
|
+
super()
|
|
140
|
+
|
|
141
|
+
resize(500, 600)
|
|
142
|
+
@main = self
|
|
143
|
+
@document = Qt::TextDocument.new
|
|
144
|
+
|
|
145
|
+
self.document = document
|
|
146
|
+
document.setDefaultStyleSheet(STYLESHEET)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def render_event(kind, time, title)
|
|
151
|
+
@text = ""
|
|
152
|
+
text << "\n<div class=#{kind}>\n <h1><span class=\"time\">#{time.to_hms}</span> #{title}</h1>\n "
|
|
153
|
+
yield
|
|
154
|
+
|
|
155
|
+
ensure
|
|
156
|
+
text << "\n</div>"
|
|
157
|
+
insertHtml(text)
|
|
158
|
+
verticalScrollBar.value = verticalScrollBar.maximum
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def render_task(task)
|
|
162
|
+
remote_siblings = "{ " << task.remote_siblings.map { |peer, id| id.to_s(peer) }.join(", ") << " }"
|
|
163
|
+
text << "<div class=\"task\">
|
|
164
|
+
#{task.model.ancestors.first.first}#{remote_siblings}\n "
|
|
165
|
+
|
|
166
|
+
unless task.arguments.empty?
|
|
167
|
+
text << "<ul class=\"task-arguments\">\n "
|
|
168
|
+
task.arguments.each do |key, value|
|
|
169
|
+
text << " <li>#{key}: #{value}<li>\n"
|
|
170
|
+
end
|
|
171
|
+
text << " </ul>\n"
|
|
172
|
+
end
|
|
173
|
+
text << "</div>"
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def render_history(history)
|
|
177
|
+
text << "<ul class=\"history\">\n"
|
|
178
|
+
history.each do |generator, id, time, context|
|
|
179
|
+
text << "<li>#{time.to_hms} #{generator.symbol} [#{context}]</li>"
|
|
180
|
+
end
|
|
181
|
+
text << "</ul>"
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def clear
|
|
185
|
+
document.clear
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def finalized_pending(time, task)
|
|
189
|
+
render_event("warn", time, "Finalized pending task") do
|
|
190
|
+
render_task(task)
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
def added_mission(time, task)
|
|
194
|
+
render_event("info", time, "New mission") do
|
|
195
|
+
render_task(task)
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
def removed_mission(time, task)
|
|
199
|
+
render_event("info", time, "Removed mission") do
|
|
200
|
+
render_task(task)
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
def render_error(error, tasks)
|
|
204
|
+
error = Qt.escape(error.to_s)
|
|
205
|
+
error = error.split("\n").map do |line|
|
|
206
|
+
line.gsub(/^\s+/) { " " * $&.size }
|
|
207
|
+
end.join("<br>")
|
|
208
|
+
|
|
209
|
+
text << error
|
|
210
|
+
text << "<h2>Involved tasks</h2>"
|
|
211
|
+
text << "<ul>"
|
|
212
|
+
tasks.each do |t|
|
|
213
|
+
text << "<li>"
|
|
214
|
+
render_task(t)
|
|
215
|
+
text << "</li>"
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def fatal_exception(time, error, tasks)
|
|
220
|
+
render_event("error", time, "Fatal exception") do
|
|
221
|
+
render_error(error, tasks)
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
def handled_exception(time, error, tasks)
|
|
225
|
+
render_event("warn", time, "Handled exception") do
|
|
226
|
+
render_error(error, tasks)
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
def failed_task(time, task, history)
|
|
230
|
+
render_event("warn", time, "Failed task") do
|
|
231
|
+
render_task(task)
|
|
232
|
+
render_history(history)
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
def overly_long_call(time, duration, task, event_name, context)
|
|
236
|
+
render_event("warn", time, "Overly long call: ") do
|
|
237
|
+
text << "Call of #{event_name}(#{context}) lasted #{Integer(duration * 1000)}ms in<br>"
|
|
238
|
+
render_task(task)
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
|
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
require 'roby/distributed/protocol'
|
|
2
|
+
require 'roby/log/data_stream'
|
|
3
|
+
require 'stringio'
|
|
4
|
+
|
|
5
|
+
module Roby
|
|
6
|
+
class ObjectIDManager
|
|
7
|
+
attr_reader :siblings
|
|
8
|
+
attr_reader :objects
|
|
9
|
+
def initialize
|
|
10
|
+
@siblings = Hash.new
|
|
11
|
+
@objects = Hash.new
|
|
12
|
+
@inserted_at = Hash.new
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def clear
|
|
16
|
+
siblings.clear
|
|
17
|
+
objects.clear
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def local_object(object, allow_new = true)
|
|
21
|
+
return unless object
|
|
22
|
+
|
|
23
|
+
current_siblings = Set.new
|
|
24
|
+
ids = Set.new
|
|
25
|
+
if object.kind_of?(Distributed::RemoteID)
|
|
26
|
+
ids << object
|
|
27
|
+
if sibling = siblings[object]
|
|
28
|
+
current_siblings << sibling
|
|
29
|
+
end
|
|
30
|
+
else
|
|
31
|
+
for _, id in object.remote_siblings
|
|
32
|
+
ids << id
|
|
33
|
+
if sibling = siblings[id]
|
|
34
|
+
current_siblings << sibling
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
if current_siblings.size > 1
|
|
40
|
+
raise "more than one object matching"
|
|
41
|
+
elsif current_siblings.empty?
|
|
42
|
+
if object.kind_of?(Distributed::RemoteID)
|
|
43
|
+
raise "no object for this ID"
|
|
44
|
+
elsif !allow_new
|
|
45
|
+
raise "new object ot type #{object.class} is not allowed here"
|
|
46
|
+
end
|
|
47
|
+
else
|
|
48
|
+
obj = current_siblings.find { true }
|
|
49
|
+
if object.kind_of?(Distributed::RemoteID)
|
|
50
|
+
object = obj
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
if obj.class != object.class
|
|
54
|
+
# Special case: +obj+ is a PlanObject and it is in no plan.
|
|
55
|
+
#
|
|
56
|
+
# In this case, we just replace it silently. It handles the
|
|
57
|
+
# corner case of having a task hanging around because it is
|
|
58
|
+
# linked to others, but has not been included in a plan.
|
|
59
|
+
#
|
|
60
|
+
# Note that this is a hack and should be fixed
|
|
61
|
+
if obj.respond_to?(:plan) && !obj.plan
|
|
62
|
+
for id in objects.delete(obj)
|
|
63
|
+
siblings.delete(id)
|
|
64
|
+
end
|
|
65
|
+
else
|
|
66
|
+
raise "class mismatch #{obj.class} != #{object.class}. Old object is #{obj}"
|
|
67
|
+
end
|
|
68
|
+
elsif block_given?
|
|
69
|
+
ids.merge objects.delete(obj)
|
|
70
|
+
object = yield(obj)
|
|
71
|
+
else
|
|
72
|
+
object = obj
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
objects[object] ||= Set.new
|
|
77
|
+
objects[object].merge ids
|
|
78
|
+
for i in ids
|
|
79
|
+
siblings[i] = object
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
object
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def add_id(object, id)
|
|
86
|
+
if siblings[id]
|
|
87
|
+
raise "there is already an object for this ID"
|
|
88
|
+
elsif !id.kind_of(Distributed::RemoteID)
|
|
89
|
+
raise "#{id} is not a valid RemoteID"
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
siblings[id] = object
|
|
93
|
+
objects[object] << id
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def remove_id(id)
|
|
97
|
+
if !(object = siblings.delete(id))
|
|
98
|
+
raise "#{id} does not reference anything"
|
|
99
|
+
end
|
|
100
|
+
objects[object].delete(id)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def remove(object)
|
|
104
|
+
object = local_object(object)
|
|
105
|
+
|
|
106
|
+
ids = objects.delete(object)
|
|
107
|
+
for i in ids
|
|
108
|
+
siblings.delete(i)
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
class PlanObject::DRoby
|
|
114
|
+
include DirectedRelationSupport
|
|
115
|
+
attr_writer :plan
|
|
116
|
+
|
|
117
|
+
def update_from(new)
|
|
118
|
+
super if defined? super
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
class TaskEventGenerator::DRoby
|
|
122
|
+
include DirectedRelationSupport
|
|
123
|
+
attr_writer :plan
|
|
124
|
+
attr_writer :task
|
|
125
|
+
|
|
126
|
+
def update_from(new)
|
|
127
|
+
super if defined? super
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
class Task::DRoby
|
|
131
|
+
attr_writer :plan
|
|
132
|
+
attribute(:events) { Hash.new }
|
|
133
|
+
|
|
134
|
+
def update_from(new)
|
|
135
|
+
super if defined? super
|
|
136
|
+
self.flags.merge! new.flags
|
|
137
|
+
self.plan = new.plan
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
class Transaction::Proxy::DRoby
|
|
142
|
+
include DirectedRelationSupport
|
|
143
|
+
attr_writer :transaction
|
|
144
|
+
attr_accessor :plan
|
|
145
|
+
|
|
146
|
+
def events; Hash.new end
|
|
147
|
+
def update_from(new)
|
|
148
|
+
super if defined? super
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
module LoggedPlan
|
|
153
|
+
attribute(:missions) { ValueSet.new }
|
|
154
|
+
attribute(:known_tasks) { ValueSet.new }
|
|
155
|
+
attribute(:free_events) { ValueSet.new }
|
|
156
|
+
attribute(:transactions) { ValueSet.new }
|
|
157
|
+
attribute(:finalized_tasks) { ValueSet.new }
|
|
158
|
+
attribute(:finalized_events) { ValueSet.new }
|
|
159
|
+
attribute(:proxies) { ValueSet.new }
|
|
160
|
+
attr_accessor :parent_plan
|
|
161
|
+
|
|
162
|
+
def root_plan?; !parent_plan end
|
|
163
|
+
def update_from(new); end
|
|
164
|
+
def clear
|
|
165
|
+
transactions.dup.each do |trsc|
|
|
166
|
+
trsc.clear
|
|
167
|
+
removed_transaction(trsc)
|
|
168
|
+
end
|
|
169
|
+
known_tasks.dup.each { |t| finalized_task(t) }
|
|
170
|
+
free_events.dup.each { |e| finalized_event(e) }
|
|
171
|
+
clear_finalized(finalized_tasks, finalized_events)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def finalized_task(task)
|
|
175
|
+
missions.delete(task)
|
|
176
|
+
known_tasks.delete(task)
|
|
177
|
+
proxies.delete(task)
|
|
178
|
+
finalized_tasks << task
|
|
179
|
+
end
|
|
180
|
+
def finalized_event(event)
|
|
181
|
+
free_events.delete(event)
|
|
182
|
+
proxies.delete(event)
|
|
183
|
+
finalized_events << event unless event.respond_to?(:task)
|
|
184
|
+
end
|
|
185
|
+
def clear_finalized(tasks, events)
|
|
186
|
+
tasks.each { |task| task.clear_vertex }
|
|
187
|
+
@finalized_tasks = finalized_tasks - tasks
|
|
188
|
+
events.each { |event| event.clear_vertex }
|
|
189
|
+
@finalized_events = finalized_events - events
|
|
190
|
+
end
|
|
191
|
+
def removed_transaction(trsc)
|
|
192
|
+
transactions.delete(trsc)
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
class Plan::DRoby
|
|
197
|
+
include LoggedPlan
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
class Distributed::Transaction::DRoby
|
|
201
|
+
include LoggedPlan
|
|
202
|
+
attr_writer :plan
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
module Log
|
|
206
|
+
# This class rebuilds a plan-like structure from events saved by a
|
|
207
|
+
# FileLogger object This is compatible with the EventStream data source
|
|
208
|
+
class PlanRebuilder < DataDecoder
|
|
209
|
+
attr_reader :plans
|
|
210
|
+
attr_reader :tasks
|
|
211
|
+
attr_reader :events
|
|
212
|
+
attr_reader :last_finalized
|
|
213
|
+
attr_reader :manager
|
|
214
|
+
|
|
215
|
+
attr_reader :start_time
|
|
216
|
+
attr_reader :time
|
|
217
|
+
def initialize(name)
|
|
218
|
+
@plans = ValueSet.new
|
|
219
|
+
@tasks = ValueSet.new
|
|
220
|
+
@events = ValueSet.new
|
|
221
|
+
@manager = ObjectIDManager.new
|
|
222
|
+
@last_finalized = Hash.new
|
|
223
|
+
super(name)
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def clear
|
|
227
|
+
manager.clear
|
|
228
|
+
super
|
|
229
|
+
|
|
230
|
+
plans.dup.each { |p, _| p.clear if p.root_plan? }
|
|
231
|
+
plans.clear
|
|
232
|
+
tasks.clear
|
|
233
|
+
events.clear
|
|
234
|
+
@start_time = nil
|
|
235
|
+
@time = nil
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def rewind
|
|
239
|
+
clear
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def process(data)
|
|
243
|
+
@time = data.last[0][:start]
|
|
244
|
+
@start_time ||= @time
|
|
245
|
+
|
|
246
|
+
data.each_slice(4) do |m, sec, usec, args|
|
|
247
|
+
time = Time.at(sec, usec)
|
|
248
|
+
reason = catch :ignored do
|
|
249
|
+
begin
|
|
250
|
+
if respond_to?(m)
|
|
251
|
+
send(m, time, *args)
|
|
252
|
+
end
|
|
253
|
+
displays.each { |d| d.send(m, time, *args) if d.respond_to?(m) }
|
|
254
|
+
rescue Exception => e
|
|
255
|
+
display_args = args.map do |obj|
|
|
256
|
+
case obj
|
|
257
|
+
when NilClass: 'nil'
|
|
258
|
+
when Time: obj.to_hms
|
|
259
|
+
when DRbObject: obj.inspect
|
|
260
|
+
else (obj.to_s rescue "failed_to_s")
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
raise e, "#{e.message} while serving #{m}(#{display_args.join(", ")})", e.backtrace
|
|
265
|
+
end
|
|
266
|
+
nil
|
|
267
|
+
end
|
|
268
|
+
if reason
|
|
269
|
+
Roby.warn "Ignored #{m}(#{args.join(", ")}): #{reason}"
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
def local_object(object)
|
|
275
|
+
return nil unless object
|
|
276
|
+
|
|
277
|
+
object = manager.local_object(object)
|
|
278
|
+
plan = if block_given?
|
|
279
|
+
yield
|
|
280
|
+
elsif object.respond_to?(:transaction)
|
|
281
|
+
local_plan(object.transaction, false)
|
|
282
|
+
elsif object.respond_to?(:plan)
|
|
283
|
+
local_plan(object.plan, false)
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
if plan
|
|
287
|
+
object.plan = plan
|
|
288
|
+
if object.respond_to?(:transaction)
|
|
289
|
+
object.transaction = plan
|
|
290
|
+
plan.proxies << object
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
object
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def clear_integrated
|
|
298
|
+
last_finalized.clear
|
|
299
|
+
plans.each do |plan|
|
|
300
|
+
plan.clear_finalized(plan.finalized_tasks.dup, plan.finalized_events.dup)
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
super
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
def display
|
|
307
|
+
plans.each do |plan|
|
|
308
|
+
if finalized = last_finalized[plan]
|
|
309
|
+
plan.clear_finalized(*finalized)
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
super
|
|
314
|
+
|
|
315
|
+
# Save a per-plan set of finalized tasks, to be removed the
|
|
316
|
+
# next time #display is called
|
|
317
|
+
@last_finalized = Hash.new
|
|
318
|
+
plans.each do |plan|
|
|
319
|
+
last_finalized[plan] = [plan.finalized_tasks.dup, plan.finalized_events.dup]
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
def local_plan(plan, allow_new = false)
|
|
324
|
+
plan = manager.local_object(plan, plans.empty? || allow_new)
|
|
325
|
+
plans << plan if plan
|
|
326
|
+
plan
|
|
327
|
+
end
|
|
328
|
+
def local_task(task, &block)
|
|
329
|
+
local_object(task, &block)
|
|
330
|
+
end
|
|
331
|
+
def local_event(event, &block)
|
|
332
|
+
if event.respond_to?(:task)
|
|
333
|
+
task = local_task(event.task, &block)
|
|
334
|
+
if task.events[event.symbol]
|
|
335
|
+
task.events[event.symbol]
|
|
336
|
+
else
|
|
337
|
+
event.task = task
|
|
338
|
+
event.plan = task.plan
|
|
339
|
+
task.events[event.symbol] = event
|
|
340
|
+
end
|
|
341
|
+
else
|
|
342
|
+
local_object(event, &block)
|
|
343
|
+
end
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
def inserted_tasks(time, plan, task)
|
|
347
|
+
plan = local_plan(plan)
|
|
348
|
+
plan.missions << task
|
|
349
|
+
end
|
|
350
|
+
def discarded_tasks(time, plan, task)
|
|
351
|
+
plan = local_plan(plan)
|
|
352
|
+
plan.missions.delete(task)
|
|
353
|
+
end
|
|
354
|
+
def replaced_tasks(time, plan, from, to)
|
|
355
|
+
end
|
|
356
|
+
def discovered_events(time, plan, events)
|
|
357
|
+
plan = local_plan(plan)
|
|
358
|
+
events.each do |ev|
|
|
359
|
+
ev = local_event(ev) { plan }
|
|
360
|
+
plan.free_events << ev
|
|
361
|
+
end
|
|
362
|
+
end
|
|
363
|
+
def discovered_tasks(time, plan, tasks)
|
|
364
|
+
plan = local_plan(plan)
|
|
365
|
+
tasks.each do |t|
|
|
366
|
+
t = local_task(t) { plan }
|
|
367
|
+
plan.known_tasks << t
|
|
368
|
+
end
|
|
369
|
+
end
|
|
370
|
+
def garbage_task(time, plan, task)
|
|
371
|
+
end
|
|
372
|
+
def finalized_event(time, plan, event)
|
|
373
|
+
event = local_event(event)
|
|
374
|
+
plan = local_plan(plan)
|
|
375
|
+
unless event.respond_to?(:task)
|
|
376
|
+
plan.finalized_event(event)
|
|
377
|
+
manager.remove(event)
|
|
378
|
+
end
|
|
379
|
+
end
|
|
380
|
+
def finalized_task(time, plan, task)
|
|
381
|
+
task = local_task(task)
|
|
382
|
+
plan = local_plan(plan)
|
|
383
|
+
plan.finalized_task(task)
|
|
384
|
+
manager.remove(task)
|
|
385
|
+
end
|
|
386
|
+
def added_transaction(time, plan, trsc)
|
|
387
|
+
plan = local_plan(plan)
|
|
388
|
+
trsc = local_plan(trsc, true)
|
|
389
|
+
plan.transactions << trsc
|
|
390
|
+
trsc.parent_plan = plan
|
|
391
|
+
end
|
|
392
|
+
def removed_transaction(time, plan, trsc)
|
|
393
|
+
plan = local_plan(plan)
|
|
394
|
+
trsc = local_plan(trsc)
|
|
395
|
+
|
|
396
|
+
(trsc.known_tasks - plan.known_tasks).each do |obj|
|
|
397
|
+
trsc.finalized_task(obj)
|
|
398
|
+
manager.remove(obj)
|
|
399
|
+
end
|
|
400
|
+
(trsc.free_events - plan.free_events).each do |obj|
|
|
401
|
+
trsc.finalized_event(obj)
|
|
402
|
+
manager.remove(obj)
|
|
403
|
+
end
|
|
404
|
+
trsc.proxies.each do |p|
|
|
405
|
+
manager.remove(p)
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
trsc.clear_finalized(trsc.finalized_tasks, trsc.finalized_events)
|
|
409
|
+
plans.delete(trsc)
|
|
410
|
+
manager.remove(trsc)
|
|
411
|
+
plan.transactions.delete(trsc)
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
GENERATOR_TO_STATE = { :start => :started,
|
|
415
|
+
:success => :success,
|
|
416
|
+
:stop => :finished }
|
|
417
|
+
|
|
418
|
+
def generator_fired(time, generator, id, ev_time, context)
|
|
419
|
+
generator = local_event(generator)
|
|
420
|
+
generator.instance_variable_set("@happened", true)
|
|
421
|
+
if generator.respond_to?(:task) && (state = GENERATOR_TO_STATE[generator.symbol])
|
|
422
|
+
generator.task.flags[state] = true
|
|
423
|
+
end
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
def added_task_child(time, parent, rel, child, info)
|
|
427
|
+
parent = local_task(parent)
|
|
428
|
+
child = local_task(child)
|
|
429
|
+
if !parent then throw :ignored, "unknown parent"
|
|
430
|
+
elsif !child then throw :ignored, "unknown child"
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
rel = rel.first if rel.kind_of?(Array)
|
|
434
|
+
rel = rel.proxy(nil)
|
|
435
|
+
parent.add_child_object(child, rel, info)
|
|
436
|
+
end
|
|
437
|
+
def removed_task_child(time, parent, rel, child)
|
|
438
|
+
parent = local_task(parent)
|
|
439
|
+
child = local_task(child)
|
|
440
|
+
rel = rel.first if rel.kind_of?(Array)
|
|
441
|
+
rel = rel.proxy(nil)
|
|
442
|
+
parent.remove_child_object(child, rel)
|
|
443
|
+
end
|
|
444
|
+
def added_event_child(time, parent, rel, child, info)
|
|
445
|
+
parent = local_event(parent)
|
|
446
|
+
child = local_event(child)
|
|
447
|
+
rel = rel.first if rel.kind_of?(Array)
|
|
448
|
+
rel = rel.proxy(nil)
|
|
449
|
+
parent.add_child_object(child, rel, info)
|
|
450
|
+
end
|
|
451
|
+
def removed_event_child(time, parent, rel, child)
|
|
452
|
+
parent = local_event(parent)
|
|
453
|
+
child = local_event(child)
|
|
454
|
+
rel = rel.first if rel.kind_of?(Array)
|
|
455
|
+
rel = rel.proxy(nil)
|
|
456
|
+
parent.remove_child_object(child, rel)
|
|
457
|
+
end
|
|
458
|
+
def added_owner(time, object, peer)
|
|
459
|
+
object = local_object(object)
|
|
460
|
+
object.owners << peer
|
|
461
|
+
end
|
|
462
|
+
def removed_owner(time, object, peer)
|
|
463
|
+
object = local_object(object)
|
|
464
|
+
object.owners.delete(peer)
|
|
465
|
+
end
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
end
|
|
469
|
+
end
|
|
470
|
+
|