roby 0.7.3 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +7 -5
- data/Manifest.txt +91 -16
- data/README.txt +24 -24
- data/Rakefile +92 -64
- data/app/config/app.yml +42 -43
- data/app/config/init.rb +26 -0
- data/benchmark/alloc_misc.rb +123 -0
- data/benchmark/discovery_latency.rb +67 -0
- data/benchmark/garbage_collection.rb +48 -0
- data/benchmark/genom.rb +31 -0
- data/benchmark/transactions.rb +62 -0
- data/bin/roby +1 -1
- data/bin/roby-log +16 -6
- data/doc/guide/.gitignore +2 -0
- data/doc/guide/config.yaml +34 -0
- data/doc/guide/ext/init.rb +14 -0
- data/doc/guide/ext/previous_next.rb +40 -0
- data/doc/guide/ext/rdoc_links.rb +33 -0
- data/doc/guide/index.rdoc +16 -0
- data/doc/guide/overview.rdoc +62 -0
- data/doc/guide/plan_modifications.rdoc +67 -0
- data/doc/guide/src/abstraction/achieve_with.page +8 -0
- data/doc/guide/src/abstraction/forwarding.page +8 -0
- data/doc/guide/src/abstraction/hierarchy.page +19 -0
- data/doc/guide/src/abstraction/index.page +28 -0
- data/doc/guide/src/abstraction/task_models.page +13 -0
- data/doc/guide/src/basics.template +6 -0
- data/doc/guide/src/basics/app.page +139 -0
- data/doc/guide/src/basics/code_examples.page +33 -0
- data/doc/guide/src/basics/dry.page +69 -0
- data/doc/guide/src/basics/errors.page +443 -0
- data/doc/guide/src/basics/events.page +179 -0
- data/doc/guide/src/basics/hierarchy.page +275 -0
- data/doc/guide/src/basics/index.page +11 -0
- data/doc/guide/src/basics/log_replay/goForward_1.png +0 -0
- data/doc/guide/src/basics/log_replay/goForward_2.png +0 -0
- data/doc/guide/src/basics/log_replay/goForward_3.png +0 -0
- data/doc/guide/src/basics/log_replay/goForward_4.png +0 -0
- data/doc/guide/src/basics/log_replay/goForward_5.png +0 -0
- data/doc/guide/src/basics/log_replay/hierarchy_error_1.png +0 -0
- data/doc/guide/src/basics/log_replay/hierarchy_error_2.png +0 -0
- data/doc/guide/src/basics/log_replay/hierarchy_error_3.png +0 -0
- data/doc/guide/src/basics/log_replay/plan_repair_1.png +0 -0
- data/doc/guide/src/basics/log_replay/plan_repair_2.png +0 -0
- data/doc/guide/src/basics/log_replay/plan_repair_3.png +0 -0
- data/doc/guide/src/basics/log_replay/plan_repair_4.png +0 -0
- data/doc/guide/src/basics/log_replay/roby_log_main_window.png +0 -0
- data/doc/guide/src/basics/log_replay/roby_log_relation_window.png +0 -0
- data/doc/guide/src/basics/log_replay/roby_replay_event_representation.png +0 -0
- data/doc/guide/src/basics/plan_objects.page +71 -0
- data/doc/guide/src/basics/relations_display.page +203 -0
- data/doc/guide/src/basics/roby_cycle_overview.png +0 -0
- data/doc/guide/src/basics/shell.page +102 -0
- data/doc/guide/src/basics/summary.page +32 -0
- data/doc/guide/src/basics/tasks.page +357 -0
- data/doc/guide/src/basics_shell_header.txt +16 -0
- data/doc/guide/src/cycle/cycle-overview.png +0 -0
- data/doc/guide/src/cycle/cycle-overview.svg +208 -0
- data/doc/guide/src/cycle/error_handling.page +168 -0
- data/doc/guide/src/cycle/error_instantaneous_repair.png +0 -0
- data/doc/guide/src/cycle/error_instantaneous_repair.svg +1224 -0
- data/doc/guide/src/cycle/garbage_collection.page +10 -0
- data/doc/guide/src/cycle/index.page +23 -0
- data/doc/guide/src/cycle/propagation.page +154 -0
- data/doc/guide/src/cycle/propagation_diamond.png +0 -0
- data/doc/guide/src/cycle/propagation_diamond.svg +1279 -0
- data/doc/guide/src/default.css +319 -0
- data/doc/guide/src/default.template +74 -0
- data/doc/guide/src/htmldoc.metainfo +20 -0
- data/doc/guide/src/htmldoc.virtual +18 -0
- data/doc/guide/src/images/bodybg.png +0 -0
- data/doc/guide/src/images/contbg.png +0 -0
- data/doc/guide/src/images/footerbg.png +0 -0
- data/doc/guide/src/images/gradient1.png +0 -0
- data/doc/guide/src/images/gradient2.png +0 -0
- data/doc/guide/src/index.page +7 -0
- data/doc/guide/src/introduction/index.page +29 -0
- data/doc/guide/src/introduction/install.page +133 -0
- data/doc/{papers.rdoc → guide/src/introduction/publications.page} +5 -2
- data/doc/{videos.rdoc → guide/src/introduction/videos.page} +4 -2
- data/doc/guide/src/plugins/fault_tolerance.page +44 -0
- data/doc/guide/src/plugins/index.page +11 -0
- data/doc/guide/src/plugins/subsystems.page +45 -0
- data/doc/guide/src/relations/dependency.page +89 -0
- data/doc/guide/src/relations/index.page +12 -0
- data/doc/misc/update_github +24 -0
- data/doc/tutorials/02-GoForward.rdoc +3 -3
- data/ext/graph/graph.cc +46 -0
- data/lib/roby.rb +57 -22
- data/lib/roby/app.rb +132 -112
- data/lib/roby/app/plugins/rake.rb +21 -0
- data/lib/roby/app/rake.rb +0 -7
- data/lib/roby/app/run.rb +1 -1
- data/lib/roby/app/scripts/distributed.rb +1 -2
- data/lib/roby/app/scripts/generate/bookmarks.rb +1 -1
- data/lib/roby/app/scripts/results.rb +2 -1
- data/lib/roby/app/scripts/run.rb +6 -2
- data/lib/roby/app/scripts/shell.rb +11 -11
- data/lib/roby/config.rb +1 -1
- data/lib/roby/decision_control.rb +62 -3
- data/lib/roby/distributed.rb +4 -0
- data/lib/roby/distributed/base.rb +8 -0
- data/lib/roby/distributed/communication.rb +12 -8
- data/lib/roby/distributed/connection_space.rb +61 -44
- data/lib/roby/distributed/distributed_object.rb +1 -1
- data/lib/roby/distributed/notifications.rb +22 -30
- data/lib/roby/distributed/peer.rb +13 -8
- data/lib/roby/distributed/proxy.rb +5 -5
- data/lib/roby/distributed/subscription.rb +4 -4
- data/lib/roby/distributed/transaction.rb +3 -3
- data/lib/roby/event.rb +176 -110
- data/lib/roby/exceptions.rb +12 -4
- data/lib/roby/execution_engine.rb +1604 -0
- data/lib/roby/external_process_task.rb +225 -0
- data/lib/roby/graph.rb +0 -6
- data/lib/roby/interface.rb +221 -137
- data/lib/roby/log/console.rb +5 -3
- data/lib/roby/log/data_stream.rb +94 -16
- data/lib/roby/log/dot.rb +8 -8
- data/lib/roby/log/event_stream.rb +13 -3
- data/lib/roby/log/file.rb +43 -18
- data/lib/roby/log/gui/basic_display_ui.rb +89 -0
- data/lib/roby/log/gui/chronicle_view_ui.rb +90 -0
- data/lib/roby/log/gui/data_displays.rb +4 -5
- data/lib/roby/log/gui/data_displays_ui.rb +146 -0
- data/lib/roby/log/gui/relations.rb +18 -18
- data/lib/roby/log/gui/relations_ui.rb +120 -0
- data/lib/roby/log/gui/relations_view_ui.rb +144 -0
- data/lib/roby/log/gui/replay.rb +41 -13
- data/lib/roby/log/gui/replay_controls.rb +3 -0
- data/lib/roby/log/gui/replay_controls.ui +133 -110
- data/lib/roby/log/gui/replay_controls_ui.rb +249 -0
- data/lib/roby/log/hooks.rb +19 -18
- data/lib/roby/log/logger.rb +7 -6
- data/lib/roby/log/notifications.rb +4 -4
- data/lib/roby/log/plan_rebuilder.rb +20 -22
- data/lib/roby/log/relations.rb +44 -16
- data/lib/roby/log/server.rb +1 -4
- data/lib/roby/log/timings.rb +88 -19
- data/lib/roby/plan-object.rb +135 -11
- data/lib/roby/plan.rb +408 -224
- data/lib/roby/planning/loops.rb +32 -25
- data/lib/roby/planning/model.rb +157 -51
- data/lib/roby/planning/task.rb +47 -20
- data/lib/roby/query.rb +128 -92
- data/lib/roby/relations.rb +254 -136
- data/lib/roby/relations/conflicts.rb +6 -9
- data/lib/roby/relations/dependency.rb +358 -0
- data/lib/roby/relations/ensured.rb +0 -1
- data/lib/roby/relations/error_handling.rb +0 -1
- data/lib/roby/relations/events.rb +0 -2
- data/lib/roby/relations/executed_by.rb +26 -11
- data/lib/roby/relations/planned_by.rb +14 -14
- data/lib/roby/robot.rb +46 -0
- data/lib/roby/schedulers/basic.rb +34 -0
- data/lib/roby/standalone.rb +4 -0
- data/lib/roby/standard_errors.rb +21 -15
- data/lib/roby/state/events.rb +5 -4
- data/lib/roby/support.rb +107 -6
- data/lib/roby/task-operations.rb +23 -19
- data/lib/roby/task.rb +522 -148
- data/lib/roby/task_index.rb +80 -0
- data/lib/roby/test/common.rb +283 -44
- data/lib/roby/test/distributed.rb +53 -37
- data/lib/roby/test/testcase.rb +9 -204
- data/lib/roby/test/tools.rb +3 -3
- data/lib/roby/transactions.rb +154 -111
- data/lib/roby/transactions/proxy.rb +40 -7
- data/manifest.xml +20 -0
- data/plugins/fault_injection/README.txt +0 -3
- data/plugins/fault_injection/Rakefile +2 -8
- data/plugins/fault_injection/app.rb +1 -1
- data/plugins/fault_injection/fault_injection.rb +3 -3
- data/plugins/fault_injection/test/test_fault_injection.rb +19 -25
- data/plugins/subsystems/README.txt +0 -3
- data/plugins/subsystems/Rakefile +2 -7
- data/plugins/subsystems/app.rb +27 -16
- data/plugins/subsystems/test/app/config/init.rb +3 -0
- data/plugins/subsystems/test/app/planners/main.rb +1 -1
- data/plugins/subsystems/test/app/tasks/services.rb +1 -1
- data/plugins/subsystems/test/test_subsystems.rb +23 -16
- data/test/distributed/test_communication.rb +32 -15
- data/test/distributed/test_connection.rb +28 -26
- data/test/distributed/test_execution.rb +59 -54
- data/test/distributed/test_mixed_plan.rb +34 -34
- data/test/distributed/test_plan_notifications.rb +26 -26
- data/test/distributed/test_protocol.rb +57 -48
- data/test/distributed/test_query.rb +11 -7
- data/test/distributed/test_remote_plan.rb +71 -71
- data/test/distributed/test_transaction.rb +50 -47
- data/test/mockups/external_process +28 -0
- data/test/planning/test_loops.rb +163 -119
- data/test/planning/test_model.rb +3 -3
- data/test/planning/test_task.rb +27 -7
- data/test/relations/test_conflicts.rb +3 -3
- data/test/relations/test_dependency.rb +324 -0
- data/test/relations/test_ensured.rb +2 -2
- data/test/relations/test_executed_by.rb +94 -19
- data/test/relations/test_planned_by.rb +11 -9
- data/test/suite_core.rb +6 -3
- data/test/suite_distributed.rb +1 -0
- data/test/suite_planning.rb +1 -0
- data/test/suite_relations.rb +2 -2
- data/test/tasks/test_external_process.rb +126 -0
- data/test/{test_thread_task.rb → tasks/test_thread_task.rb} +17 -20
- data/test/test_bgl.rb +21 -1
- data/test/test_event.rb +229 -155
- data/test/test_exceptions.rb +79 -80
- data/test/test_execution_engine.rb +987 -0
- data/test/test_gui.rb +1 -1
- data/test/test_interface.rb +11 -5
- data/test/test_log.rb +18 -7
- data/test/test_log_server.rb +1 -0
- data/test/test_plan.rb +229 -395
- data/test/test_query.rb +193 -35
- data/test/test_relations.rb +88 -8
- data/test/test_state.rb +55 -37
- data/test/test_support.rb +1 -1
- data/test/test_task.rb +371 -218
- data/test/test_testcase.rb +32 -16
- data/test/test_transactions.rb +211 -170
- data/test/test_transactions_proxy.rb +37 -19
- metadata +169 -71
- data/.gitignore +0 -29
- data/doc/styles/allison.css +0 -314
- data/doc/styles/allison.js +0 -316
- data/doc/styles/allison.rb +0 -276
- data/doc/styles/jamis.rb +0 -593
- data/lib/roby/control.rb +0 -746
- data/lib/roby/executives/simple.rb +0 -30
- data/lib/roby/propagation.rb +0 -562
- data/lib/roby/relations/hierarchy.rb +0 -239
- data/lib/roby/transactions/updates.rb +0 -139
- data/test/relations/test_hierarchy.rb +0 -158
- data/test/test_control.rb +0 -399
- data/test/test_propagation.rb +0 -210
data/lib/roby/log/relations.rb
CHANGED
|
@@ -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
|
-
|
|
519
|
-
|
|
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
|
-
|
|
760
|
-
|
|
761
|
-
|
|
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
|
-
|
|
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
|
|
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)
|
data/lib/roby/log/server.rb
CHANGED
|
@@ -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
|
-
|
|
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
|
data/lib/roby/log/timings.rb
CHANGED
|
@@ -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,
|
|
8
|
-
:
|
|
9
|
+
:exceptions_fatal, :garbage_collect,
|
|
10
|
+
:ruby_gc, :expected_sleep, :sleep, :end ]
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
|
|
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
|
-
|
|
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(*
|
|
58
|
-
|
|
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
|
data/lib/roby/plan-object.rb
CHANGED
|
@@ -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.
|
|
173
|
+
self.plan.add(other)
|
|
72
174
|
elsif other.plan
|
|
73
|
-
other.plan.
|
|
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
|
-
#
|
|
237
|
-
#
|
|
238
|
-
|
|
239
|
-
|
|
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
|
-
|
|
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
|
|