pacer 2.0.10.pre-java → 2.0.12-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/.autotest +0 -4
- data/.gitignore +1 -0
- data/.travis.yml +2 -2
- data/Rakefile +25 -0
- data/blog/detach_benchmarks.txt +56 -0
- data/ext/.classpath +26 -0
- data/ext/.gitignore +44 -0
- data/ext/.project +23 -0
- data/ext/pom.xml +76 -0
- data/ext/src/main/java/com/xnlogic/pacer/pipes/BlackboxPipeline.java +56 -0
- data/ext/src/main/java/com/xnlogic/pacer/pipes/CollectionFilterPipe.java +18 -0
- data/ext/src/main/java/com/xnlogic/pacer/pipes/EdgesPipe.java +26 -0
- data/ext/src/main/java/com/xnlogic/pacer/pipes/ExpandablePipe.java +93 -0
- data/ext/src/main/java/com/xnlogic/pacer/pipes/IdCollectionFilterPipe.java +50 -0
- data/ext/src/main/java/com/xnlogic/pacer/pipes/IsEmptyPipe.java +35 -0
- data/ext/src/main/java/com/xnlogic/pacer/pipes/IsUniquePipe.java +58 -0
- data/ext/src/main/java/com/xnlogic/pacer/pipes/LabelCollectionFilterPipe.java +32 -0
- data/ext/src/main/java/com/xnlogic/pacer/pipes/LabelPrefixPipe.java +23 -0
- data/ext/src/main/java/com/xnlogic/pacer/pipes/NeverPipe.java +10 -0
- data/ext/src/main/java/com/xnlogic/pacer/pipes/VerticesPipe.java +26 -0
- data/ext/src/test/java/com/xnlogic/pacer/pipes/BlackboxPipelineTest.java +33 -0
- data/ext/src/test/java/com/xnlogic/pacer/pipes/CollectionFilterPipeTest.java +50 -0
- data/ext/src/test/java/com/xnlogic/pacer/pipes/EdgesPipeTest.java +103 -0
- data/ext/src/test/java/com/xnlogic/pacer/pipes/ExpandablePipeTest.java +66 -0
- data/ext/src/test/java/com/xnlogic/pacer/pipes/IdCollectionFilterPipeTest.java +85 -0
- data/ext/src/test/java/com/xnlogic/pacer/pipes/IsUniquePipeTest.java +62 -0
- data/ext/src/test/java/com/xnlogic/pacer/pipes/LabelCollectionFilterPipeTest.java +97 -0
- data/ext/src/test/java/com/xnlogic/pacer/pipes/LabelPrefixPipeTest.java +69 -0
- data/ext/src/test/java/com/xnlogic/pacer/pipes/NeverPipeTest.java +17 -0
- data/ext/src/test/java/com/xnlogic/pacer/pipes/VerticesPipeTest.java +97 -0
- data/lib/pacer/core/graph/element_route.rb +2 -2
- data/lib/pacer/core/graph/path_route.rb +2 -2
- data/lib/pacer/core/route.rb +77 -1
- data/lib/pacer/filter/property_filter/edge_filters.rb +5 -1
- data/lib/pacer/filter/property_filter/filters.rb +23 -7
- data/lib/pacer/pipe/path_wrapping_pipe.rb +14 -3
- data/lib/pacer/pipe/wrapping_pipe.rb +15 -4
- data/lib/pacer/pipes.rb +15 -13
- data/lib/pacer/route.rb +1 -0
- data/lib/pacer/side_effect/as_var.rb +1 -1
- data/lib/pacer/side_effect/is_unique.rb +2 -2
- data/lib/pacer/transform/branch.rb +1 -1
- data/lib/pacer/transform/lookup_ids.rb +1 -1
- data/lib/pacer/transform/path_tree.rb +1 -1
- data/lib/pacer/transform/reduce.rb +1 -1
- data/lib/pacer/transform/sort_section.rb +17 -9
- data/lib/pacer/transform/stream_sort.rb +1 -0
- data/lib/pacer/transform/stream_uniq.rb +1 -0
- data/lib/pacer/transform/wrapped_path.rb +1 -1
- data/lib/pacer/version.rb +1 -1
- data/lib/pacer/visitors/section.rb +10 -3
- data/lib/pacer/visitors/visits_section.rb +4 -4
- data/lib/pacer-ext.jar +0 -0
- data/lib/pacer.rb +1 -0
- data/pacer.gemspec +2 -1
- data/spec/pacer/filter/property_filter_spec.rb +17 -0
- data/spec/pacer/transform/path_spec.rb +10 -0
- data/spec/pacer/transform/sort_section_spec.rb +8 -1
- metadata +59 -30
- data/lib/pacer/pipe/blackbox_pipeline.rb +0 -55
- data/lib/pacer/pipe/collection_filter_pipe.rb +0 -12
- data/lib/pacer/pipe/edges_pipe.rb +0 -22
- data/lib/pacer/pipe/expandable_pipe.rb +0 -51
- data/lib/pacer/pipe/id_collection_filter_pipe.rb +0 -37
- data/lib/pacer/pipe/is_empty_pipe.rb +0 -23
- data/lib/pacer/pipe/is_unique_pipe.rb +0 -51
- data/lib/pacer/pipe/label_collection_filter_pipe.rb +0 -15
- data/lib/pacer/pipe/label_prefix_pipe.rb +0 -15
- data/lib/pacer/pipe/never_pipe.rb +0 -9
- data/lib/pacer/pipe/vertices_pipe.rb +0 -22
@@ -0,0 +1,97 @@
|
|
1
|
+
package com.xnlogic.pacer.pipes;
|
2
|
+
|
3
|
+
import static org.junit.Assert.*;
|
4
|
+
import org.junit.Test;
|
5
|
+
import org.junit.Before;
|
6
|
+
import org.junit.After;
|
7
|
+
import com.tinkerpop.blueprints.impls.tg.TinkerGraph;
|
8
|
+
import com.tinkerpop.blueprints.Graph;
|
9
|
+
import com.tinkerpop.blueprints.Vertex;
|
10
|
+
import java.util.Collection;
|
11
|
+
import java.util.Arrays;
|
12
|
+
import java.util.ArrayList;
|
13
|
+
import com.xnlogic.pacer.pipes.VerticesPipe;
|
14
|
+
|
15
|
+
public class VerticesPipeTest {
|
16
|
+
private TinkerGraph graph = null;
|
17
|
+
private Collection<Graph> graphs;
|
18
|
+
private Collection<Vertex> verticesThatCount;
|
19
|
+
|
20
|
+
@Before
|
21
|
+
public void setup() throws Exception {
|
22
|
+
this.graph = new TinkerGraph();
|
23
|
+
this.graphs = Arrays.asList((Graph)this.graph);
|
24
|
+
}
|
25
|
+
|
26
|
+
private void createVertices() {
|
27
|
+
Vertex v1 = this.graph.addVertex(1);
|
28
|
+
Vertex v2 = this.graph.addVertex(2);
|
29
|
+
Vertex v3 = this.graph.addVertex(3);
|
30
|
+
|
31
|
+
this.verticesThatCount = Arrays.asList(v1, v2, v3);
|
32
|
+
}
|
33
|
+
|
34
|
+
@After
|
35
|
+
public void teardown() throws Exception {
|
36
|
+
this.graph.shutdown();
|
37
|
+
this.graph = null;
|
38
|
+
}
|
39
|
+
|
40
|
+
@Test
|
41
|
+
public void getVerticesFromGraphTest() {
|
42
|
+
this.createVertices();
|
43
|
+
|
44
|
+
VerticesPipe verticesPipe = new VerticesPipe();
|
45
|
+
verticesPipe.setStarts(this.graphs);
|
46
|
+
|
47
|
+
Collection<Vertex> vertices = new ArrayList<Vertex>();
|
48
|
+
|
49
|
+
while (verticesPipe.hasNext()) {
|
50
|
+
vertices.add(verticesPipe.next());
|
51
|
+
}
|
52
|
+
|
53
|
+
assertEquals(3, vertices.size());
|
54
|
+
assertTrue(vertices.containsAll(this.verticesThatCount));
|
55
|
+
}
|
56
|
+
|
57
|
+
@Test
|
58
|
+
public void getVerticesFromGraphAfterResetTest() {
|
59
|
+
this.createVertices();
|
60
|
+
|
61
|
+
VerticesPipe verticesPipe = new VerticesPipe();
|
62
|
+
verticesPipe.setStarts(this.graphs);
|
63
|
+
|
64
|
+
Collection<Vertex> vertices = new ArrayList<Vertex>();
|
65
|
+
|
66
|
+
while (verticesPipe.hasNext()) {
|
67
|
+
vertices.add(verticesPipe.next());
|
68
|
+
}
|
69
|
+
|
70
|
+
assertEquals(3, vertices.size());
|
71
|
+
assertTrue(vertices.containsAll(this.verticesThatCount));
|
72
|
+
|
73
|
+
verticesPipe.reset();
|
74
|
+
vertices.clear();
|
75
|
+
|
76
|
+
while (verticesPipe.hasNext()) {
|
77
|
+
vertices.add(verticesPipe.next());
|
78
|
+
}
|
79
|
+
|
80
|
+
assertEquals(3, vertices.size());
|
81
|
+
assertTrue(vertices.containsAll(this.verticesThatCount));
|
82
|
+
}
|
83
|
+
|
84
|
+
@Test
|
85
|
+
public void getNoVerticesFromGraphTest() {
|
86
|
+
VerticesPipe verticesPipe = new VerticesPipe();
|
87
|
+
verticesPipe.setStarts(this.graphs);
|
88
|
+
|
89
|
+
Collection<Vertex> vertices = new ArrayList<Vertex>();
|
90
|
+
|
91
|
+
while (verticesPipe.hasNext()) {
|
92
|
+
vertices.add(verticesPipe.next());
|
93
|
+
}
|
94
|
+
|
95
|
+
assertEquals(0, vertices.size());
|
96
|
+
}
|
97
|
+
}
|
@@ -166,8 +166,8 @@ module Pacer::Core::Graph
|
|
166
166
|
|
167
167
|
protected
|
168
168
|
|
169
|
-
def configure_iterator(iter)
|
170
|
-
pipe = Pacer::Pipes::WrappingPipe.new graph, element_type, extensions
|
169
|
+
def configure_iterator(iter = nil, g = nil)
|
170
|
+
pipe = Pacer::Pipes::WrappingPipe.new((g || graph), element_type, extensions)
|
171
171
|
pipe.wrapper = wrapper if wrapper
|
172
172
|
pipe.setStarts iter
|
173
173
|
pipe
|
@@ -96,9 +96,9 @@ HELP
|
|
96
96
|
end
|
97
97
|
protected
|
98
98
|
|
99
|
-
def configure_iterator(iter)
|
99
|
+
def configure_iterator(iter = nil, g = nil)
|
100
100
|
if respond_to? :graph
|
101
|
-
pipe = Pacer::Pipes::PathWrappingPipe.new(graph)
|
101
|
+
pipe = Pacer::Pipes::PathWrappingPipe.new(g || graph)
|
102
102
|
pipe.setStarts iter
|
103
103
|
pipe
|
104
104
|
else
|
data/lib/pacer/core/route.rb
CHANGED
@@ -380,6 +380,25 @@ HELP
|
|
380
380
|
chain_route(:extensions => [], :wrapper => nil)
|
381
381
|
end
|
382
382
|
|
383
|
+
# Returns an outer proc that returns an inner proc that will execute the given route for a given input data or element.
|
384
|
+
#
|
385
|
+
# The outer proc contains the already-compiled route (the most expensive part of the process). When you call it, it returns
|
386
|
+
# the inner proc. If you call it with no arguments, it will prepare the proc in the context of the original route used to create
|
387
|
+
# it. In a multi-tenant or multi-graph system, call the outer proc with the current graph to prepare so that it correctly wraps
|
388
|
+
# returned elements.
|
389
|
+
#
|
390
|
+
# The inner proc contains a non-thread-safe data pipeline compiled from the route. Call it with an item of input data for the detached
|
391
|
+
# pipe and it will execute the pipeline for that piece of data and return the result or results.
|
392
|
+
#
|
393
|
+
# A detached route can be configured with or without gather enabled. If enabled (default), the result will be an ArrayList of
|
394
|
+
# all result data produced by the detached route. If not, the result will be either the first thing produced by the route or null if
|
395
|
+
# nothing was produced.
|
396
|
+
def detach
|
397
|
+
route = yield Pacer::Route.empty(self)
|
398
|
+
DetachedRoute.new route
|
399
|
+
end
|
400
|
+
|
401
|
+
|
383
402
|
# Change the source of this route.
|
384
403
|
#
|
385
404
|
# @note all routes derived from any route in the chain will be
|
@@ -421,7 +440,7 @@ HELP
|
|
421
440
|
|
422
441
|
# Overridden to extend the iterator to apply mixins
|
423
442
|
# or wrap elements
|
424
|
-
def configure_iterator(iter)
|
443
|
+
def configure_iterator(iter = nil, g = nil)
|
425
444
|
iter
|
426
445
|
end
|
427
446
|
|
@@ -617,6 +636,63 @@ HELP
|
|
617
636
|
end
|
618
637
|
end
|
619
638
|
|
639
|
+
|
640
|
+
class DetachedRoute
|
641
|
+
attr_reader :route, :preconfig
|
642
|
+
|
643
|
+
def initialize(route)
|
644
|
+
@route = route
|
645
|
+
w = route.send(:configure_iterator)
|
646
|
+
if w.respond_to? :instance
|
647
|
+
@preconfig = w
|
648
|
+
end
|
649
|
+
end
|
650
|
+
|
651
|
+
def build(graph, gather = true)
|
652
|
+
if route.is_a? Pacer::Filter::EmptyFilter
|
653
|
+
pipe = Pacer::Pipes::IdentityPipe.new
|
654
|
+
else
|
655
|
+
pipe = Pacer::Route.pipeline route
|
656
|
+
end
|
657
|
+
expando = Pacer::Pipes::ExpandablePipe.new
|
658
|
+
expando.enablePath true
|
659
|
+
expando.setStarts(Pacer::Pipes::EmptyIterator::INSTANCE)
|
660
|
+
pipe.setStarts expando
|
661
|
+
if preconfig
|
662
|
+
pipe = preconfig.instance pipe, graph
|
663
|
+
else
|
664
|
+
pipe = route.send(:configure_iterator, pipe, graph)
|
665
|
+
end
|
666
|
+
pipe = yield pipe if block_given?
|
667
|
+
if gather
|
668
|
+
g = Pacer::Pipes::GatherPipe.new
|
669
|
+
g.setStarts pipe
|
670
|
+
DetachedPipe.new(expando, g, true)
|
671
|
+
else
|
672
|
+
DetachedPipe.new(expando, pipe, false)
|
673
|
+
end
|
674
|
+
end
|
675
|
+
end
|
676
|
+
|
677
|
+
class DetachedPipe
|
678
|
+
attr_reader :expando, :pipe, :collection
|
679
|
+
|
680
|
+
def initialize(expando, pipe, collection)
|
681
|
+
@expando = expando
|
682
|
+
@pipe = pipe
|
683
|
+
@collection = collection
|
684
|
+
end
|
685
|
+
|
686
|
+
def read(element)
|
687
|
+
pipe.reset unless collection
|
688
|
+
expando.add element
|
689
|
+
if pipe.hasNext
|
690
|
+
pipe.next
|
691
|
+
elsif collection
|
692
|
+
[]
|
693
|
+
end
|
694
|
+
end
|
695
|
+
end
|
620
696
|
end
|
621
697
|
end
|
622
698
|
end
|
@@ -31,7 +31,7 @@ module Pacer
|
|
31
31
|
def build_pipeline(route, start_pipe = nil, pipe = nil)
|
32
32
|
pipe ||= start_pipe
|
33
33
|
if labels.any?
|
34
|
-
label_pipe = Pacer::Pipes::LabelCollectionFilterPipe.new labels
|
34
|
+
label_pipe = Pacer::Pipes::LabelCollectionFilterPipe.new labels.map(&:to_s)
|
35
35
|
label_pipe.set_starts pipe if pipe
|
36
36
|
Pacer.debug_pipes << { :name => labels.inspect, :start => pipe, :end => block_pipe } if Pacer.debug_pipes
|
37
37
|
pipe = label_pipe
|
@@ -44,6 +44,10 @@ module Pacer
|
|
44
44
|
labels.any? or super
|
45
45
|
end
|
46
46
|
|
47
|
+
def extensions_only?
|
48
|
+
labels.empty? and super
|
49
|
+
end
|
50
|
+
|
47
51
|
def to_s
|
48
52
|
if labels.any?
|
49
53
|
[labels.map { |l| l.to_sym.inspect }.join(', '), super].reject { |s| s == '' }.join ', '
|
@@ -134,15 +134,30 @@ module Pacer
|
|
134
134
|
end
|
135
135
|
end
|
136
136
|
|
137
|
+
# Not used for regular filtering, but useful to test an element against
|
138
|
+
# a complex set of conditions without having to build a route.
|
139
|
+
#
|
140
|
+
# Returns a proc that can be called with an element to test and returns
|
141
|
+
# true if the element matches the conditions.
|
142
|
+
def to_predicate
|
143
|
+
expando, pipe = build_pipeline(nil, com.tinkerpop.pipes.util.iterators.ExpandableIterator.new)
|
144
|
+
proc do |e|
|
145
|
+
expando.add e
|
146
|
+
pipe.next if pipe.hasNext
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
137
150
|
def build_pipeline(route, start_pipe, pipe = nil)
|
138
|
-
self.graph = route.graph
|
139
151
|
pipe ||= start_pipe
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
152
|
+
if route
|
153
|
+
self.graph = route.graph
|
154
|
+
route_modules.each do |mod|
|
155
|
+
extension_route = mod.route(Pacer::Route.empty(route))
|
156
|
+
s, e = extension_route.send :build_pipeline
|
157
|
+
s.setStarts(pipe) if pipe
|
158
|
+
start_pipe ||= s
|
159
|
+
pipe = e
|
160
|
+
end
|
146
161
|
end
|
147
162
|
encoded_properties.each do |key, value|
|
148
163
|
case value
|
@@ -161,6 +176,7 @@ module Pacer
|
|
161
176
|
end
|
162
177
|
end
|
163
178
|
blocks.each do |block|
|
179
|
+
# Will work if route is nil.
|
164
180
|
block_pipe = Pacer::Pipes::BlockFilterPipe.new(route, block)
|
165
181
|
block_pipe.set_starts pipe if pipe
|
166
182
|
Pacer.debug_pipes << { :name => 'block', :start => pipe, :end => block_pipe } if Pacer.debug_pipes
|
@@ -6,9 +6,20 @@ module Pacer
|
|
6
6
|
|
7
7
|
def initialize(graph, vertex_extensions = [], edge_extensions = [])
|
8
8
|
super()
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
if graph.is_a? Array
|
10
|
+
@graph, @vertex_wrapper, @edge_wrapper = graph
|
11
|
+
else
|
12
|
+
@graph = graph
|
13
|
+
@vertex_wrapper = Pacer::Wrappers::WrapperSelector.build graph, :vertex, vertex_extensions || Set[]
|
14
|
+
@edge_wrapper = Pacer::Wrappers::WrapperSelector.build graph, :edge, edge_extensions || Set[]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def instance(pipe, g)
|
19
|
+
g ||= graph
|
20
|
+
p = PathWrappingPipe.new [g, vertex_wrapper, edge_wrapper]
|
21
|
+
p.setStarts pipe
|
22
|
+
p
|
12
23
|
end
|
13
24
|
|
14
25
|
def getCurrentPath
|
@@ -5,10 +5,21 @@ module Pacer
|
|
5
5
|
|
6
6
|
def initialize(graph, element_type = nil, extensions = [])
|
7
7
|
super()
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
if graph.is_a? Array
|
9
|
+
@graph, @wrapper = graph
|
10
|
+
else
|
11
|
+
@graph = graph
|
12
|
+
@element_type = element_type
|
13
|
+
@extensions = extensions || []
|
14
|
+
@wrapper = Pacer::Wrappers::WrapperSelector.build graph, element_type, @extensions
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def instance(pipe, g)
|
19
|
+
g ||= graph
|
20
|
+
p = WrappingPipe.new [g, wrapper]
|
21
|
+
p.setStarts pipe
|
22
|
+
p
|
12
23
|
end
|
13
24
|
|
14
25
|
def getSideEffect
|
data/lib/pacer/pipes.rb
CHANGED
@@ -15,6 +15,21 @@ module Pacer
|
|
15
15
|
import com.tinkerpop.pipes.transform.PropertyPipe
|
16
16
|
import com.tinkerpop.pipes.transform.PropertyMapPipe
|
17
17
|
|
18
|
+
import com.xnlogic.pacer.pipes.BlackboxPipeline
|
19
|
+
import com.xnlogic.pacer.pipes.EdgesPipe
|
20
|
+
import com.xnlogic.pacer.pipes.CollectionFilterPipe
|
21
|
+
import com.xnlogic.pacer.pipes.ExpandablePipe
|
22
|
+
SimpleExpandablePipe = com.tinkerpop.pipes.util.ExpandablePipe
|
23
|
+
import com.xnlogic.pacer.pipes.IdCollectionFilterPipe
|
24
|
+
import com.xnlogic.pacer.pipes.IsEmptyPipe
|
25
|
+
import com.xnlogic.pacer.pipes.LabelCollectionFilterPipe
|
26
|
+
import com.xnlogic.pacer.pipes.IsUniquePipe
|
27
|
+
import com.xnlogic.pacer.pipes.VerticesPipe
|
28
|
+
import com.xnlogic.pacer.pipes.LabelPrefixPipe
|
29
|
+
import com.xnlogic.pacer.pipes.NeverPipe
|
30
|
+
import com.tinkerpop.pipes.util.iterators.EmptyIterator
|
31
|
+
import com.tinkerpop.pipes.transform.GatherPipe
|
32
|
+
|
18
33
|
IN = com.tinkerpop.blueprints.Direction::IN
|
19
34
|
OUT = com.tinkerpop.blueprints.Direction::OUT
|
20
35
|
BOTH = com.tinkerpop.blueprints.Direction::BOTH
|
@@ -33,32 +48,19 @@ end
|
|
33
48
|
|
34
49
|
require 'pacer/pipe/ruby_pipe'
|
35
50
|
|
36
|
-
require 'pacer/pipe/vertices_pipe'
|
37
|
-
require 'pacer/pipe/edges_pipe'
|
38
|
-
|
39
|
-
require 'pacer/pipe/never_pipe'
|
40
51
|
require 'pacer/pipe/multi_pipe'
|
41
52
|
require 'pacer/pipe/block_filter_pipe'
|
42
|
-
require 'pacer/pipe/collection_filter_pipe'
|
43
53
|
require 'pacer/pipe/enumerable_pipe'
|
44
|
-
require 'pacer/pipe/expandable_pipe'
|
45
54
|
require 'pacer/pipe/loop_pipe'
|
46
55
|
require 'pacer/pipe/process_pipe'
|
47
56
|
require 'pacer/pipe/visitor_pipe'
|
48
57
|
require 'pacer/pipe/simple_visitor_pipe'
|
49
|
-
require 'pacer/pipe/is_unique_pipe'
|
50
|
-
require 'pacer/pipe/is_empty_pipe'
|
51
58
|
require 'pacer/pipe/stream_sort_pipe'
|
52
59
|
require 'pacer/pipe/stream_uniq_pipe'
|
53
60
|
require 'pacer/pipe/type_filter_pipe'
|
54
|
-
require 'pacer/pipe/label_collection_filter_pipe'
|
55
|
-
require 'pacer/pipe/id_collection_filter_pipe'
|
56
|
-
require 'pacer/pipe/label_prefix_pipe'
|
57
61
|
|
58
62
|
require 'pacer/pipe/property_comparison_pipe'
|
59
63
|
|
60
|
-
require 'pacer/pipe/blackbox_pipeline'
|
61
|
-
|
62
64
|
require 'pacer/pipe/unary_transform_pipe'
|
63
65
|
require 'pacer/pipe/cross_product_transform_pipe'
|
64
66
|
|
data/lib/pacer/route.rb
CHANGED
@@ -44,7 +44,7 @@ module Pacer
|
|
44
44
|
def attach_pipe(pipe)
|
45
45
|
if element_type == :vertex or element_type == :edge or element_type == :mixed
|
46
46
|
wrapped = Pacer::Pipes::WrappingPipe.new graph, element_type, extensions
|
47
|
-
wrapped.setStarts pipe
|
47
|
+
wrapped.setStarts pipe if pipe
|
48
48
|
as_pipe = AsPipe.new(wrapped, vars, variable_name)
|
49
49
|
unwrapped = Pacer::Pipes::UnwrappingPipe.new
|
50
50
|
unwrapped.setStarts as_pipe
|
@@ -14,7 +14,7 @@ module Pacer
|
|
14
14
|
def unique?
|
15
15
|
check = nil
|
16
16
|
is_unique { |pipe| check = pipe }.each do
|
17
|
-
return false unless check.
|
17
|
+
return false unless check.isUnique
|
18
18
|
end
|
19
19
|
true
|
20
20
|
end
|
@@ -30,7 +30,7 @@ module Pacer
|
|
30
30
|
|
31
31
|
def attach_pipe(end_pipe)
|
32
32
|
checked = Pacer::Pipes::IsUniquePipe.new
|
33
|
-
checked.setStarts end_pipe
|
33
|
+
checked.setStarts end_pipe if end_pipe
|
34
34
|
on_build_pipe.call checked if on_build_pipe
|
35
35
|
checked
|
36
36
|
end
|
@@ -44,7 +44,7 @@ module Pacer
|
|
44
44
|
def clone(conf = {})
|
45
45
|
back.chain_route({transform: Branch,
|
46
46
|
branches: branches.clone,
|
47
|
-
element_type:
|
47
|
+
element_type: element_type,
|
48
48
|
conds: conds.clone,
|
49
49
|
extensions: extensions.clone,
|
50
50
|
split_pipe_class: split_pipe_class,
|
@@ -86,7 +86,7 @@ HELP
|
|
86
86
|
def attach_pipe(end_pipe)
|
87
87
|
if @enter and @reduce and @leave
|
88
88
|
pipe = ReducerPipe.new self, @enter, @reduce, @leave
|
89
|
-
pipe.setStarts end_pipe
|
89
|
+
pipe.setStarts end_pipe if end_pipe
|
90
90
|
pipe
|
91
91
|
else
|
92
92
|
fail Pacer::ClientError, 'enter, reduce, and leave must all be specified for reducers'
|
@@ -1,10 +1,18 @@
|
|
1
1
|
module Pacer
|
2
2
|
module Routes
|
3
3
|
module RouteOperations
|
4
|
+
# Arity 2 uses custom sort logic. Arity 1 uses sort_by logic.
|
4
5
|
def sort_section(section = nil, &block)
|
5
|
-
|
6
|
+
if not block
|
7
|
+
chain_route transform: :sort_section, section: section
|
8
|
+
elsif block.arity == 2
|
9
|
+
chain_route transform: :sort_section, custom_sort_block: block, section: section
|
10
|
+
else
|
11
|
+
chain_route transform: :sort_section, sort_by_block: block, section: section
|
12
|
+
end
|
6
13
|
end
|
7
14
|
|
15
|
+
# Deprecated: use sort_section
|
8
16
|
def custom_sort_section(section = nil, &block)
|
9
17
|
chain_route transform: :sort_section, custom_sort_block: block, section: section
|
10
18
|
end
|
@@ -40,27 +48,27 @@ module Pacer
|
|
40
48
|
attr_reader :pf_1, :pf_2, :to_sort, :to_emit, :section, :route
|
41
49
|
attr_reader :getPathToHere
|
42
50
|
|
43
|
-
def initialize(route,
|
51
|
+
def initialize(route, visitor_pipe, pipe_function)
|
44
52
|
super()
|
45
53
|
@to_emit = []
|
46
|
-
@
|
54
|
+
@visitor_pipe = visitor_pipe
|
47
55
|
@route = route
|
48
56
|
@to_sort = []
|
49
57
|
@paths = []
|
50
|
-
if
|
51
|
-
|
58
|
+
if visitor_pipe
|
59
|
+
visitor_pipe.visitor = self
|
52
60
|
else
|
53
61
|
on_element nil
|
54
62
|
end
|
55
63
|
if pipe_function
|
56
64
|
if pipe_function.arity == 1
|
57
65
|
@pf_1 = pipe_function
|
58
|
-
|
66
|
+
visitor_pipe.use_on_element = false
|
59
67
|
else
|
60
68
|
@pf_2 = pipe_function
|
61
69
|
end
|
62
70
|
else
|
63
|
-
|
71
|
+
visitor_pipe.use_on_element = false
|
64
72
|
end
|
65
73
|
end
|
66
74
|
|
@@ -119,8 +127,8 @@ module Pacer
|
|
119
127
|
class CustomSortPipe < SortBySectionPipe
|
120
128
|
attr_reader :sort_block
|
121
129
|
|
122
|
-
def initialize(route,
|
123
|
-
super route,
|
130
|
+
def initialize(route, visitor_pipe, sort_block, graph, wrapper)
|
131
|
+
super route, visitor_pipe, nil
|
124
132
|
@sort_block = sort_block
|
125
133
|
@graph = graph
|
126
134
|
@wrapper = wrapper
|
data/lib/pacer/version.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module Pacer
|
2
|
-
VERSION = "2.0.
|
2
|
+
VERSION = "2.0.12"
|
3
3
|
# Clients may optionally define the following constants in the Pacer namespace:
|
4
4
|
# - LOAD_JARS : set to false to manage jar loading in the client. Be sure to load the jars defined in JARFILES.
|
5
5
|
# - LOCKJAR_LOCK_OPTS : set some options to be passed to LockJar.lock (ie. :lockfile, :download_artifacts, :local_repo)
|
@@ -18,10 +18,14 @@ module Pacer
|
|
18
18
|
|
19
19
|
def will_visit!
|
20
20
|
@visitor_count = visitor_count + 1
|
21
|
+
visitor_count - 1
|
21
22
|
end
|
22
23
|
|
23
|
-
def section_visitor
|
24
|
-
|
24
|
+
def section_visitor!(visitor_num)
|
25
|
+
vpipes = Thread.current["visitors_#{object_id}"]
|
26
|
+
vpipe = vpipes[visitor_num]
|
27
|
+
vpipes[visitor_num] = nil
|
28
|
+
vpipe
|
25
29
|
end
|
26
30
|
|
27
31
|
protected
|
@@ -34,12 +38,15 @@ module Pacer
|
|
34
38
|
attr_reader :section_visitors
|
35
39
|
|
36
40
|
def attach_pipe(end_pipe)
|
41
|
+
# With detached pipes, pipe construction happens in
|
42
|
+
# multiple threads, multiple times.
|
37
43
|
pipe = end_pipe
|
38
|
-
|
44
|
+
vpipes = (1..visitor_count).map do
|
39
45
|
pipe = Pacer::Pipes::SimpleVisitorPipe.new Pacer::Wrappers::WrapperSelector.build(graph, element_type, extensions), graph
|
40
46
|
pipe.setStarts end_pipe if end_pipe
|
41
47
|
end_pipe = pipe
|
42
48
|
end
|
49
|
+
Thread.current["visitors_#{object_id}"] = vpipes
|
43
50
|
pipe
|
44
51
|
end
|
45
52
|
|
@@ -2,7 +2,7 @@ module Pacer
|
|
2
2
|
module Visitors
|
3
3
|
# This module is mixed in to the route that actually refers to this section.
|
4
4
|
module VisitsSection
|
5
|
-
attr_reader :section, :section_route
|
5
|
+
attr_reader :section, :section_route, :visitor_num
|
6
6
|
|
7
7
|
def section=(section)
|
8
8
|
if section.is_a? Symbol
|
@@ -14,14 +14,14 @@ module Pacer
|
|
14
14
|
else
|
15
15
|
raise ArgumentError, "Unknown section #{ section }. Provide either a name or a route created with the #section methed."
|
16
16
|
end
|
17
|
-
@section_route.will_visit!
|
18
|
-
|
17
|
+
@visitor_num = section_route.will_visit!
|
18
|
+
section_route
|
19
19
|
end
|
20
20
|
|
21
21
|
protected
|
22
22
|
|
23
23
|
def section_visitor
|
24
|
-
section_route.section_visitor if
|
24
|
+
section_route.section_visitor!(visitor_num) if visitor_num
|
25
25
|
end
|
26
26
|
|
27
27
|
def section_visitor_target
|
data/lib/pacer-ext.jar
ADDED
Binary file
|
data/lib/pacer.rb
CHANGED
@@ -23,6 +23,7 @@ require 'pp'
|
|
23
23
|
require 'rubygems'
|
24
24
|
require 'lock_jar'
|
25
25
|
require 'pacer/support/lock_jar'
|
26
|
+
require 'pacer-ext.jar'
|
26
27
|
|
27
28
|
if (not defined? Pacer::LOAD_JARS) or Pacer::LOAD_JARS == true
|
28
29
|
bundle_jarfiles = LockJar.register_bundled_jarfiles # defined in pacer/support/lock_jar.rb
|
data/pacer.gemspec
CHANGED
@@ -13,10 +13,11 @@ Gem::Specification.new do |s|
|
|
13
13
|
s.summary = %Q{A very efficient and easy to use graph traversal engine.}
|
14
14
|
s.description = %Q{Pacer defines composeable routes through a graph and then traverses them very quickly.}
|
15
15
|
|
16
|
-
s.files = `git ls-files`.split("\n")
|
16
|
+
s.files = `git ls-files`.split("\n") + ['lib/pacer-ext.jar']
|
17
17
|
s.test_files = `git ls-files -- spec/*`.split("\n")
|
18
18
|
s.require_paths = ['lib']
|
19
19
|
s.add_dependency "lock_jar", "~> 0.10.2"
|
20
20
|
s.add_development_dependency 'xn_gem_release_tasks'
|
21
|
+
s.add_development_dependency "rake-compiler", "~> 0.9.2"
|
21
22
|
end
|
22
23
|
|