Class: Roby::Queries::TransactionQueryResult

Inherits:
Object
  • Object
show all
Defined in:
lib/roby/queries/transaction_query_result.rb

Defined Under Namespace

Classes: QueryRootsStackLevel, ReachabilityVisitor

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(stack = []) ⇒ TransactionQueryResult

Returns a new instance of TransactionQueryResult.



6
7
8
# File 'lib/roby/queries/transaction_query_result.rb', line 6

def initialize(stack = [])
    @stack = stack
end

Class Method Details

.from_transaction(transaction, matcher) ⇒ Object

:nodoc:



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/roby/queries/transaction_query_result.rb', line 44

def self.from_transaction(transaction, matcher) # :nodoc:
    if matcher.scope == :global
        up_results =
            transaction
            .plan.query_result_set(matcher)
            .local_query_results
        # remove tasks from the LAST plan that are proxied in self
        # This is done recursively (i.e. already done for all the
        # other levels)
        plan_results = up_results.pop

        final_result_set = Set.new
        final_result_set.compare_by_identity
        plan_results.each do |task|
            unless transaction.has_proxy_for_task?(task)
                final_result_set << task
            end
        end
        plan_results.result_set = final_result_set
        up_results.push plan_results
    else
        up_results = []
    end

    new(up_results +
        PlanQueryResult.from_plan(transaction, matcher).local_query_results)
end

.reachable_on_applied_transactions?(stack) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Tests whether a set of tasks can be reached from a set of seeds ‘as if’ the transaction stack was applied

Within ‘stack’, level N-1 is ‘up’, that is the plan of the transaction at level N, and level N+1 is ‘down’, that is a transaction built on top of level N.

Parameters:

Returns:

  • (Boolean)


114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/roby/queries/transaction_query_result.rb', line 114

def self.reachable_on_applied_transactions?(stack)
    visitors =
        [QueryRootsStackLevel.null, *stack, QueryRootsStackLevel.null]
        .each_cons(3).map do |up, this, down|
            visitor = ReachabilityVisitor.new(
                this.graph,
                up.plan, up.seeds,
                this.result_set,
                down.plan, down.seeds
            )
            if (start = this.seeds.first)
                visitor.handle_start_vertex(start)
            end
            [this, visitor]
        end

    catch(:reachable) do
        loop do
            all_empty = true
            visitors.each do |stack_level, visitor|
                seeds = stack_level.seeds
                until seeds.empty?
                    all_empty = false
                    seed = seeds.shift
                    unless visitor.finished_vertex?(seed)
                        stack_level.graph.depth_first_visit(
                            seed, visitor
                        ) {}
                    end
                end
            end
            break if all_empty
        end
        return false
    end
    true
end

.roots_of(from, in_relation) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Given the result set of query, returns the subset of tasks which have no parent in query

This is never called directly, but is used by the Query API



174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/roby/queries/transaction_query_result.rb', line 174

def self.roots_of(from, in_relation) # :nodoc:
    stack = from.local_query_results.map do |local_results|
        local_plan = local_results.plan
        local_graph = local_plan.task_relation_graph_for(in_relation)
                                .reverse
        QueryRootsStackLevel.new(local_results, local_graph, [])
    end

    roots_results = stack.map do |stack_level|
        set = stack_level.local_results.result_set
        roots = set.find_all do |task|
            stack_level.seeds[0] = task
            !reachable_on_applied_transactions?(stack)
        end

        new_results = stack_level.local_results.dup
        new_results.result_set = roots
        new_results
    end

    new(roots_results)
end

Instance Method Details

#each_in_plan(plan, &block) ⇒ Object



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/roby/queries/transaction_query_result.rb', line 18

def each_in_plan(plan, &block)
    if plan != @stack.last.plan
        raise ArgumentError,
              "attempting to enumerate results of a query ran "\
              "in #{@stack.first.plan} from #{plan}"
    end

    stack = @stack.dup
    stack.pop.each(&block)
    plan_stack = [plan]

    until stack.empty?
        local_results = stack.pop
        local_results.each do |local_obj|
            wrapped_obj = plan_stack.inject(local_obj) do |obj, p|
                p.wrap(obj)
            end
            yield(wrapped_obj)
        end
    end
end

#local_query_resultsObject



10
11
12
# File 'lib/roby/queries/transaction_query_result.rb', line 10

def local_query_results
    @stack
end

#push(query_result) ⇒ Object



14
15
16
# File 'lib/roby/queries/transaction_query_result.rb', line 14

def push(query_result)
    @stack.push(query_result)
end

#roots(in_relation) ⇒ Object



40
41
42
# File 'lib/roby/queries/transaction_query_result.rb', line 40

def roots(in_relation)
    self.class.roots_of(self, in_relation)
end