roby 0.7.3 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (236) hide show
  1. data/History.txt +7 -5
  2. data/Manifest.txt +91 -16
  3. data/README.txt +24 -24
  4. data/Rakefile +92 -64
  5. data/app/config/app.yml +42 -43
  6. data/app/config/init.rb +26 -0
  7. data/benchmark/alloc_misc.rb +123 -0
  8. data/benchmark/discovery_latency.rb +67 -0
  9. data/benchmark/garbage_collection.rb +48 -0
  10. data/benchmark/genom.rb +31 -0
  11. data/benchmark/transactions.rb +62 -0
  12. data/bin/roby +1 -1
  13. data/bin/roby-log +16 -6
  14. data/doc/guide/.gitignore +2 -0
  15. data/doc/guide/config.yaml +34 -0
  16. data/doc/guide/ext/init.rb +14 -0
  17. data/doc/guide/ext/previous_next.rb +40 -0
  18. data/doc/guide/ext/rdoc_links.rb +33 -0
  19. data/doc/guide/index.rdoc +16 -0
  20. data/doc/guide/overview.rdoc +62 -0
  21. data/doc/guide/plan_modifications.rdoc +67 -0
  22. data/doc/guide/src/abstraction/achieve_with.page +8 -0
  23. data/doc/guide/src/abstraction/forwarding.page +8 -0
  24. data/doc/guide/src/abstraction/hierarchy.page +19 -0
  25. data/doc/guide/src/abstraction/index.page +28 -0
  26. data/doc/guide/src/abstraction/task_models.page +13 -0
  27. data/doc/guide/src/basics.template +6 -0
  28. data/doc/guide/src/basics/app.page +139 -0
  29. data/doc/guide/src/basics/code_examples.page +33 -0
  30. data/doc/guide/src/basics/dry.page +69 -0
  31. data/doc/guide/src/basics/errors.page +443 -0
  32. data/doc/guide/src/basics/events.page +179 -0
  33. data/doc/guide/src/basics/hierarchy.page +275 -0
  34. data/doc/guide/src/basics/index.page +11 -0
  35. data/doc/guide/src/basics/log_replay/goForward_1.png +0 -0
  36. data/doc/guide/src/basics/log_replay/goForward_2.png +0 -0
  37. data/doc/guide/src/basics/log_replay/goForward_3.png +0 -0
  38. data/doc/guide/src/basics/log_replay/goForward_4.png +0 -0
  39. data/doc/guide/src/basics/log_replay/goForward_5.png +0 -0
  40. data/doc/guide/src/basics/log_replay/hierarchy_error_1.png +0 -0
  41. data/doc/guide/src/basics/log_replay/hierarchy_error_2.png +0 -0
  42. data/doc/guide/src/basics/log_replay/hierarchy_error_3.png +0 -0
  43. data/doc/guide/src/basics/log_replay/plan_repair_1.png +0 -0
  44. data/doc/guide/src/basics/log_replay/plan_repair_2.png +0 -0
  45. data/doc/guide/src/basics/log_replay/plan_repair_3.png +0 -0
  46. data/doc/guide/src/basics/log_replay/plan_repair_4.png +0 -0
  47. data/doc/guide/src/basics/log_replay/roby_log_main_window.png +0 -0
  48. data/doc/guide/src/basics/log_replay/roby_log_relation_window.png +0 -0
  49. data/doc/guide/src/basics/log_replay/roby_replay_event_representation.png +0 -0
  50. data/doc/guide/src/basics/plan_objects.page +71 -0
  51. data/doc/guide/src/basics/relations_display.page +203 -0
  52. data/doc/guide/src/basics/roby_cycle_overview.png +0 -0
  53. data/doc/guide/src/basics/shell.page +102 -0
  54. data/doc/guide/src/basics/summary.page +32 -0
  55. data/doc/guide/src/basics/tasks.page +357 -0
  56. data/doc/guide/src/basics_shell_header.txt +16 -0
  57. data/doc/guide/src/cycle/cycle-overview.png +0 -0
  58. data/doc/guide/src/cycle/cycle-overview.svg +208 -0
  59. data/doc/guide/src/cycle/error_handling.page +168 -0
  60. data/doc/guide/src/cycle/error_instantaneous_repair.png +0 -0
  61. data/doc/guide/src/cycle/error_instantaneous_repair.svg +1224 -0
  62. data/doc/guide/src/cycle/garbage_collection.page +10 -0
  63. data/doc/guide/src/cycle/index.page +23 -0
  64. data/doc/guide/src/cycle/propagation.page +154 -0
  65. data/doc/guide/src/cycle/propagation_diamond.png +0 -0
  66. data/doc/guide/src/cycle/propagation_diamond.svg +1279 -0
  67. data/doc/guide/src/default.css +319 -0
  68. data/doc/guide/src/default.template +74 -0
  69. data/doc/guide/src/htmldoc.metainfo +20 -0
  70. data/doc/guide/src/htmldoc.virtual +18 -0
  71. data/doc/guide/src/images/bodybg.png +0 -0
  72. data/doc/guide/src/images/contbg.png +0 -0
  73. data/doc/guide/src/images/footerbg.png +0 -0
  74. data/doc/guide/src/images/gradient1.png +0 -0
  75. data/doc/guide/src/images/gradient2.png +0 -0
  76. data/doc/guide/src/index.page +7 -0
  77. data/doc/guide/src/introduction/index.page +29 -0
  78. data/doc/guide/src/introduction/install.page +133 -0
  79. data/doc/{papers.rdoc → guide/src/introduction/publications.page} +5 -2
  80. data/doc/{videos.rdoc → guide/src/introduction/videos.page} +4 -2
  81. data/doc/guide/src/plugins/fault_tolerance.page +44 -0
  82. data/doc/guide/src/plugins/index.page +11 -0
  83. data/doc/guide/src/plugins/subsystems.page +45 -0
  84. data/doc/guide/src/relations/dependency.page +89 -0
  85. data/doc/guide/src/relations/index.page +12 -0
  86. data/doc/misc/update_github +24 -0
  87. data/doc/tutorials/02-GoForward.rdoc +3 -3
  88. data/ext/graph/graph.cc +46 -0
  89. data/lib/roby.rb +57 -22
  90. data/lib/roby/app.rb +132 -112
  91. data/lib/roby/app/plugins/rake.rb +21 -0
  92. data/lib/roby/app/rake.rb +0 -7
  93. data/lib/roby/app/run.rb +1 -1
  94. data/lib/roby/app/scripts/distributed.rb +1 -2
  95. data/lib/roby/app/scripts/generate/bookmarks.rb +1 -1
  96. data/lib/roby/app/scripts/results.rb +2 -1
  97. data/lib/roby/app/scripts/run.rb +6 -2
  98. data/lib/roby/app/scripts/shell.rb +11 -11
  99. data/lib/roby/config.rb +1 -1
  100. data/lib/roby/decision_control.rb +62 -3
  101. data/lib/roby/distributed.rb +4 -0
  102. data/lib/roby/distributed/base.rb +8 -0
  103. data/lib/roby/distributed/communication.rb +12 -8
  104. data/lib/roby/distributed/connection_space.rb +61 -44
  105. data/lib/roby/distributed/distributed_object.rb +1 -1
  106. data/lib/roby/distributed/notifications.rb +22 -30
  107. data/lib/roby/distributed/peer.rb +13 -8
  108. data/lib/roby/distributed/proxy.rb +5 -5
  109. data/lib/roby/distributed/subscription.rb +4 -4
  110. data/lib/roby/distributed/transaction.rb +3 -3
  111. data/lib/roby/event.rb +176 -110
  112. data/lib/roby/exceptions.rb +12 -4
  113. data/lib/roby/execution_engine.rb +1604 -0
  114. data/lib/roby/external_process_task.rb +225 -0
  115. data/lib/roby/graph.rb +0 -6
  116. data/lib/roby/interface.rb +221 -137
  117. data/lib/roby/log/console.rb +5 -3
  118. data/lib/roby/log/data_stream.rb +94 -16
  119. data/lib/roby/log/dot.rb +8 -8
  120. data/lib/roby/log/event_stream.rb +13 -3
  121. data/lib/roby/log/file.rb +43 -18
  122. data/lib/roby/log/gui/basic_display_ui.rb +89 -0
  123. data/lib/roby/log/gui/chronicle_view_ui.rb +90 -0
  124. data/lib/roby/log/gui/data_displays.rb +4 -5
  125. data/lib/roby/log/gui/data_displays_ui.rb +146 -0
  126. data/lib/roby/log/gui/relations.rb +18 -18
  127. data/lib/roby/log/gui/relations_ui.rb +120 -0
  128. data/lib/roby/log/gui/relations_view_ui.rb +144 -0
  129. data/lib/roby/log/gui/replay.rb +41 -13
  130. data/lib/roby/log/gui/replay_controls.rb +3 -0
  131. data/lib/roby/log/gui/replay_controls.ui +133 -110
  132. data/lib/roby/log/gui/replay_controls_ui.rb +249 -0
  133. data/lib/roby/log/hooks.rb +19 -18
  134. data/lib/roby/log/logger.rb +7 -6
  135. data/lib/roby/log/notifications.rb +4 -4
  136. data/lib/roby/log/plan_rebuilder.rb +20 -22
  137. data/lib/roby/log/relations.rb +44 -16
  138. data/lib/roby/log/server.rb +1 -4
  139. data/lib/roby/log/timings.rb +88 -19
  140. data/lib/roby/plan-object.rb +135 -11
  141. data/lib/roby/plan.rb +408 -224
  142. data/lib/roby/planning/loops.rb +32 -25
  143. data/lib/roby/planning/model.rb +157 -51
  144. data/lib/roby/planning/task.rb +47 -20
  145. data/lib/roby/query.rb +128 -92
  146. data/lib/roby/relations.rb +254 -136
  147. data/lib/roby/relations/conflicts.rb +6 -9
  148. data/lib/roby/relations/dependency.rb +358 -0
  149. data/lib/roby/relations/ensured.rb +0 -1
  150. data/lib/roby/relations/error_handling.rb +0 -1
  151. data/lib/roby/relations/events.rb +0 -2
  152. data/lib/roby/relations/executed_by.rb +26 -11
  153. data/lib/roby/relations/planned_by.rb +14 -14
  154. data/lib/roby/robot.rb +46 -0
  155. data/lib/roby/schedulers/basic.rb +34 -0
  156. data/lib/roby/standalone.rb +4 -0
  157. data/lib/roby/standard_errors.rb +21 -15
  158. data/lib/roby/state/events.rb +5 -4
  159. data/lib/roby/support.rb +107 -6
  160. data/lib/roby/task-operations.rb +23 -19
  161. data/lib/roby/task.rb +522 -148
  162. data/lib/roby/task_index.rb +80 -0
  163. data/lib/roby/test/common.rb +283 -44
  164. data/lib/roby/test/distributed.rb +53 -37
  165. data/lib/roby/test/testcase.rb +9 -204
  166. data/lib/roby/test/tools.rb +3 -3
  167. data/lib/roby/transactions.rb +154 -111
  168. data/lib/roby/transactions/proxy.rb +40 -7
  169. data/manifest.xml +20 -0
  170. data/plugins/fault_injection/README.txt +0 -3
  171. data/plugins/fault_injection/Rakefile +2 -8
  172. data/plugins/fault_injection/app.rb +1 -1
  173. data/plugins/fault_injection/fault_injection.rb +3 -3
  174. data/plugins/fault_injection/test/test_fault_injection.rb +19 -25
  175. data/plugins/subsystems/README.txt +0 -3
  176. data/plugins/subsystems/Rakefile +2 -7
  177. data/plugins/subsystems/app.rb +27 -16
  178. data/plugins/subsystems/test/app/config/init.rb +3 -0
  179. data/plugins/subsystems/test/app/planners/main.rb +1 -1
  180. data/plugins/subsystems/test/app/tasks/services.rb +1 -1
  181. data/plugins/subsystems/test/test_subsystems.rb +23 -16
  182. data/test/distributed/test_communication.rb +32 -15
  183. data/test/distributed/test_connection.rb +28 -26
  184. data/test/distributed/test_execution.rb +59 -54
  185. data/test/distributed/test_mixed_plan.rb +34 -34
  186. data/test/distributed/test_plan_notifications.rb +26 -26
  187. data/test/distributed/test_protocol.rb +57 -48
  188. data/test/distributed/test_query.rb +11 -7
  189. data/test/distributed/test_remote_plan.rb +71 -71
  190. data/test/distributed/test_transaction.rb +50 -47
  191. data/test/mockups/external_process +28 -0
  192. data/test/planning/test_loops.rb +163 -119
  193. data/test/planning/test_model.rb +3 -3
  194. data/test/planning/test_task.rb +27 -7
  195. data/test/relations/test_conflicts.rb +3 -3
  196. data/test/relations/test_dependency.rb +324 -0
  197. data/test/relations/test_ensured.rb +2 -2
  198. data/test/relations/test_executed_by.rb +94 -19
  199. data/test/relations/test_planned_by.rb +11 -9
  200. data/test/suite_core.rb +6 -3
  201. data/test/suite_distributed.rb +1 -0
  202. data/test/suite_planning.rb +1 -0
  203. data/test/suite_relations.rb +2 -2
  204. data/test/tasks/test_external_process.rb +126 -0
  205. data/test/{test_thread_task.rb → tasks/test_thread_task.rb} +17 -20
  206. data/test/test_bgl.rb +21 -1
  207. data/test/test_event.rb +229 -155
  208. data/test/test_exceptions.rb +79 -80
  209. data/test/test_execution_engine.rb +987 -0
  210. data/test/test_gui.rb +1 -1
  211. data/test/test_interface.rb +11 -5
  212. data/test/test_log.rb +18 -7
  213. data/test/test_log_server.rb +1 -0
  214. data/test/test_plan.rb +229 -395
  215. data/test/test_query.rb +193 -35
  216. data/test/test_relations.rb +88 -8
  217. data/test/test_state.rb +55 -37
  218. data/test/test_support.rb +1 -1
  219. data/test/test_task.rb +371 -218
  220. data/test/test_testcase.rb +32 -16
  221. data/test/test_transactions.rb +211 -170
  222. data/test/test_transactions_proxy.rb +37 -19
  223. metadata +169 -71
  224. data/.gitignore +0 -29
  225. data/doc/styles/allison.css +0 -314
  226. data/doc/styles/allison.js +0 -316
  227. data/doc/styles/allison.rb +0 -276
  228. data/doc/styles/jamis.rb +0 -593
  229. data/lib/roby/control.rb +0 -746
  230. data/lib/roby/executives/simple.rb +0 -30
  231. data/lib/roby/propagation.rb +0 -562
  232. data/lib/roby/relations/hierarchy.rb +0 -239
  233. data/lib/roby/transactions/updates.rb +0 -139
  234. data/test/relations/test_hierarchy.rb +0 -158
  235. data/test/test_control.rb +0 -399
  236. data/test/test_propagation.rb +0 -210
@@ -419,6 +419,18 @@ module Roby
419
419
 
420
420
  include TaskDisplaySupport
421
421
 
422
+ def self.all_task_relations
423
+ if @all_task_relations
424
+ @all_task_relations
425
+ else
426
+ result = []
427
+ ObjectSpace.each_object(Roby::RelationSpace) do |space|
428
+ result.concat(space.relations) if space.applied.find { |t| t <= Roby::Task }
429
+ end
430
+ @all_task_relations = result
431
+ end
432
+ end
433
+
422
434
  attr_reader :ui, :scene
423
435
 
424
436
  # A [DRbObject, DRbObject] => GraphicsItem mapping of arrows
@@ -510,25 +522,31 @@ module Roby
510
522
  obj
511
523
  end
512
524
 
525
+ # Initializes the display with the data already decoded from the
526
+ # given data stream, and binds this display to the stream.
513
527
  def stream=(data_stream)
514
528
  super
515
529
 
516
530
  # Initialize the display ...
517
531
  decoder.plans.each do |plan|
518
- discovered_tasks(Time.now, plan, plan.known_tasks)
519
- discovered_events(Time.now, plan, plan.free_events)
532
+ added_tasks(Time.now, plan, plan.known_tasks)
533
+ added_events(Time.now, plan, plan.free_events)
520
534
  end
521
535
  display
522
536
  end
523
537
 
524
538
  def [](item); graphics[item] end
539
+
540
+ # Returns a canvas object that represents this relation
525
541
  def task_relation(from, to, rel, info)
526
542
  arrow(from, to, rel, info, TASK_LAYER)
527
543
  end
544
+ # Returns a canvas object that represents this relation
528
545
  def event_relation(form, to, rel, info)
529
546
  arrow(from, to, rel, info, EVENT_LAYER)
530
547
  end
531
548
 
549
+ # Creates or reuses an arrow object to represent the given relation
532
550
  def arrow(from, to, rel, info, base_layer)
533
551
  id = [from, to, rel]
534
552
  unless item = arrows[id]
@@ -589,9 +607,14 @@ module Roby
589
607
  COLORS[current_color]
590
608
  end
591
609
 
610
+ # True if this relation should be displayed
592
611
  def relation_enabled?(relation); @enabled_relations.include?(relation) end
612
+ # True if this relation should be used for layout
613
+ #
614
+ # See also #relation_enabled?, #layout_relation, #ignore_relation
593
615
  def layout_relation?(relation); relation_enabled?(relation) || @layout_relations.include?(relation) end
594
616
 
617
+ # Display this relation
595
618
  def enable_relation(relation)
596
619
  return if relation_enabled?(relation)
597
620
  @enabled_relations << relation
@@ -602,11 +625,17 @@ module Roby
602
625
  end
603
626
  end
604
627
 
628
+ # The set of relations that should be displayed
605
629
  attr_reader :enabled_relations
630
+
631
+ # Use this relation for layout but not for display
632
+ #
633
+ # See also #ignore_relation
606
634
  def layout_relation(relation)
607
635
  disable_relation(relation)
608
636
  @layout_relations << relation
609
637
  end
638
+ # Don't use this relation at all
610
639
  def ignore_relation(relation)
611
640
  disable_relation(relation)
612
641
  @layout_relations.delete(relation)
@@ -756,19 +785,22 @@ module Roby
756
785
  end
757
786
 
758
787
  def clear_integrated
759
- postponed_events.clear
760
- execution_events.clear
761
- @execution_events = execution_events.find_all { |fired, ev| !fired }
788
+ unless keep_signals
789
+ last_propagated_events, @propagated_events = propagated_events, Array.new
790
+ last_execution_events, @execution_events =
791
+ execution_events.partition { |fired, ev| fired }
792
+ end
793
+ !(last_propagated_events.empty? && last_execution_events.empty?)
762
794
  end
763
795
 
796
+ # Update the display with new data that has come from the data
797
+ # stream.
798
+ #
799
+ # It would be too complex at this stage to know if the plan has been
800
+ # updated, so the method always returns true
764
801
  def update
765
802
  return unless decoder
766
803
 
767
- if keep_signals
768
- @execution_events = @last_execution_events.concat(execution_events)
769
- @propagated_events.concat @last_propagated_events
770
- end
771
-
772
804
  update_prefixes_removal
773
805
  clear_flashing_objects
774
806
 
@@ -912,11 +944,7 @@ module Roby
912
944
  end
913
945
  end
914
946
 
915
- @last_propagated_events, @propagated_events = propagated_events, Array.new
916
- @last_execution_events, @execution_events =
917
- execution_events.partition { |fired, ev| fired }
918
-
919
- postponed_events.clear
947
+ true
920
948
  end
921
949
 
922
950
  def remove_graphics(item, scene = nil)
@@ -995,7 +1023,7 @@ module Roby
995
1023
  def removed_event_child(time, parent, rel, child)
996
1024
  remove_graphics(arrows.delete([local_event(parent), local_event(child), rel]))
997
1025
  end
998
- def discovered_tasks(time, plan, tasks)
1026
+ def added_tasks(time, plan, tasks)
999
1027
  tasks.each do |obj|
1000
1028
  obj.flags[:pending] = true if obj.respond_to?(:flags)
1001
1029
  task = local_task(obj)
@@ -47,9 +47,6 @@ module Roby
47
47
  discovered_displays = Array.new
48
48
  @available_servers = Array.new
49
49
 
50
- # Add disable_discovery in the list of finalizers
51
- Control.finalizers << method(:disable_discovery)
52
-
53
50
  @discovery_thread = Thread.new do
54
51
  begin
55
52
  loop do
@@ -75,7 +72,7 @@ module Roby
75
72
 
76
73
  # Stops the discovery thread if it is running
77
74
  def self.disable_discovery
78
- Control.finalizers.delete(method(:disable_discovery))
75
+ Roby.engine.finalizers.delete(method(:disable_discovery))
79
76
  if @discovery_thread
80
77
  @discovery_thread.raise Interrupt, "quitting"
81
78
  @discovery_thread.join
@@ -1,16 +1,16 @@
1
+ require 'set'
2
+
1
3
  module Roby
2
4
  module Log
3
5
  class Timings
4
6
  REF_TIMING = :start
5
7
  ALL_TIMINGS = [ :real_start, :events,
6
8
  :structure_check, :exception_propagation,
7
- :exceptions_fatal, :garbage_collect, :application_errors,
8
- :expected_ruby_gc, :ruby_gc, :droby, :expected_sleep, :sleep, :end ]
9
+ :exceptions_fatal, :garbage_collect,
10
+ :ruby_gc, :expected_sleep, :sleep, :end ]
9
11
 
10
- NUMERIC_FIELDS = [:cycle_index, :live_objects, :object_allocation, :log_queue_size, :ruby_gc_duration,
11
- :plan_task_count, :plan_event_count]
12
- DELTAS = [:cpu_time]
13
- ALL_NUMERIC_FIELDS = NUMERIC_FIELDS + DELTAS
12
+ ALL_NUMERIC_FIELDS = [:cycle_index, :live_objects, :object_allocation, :heap_slots,
13
+ :log_queue_size, :plan_task_count, :plan_event_count, :cpu_time]
14
14
 
15
15
  ALL_FIELDS = ALL_TIMINGS + ALL_NUMERIC_FIELDS + [:event_count, :pos]
16
16
 
@@ -23,7 +23,86 @@ module Roby
23
23
  end
24
24
  def rewind; logfile.rewind end
25
25
 
26
- def each_cycle(cumulative = false)
26
+ # Read the logfile index, extract statistic information from it and
27
+ # yield them cycle-by-cycle. The format of +timings+ is the
28
+ # following:
29
+ #
30
+ # [start, real_start, events,
31
+ # structure_check, exception_propagation,
32
+ # exceptions_fatal, garbage_collect,
33
+ # ruby_gc, expected_sleep, sleep, end]
34
+ #
35
+ # where +start+ is the target start time of the cycle as a Time
36
+ # object. The rest of the values are floating-point values which
37
+ # represent offset from +start+ if +cumulative+ is true or offset
38
+ # from the previous one if +cumulative+ is false. Therefore, in the
39
+ # latter case, the values represent the actual duration of each
40
+ # phase in the execution engine.
41
+ #
42
+ # The phases are as follows:
43
+ # real_start::
44
+ # the actual starting time. It allows to see the offset due (for
45
+ # instance) to the uncertainty in sleep
46
+ # events::
47
+ # event propagation phase, including the propagation of dRoby
48
+ # events (events coming from remote hosts)
49
+ # structure_check::
50
+ # first structure checking pass
51
+ # exception_propagation::
52
+ # exception propagation phase
53
+ # exceptions_fatal::
54
+ # second structure checking pass, and propagation of the fatal
55
+ # errors (i.e. killing the involved tasks)
56
+ # garbage_collect::
57
+ # Roby's garbage collection pass
58
+ # ruby_gc::
59
+ # if GC.enable accepts a true/false argument, Roby will
60
+ # explicitely allow the GC to run only at a specific point, and
61
+ # monitor its execution time. This is the result. Note that Roby
62
+ # issues a warning at startup if it is not the case.
63
+ # expected_sleep::
64
+ # how much time Roby wanted to sleep (i.e. how many milliseconds
65
+ # were given to the sleep() call)
66
+ # sleep::
67
+ # how much time Roby actually slept
68
+ # end::
69
+ # end of the cycle
70
+ #
71
+ # The second array that is yield, +numeric+, contains non-timing
72
+ # statistics. Its format is:
73
+ #
74
+ # [cycle_index, live_objects, object_allocation, log_queue_size,
75
+ # plan_task_count, plan_event_count, cpu_time]
76
+ #
77
+ # where
78
+ #
79
+ # cycle_index::
80
+ # The index of this cycle. Note that some number can be missing: if one
81
+ # cycle takes more than two time its allocated period, then +cycle_index+ is
82
+ # updated to reflect the cycles that have been missed.
83
+ # live_objects::
84
+ # The count of allocated objects at the end of the cycle. It is only valid
85
+ # on Ruby interpreters that have been patched to report this value
86
+ # efficiently.
87
+ # object_allocation::
88
+ # How many objects have been allocated during this cycle. This is valid only
89
+ # if Ruby GC is controlled by Roby (see the description of +ruby_gc+ above).
90
+ # Otherwise, it will be invalid in cycles where the Ruby GC ran, as the
91
+ # statistics can't correct the objects freed by Ruby's GC.
92
+ # log_queue_size::
93
+ # The logger runs in a thread separated from the execution engine, and a
94
+ # fixed-size queue is used to communicate between the threads. This value is
95
+ # the size of the queue at the end of the cycle (after sleep()). It is
96
+ # mainly used for debugging purposes: if this queue is almost full, then the
97
+ # execution engine thread will probably be interrupted to let the log thread
98
+ # empty the queue.
99
+ # plan_task_count::
100
+ # The count of tasks in the plan at the end of the cycle.
101
+ # plan_event_count::
102
+ # The count of free events in the plan at the end of the cycle.
103
+ # cpu_time::
104
+ # The CPU time taken by the Roby controller for this cycle.
105
+ def each_cycle(cumulative = false) # :yield:numeric, timings
27
106
  last_deltas = Hash.new
28
107
  for data in logfile.index_data[1..-1]
29
108
  result = []
@@ -54,18 +133,8 @@ module Roby
54
133
  end
55
134
  end
56
135
 
57
- numeric = data.values_at(*NUMERIC_FIELDS)
58
- deltas = DELTAS.map do |name|
59
- value = if old_value = last_deltas[name]
60
- data[name] - old_value
61
- else
62
- 0
63
- end
64
- last_deltas[name] = data[name]
65
- value
66
- end
67
-
68
- yield(numeric + deltas, result)
136
+ numeric = data.values_at(*ALL_NUMERIC_FIELDS)
137
+ yield(numeric, result)
69
138
  end
70
139
 
71
140
  rescue ArgumentError => e
@@ -1,7 +1,3 @@
1
- require 'roby/relations'
2
- require 'roby/distributed/base'
3
- require 'roby/basic_object'
4
-
5
1
  module Roby
6
2
  # Base class for all objects which are included in a plan.
7
3
  class PlanObject < BasicObject
@@ -10,6 +6,9 @@ module Roby
10
6
  # The plan this object belongs to
11
7
  attr_reader :plan
12
8
 
9
+ # The engine which acts on +plan+ (if there is one)
10
+ def engine; plan.engine end
11
+
13
12
  # The place where this object has been removed from its plan. Once an
14
13
  # object is removed from its plan, it cannot be added back again.
15
14
  attr_accessor :removed_at
@@ -29,6 +28,109 @@ module Roby
29
28
  @plan = new_plan
30
29
  end
31
30
 
31
+ # The propagation engine object for this. For PlanObject instances, it
32
+ # is always the plan itself.
33
+ def propagation_engine
34
+ plan
35
+ end
36
+
37
+ # If +self+ is a transaction proxy, returns the underlying plan object,
38
+ # regardless of how many transactions there is on the stack. Otherwise,
39
+ # return self.
40
+ def real_object
41
+ result = self
42
+ while result.respond_to?(:__getobj__)
43
+ result = result.__getobj__
44
+ end
45
+ result
46
+ end
47
+
48
+ # Returns the stack of transactions/plans this object is part of,
49
+ # starting with self.plan.
50
+ def transaction_stack
51
+ result = [plan]
52
+ obj = self
53
+ while obj.respond_to?(:__getobj__)
54
+ obj = obj.__getobj__
55
+ result << obj.plan
56
+ end
57
+ result
58
+ end
59
+
60
+ # call-seq:
61
+ # merged_relation(:each_child_object, false, Dependency) do |parent, child|
62
+ # end
63
+ # merged_relation(:each_child_object, true, Dependency) do |child|
64
+ # end
65
+ #
66
+ # Behaves like +enumerator+, but merges all the changes that underlying
67
+ # transactions may have applied. I.e. it is equivalent to applying
68
+ # +enumerator+ on the plan that would be the result of the application
69
+ # of the whole transaction stack
70
+ #
71
+ # If +instrusive+ is false, the edges are yielded at the level they
72
+ # appear. I.e. both the parent and the child are given, and [parent,
73
+ # child] may be part of a parent plan of self.plan.
74
+ #
75
+ # If +instrusive+ is true, the related objects are recursively added to
76
+ # all transactions in the transaction stack, and are given at the end.
77
+ # I.e. only the related object is yield, and it is guaranteed to be
78
+ # included in self.plan.
79
+ def merged_relations(enumerator, intrusive, *args, &block)
80
+ if !block_given?
81
+ return enum_for(:merged_relations, enumerator, intrusive, *args)
82
+ end
83
+
84
+ plan_chain = self.transaction_stack
85
+ object = self.real_object
86
+
87
+ pending = Array.new
88
+ while plan_chain.size > 1
89
+ plan = plan_chain.pop
90
+ next_plan = plan_chain.last
91
+
92
+ # Objects that are in +plan+ but not in +next_plan+ are
93
+ # automatically added, as +next_plan+ is not able to change
94
+ # them. Those that are included in +next_plan+ are handled
95
+ # later.
96
+ new_objects = Array.new
97
+ object.send(enumerator, *args) do |related_object, _|
98
+ next if next_plan[related_object, false]
99
+
100
+ if !intrusive
101
+ yield(object, related_object)
102
+ else
103
+ new_objects << related_object
104
+ end
105
+ end
106
+
107
+ # Here, pending contains objects from the previous plan (i.e. in
108
+ # plan.plan). Proxy them in +plan+.
109
+ #
110
+ # It is important to do that *after* we enumerated the relations
111
+ # that exist in +plan+ (above), as it reduces the number of
112
+ # relations at each level.
113
+ pending.map! { |t| plan[t] }
114
+ # And add the new objects that we just discovered
115
+ pending.concat(new_objects)
116
+
117
+ if next_plan
118
+ object = next_plan[object]
119
+ end
120
+ end
121
+
122
+ if intrusive
123
+ send(enumerator, *args, &block)
124
+ for related_object in pending
125
+ yield(self.plan[related_object])
126
+ end
127
+ else
128
+ send(enumerator, *args) do |related_object, _|
129
+ yield(self, related_object)
130
+ end
131
+ end
132
+ end
133
+
32
134
  # A three-state flag with the following values:
33
135
  # nil:: the object is executable if its plan is
34
136
  # true:: the object is executable
@@ -68,9 +170,9 @@ module Roby
68
170
  elsif other.plan && plan
69
171
  raise RuntimeError, "cannot add a relation between two objects from different plans. #{self} is from #{plan} and #{other} is from #{other.plan}"
70
172
  elsif plan
71
- self.plan.discover(other)
173
+ self.plan.add(other)
72
174
  elsif other.plan
73
- other.plan.discover(self)
175
+ other.plan.add(self)
74
176
  end
75
177
  end
76
178
  protected :synchronize_plan
@@ -233,15 +335,37 @@ module Roby
233
335
  end
234
336
  end
235
337
 
236
- # Checks if we have the right to remove a relation. Raises
237
- # OwnershipError if it is not the case
238
- def removing_child_object(child, type)
239
- super if defined? super
338
+ # Hook called when a new child is added to this object in the given
339
+ # relations and with the given information object.
340
+ def adding_child_object(child, relations, info)
341
+ super if defined? super
342
+ return if !plan
343
+
344
+ for trsc in plan.transactions
345
+ next unless trsc.proxying?
346
+ if (parent_proxy = trsc[self, false]) && (child_proxy = trsc[child, false])
347
+ trsc.adding_plan_relation(parent_proxy, child_proxy, relations, info)
348
+ end
349
+ end
350
+ end
240
351
 
352
+ # Hook called when a child of this object is being removed from the
353
+ # given relations.
354
+ def removing_child_object(child, relations)
241
355
  unless read_write? || child.read_write?
242
356
  raise OwnershipError, "cannot remove a relation between two objects we don't own"
243
357
  end
244
- end
358
+
359
+ super if defined? super
360
+ return if !plan
361
+
362
+ for trsc in plan.transactions
363
+ next unless trsc.proxying?
364
+ if (parent_proxy = trsc[self, false]) && (child_proxy = trsc[child, false])
365
+ trsc.removing_plan_relation(parent_proxy, child_proxy, relations)
366
+ end
367
+ end
368
+ end
245
369
  end
246
370
  end
247
371