pacer 2.0.10.pre-java → 2.0.12-java
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.
- 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
|
|