pacer 0.9.1.1-java
Sign up to get free protection for your applications and to get access to all the features.
- data/.autotest +8 -0
- data/.document +5 -0
- data/.gitignore +26 -0
- data/.rspec +1 -0
- data/.rvmrc +0 -0
- data/CONTRIBUTORS +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +24 -0
- data/README.md +187 -0
- data/Rakefile +49 -0
- data/autotest/discover.rb +1 -0
- data/bin/autospec +16 -0
- data/bin/autotest +16 -0
- data/bin/rake +16 -0
- data/bin/rcov +16 -0
- data/bin/rspec +16 -0
- data/bin/yard +16 -0
- data/bin/yardoc +16 -0
- data/lib/pacer/blueprints/extensions.rb +77 -0
- data/lib/pacer/blueprints/multi_graph.rb +121 -0
- data/lib/pacer/blueprints/ruby_graph.rb +199 -0
- data/lib/pacer/blueprints/tg.rb +100 -0
- data/lib/pacer/blueprints.rb +4 -0
- data/lib/pacer/core/graph/edges_route.rb +92 -0
- data/lib/pacer/core/graph/element_route.rb +171 -0
- data/lib/pacer/core/graph/graph_index_route.rb +48 -0
- data/lib/pacer/core/graph/graph_route.rb +55 -0
- data/lib/pacer/core/graph/mixed_route.rb +96 -0
- data/lib/pacer/core/graph/vertices_route.rb +220 -0
- data/lib/pacer/core/graph.rb +13 -0
- data/lib/pacer/core/route.rb +502 -0
- data/lib/pacer/core/side_effect.rb +11 -0
- data/lib/pacer/core.rb +8 -0
- data/lib/pacer/exceptions.rb +11 -0
- data/lib/pacer/extensions/block_filter_element.rb +22 -0
- data/lib/pacer/extensions.rb +6 -0
- data/lib/pacer/filter/block_filter.rb +31 -0
- data/lib/pacer/filter/collection_filter.rb +109 -0
- data/lib/pacer/filter/empty_filter.rb +70 -0
- data/lib/pacer/filter/future_filter.rb +68 -0
- data/lib/pacer/filter/index_filter.rb +30 -0
- data/lib/pacer/filter/loop_filter.rb +95 -0
- data/lib/pacer/filter/object_filter.rb +55 -0
- data/lib/pacer/filter/property_filter/edge_filters.rb +93 -0
- data/lib/pacer/filter/property_filter/filters.rb +269 -0
- data/lib/pacer/filter/property_filter.rb +111 -0
- data/lib/pacer/filter/random_filter.rb +13 -0
- data/lib/pacer/filter/range_filter.rb +104 -0
- data/lib/pacer/filter/uniq_filter.rb +12 -0
- data/lib/pacer/filter/where_filter/node_visitor.rb +280 -0
- data/lib/pacer/filter/where_filter.rb +47 -0
- data/lib/pacer/filter.rb +17 -0
- data/lib/pacer/function_resolver.rb +43 -0
- data/lib/pacer/graph/edge_mixin.rb +127 -0
- data/lib/pacer/graph/element_mixin.rb +202 -0
- data/lib/pacer/graph/graph_indices_mixin.rb +93 -0
- data/lib/pacer/graph/graph_mixin.rb +361 -0
- data/lib/pacer/graph/graph_transactions_mixin.rb +207 -0
- data/lib/pacer/graph/index_mixin.rb +30 -0
- data/lib/pacer/graph/vertex_mixin.rb +119 -0
- data/lib/pacer/graph.rb +14 -0
- data/lib/pacer/pipe/blackbox_pipeline.rb +48 -0
- data/lib/pacer/pipe/block_filter_pipe.rb +38 -0
- data/lib/pacer/pipe/collection_filter_pipe.rb +10 -0
- data/lib/pacer/pipe/cross_product_transform_pipe.rb +48 -0
- data/lib/pacer/pipe/enumerable_pipe.rb +30 -0
- data/lib/pacer/pipe/expandable_pipe.rb +63 -0
- data/lib/pacer/pipe/id_collection_filter_pipe.rb +33 -0
- data/lib/pacer/pipe/is_empty_pipe.rb +30 -0
- data/lib/pacer/pipe/is_unique_pipe.rb +61 -0
- data/lib/pacer/pipe/label_collection_filter_pipe.rb +21 -0
- data/lib/pacer/pipe/label_prefix_pipe.rb +21 -0
- data/lib/pacer/pipe/loop_pipe.rb +86 -0
- data/lib/pacer/pipe/map_pipe.rb +36 -0
- data/lib/pacer/pipe/never_pipe.rb +9 -0
- data/lib/pacer/pipe/process_pipe.rb +37 -0
- data/lib/pacer/pipe/property_comparison_pipe.rb +40 -0
- data/lib/pacer/pipe/ruby_pipe.rb +25 -0
- data/lib/pacer/pipe/simple_visitor_pipe.rb +43 -0
- data/lib/pacer/pipe/stream_sort_pipe.rb +84 -0
- data/lib/pacer/pipe/stream_uniq_pipe.rb +33 -0
- data/lib/pacer/pipe/type_filter_pipe.rb +22 -0
- data/lib/pacer/pipe/unary_transform_pipe.rb +59 -0
- data/lib/pacer/pipe/variable_store_iterator_wrapper.rb +26 -0
- data/lib/pacer/pipe/visitor_pipe.rb +67 -0
- data/lib/pacer/pipes.rb +61 -0
- data/lib/pacer/route/mixin/bulk_operations.rb +52 -0
- data/lib/pacer/route/mixin/route_operations.rb +107 -0
- data/lib/pacer/route/mixin/variable_route_module.rb +26 -0
- data/lib/pacer/route/mixins.rb +3 -0
- data/lib/pacer/route.rb +228 -0
- data/lib/pacer/routes.rb +6 -0
- data/lib/pacer/side_effect/aggregate.rb +31 -0
- data/lib/pacer/side_effect/counted.rb +30 -0
- data/lib/pacer/side_effect/group_count.rb +44 -0
- data/lib/pacer/side_effect/is_unique.rb +32 -0
- data/lib/pacer/side_effect/section.rb +25 -0
- data/lib/pacer/side_effect/visitor.rb +37 -0
- data/lib/pacer/side_effect.rb +11 -0
- data/lib/pacer/support/array_list.rb +28 -0
- data/lib/pacer/support/enumerable.rb +100 -0
- data/lib/pacer/support/hash.rb +9 -0
- data/lib/pacer/support/iterator_mixins.rb +110 -0
- data/lib/pacer/support/native_exception.rb +22 -0
- data/lib/pacer/support/proc.rb +16 -0
- data/lib/pacer/support.rb +10 -0
- data/lib/pacer/transform/cap.rb +50 -0
- data/lib/pacer/transform/gather.rb +9 -0
- data/lib/pacer/transform/has_count_cap.rb +41 -0
- data/lib/pacer/transform/join.rb +181 -0
- data/lib/pacer/transform/map.rb +23 -0
- data/lib/pacer/transform/path.rb +50 -0
- data/lib/pacer/transform/process.rb +23 -0
- data/lib/pacer/transform/scatter.rb +23 -0
- data/lib/pacer/transform/sort_section.rb +103 -0
- data/lib/pacer/transform/stream_sort.rb +21 -0
- data/lib/pacer/transform/stream_uniq.rb +21 -0
- data/lib/pacer/transform.rb +16 -0
- data/lib/pacer/utils/graph_analysis.rb +112 -0
- data/lib/pacer/utils/trie.rb +93 -0
- data/lib/pacer/utils/tsort.rb +65 -0
- data/lib/pacer/utils/y_files.rb +127 -0
- data/lib/pacer/utils.rb +10 -0
- data/lib/pacer/version.rb +13 -0
- data/lib/pacer/wrappers/edge_wrapper.rb +51 -0
- data/lib/pacer/wrappers/element_wrapper.rb +78 -0
- data/lib/pacer/wrappers/new_element.rb +106 -0
- data/lib/pacer/wrappers/vertex_wrapper.rb +51 -0
- data/lib/pacer/wrappers.rb +19 -0
- data/lib/pacer-0.9.1.1-standalone.jar +0 -0
- data/lib/pacer.rb +290 -0
- data/pacer.gemspec +30 -0
- data/pom/standalone.xml +22 -0
- data/pom.xml +124 -0
- data/samples/grateful-dead.xml +26380 -0
- data/samples/grateful_dead.rb +63 -0
- data/samples/profile.rb +15 -0
- data/spec/data/grateful-dead.xml +26380 -0
- data/spec/data/pacer.graphml +319 -0
- data/spec/pacer/blueprints/dex_spec.rb +172 -0
- data/spec/pacer/blueprints/neo4j_spec.rb +177 -0
- data/spec/pacer/blueprints/tg_spec.rb +128 -0
- data/spec/pacer/core/graph/edges_route_spec.rb +52 -0
- data/spec/pacer/core/graph/element_route_spec.rb +46 -0
- data/spec/pacer/core/graph/graph_route_spec.rb +94 -0
- data/spec/pacer/core/graph/vertices_route_spec.rb +169 -0
- data/spec/pacer/core/route_spec.rb +197 -0
- data/spec/pacer/filter/collection_filter_spec.rb +19 -0
- data/spec/pacer/filter/empty_filter_spec.rb +29 -0
- data/spec/pacer/filter/future_filter_spec.rb +97 -0
- data/spec/pacer/filter/loop_filter_spec.rb +31 -0
- data/spec/pacer/filter/property_filter_spec.rb +111 -0
- data/spec/pacer/filter/random_filter_spec.rb +17 -0
- data/spec/pacer/filter/uniq_filter_spec.rb +18 -0
- data/spec/pacer/filter/where_filter_spec.rb +93 -0
- data/spec/pacer/graph/edge_mixin_spec.rb +116 -0
- data/spec/pacer/graph/element_mixin_spec.rb +297 -0
- data/spec/pacer/graph/graph_mixin_spec.rb +538 -0
- data/spec/pacer/graph/index_mixin_spec.rb +0 -0
- data/spec/pacer/graph/vertex_mixin_spec.rb +192 -0
- data/spec/pacer/pipe/block_filter_pipe_spec.rb +0 -0
- data/spec/pacer/pipe/labels_filter_pipe_spec.rb +0 -0
- data/spec/pacer/pipe/ruby_pipe_spec.rb +0 -0
- data/spec/pacer/pipe/type_filter_pipe_spec.rb +0 -0
- data/spec/pacer/route/mixin/base_spec.rb +419 -0
- data/spec/pacer/route/mixin/bulk_operations_spec.rb +30 -0
- data/spec/pacer/route/mixin/route_operations_spec.rb +127 -0
- data/spec/pacer/support/array_list_spec.rb +0 -0
- data/spec/pacer/support/enumerable_spec.rb +115 -0
- data/spec/pacer/transform/join_spec.rb +138 -0
- data/spec/pacer/transform/path_spec.rb +54 -0
- data/spec/pacer/utils/tsort_spec.rb +89 -0
- data/spec/pacer/wrapper/edge_wrapper_spec.rb +33 -0
- data/spec/pacer/wrapper/element_wrapper_spec.rb +169 -0
- data/spec/pacer/wrapper/vertex_wrapper_spec.rb +33 -0
- data/spec/pacer_spec.rb +0 -0
- data/spec/spec_helper.rb +91 -0
- data/spec/support/contexts.rb +14 -0
- data/spec/support/graph_runner.rb +142 -0
- data/spec/support/matchers.rb +19 -0
- data/spec/support/use_transactions.rb +31 -0
- data/spec/tackle/simple_mixin.rb +21 -0
- data/spec/tackle/tinkerpop_graph_mixins.rb +60 -0
- metadata +364 -0
@@ -0,0 +1,43 @@
|
|
1
|
+
module Pacer
|
2
|
+
module Pipes
|
3
|
+
class SimpleVisitorPipe < Pacer::Pipes::RubyPipe
|
4
|
+
attr_reader :visitor, :in_section
|
5
|
+
|
6
|
+
attr_accessor :use_on_element, :use_after_element, :use_reset
|
7
|
+
|
8
|
+
def initialize(visitor = nil)
|
9
|
+
super()
|
10
|
+
self.visitor = visitor if visitor
|
11
|
+
@in_section = false
|
12
|
+
end
|
13
|
+
|
14
|
+
def visitor=(visitor)
|
15
|
+
@visitor = visitor
|
16
|
+
@use_on_element = visitor.respond_to? :on_element
|
17
|
+
@use_after_element = visitor.respond_to? :after_element
|
18
|
+
@use_reset = visitor.respond_to? :reset
|
19
|
+
end
|
20
|
+
|
21
|
+
def processNextStart
|
22
|
+
visitor.after_element if use_after_element and in_section
|
23
|
+
current = starts.next
|
24
|
+
@in_section = true unless in_section
|
25
|
+
visitor.on_element(current) if use_on_element
|
26
|
+
return current
|
27
|
+
rescue NativeException => e
|
28
|
+
if e.cause.getClass == Pacer::NoSuchElementException.getClass
|
29
|
+
@in_section = false
|
30
|
+
raise e.cause
|
31
|
+
else
|
32
|
+
raise
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def reset
|
37
|
+
visitor.reset if use_reset
|
38
|
+
@in_section = false
|
39
|
+
super
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Pacer::Pipes
|
2
|
+
# has 3 states:
|
3
|
+
# - starts in rebalancing mode to build up a working set which stores
|
4
|
+
# elements in 4 silos
|
5
|
+
# - if the first silo becomes empty, it goes into clearing mode
|
6
|
+
# - in clearing mode, it will empty all elements out of the first non-empty silo
|
7
|
+
# - it then goes back into rebalancing mode
|
8
|
+
#
|
9
|
+
# Number of silos is 4 by default, a number I pulled out of my ass without any testing.
|
10
|
+
class StreamSortPipe < RubyPipe
|
11
|
+
def initialize(queue_length = 100, silo_size = 10)
|
12
|
+
super()
|
13
|
+
@queue_length = queue_length
|
14
|
+
@rebalancing = []
|
15
|
+
@rebal_length = 0
|
16
|
+
@first_silo = []
|
17
|
+
@second_silo = []
|
18
|
+
@third_silo = []
|
19
|
+
@clearing = []
|
20
|
+
@silo_size = silo_size
|
21
|
+
end
|
22
|
+
|
23
|
+
def setSiloSize(n)
|
24
|
+
@silo_size = n
|
25
|
+
end
|
26
|
+
|
27
|
+
def processNextStart
|
28
|
+
if @clearing.any?
|
29
|
+
return @clearing.shift
|
30
|
+
end
|
31
|
+
while @rebal_length < @queue_length and @starts.hasNext
|
32
|
+
@rebalancing << @starts.next
|
33
|
+
@rebal_length += 1
|
34
|
+
end
|
35
|
+
if @rebalancing.any?
|
36
|
+
if @starts.hasNext
|
37
|
+
@rebalancing.sort!
|
38
|
+
@first_silo = @rebalancing.slice(0, @silo_size)
|
39
|
+
@second_silo = @rebalancing.slice(@silo_size, @silo_size * 2) || []
|
40
|
+
@third_silo = @rebalancing.slice(@silo_size * 2..-1) || []
|
41
|
+
@rebalancing = []
|
42
|
+
else
|
43
|
+
@clearing = @rebalancing.sort
|
44
|
+
@rebalancing = []
|
45
|
+
return processNextStart
|
46
|
+
end
|
47
|
+
end
|
48
|
+
if @starts.hasNext
|
49
|
+
if @first_silo.any?
|
50
|
+
element = @starts.next
|
51
|
+
begin
|
52
|
+
if element < @first_silo.last
|
53
|
+
@first_silo << element
|
54
|
+
@first_silo.sort!
|
55
|
+
elsif @second_silo.none? or element < @second_silo.last
|
56
|
+
@second_silo.unshift element
|
57
|
+
else
|
58
|
+
@third_silo << element
|
59
|
+
end
|
60
|
+
rescue => e
|
61
|
+
@first_silo.unshift element
|
62
|
+
end
|
63
|
+
return @first_silo.shift
|
64
|
+
else
|
65
|
+
@clearing = @second_silo
|
66
|
+
@clearing.sort!
|
67
|
+
@rebalancing = @third_silo
|
68
|
+
@rebal_length = @rebalancing.length
|
69
|
+
return @rebalancing.shift
|
70
|
+
end
|
71
|
+
else
|
72
|
+
@clearing = @first_silo + @second_silo.sort! + @third_silo.sort!
|
73
|
+
return processNextStart if @clearing.any?
|
74
|
+
end
|
75
|
+
raise Pacer::NoSuchElementException
|
76
|
+
rescue NativeException => e
|
77
|
+
if e.cause.getClass == NoSuchElementException.getClass
|
78
|
+
raise e.cause
|
79
|
+
else
|
80
|
+
raise e
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Pacer::Pipes
|
2
|
+
class StreamUniqPipe < RubyPipe
|
3
|
+
def initialize(buffer = 1000)
|
4
|
+
super()
|
5
|
+
@list = java.util.LinkedList.new
|
6
|
+
@buffer = buffer
|
7
|
+
end
|
8
|
+
|
9
|
+
protected
|
10
|
+
|
11
|
+
def processNextStart
|
12
|
+
while true
|
13
|
+
obj = @starts.next
|
14
|
+
duplicate = @list.removeLastOccurrence(obj)
|
15
|
+
@list.addLast obj
|
16
|
+
if not duplicate
|
17
|
+
if @buffer == 0
|
18
|
+
@list.removeFirst
|
19
|
+
else
|
20
|
+
@buffer -= 1
|
21
|
+
end
|
22
|
+
return obj
|
23
|
+
end
|
24
|
+
end
|
25
|
+
rescue NativeException => e
|
26
|
+
if e.cause.getClass == NoSuchElementException.getClass
|
27
|
+
raise e.cause
|
28
|
+
else
|
29
|
+
raise e
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Pacer::Pipes
|
2
|
+
class TypeFilterPipe < RubyPipe
|
3
|
+
def initialize(type)
|
4
|
+
super()
|
5
|
+
@type = type
|
6
|
+
end
|
7
|
+
|
8
|
+
def processNextStart()
|
9
|
+
while @starts.hasNext
|
10
|
+
s = @starts.next
|
11
|
+
return s if s.is_a? @type
|
12
|
+
end
|
13
|
+
raise Pacer::NoSuchElementException
|
14
|
+
rescue NativeException => e
|
15
|
+
if e.cause.getClass == Pacer::NoSuchElementException.getClass
|
16
|
+
raise e.cause
|
17
|
+
else
|
18
|
+
raise e
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Pacer::Pipes
|
2
|
+
class UnaryTransformPipe < RubyPipe
|
3
|
+
import com.tinkerpop.pipes.Pipe
|
4
|
+
import com.tinkerpop.pipes.util.SingleIterator
|
5
|
+
|
6
|
+
attr_reader :branch_a, :method
|
7
|
+
|
8
|
+
def initialize(method, branch_a)
|
9
|
+
super()
|
10
|
+
if branch_a.is_a? Pipe
|
11
|
+
@branch_a = branch_a
|
12
|
+
@a = nil
|
13
|
+
else
|
14
|
+
@a = branch_a
|
15
|
+
end
|
16
|
+
@first = true
|
17
|
+
@method = method
|
18
|
+
@element = nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def processNextStart
|
22
|
+
next_a
|
23
|
+
a.send method rescue nil if a.respond_to? method
|
24
|
+
rescue NativeException => e
|
25
|
+
if e.cause.getClass == Pacer::NoSuchElementException.getClass
|
26
|
+
raise e.cause
|
27
|
+
else
|
28
|
+
raise e
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
protected
|
33
|
+
|
34
|
+
attr_accessor :element, :a
|
35
|
+
|
36
|
+
def next_element
|
37
|
+
@first = false
|
38
|
+
self.element = starts.next
|
39
|
+
end
|
40
|
+
|
41
|
+
def next_a
|
42
|
+
if branch_a
|
43
|
+
begin
|
44
|
+
self.a = branch_a.next
|
45
|
+
rescue NativeException => e
|
46
|
+
if e.cause.getClass == Pacer::NoSuchElementException.getClass or @first
|
47
|
+
next_element
|
48
|
+
branch_a.setStarts SingleIterator.new(element) if branch_a
|
49
|
+
retry
|
50
|
+
else
|
51
|
+
raise e
|
52
|
+
end
|
53
|
+
end
|
54
|
+
else
|
55
|
+
next_element
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Pacer::Pipes
|
2
|
+
class VariableStoreIteratorWrapper < AbstractPipe
|
3
|
+
|
4
|
+
field_reader :starts
|
5
|
+
attr_accessor :vars
|
6
|
+
|
7
|
+
def initialize(pipe, vars, variable_name)
|
8
|
+
super()
|
9
|
+
setStarts pipe if pipe
|
10
|
+
@vars = vars
|
11
|
+
@variable_name = variable_name
|
12
|
+
end
|
13
|
+
|
14
|
+
protected
|
15
|
+
|
16
|
+
def processNextStart
|
17
|
+
@vars[@variable_name] = starts.next
|
18
|
+
rescue NativeException => e
|
19
|
+
if e.cause.getClass == Pacer::NoSuchElementException.getClass
|
20
|
+
raise e.cause
|
21
|
+
else
|
22
|
+
raise e
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Pacer
|
2
|
+
module Pipes
|
3
|
+
class VisitorPipe < Pacer::Pipes::RubyPipe
|
4
|
+
attr_reader :visitor, :queue, :in_section
|
5
|
+
|
6
|
+
attr_accessor :use_on_element, :use_replace_element,
|
7
|
+
:use_after_element, :use_reset, :use_hasNext, :use_next
|
8
|
+
|
9
|
+
def initialize(visitor = nil)
|
10
|
+
super()
|
11
|
+
self.visitor = visitor if visitor
|
12
|
+
@queue = []
|
13
|
+
@in_section = false
|
14
|
+
end
|
15
|
+
|
16
|
+
def visitor=(visitor)
|
17
|
+
if visitor.respond_to? :on_pipe
|
18
|
+
@visitor = visitor.on_pipe(self)
|
19
|
+
else
|
20
|
+
@visitor = visitor
|
21
|
+
end
|
22
|
+
@use_hasNext = visitor.respond_to? :hasNext
|
23
|
+
@use_next = visitor.respond_to? :next
|
24
|
+
@use_on_element = visitor.respond_to? :on_element
|
25
|
+
@use_replace_element = visitor.respond_to? :replace_element
|
26
|
+
@use_after_element = visitor.respond_to? :after_element
|
27
|
+
@use_reset = visitor.respond_to? :reset
|
28
|
+
end
|
29
|
+
|
30
|
+
def processNextStart
|
31
|
+
while true
|
32
|
+
visitor.after_element if use_after_element and in_section
|
33
|
+
if use_next and (not use_hasNext or visitor.hasNext)
|
34
|
+
return visitor.next
|
35
|
+
elsif queue.any?
|
36
|
+
return queue.shift
|
37
|
+
else
|
38
|
+
current = starts.next
|
39
|
+
@in_section = true unless in_section
|
40
|
+
visitor.on_element(current) if use_on_element
|
41
|
+
if use_replace_element
|
42
|
+
visitor.replace_element(current) do |e|
|
43
|
+
queue << e
|
44
|
+
end
|
45
|
+
else
|
46
|
+
return current
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
rescue NativeException => e
|
51
|
+
if e.cause.getClass == Pacer::NoSuchElementException.getClass
|
52
|
+
@in_section = false
|
53
|
+
raise e.cause
|
54
|
+
else
|
55
|
+
raise
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def reset
|
60
|
+
visitor.reset if use_reset
|
61
|
+
@in_section = false
|
62
|
+
@queue = []
|
63
|
+
super
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/pacer/pipes.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
module Pacer
|
2
|
+
# Import the Pipes and related objects that we'll be using.
|
3
|
+
module Pipes
|
4
|
+
# TODO: move pipe imports to the modules that actually use them.
|
5
|
+
import com.tinkerpop.pipes.AbstractPipe
|
6
|
+
import com.tinkerpop.pipes.transform.IdentityPipe
|
7
|
+
import com.tinkerpop.pipes.util.Pipeline
|
8
|
+
import com.tinkerpop.pipes.util.ExpandableIterator
|
9
|
+
import com.tinkerpop.pipes.util.MultiIterator
|
10
|
+
import com.tinkerpop.pipes.util.PipeHelper
|
11
|
+
|
12
|
+
import com.tinkerpop.pipes.filter.RandomFilterPipe
|
13
|
+
import com.tinkerpop.pipes.filter.DuplicateFilterPipe
|
14
|
+
import com.tinkerpop.pipes.filter.RangeFilterPipe
|
15
|
+
import com.tinkerpop.pipes.filter.FilterPipe
|
16
|
+
|
17
|
+
import com.tinkerpop.pipes.transform.IdPipe
|
18
|
+
import com.tinkerpop.pipes.transform.PropertyPipe
|
19
|
+
|
20
|
+
EQUAL = FilterPipe::Filter::EQUAL
|
21
|
+
NOT_EQUAL = FilterPipe::Filter::NOT_EQUAL
|
22
|
+
#GREATER_THAN, LESS_THAN, GREATER_THAN_EQUAL, LESS_THAN_EQUAL
|
23
|
+
end
|
24
|
+
|
25
|
+
import java.util.Iterator
|
26
|
+
begin
|
27
|
+
java.util.ArrayList.new.iterator.next
|
28
|
+
rescue NativeException => e
|
29
|
+
NoSuchElementException = e.cause
|
30
|
+
Pipes::NoSuchElementException = e.cause
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
require 'pacer/pipe/ruby_pipe'
|
35
|
+
|
36
|
+
require 'pacer/pipe/never_pipe'
|
37
|
+
require 'pacer/pipe/block_filter_pipe'
|
38
|
+
require 'pacer/pipe/collection_filter_pipe'
|
39
|
+
require 'pacer/pipe/enumerable_pipe'
|
40
|
+
require 'pacer/pipe/expandable_pipe'
|
41
|
+
require 'pacer/pipe/loop_pipe'
|
42
|
+
require 'pacer/pipe/map_pipe'
|
43
|
+
require 'pacer/pipe/process_pipe'
|
44
|
+
require 'pacer/pipe/visitor_pipe'
|
45
|
+
require 'pacer/pipe/simple_visitor_pipe'
|
46
|
+
require 'pacer/pipe/is_unique_pipe'
|
47
|
+
require 'pacer/pipe/is_empty_pipe'
|
48
|
+
require 'pacer/pipe/stream_sort_pipe'
|
49
|
+
require 'pacer/pipe/stream_uniq_pipe'
|
50
|
+
require 'pacer/pipe/type_filter_pipe'
|
51
|
+
require 'pacer/pipe/label_collection_filter_pipe'
|
52
|
+
require 'pacer/pipe/id_collection_filter_pipe'
|
53
|
+
require 'pacer/pipe/label_prefix_pipe'
|
54
|
+
require 'pacer/pipe/variable_store_iterator_wrapper'
|
55
|
+
|
56
|
+
require 'pacer/pipe/property_comparison_pipe'
|
57
|
+
|
58
|
+
require 'pacer/pipe/blackbox_pipeline'
|
59
|
+
|
60
|
+
require 'pacer/pipe/unary_transform_pipe'
|
61
|
+
require 'pacer/pipe/cross_product_transform_pipe'
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Pacer::Routes
|
2
|
+
|
3
|
+
# Additional iteration methods that allow for rapid data
|
4
|
+
# manipulation in transactional graphs. Bulk operations automatically
|
5
|
+
# manage transactions in larger batches rather than on every
|
6
|
+
# element created or removed or every property set.
|
7
|
+
module BulkOperations
|
8
|
+
# Like bulk_job that also returns an array of results
|
9
|
+
def bulk_map(size = nil, target_graph = nil)
|
10
|
+
result = []
|
11
|
+
bulk_job(size, target_graph) do |e|
|
12
|
+
result << yield(e)
|
13
|
+
end
|
14
|
+
result
|
15
|
+
end
|
16
|
+
|
17
|
+
# Iterates over each element in the route, controlling
|
18
|
+
# transactions so that they are only committed once every
|
19
|
+
# +size+ records.
|
20
|
+
def bulk_job(size = nil, target_graph = nil)
|
21
|
+
target_graph ||= graph
|
22
|
+
if target_graph and not target_graph.in_bulk_job?
|
23
|
+
begin
|
24
|
+
target_graph.in_bulk_job = true
|
25
|
+
size ||= target_graph.bulk_job_size
|
26
|
+
counter = 0
|
27
|
+
each_slice(size) do |slice|
|
28
|
+
print counter if Pacer.verbose?
|
29
|
+
counter += size
|
30
|
+
target_graph.managed_manual_transaction do
|
31
|
+
target_graph.unmanaged_transactions do
|
32
|
+
slice.each do |element|
|
33
|
+
yield element
|
34
|
+
end
|
35
|
+
end
|
36
|
+
print '.' if Pacer.verbose?
|
37
|
+
end
|
38
|
+
end
|
39
|
+
ensure
|
40
|
+
puts '!' if Pacer.verbose?
|
41
|
+
target_graph.in_bulk_job = false
|
42
|
+
end
|
43
|
+
elsif target_graph
|
44
|
+
each do |element|
|
45
|
+
yield element
|
46
|
+
end
|
47
|
+
else
|
48
|
+
raise 'No graph in route for bulk job'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
module Pacer::Routes
|
2
|
+
|
3
|
+
# Additional convenience and data analysis methods that can be mixed into
|
4
|
+
# routes if they support the full route interface.
|
5
|
+
module RouteOperations
|
6
|
+
include BulkOperations
|
7
|
+
|
8
|
+
def has?(element)
|
9
|
+
any? { |e| e == element }
|
10
|
+
end
|
11
|
+
|
12
|
+
# Creates a hash where the key is the properties and return value of the
|
13
|
+
# given block, and the value is the number of times each key was found in
|
14
|
+
# the results set.
|
15
|
+
def group_count(*props)
|
16
|
+
result = Hash.new(0)
|
17
|
+
props = props.collect { |p| p.to_s }
|
18
|
+
if props.empty? and block_given?
|
19
|
+
each { |e| result[yield(e)] += 1 }
|
20
|
+
elsif block_given?
|
21
|
+
each do |e|
|
22
|
+
key = props.collect { |p| e.getProperty(p) }
|
23
|
+
key << yield(e)
|
24
|
+
result[key] += 1
|
25
|
+
end
|
26
|
+
elsif props.count == 1
|
27
|
+
prop = props.first
|
28
|
+
each do |e|
|
29
|
+
result[e.getProperty(prop)] += 1
|
30
|
+
end
|
31
|
+
elsif props.any?
|
32
|
+
each do |e|
|
33
|
+
result[props.collect { |p| e.getProperty(p) }] += 1
|
34
|
+
end
|
35
|
+
else
|
36
|
+
each do |e|
|
37
|
+
result[e] += 1
|
38
|
+
end
|
39
|
+
end
|
40
|
+
result
|
41
|
+
end
|
42
|
+
|
43
|
+
def most_frequent(range = 0, include_counts = false)
|
44
|
+
if include_counts
|
45
|
+
result = group_count.sort_by { |k, v| -v }[range]
|
46
|
+
if not result and range.is_a? Fixnum
|
47
|
+
[]
|
48
|
+
else
|
49
|
+
result
|
50
|
+
end
|
51
|
+
else
|
52
|
+
result = group_count.sort_by { |k, v| -v }[range]
|
53
|
+
if range.is_a? Fixnum
|
54
|
+
result.first if result
|
55
|
+
elsif result
|
56
|
+
result.collect { |k, v| k }.to_route(:based_on => self)
|
57
|
+
else
|
58
|
+
[].to_route(:based_on => self)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Store the current intermediate element in the route's vars hash by the
|
64
|
+
# given name so that it is accessible subsequently in the processing of the
|
65
|
+
# route.
|
66
|
+
def as(name)
|
67
|
+
chain_route :modules => VariableRouteModule, :variable_name => name
|
68
|
+
end
|
69
|
+
|
70
|
+
# Returns true if this route could contain both vertices and edges.
|
71
|
+
def mixed_route?
|
72
|
+
self.is_a? Pacer::Core::Graph::MixedRoute
|
73
|
+
end
|
74
|
+
|
75
|
+
# Returns true if this route countains only vertices.
|
76
|
+
def vertices_route?
|
77
|
+
self.is_a? Pacer::Core::Graph::VerticesRoute
|
78
|
+
end
|
79
|
+
|
80
|
+
# Returns true if this route countains only edges.
|
81
|
+
def edges_route?
|
82
|
+
self.is_a? Pacer::Core::Graph::EdgesRoute
|
83
|
+
end
|
84
|
+
|
85
|
+
def pages(elements_per_page = 1000)
|
86
|
+
page = []
|
87
|
+
results = []
|
88
|
+
idx = 0
|
89
|
+
each do |e|
|
90
|
+
page << e
|
91
|
+
idx += 1
|
92
|
+
if idx % elements_per_page == 0
|
93
|
+
results << yield(page)
|
94
|
+
page = []
|
95
|
+
end
|
96
|
+
end
|
97
|
+
yield page unless page.empty?
|
98
|
+
results
|
99
|
+
end
|
100
|
+
|
101
|
+
protected
|
102
|
+
|
103
|
+
def has_routable_class?
|
104
|
+
true
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Pacer::Routes
|
2
|
+
|
3
|
+
# Adds support to a route to store a variable inline during processing. See
|
4
|
+
# Pacer::Routes::RouteOperations#as
|
5
|
+
module VariableRouteModule
|
6
|
+
attr_accessor :variable_name
|
7
|
+
|
8
|
+
def root?
|
9
|
+
false
|
10
|
+
end
|
11
|
+
|
12
|
+
protected
|
13
|
+
|
14
|
+
def attach_pipe(pipe)
|
15
|
+
Pacer::Pipes::VariableStoreIteratorWrapper.new(pipe, vars, @variable_name)
|
16
|
+
end
|
17
|
+
|
18
|
+
def has_routable_class?
|
19
|
+
false
|
20
|
+
end
|
21
|
+
|
22
|
+
def inspect_class_name
|
23
|
+
@variable_name.inspect
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|