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.
Files changed (240) hide show
  1. data/.gitignore +29 -0
  2. data/History.txt +4 -0
  3. data/License-fr.txt +519 -0
  4. data/License.txt +515 -0
  5. data/Manifest.txt +245 -0
  6. data/NOTES +4 -0
  7. data/README.txt +163 -0
  8. data/Rakefile +161 -0
  9. data/TODO.txt +146 -0
  10. data/app/README.txt +24 -0
  11. data/app/Rakefile +8 -0
  12. data/app/config/ROBOT.rb +5 -0
  13. data/app/config/app.yml +91 -0
  14. data/app/config/init.rb +7 -0
  15. data/app/config/roby.yml +3 -0
  16. data/app/controllers/.gitattributes +0 -0
  17. data/app/controllers/ROBOT.rb +2 -0
  18. data/app/data/.gitattributes +0 -0
  19. data/app/planners/ROBOT/main.rb +6 -0
  20. data/app/planners/main.rb +5 -0
  21. data/app/scripts/distributed +3 -0
  22. data/app/scripts/generate/bookmarks +3 -0
  23. data/app/scripts/replay +3 -0
  24. data/app/scripts/results +3 -0
  25. data/app/scripts/run +3 -0
  26. data/app/scripts/server +3 -0
  27. data/app/scripts/shell +3 -0
  28. data/app/scripts/test +3 -0
  29. data/app/tasks/.gitattributes +0 -0
  30. data/app/tasks/ROBOT/.gitattributes +0 -0
  31. data/bin/roby +210 -0
  32. data/bin/roby-log +168 -0
  33. data/bin/roby-shell +25 -0
  34. data/doc/images/event_generalization.png +0 -0
  35. data/doc/images/exception_propagation_1.png +0 -0
  36. data/doc/images/exception_propagation_2.png +0 -0
  37. data/doc/images/exception_propagation_3.png +0 -0
  38. data/doc/images/exception_propagation_4.png +0 -0
  39. data/doc/images/exception_propagation_5.png +0 -0
  40. data/doc/images/replay_handler_error.png +0 -0
  41. data/doc/images/replay_handler_error_0.png +0 -0
  42. data/doc/images/replay_handler_error_1.png +0 -0
  43. data/doc/images/roby_cycle_overview.png +0 -0
  44. data/doc/images/roby_replay_02.png +0 -0
  45. data/doc/images/roby_replay_03.png +0 -0
  46. data/doc/images/roby_replay_04.png +0 -0
  47. data/doc/images/roby_replay_event_representation.png +0 -0
  48. data/doc/images/roby_replay_first_state.png +0 -0
  49. data/doc/images/roby_replay_relations.png +0 -0
  50. data/doc/images/roby_replay_startup.png +0 -0
  51. data/doc/images/task_event_generalization.png +0 -0
  52. data/doc/papers.rdoc +11 -0
  53. data/doc/styles/allison.css +314 -0
  54. data/doc/styles/allison.js +316 -0
  55. data/doc/styles/allison.rb +276 -0
  56. data/doc/styles/jamis.rb +593 -0
  57. data/doc/tutorials/01-GettingStarted.rdoc +86 -0
  58. data/doc/tutorials/02-GoForward.rdoc +220 -0
  59. data/doc/tutorials/03-PlannedPath.rdoc +268 -0
  60. data/doc/tutorials/04-EventPropagation.rdoc +236 -0
  61. data/doc/tutorials/05-ErrorHandling.rdoc +319 -0
  62. data/doc/tutorials/06-Overview.rdoc +40 -0
  63. data/doc/videos.rdoc +69 -0
  64. data/ext/droby/dump.cc +175 -0
  65. data/ext/droby/extconf.rb +3 -0
  66. data/ext/graph/algorithm.cc +746 -0
  67. data/ext/graph/extconf.rb +7 -0
  68. data/ext/graph/graph.cc +529 -0
  69. data/ext/graph/graph.hh +183 -0
  70. data/ext/graph/iterator_sequence.hh +102 -0
  71. data/ext/graph/undirected_dfs.hh +226 -0
  72. data/ext/graph/undirected_graph.hh +421 -0
  73. data/lib/roby.rb +41 -0
  74. data/lib/roby/app.rb +870 -0
  75. data/lib/roby/app/rake.rb +56 -0
  76. data/lib/roby/app/run.rb +14 -0
  77. data/lib/roby/app/scripts/distributed.rb +13 -0
  78. data/lib/roby/app/scripts/generate/bookmarks.rb +162 -0
  79. data/lib/roby/app/scripts/replay.rb +31 -0
  80. data/lib/roby/app/scripts/results.rb +15 -0
  81. data/lib/roby/app/scripts/run.rb +26 -0
  82. data/lib/roby/app/scripts/server.rb +18 -0
  83. data/lib/roby/app/scripts/shell.rb +88 -0
  84. data/lib/roby/app/scripts/test.rb +40 -0
  85. data/lib/roby/basic_object.rb +151 -0
  86. data/lib/roby/config.rb +5 -0
  87. data/lib/roby/control.rb +747 -0
  88. data/lib/roby/decision_control.rb +17 -0
  89. data/lib/roby/distributed.rb +32 -0
  90. data/lib/roby/distributed/base.rb +440 -0
  91. data/lib/roby/distributed/communication.rb +871 -0
  92. data/lib/roby/distributed/connection_space.rb +592 -0
  93. data/lib/roby/distributed/distributed_object.rb +206 -0
  94. data/lib/roby/distributed/drb.rb +62 -0
  95. data/lib/roby/distributed/notifications.rb +539 -0
  96. data/lib/roby/distributed/peer.rb +550 -0
  97. data/lib/roby/distributed/protocol.rb +529 -0
  98. data/lib/roby/distributed/proxy.rb +343 -0
  99. data/lib/roby/distributed/subscription.rb +311 -0
  100. data/lib/roby/distributed/transaction.rb +498 -0
  101. data/lib/roby/event.rb +897 -0
  102. data/lib/roby/exceptions.rb +234 -0
  103. data/lib/roby/executives/simple.rb +30 -0
  104. data/lib/roby/graph.rb +166 -0
  105. data/lib/roby/interface.rb +390 -0
  106. data/lib/roby/log.rb +3 -0
  107. data/lib/roby/log/chronicle.rb +303 -0
  108. data/lib/roby/log/console.rb +72 -0
  109. data/lib/roby/log/data_stream.rb +197 -0
  110. data/lib/roby/log/dot.rb +279 -0
  111. data/lib/roby/log/event_stream.rb +151 -0
  112. data/lib/roby/log/file.rb +340 -0
  113. data/lib/roby/log/gui/basic_display.ui +83 -0
  114. data/lib/roby/log/gui/chronicle.rb +26 -0
  115. data/lib/roby/log/gui/chronicle_view.rb +40 -0
  116. data/lib/roby/log/gui/chronicle_view.ui +70 -0
  117. data/lib/roby/log/gui/data_displays.rb +172 -0
  118. data/lib/roby/log/gui/data_displays.ui +155 -0
  119. data/lib/roby/log/gui/notifications.rb +26 -0
  120. data/lib/roby/log/gui/relations.rb +248 -0
  121. data/lib/roby/log/gui/relations.ui +123 -0
  122. data/lib/roby/log/gui/relations_view.rb +185 -0
  123. data/lib/roby/log/gui/relations_view.ui +149 -0
  124. data/lib/roby/log/gui/replay.rb +327 -0
  125. data/lib/roby/log/gui/replay_controls.rb +200 -0
  126. data/lib/roby/log/gui/replay_controls.ui +259 -0
  127. data/lib/roby/log/gui/runtime.rb +130 -0
  128. data/lib/roby/log/hooks.rb +185 -0
  129. data/lib/roby/log/logger.rb +202 -0
  130. data/lib/roby/log/notifications.rb +244 -0
  131. data/lib/roby/log/plan_rebuilder.rb +470 -0
  132. data/lib/roby/log/relations.rb +1056 -0
  133. data/lib/roby/log/server.rb +550 -0
  134. data/lib/roby/log/sqlite.rb +47 -0
  135. data/lib/roby/log/timings.rb +164 -0
  136. data/lib/roby/plan-object.rb +247 -0
  137. data/lib/roby/plan.rb +762 -0
  138. data/lib/roby/planning.rb +13 -0
  139. data/lib/roby/planning/loops.rb +302 -0
  140. data/lib/roby/planning/model.rb +906 -0
  141. data/lib/roby/planning/task.rb +151 -0
  142. data/lib/roby/propagation.rb +562 -0
  143. data/lib/roby/query.rb +619 -0
  144. data/lib/roby/relations.rb +583 -0
  145. data/lib/roby/relations/conflicts.rb +70 -0
  146. data/lib/roby/relations/ensured.rb +20 -0
  147. data/lib/roby/relations/error_handling.rb +23 -0
  148. data/lib/roby/relations/events.rb +9 -0
  149. data/lib/roby/relations/executed_by.rb +193 -0
  150. data/lib/roby/relations/hierarchy.rb +239 -0
  151. data/lib/roby/relations/influence.rb +10 -0
  152. data/lib/roby/relations/planned_by.rb +63 -0
  153. data/lib/roby/robot.rb +7 -0
  154. data/lib/roby/standard_errors.rb +218 -0
  155. data/lib/roby/state.rb +5 -0
  156. data/lib/roby/state/events.rb +221 -0
  157. data/lib/roby/state/information.rb +55 -0
  158. data/lib/roby/state/pos.rb +110 -0
  159. data/lib/roby/state/shapes.rb +32 -0
  160. data/lib/roby/state/state.rb +353 -0
  161. data/lib/roby/support.rb +92 -0
  162. data/lib/roby/task-operations.rb +182 -0
  163. data/lib/roby/task.rb +1618 -0
  164. data/lib/roby/test/common.rb +399 -0
  165. data/lib/roby/test/distributed.rb +214 -0
  166. data/lib/roby/test/tasks/empty_task.rb +9 -0
  167. data/lib/roby/test/tasks/goto.rb +36 -0
  168. data/lib/roby/test/tasks/simple_task.rb +23 -0
  169. data/lib/roby/test/testcase.rb +519 -0
  170. data/lib/roby/test/tools.rb +160 -0
  171. data/lib/roby/thread_task.rb +87 -0
  172. data/lib/roby/transactions.rb +462 -0
  173. data/lib/roby/transactions/proxy.rb +292 -0
  174. data/lib/roby/transactions/updates.rb +139 -0
  175. data/plugins/fault_injection/History.txt +4 -0
  176. data/plugins/fault_injection/README.txt +37 -0
  177. data/plugins/fault_injection/Rakefile +18 -0
  178. data/plugins/fault_injection/TODO.txt +0 -0
  179. data/plugins/fault_injection/app.rb +52 -0
  180. data/plugins/fault_injection/fault_injection.rb +89 -0
  181. data/plugins/fault_injection/test/test_fault_injection.rb +84 -0
  182. data/plugins/subsystems/README.txt +40 -0
  183. data/plugins/subsystems/Rakefile +18 -0
  184. data/plugins/subsystems/app.rb +171 -0
  185. data/plugins/subsystems/test/app/README +24 -0
  186. data/plugins/subsystems/test/app/Rakefile +8 -0
  187. data/plugins/subsystems/test/app/config/app.yml +71 -0
  188. data/plugins/subsystems/test/app/config/init.rb +9 -0
  189. data/plugins/subsystems/test/app/config/roby.yml +3 -0
  190. data/plugins/subsystems/test/app/planners/main.rb +20 -0
  191. data/plugins/subsystems/test/app/scripts/distributed +3 -0
  192. data/plugins/subsystems/test/app/scripts/replay +3 -0
  193. data/plugins/subsystems/test/app/scripts/results +3 -0
  194. data/plugins/subsystems/test/app/scripts/run +3 -0
  195. data/plugins/subsystems/test/app/scripts/server +3 -0
  196. data/plugins/subsystems/test/app/scripts/shell +3 -0
  197. data/plugins/subsystems/test/app/scripts/test +3 -0
  198. data/plugins/subsystems/test/app/tasks/services.rb +15 -0
  199. data/plugins/subsystems/test/test_subsystems.rb +71 -0
  200. data/test/distributed/test_communication.rb +178 -0
  201. data/test/distributed/test_connection.rb +282 -0
  202. data/test/distributed/test_execution.rb +373 -0
  203. data/test/distributed/test_mixed_plan.rb +341 -0
  204. data/test/distributed/test_plan_notifications.rb +238 -0
  205. data/test/distributed/test_protocol.rb +516 -0
  206. data/test/distributed/test_query.rb +102 -0
  207. data/test/distributed/test_remote_plan.rb +491 -0
  208. data/test/distributed/test_transaction.rb +463 -0
  209. data/test/mockups/tasks.rb +27 -0
  210. data/test/planning/test_loops.rb +380 -0
  211. data/test/planning/test_model.rb +427 -0
  212. data/test/planning/test_task.rb +106 -0
  213. data/test/relations/test_conflicts.rb +42 -0
  214. data/test/relations/test_ensured.rb +38 -0
  215. data/test/relations/test_executed_by.rb +149 -0
  216. data/test/relations/test_hierarchy.rb +158 -0
  217. data/test/relations/test_planned_by.rb +54 -0
  218. data/test/suite_core.rb +24 -0
  219. data/test/suite_distributed.rb +9 -0
  220. data/test/suite_planning.rb +3 -0
  221. data/test/suite_relations.rb +8 -0
  222. data/test/test_bgl.rb +508 -0
  223. data/test/test_control.rb +399 -0
  224. data/test/test_event.rb +894 -0
  225. data/test/test_exceptions.rb +592 -0
  226. data/test/test_interface.rb +37 -0
  227. data/test/test_log.rb +114 -0
  228. data/test/test_log_server.rb +132 -0
  229. data/test/test_plan.rb +584 -0
  230. data/test/test_propagation.rb +210 -0
  231. data/test/test_query.rb +266 -0
  232. data/test/test_relations.rb +180 -0
  233. data/test/test_state.rb +414 -0
  234. data/test/test_support.rb +16 -0
  235. data/test/test_task.rb +938 -0
  236. data/test/test_testcase.rb +122 -0
  237. data/test/test_thread_task.rb +73 -0
  238. data/test/test_transactions.rb +569 -0
  239. data/test/test_transactions_proxy.rb +198 -0
  240. metadata +570 -0
@@ -0,0 +1,130 @@
1
+ require 'Qt4'
2
+ require 'roby/app'
3
+
4
+ require 'roby/log/gui/replay_controls_ui'
5
+ require 'roby/log/gui/data_displays'
6
+ require 'roby/log/server'
7
+
8
+ class RemoteStreamListModel < DataStreamListModel
9
+ attr_reader :known_servers
10
+ def initialize(streams)
11
+ super
12
+ @known_servers = []
13
+ end
14
+
15
+ # Update the list of available servers and streams
16
+ def update
17
+ Roby::Log::Server.available_servers.each do |server|
18
+ unless known_servers.find { |str| str.server == server }
19
+ begin
20
+ known_servers << Roby::Log::Client.new(server)
21
+ rescue DRb::DRbConnError
22
+ end
23
+ end
24
+ end
25
+
26
+ known_servers.delete_if { |s| !s.connected? }
27
+
28
+ found_streams = []
29
+ known_servers.delete_if do |server|
30
+ begin
31
+ server.streams.each do |stream|
32
+ found_streams << stream
33
+ unless streams.include?(stream)
34
+ server.subscribe(stream)
35
+ add_new(stream)
36
+ end
37
+ end
38
+ false
39
+ rescue DRb::DRbConnError
40
+ s.disconnect
41
+ true
42
+ end
43
+ end
44
+
45
+ (streams - found_streams).each do |s|
46
+ row = streams.index(s)
47
+ removeRow(row, Qt::ModelIndex.new)
48
+ end
49
+ end
50
+ end
51
+
52
+ class RuntimeDisplay < Qt::MainWindow
53
+ attr_reader :ui_displays
54
+
55
+ attr_reader :streams
56
+ attr_reader :streams_model
57
+
58
+ DISPLAY_MINIMUM_DURATION = 5
59
+
60
+ def initialize(broadcast, port, period)
61
+ super()
62
+
63
+ # Create the vertical layout for this window
64
+ central_widget = Qt::Widget.new(self)
65
+ self.central_widget = central_widget
66
+ layout = Qt::VBoxLayout.new(central_widget)
67
+ layout.spacing = 6
68
+ layout.margin = 0
69
+
70
+ # add GUI for the data streams and display setup
71
+ @streams = Array.new
72
+ @streams_model = RemoteStreamListModel.new(streams)
73
+ displays_holder = Qt::Widget.new(central_widget)
74
+ layout.add_widget displays_holder
75
+ @ui_displays = Ui_DataDisplays.new
76
+ ui_displays.setupUi(displays_holder)
77
+ ui_displays.streams.model = streams_model
78
+ ui_displays.add_stream.enabled = false
79
+ ui_displays.remove_stream.enabled = false
80
+ connect(ui_displays.display_add, SIGNAL("clicked()"), self, SLOT("add_display()"))
81
+
82
+ # Set up the stream discovery
83
+ Roby::Log::Server.enable_discovery(broadcast, port, period)
84
+
85
+ # This timer is used to call Thread.pass ... of course needed or Ruby
86
+ # threads won't be woken up
87
+ Thread.current.priority = -1
88
+
89
+ @threads_timer = Qt::Timer.new(self)
90
+ connect(@threads_timer, SIGNAL('timeout()')) do
91
+ Thread.pass
92
+ end
93
+ @threads_timer.start(50)
94
+
95
+ @display_timer = Qt::Timer.new(self)
96
+ connect(@display_timer, SIGNAL('timeout()')) do
97
+ streams.each do |s|
98
+ s.synchronize do
99
+ s.display
100
+ end
101
+ end
102
+ end
103
+ @display_timer.start(5000)
104
+
105
+ sleep(0.5)
106
+ streams_model.update
107
+
108
+ @discovery_timer = Qt::Timer.new(self)
109
+ connect(@discovery_timer, SIGNAL('timeout()')) do
110
+ streams_model.update
111
+ end
112
+ @discovery_timer.start(Integer(period * 1000))
113
+ end
114
+
115
+ def add_display(kind = nil)
116
+ ui_displays.add_display(streams_model, kind)
117
+ end
118
+ slots 'add_display()'
119
+ end
120
+
121
+ if $0 == __FILE__
122
+ DRb.start_service "druby://:0"
123
+ Roby::Log::Server.logger.level = Logger::DEBUG
124
+
125
+ a = Qt::Application.new(ARGV)
126
+ w = RuntimeDisplay.new('localhost', Roby::Log::Server::RING_PORT, 5)
127
+ w.show
128
+ a.exec
129
+ end
130
+
@@ -0,0 +1,185 @@
1
+ require 'roby/log/logger'
2
+ require 'roby'
3
+
4
+ module Roby::Log
5
+ module BasicObjectHooks
6
+ HOOKS = %w{added_owner removed_owner}
7
+
8
+ def added_owner(peer)
9
+ super if defined? super
10
+ Roby::Log.log(:added_owner) { [self, peer] }
11
+ end
12
+
13
+ def removed_owner(peer)
14
+ super if defined? super
15
+ Roby::Log.log(:removed_owner) { [self, peer] }
16
+ end
17
+ end
18
+ Roby::BasicObject.include BasicObjectHooks
19
+
20
+ module TaskHooks
21
+ HOOKS = %w{added_task_child removed_task_child}
22
+
23
+ def added_child_object(child, relations, info)
24
+ super if defined? super
25
+ Roby::Log.log(:added_task_child) { [self, relations, child, info] }
26
+ end
27
+
28
+ def removed_child_object(child, relations)
29
+ super if defined? super
30
+ Roby::Log.log(:removed_task_child) { [self, relations, child] }
31
+ end
32
+ end
33
+ Roby::Task.include TaskHooks
34
+
35
+ module PlanHooks
36
+ HOOKS = %w{inserted_tasks discarded_tasks replaced_tasks
37
+ discovered_tasks discovered_events
38
+ garbage_task finalized_task finalized_event
39
+ added_transaction removed_transaction}
40
+
41
+ def inserted(tasks)
42
+ super if defined? super
43
+ Roby::Log.log(:inserted_tasks) { [self, tasks] }
44
+ end
45
+ def discarded(tasks)
46
+ super if defined? super
47
+ Roby::Log.log(:discarded_tasks) { [self, tasks] }
48
+ end
49
+ def replaced(from, to)
50
+ super if defined? super
51
+ Roby::Log.log(:replaced_tasks) { [self, from, to] }
52
+ end
53
+ def discovered_events(tasks)
54
+ super if defined? super
55
+ Roby::Log.log(:discovered_events) { [self, tasks] }
56
+ end
57
+ def discovered_tasks(tasks)
58
+ super if defined? super
59
+ Roby::Log.log(:discovered_tasks) { [self, tasks] }
60
+ end
61
+ def garbage(task)
62
+ super if defined? super
63
+ Roby::Log.log(:garbage_task) { [self, task] }
64
+ end
65
+ def finalized_event(event)
66
+ super if defined? super
67
+ Roby::Log.log(:finalized_event) { [self, event] }
68
+ end
69
+ def finalized_task(task)
70
+ super if defined? super
71
+ Roby::Log.log(:finalized_task) { [self, task] }
72
+ end
73
+
74
+ def added_transaction(trsc)
75
+ super if defined? super
76
+ Roby::Log.log(:added_transaction) { [self, trsc] }
77
+ end
78
+ def removed_transaction(trsc)
79
+ super if defined? super
80
+ Roby::Log.log(:removed_transaction) { [self, trsc] }
81
+ end
82
+ end
83
+ Roby::Plan.include PlanHooks
84
+
85
+ module TransactionHooks
86
+ HOOKS = %w{committed_transaction discarded_transaction}
87
+
88
+ def committed_transaction
89
+ super if defined? super
90
+ Roby::Log.log(:committed_transaction) { [self] }
91
+ end
92
+ def discarded_transaction
93
+ super if defined? super
94
+ Roby::Log.log(:discarded_transaction) { [self] }
95
+ end
96
+ end
97
+ Roby::Transaction.include TransactionHooks
98
+
99
+ module EventGeneratorHooks
100
+ HOOKS = %w{added_event_child removed_event_child
101
+ generator_calling generator_called generator_fired
102
+ generator_signalling generator_forwarding generator_emitting
103
+ generator_postponed}
104
+
105
+ def added_child_object(to, relations, info)
106
+ super if defined? super
107
+ Roby::Log.log(:added_event_child) { [self, relations, to, info] }
108
+ end
109
+
110
+ def removed_child_object(to, relations)
111
+ super if defined? super
112
+ Roby::Log.log(:removed_event_child) { [self, relations, to] }
113
+ end
114
+
115
+ def calling(context)
116
+ super if defined? super
117
+ Roby::Log.log(:generator_calling) { [self, Roby::Propagation.source_generators, context.to_s] }
118
+ end
119
+
120
+ def called(context)
121
+ super if defined? super
122
+ Roby::Log.log(:generator_called) { [self, context.to_s] }
123
+ end
124
+
125
+ def fired(event)
126
+ super if defined? super
127
+ Roby::Log.log(:generator_fired) { [self, event.object_id, event.time, event.context.to_s] }
128
+ end
129
+
130
+ def signalling(event, to)
131
+ super if defined? super
132
+ Roby::Log.log(:generator_signalling) { [false, self, to, event.object_id, event.time, event.context.to_s] }
133
+ end
134
+
135
+ def emitting(context)
136
+ super if defined? super
137
+ Roby::Log.log(:generator_emitting) { [self, Roby::Propagation.source_generators, context.to_s] }
138
+ end
139
+
140
+ def forwarding(event, to)
141
+ super if defined? super
142
+ Roby::Log.log(:generator_forwarding) { [true, self, to, event.object_id, event.time, event.context.to_s] }
143
+ end
144
+
145
+ def postponed(context, generator, reason)
146
+ super if defined? super
147
+ Roby::Log.log(:generator_postponed) { [self, context.to_s, generator, reason.to_s] }
148
+ end
149
+ end
150
+ Roby::EventGenerator.include EventGeneratorHooks
151
+
152
+ module ControlHooks
153
+ HOOKS = %w{cycle_end}
154
+
155
+ def cycle_end(timings)
156
+ super if defined? super
157
+ Roby::Log.log(:cycle_end) { [timings] }
158
+ end
159
+
160
+ module ClassExtension
161
+ HOOKS = %w{fatal_exception handled_exception}
162
+
163
+ def fatal_exception(error, tasks)
164
+ super if defined? super
165
+ Roby::Log.log(:fatal_exception) { [error.exception, tasks] }
166
+ end
167
+ def handled_exception(error, task)
168
+ super if defined? super
169
+ Roby::Log.log(:handled_exception) { [error.exception, task] }
170
+ end
171
+ end
172
+ end
173
+ Roby::Control.include ControlHooks
174
+
175
+ def self.each_hook
176
+ [TransactionHooks, BasicObjectHooks, TaskHooks,
177
+ PlanHooks, EventGeneratorHooks, ControlHooks,
178
+ ControlHooks::ClassExtension].each do |klass|
179
+ klass::HOOKS.each do |m|
180
+ yield(klass, m.to_sym)
181
+ end
182
+ end
183
+ end
184
+ end
185
+
@@ -0,0 +1,202 @@
1
+ require 'roby/log/hooks'
2
+ require 'roby/log/file'
3
+
4
+ module Roby::Log
5
+ @loggers = Array.new
6
+ @@logging_thread = nil
7
+
8
+ extend Logger::Hierarchy
9
+ extend Logger::Forward
10
+
11
+ class << self
12
+ # Start the logging framework
13
+ def logging?
14
+ @@logging_thread
15
+ end
16
+
17
+ # Start the logging framework
18
+ def start_logging # :nodoc:
19
+ return if logging?
20
+ logged_events.clear
21
+ @@logging_thread = Thread.new(&method(:logger_loop))
22
+ end
23
+
24
+ # Stop the logging framework
25
+ def stop_logging # :nodoc:
26
+ return unless logging?
27
+ logged_events.push nil
28
+ flushed_logger_mutex.synchronize do
29
+ while @@logging_thread
30
+ flushed_logger.wait(flushed_logger_mutex)
31
+ end
32
+ end
33
+ end
34
+
35
+ # Add a logger object in the system
36
+ def add_logger(logger)
37
+ start_logging
38
+ @loggers << logger
39
+ end
40
+
41
+ # Remove a logger from the list of loggers
42
+ def remove_logger(logger)
43
+ flush if logging?
44
+ if @loggers.size == 1
45
+ stop_logging
46
+ end
47
+ @loggers.delete logger
48
+ end
49
+
50
+ # Remove all loggers
51
+ def clear_loggers
52
+ stop_logging
53
+ @loggers.clear
54
+ end
55
+
56
+ # Iterates on all the logger objects. If +m+ is given, yields only the loggers
57
+ # which respond to this method.
58
+ def each_logger(m = nil)
59
+ for l in @loggers
60
+ if !m || l.respond_to?(m)
61
+ yield(l)
62
+ end
63
+ end
64
+ end
65
+
66
+ # Returns true if there is at least one loggr for the +m+ message
67
+ def has_logger?(m)
68
+ for l in @loggers
69
+ return true if l.respond_to?(m)
70
+ end
71
+ false
72
+ end
73
+
74
+ attr_reader :logged_events
75
+ attr_reader :flushed_logger_mutex
76
+ attr_reader :flushed_logger
77
+ attr_reader :known_objects
78
+
79
+ def incremental_dump?(object); known_objects.include?(object) end
80
+
81
+ # call-seq:
82
+ # Log.log(message) { args }
83
+ #
84
+ # Logs +message+ with argument +args+. The block is called only once if
85
+ # there is at least one logger which listens for +message+.
86
+ def log(m, args = nil)
87
+ if m == :discovered_tasks || m == :discovered_events
88
+ Roby::Control.synchronize do
89
+ args ||= yield
90
+ objects = args[1].to_value_set
91
+ # Do not give a 'peer' argument at Distributed.format, to
92
+ # make sure we do a full dump
93
+ args = Roby::Distributed.format(args) if has_logger?(m)
94
+ known_objects.merge(objects)
95
+ end
96
+ elsif m == :finalized_task || m == :finalized_event
97
+ Roby::Control.synchronize do
98
+ args ||= yield
99
+ object = args[1]
100
+ args = Roby::Distributed.format(args, self) if has_logger?(m)
101
+ known_objects.delete(object)
102
+ end
103
+ end
104
+
105
+ if has_logger?(m)
106
+ if !args && block_given?
107
+ Roby::Control.synchronize do
108
+ args = Roby::Distributed.format(yield, self)
109
+ end
110
+ end
111
+
112
+ logged_events << [m, Time.now, args]
113
+ end
114
+ end
115
+
116
+ # The main logging loop. We use a separate loop to avoid having logging
117
+ # have too much influence on the control thread. The Log.logged_events
118
+ # attribute is a sized queue (of size LOGGED_EVENTS_QUEUE_SIZE) in
119
+ # which all the events needing logging are saved
120
+ def logger_loop
121
+ Thread.current.priority = 2
122
+ loop do
123
+ m, time, args = logged_events.pop
124
+ break unless m
125
+
126
+ each_logger(m) do |logger|
127
+ if logger.splat?
128
+ logger.send(m, time, *args)
129
+ else
130
+ logger.send(m, time, args)
131
+ end
132
+ end
133
+
134
+ if m == :flush && logged_events.empty?
135
+ flushed_logger_mutex.synchronize do
136
+ flushed_logger.broadcast
137
+ end
138
+ end
139
+ end
140
+
141
+ rescue Exception => e
142
+ Roby.fatal "logger thread dies with #{e.full_message}" unless e.kind_of?(Interrupt)
143
+
144
+ ensure
145
+ # Wake up any waiting thread
146
+ flushed_logger_mutex.synchronize do
147
+ @@logging_thread = nil
148
+ flushed_logger.broadcast
149
+ end
150
+ end
151
+
152
+ # Waits for all the events queued in +logged_events+ to be processed by
153
+ # the logging thread. Also sends the +flush+ message to all loggers
154
+ # that respond to it
155
+ def flush
156
+ flushed_logger_mutex.synchronize do
157
+ if !logging?
158
+ raise "not logging"
159
+ end
160
+
161
+ logged_events.push [:flush, []]
162
+ flushed_logger.wait(flushed_logger_mutex)
163
+ end
164
+ end
165
+
166
+ # Requires all displays
167
+ def load_all_displays
168
+ require 'roby/log/relations'
169
+ require 'roby/log/execution-state'
170
+ end
171
+
172
+ def open(file)
173
+ Logfile.open(file)
174
+ end
175
+
176
+ def replay(file, &block)
177
+ if file =~ /\.gz$/
178
+ require 'zlib'
179
+ require 'roby/log/file'
180
+ Zlib::GzipReader.open(file) do |io|
181
+ FileLogger.replay(io, &block)
182
+ end
183
+ elsif file =~ /\.db$/
184
+ require 'roby/log/sqlite'
185
+ SQLiteLogger.replay(file, &block)
186
+ else
187
+ require 'roby/log/file'
188
+ File.open(file) do |io|
189
+ FileLogger.replay(io, &block)
190
+ end
191
+ end
192
+ end
193
+ end
194
+
195
+ LOGGED_EVENTS_QUEUE_SIZE = 2000
196
+ @logged_events = SizedQueue.new(LOGGED_EVENTS_QUEUE_SIZE)
197
+ @flushed_logger_mutex = Mutex.new
198
+ @flushed_logger = ConditionVariable.new
199
+ @known_objects = ValueSet.new
200
+
201
+ end
202
+