pacer 0.9.1.1-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.
- 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
|