pacer 1.3.2-java → 1.3.3-java

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 941518faaec723674b8421588ee147d210b65b7a
4
- data.tar.gz: 5624f8bf440519e6335d7f850d8cb0b3403c4d49
3
+ metadata.gz: e7e0a5a234c35970d36d359c87ba463f288153b1
4
+ data.tar.gz: 8fc9db2381222ca87e44dea2c59b41b8c41cf552
5
5
  SHA512:
6
- metadata.gz: 85df9faed211d24e9a2810867194a41494955d76e03918b99150b03720eb93c2c83e1d4832215424b7f30d07138d0226333c634782950cd31a1d903c42004585
7
- data.tar.gz: 25b18a28d5f9f25ee014ae6ea3940dc0c6dce0abfebdab76414394252018aa6d8da58da5e5faf45eec324861e7d910a3f84344151a67b8da72b0b0a4157f0e01
6
+ metadata.gz: 188528a64f6d2cb85fa57176ac500e9f9dc68b9859dc9b9fe6853025d5ce2a73812401f696654f8b5f8e5748671594dfd950088a96587a0fa2b15d285e03263d
7
+ data.tar.gz: 84608cddad663f171a8ad886f2c1f68e65ec33b9bea94a1107ec39301a2816e6fd10f69f49994145c0671effd4379ffc9c7c59819e4fd416c89cc40e65ee189c
data/ideas.rb ADDED
@@ -0,0 +1,32 @@
1
+ g.v.parallel(threads: 8, in_buffer: 4, out_buffer: 10) { |v| v.out.out.out.out.out }
2
+
3
+ # - eagerly consume (1) input and push into a channel
4
+ # - ChannelCapPipe
5
+ # - create a cap pipe that does this. The pipe's output is the channel
6
+ # - source data may be slow. Should probably not use a go block
7
+ # - 1 thread in a loop
8
+ # - Control the construction of parallel pipes. Default 2 threads, make
9
+ # it configurable.
10
+ # - standard copy split pipe can push the channel to subchannels
11
+ # - each parallel route pulls from the channel.
12
+ # - in a go block (waits will not block go thread pool)
13
+ # - ChannelReaderPipe
14
+ # - PathChannelReaderPipe
15
+ # - parallel routes are unmodified
16
+ # - cap each route - eagerly consume input and push into a channel
17
+ # - ChannelCapPipe again
18
+ # -
19
+ # - like ExhaustMergePipe + GatherPipe
20
+ # - use alts to read from any of the channels
21
+ # - ChannelAltsReaderPipe
22
+
23
+
24
+
25
+ # CCP
26
+ # CSP (parallelism is 1 thread per pipe being split into)
27
+ # CRP -> Work ... -> CCP
28
+ # CRP -> Work ... -> CCP
29
+ # ...
30
+ # EMP
31
+ # GP
32
+ # CARP
@@ -0,0 +1,59 @@
1
+ module Pacer
2
+ # Created without property support, though it could easily be added if it is ever needed.
3
+ class GroupVertex
4
+ import com.tinkerpop.blueprints.util.VerticesFromEdgesIterable
5
+ IN = com.tinkerpop.blueprints.Direction::IN
6
+ OUT = com.tinkerpop.blueprints.Direction::OUT
7
+ BOTH = com.tinkerpop.blueprints.Direction::BOTH
8
+
9
+ attr_reader :components, :key
10
+ attr_reader :paths, :wrapper, :graph
11
+
12
+ # Initialize it with an empty set to force uniqueness. Non-unique by default.
13
+ def initialize(key, graph, wrapper, components = nil)
14
+ @key = key
15
+ @wrapper = wrapper
16
+ if components
17
+ @components = components
18
+ else
19
+ @components = []
20
+ end
21
+ end
22
+
23
+ def add_component(vertex)
24
+ components << vertex
25
+ end
26
+
27
+ include com.tinkerpop.blueprints.Element
28
+
29
+ def getId
30
+ "#{ key }:#{ components.count }"
31
+ end
32
+
33
+ def getPropertyKeys
34
+ Set[]
35
+ end
36
+
37
+ def getProperty(key)
38
+ case key
39
+ when 'components' then components.map { |c| wrapper.new graph, c }
40
+ when 'key' then key
41
+ when 'count' then components.count
42
+ end
43
+ end
44
+
45
+ include com.tinkerpop.blueprints.Vertex
46
+
47
+ def getRawVertex
48
+ self
49
+ end
50
+
51
+ def getVertices(direction, *labels)
52
+ VerticesFromEdgesIterable.new self, direction, *labels
53
+ end
54
+
55
+ def getEdges(direction, *labels)
56
+ Pacer::Pipes::MultiPipe.new components.map { |v| v.getEdges(direction, *labels) }
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,57 @@
1
+ module Pacer
2
+ module Routes
3
+ module RouteOperations
4
+ def limit_section(section = nil, max)
5
+ chain_route filter: Pacer::Filter::LimitSectionFilter, section_max: max, section: section
6
+ end
7
+ end
8
+ end
9
+
10
+ module Filter
11
+ module LimitSectionFilter
12
+ # VisitsSection module provides:
13
+ # section=
14
+ # section_visitor
15
+ include Pacer::Visitors::VisitsSection
16
+
17
+ attr_accessor :section_max
18
+
19
+ def attach_pipe(end_pipe)
20
+ pipe = LimitSectionPipe.new(self, section_visitor, section_max)
21
+ pipe.setStarts end_pipe if end_pipe
22
+ pipe
23
+ end
24
+
25
+ class LimitSectionPipe < Pacer::Pipes::RubyPipe
26
+ attr_reader :max, :section, :route
27
+ attr_accessor :hits
28
+
29
+
30
+ def initialize(route, section, max)
31
+ super()
32
+ @hits = 0
33
+ @max = max
34
+ @section = section
35
+ @route = route
36
+ section.visitor = self if section
37
+ end
38
+
39
+ def processNextStart
40
+ while hits == max
41
+ starts.next
42
+ end
43
+ self.hits += 1
44
+ starts.next
45
+ end
46
+
47
+ def after_element
48
+ self.hits = 0
49
+ end
50
+
51
+ def reset
52
+ self.hits = 0
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -1,12 +1,12 @@
1
1
  module Pacer
2
2
  module Routes
3
3
  module RouteOperations
4
- def loop(&block)
5
- chain_route :filter => :loop, :looping_route => block
4
+ def loop(opts = {}, &block)
5
+ chain_route(opts.merge :filter => :loop, :looping_route => block)
6
6
  end
7
7
 
8
- def all(&block)
9
- loop(&block).while do |e, depth|
8
+ def all(opts = {}, &block)
9
+ loop(opts, &block).while do |e, depth|
10
10
  if depth == 0
11
11
  :loop
12
12
  else
@@ -60,6 +60,7 @@ module Pacer
60
60
  module LoopFilter
61
61
  attr_reader :looping_route
62
62
  attr_accessor :while_description
63
+ attr_reader :reverse_loop_route, :reverse_emit_route
63
64
 
64
65
  def help(section = nil)
65
66
  case section
@@ -162,15 +163,42 @@ HELP
162
163
  # this could have concurrency problems if multiple instances of the same
163
164
  # route
164
165
  def deepest!
165
- @deepest = true
166
+ @loop_when_route = @looping_route
167
+ @reverse_loop_route = false
168
+ @emit_when_route = @looping_route
169
+ @reverse_emit_route = true
170
+ self
171
+ end
172
+
173
+ def loop_when(&block)
174
+ @loop_when_route = Pacer::Route.block_branch(self, block)
175
+ @reverse_loop_route = false
176
+ self
177
+ end
178
+
179
+ def loop_when_not(&block)
180
+ @loop_when_route = Pacer::Route.block_branch(self, block)
181
+ @reverse_loop_route = true
182
+ self
183
+ end
184
+
185
+ def emit_when(&block)
186
+ @emit_when_route = Pacer::Route.block_branch(self, block)
187
+ @reverse_emit_route = false
188
+ self
189
+ end
190
+
191
+ def emit_when_not(&block)
192
+ @emit_when_route = Pacer::Route.block_branch(self, block)
193
+ @reverse_emit_route = true
166
194
  self
167
195
  end
168
196
 
169
197
  protected
170
198
 
171
199
  def attach_pipe(end_pipe)
172
- if @deepest
173
- control_block = deepest_control_block
200
+ if @loop_when_route or @emit_when_route
201
+ control_block = route_control_block
174
202
  elsif @control_block
175
203
  control_block = @control_block
176
204
  else
@@ -181,19 +209,37 @@ HELP
181
209
  pipe
182
210
  end
183
211
 
184
- def deepest_control_block
212
+ def expandable(route = nil)
185
213
  expando = Pacer::Pipes::ExpandablePipe.new
186
214
  empty = java.util.ArrayList.new
187
215
  expando.setStarts empty.iterator
188
- control_pipe = looping_pipe
216
+ if route
217
+ control_pipe = Pacer::Route.pipeline route
218
+ else
219
+ control_pipe = Pacer::Pipes::IdentityPipe.new
220
+ end
189
221
  control_pipe.setStarts expando
222
+ [expando, control_pipe]
223
+ end
224
+
225
+ def route_control_block
226
+ loop_expando, loop_pipe = expandable @loop_when_route
227
+ emit_expando, emit_pipe = expandable @emit_when_route
190
228
  proc do |el, depth|
191
- control_pipe.reset
192
- expando.add el.element
193
- if control_pipe.hasNext
194
- :loop
229
+ loop_pipe.reset
230
+ loop_expando.add el.element
231
+ emit_pipe.reset
232
+ emit_expando.add el.element
233
+ if loop_pipe.hasNext ^ reverse_loop_route
234
+ if emit_pipe.hasNext ^ reverse_emit_route
235
+ :loop_and_emit
236
+ else
237
+ :loop
238
+ end
195
239
  elsif depth > 0
196
- :emit
240
+ if emit_pipe.hasNext ^ reverse_emit_route
241
+ :emit
242
+ end
197
243
  end
198
244
  end
199
245
  end
data/lib/pacer/loader.rb CHANGED
@@ -49,8 +49,7 @@ require 'pacer/function_resolver'
49
49
  require 'pacer/route'
50
50
 
51
51
  require 'pacer/blueprints/tg'
52
- require 'pacer/blueprints/ruby_graph'
53
- require 'pacer/blueprints/multi_graph'
52
+ require 'pacer/blueprints/group_vertex'
54
53
 
55
54
  require 'pacer/blueprints/payload_elements'
56
55
 
@@ -79,6 +78,7 @@ require 'pacer/filter/loop_filter'
79
78
  require 'pacer/filter/block_filter'
80
79
  require 'pacer/filter/object_filter'
81
80
  require 'pacer/filter/random_filter'
81
+ require 'pacer/filter/limit_section_filter'
82
82
 
83
83
  require 'pacer/transform/branch'
84
84
  require 'pacer/transform/cap'
@@ -97,6 +97,7 @@ require 'pacer/transform/wrapped_path'
97
97
  require 'pacer/transform/scatter'
98
98
  require 'pacer/transform/has_count_cap'
99
99
  require 'pacer/transform/sort_section'
100
+ require 'pacer/transform/intersect_sections'
100
101
  require 'pacer/transform/payload'
101
102
  require 'pacer/transform/lookup_ids'
102
103
 
@@ -42,6 +42,7 @@ module Pacer
42
42
  end
43
43
 
44
44
  def type_def(source, args)
45
+ source = args.fetch(:based_on, source)
45
46
  [
46
47
  type_modules(source, args),
47
48
  function_modules(source, args),
@@ -51,6 +52,7 @@ module Pacer
51
52
  end
52
53
 
53
54
  def configuration(source, args)
55
+ source = args.fetch(:based_on, source)
54
56
  {
55
57
  element_type: element_type(source, args),
56
58
  graph: graph(source, args),
@@ -62,7 +64,7 @@ module Pacer
62
64
 
63
65
  def arguments(source, args)
64
66
  args.reject do |key, val|
65
- Set[:element_type, :wrapper, :extensions, :modules, :graph, :back, :filter, :side_effect, :transform, :visitor].include? key
67
+ Set[:element_type, :wrapper, :extensions, :modules, :graph, :back, :filter, :side_effect, :transform, :visitor, :based_on].include? key
66
68
  end
67
69
  end
68
70
 
@@ -0,0 +1,83 @@
1
+ module Pacer
2
+ module Routes
3
+ module RouteOperations
4
+ def intersect_sections(section)
5
+ chain_route transform: Pacer::Transform::IntersectSections, section: section, operation: :intersection
6
+ end
7
+
8
+ def difference_sections(section)
9
+ chain_route transform: Pacer::Transform::IntersectSections, section: section, operation: :difference
10
+ end
11
+
12
+ def left_difference_sections(section)
13
+ chain_route transform: Pacer::Transform::IntersectSections, section: section, operation: :left_difference
14
+ end
15
+
16
+ def right_difference_sections(section)
17
+ chain_route transform: Pacer::Transform::IntersectSections, section: section, operation: :right_difference
18
+ end
19
+ end
20
+ end
21
+
22
+
23
+ module Transform
24
+ module IntersectSections
25
+ # VisitsSection module provides:
26
+ # section=
27
+ # section_visitor
28
+ include Pacer::Visitors::VisitsSection
29
+
30
+ attr_accessor :operation
31
+
32
+ protected
33
+
34
+ def attach_pipe(end_pipe)
35
+ pipe = IntersectSectionPipe.new(section_visitor, operation)
36
+ pipe.setStarts end_pipe if end_pipe
37
+ pipe
38
+ end
39
+
40
+ class IntersectSectionPipe < Pacer::Pipes::RubyPipe
41
+ attr_reader :section, :reduce_block
42
+ attr_accessor :to_emit, :current_set, :all_sets
43
+
44
+ def initialize(section, operation)
45
+ super()
46
+ @section = section
47
+ case operation
48
+ when :difference
49
+ @reduce_block = proc { |a, b| (a - b) + (b - a) }
50
+ when :left_difference
51
+ @reduce_block = proc { |a, b| a - b }
52
+ when :right_difference
53
+ @reduce_block = proc { |a, b| b - a }
54
+ when :intersection
55
+ @reduce_block = proc { |a, b| a.intersection b }
56
+ end
57
+ self.all_sets = []
58
+ if section
59
+ section.visitor = self
60
+ else
61
+ on_element nil
62
+ end
63
+ end
64
+
65
+ def processNextStart
66
+ unless to_emit
67
+ while starts.hasNext
68
+ current_set << starts.next
69
+ end
70
+ self.to_emit = all_sets.reduce(&reduce_block).to_a
71
+ end
72
+ raise EmptyPipe.instance if to_emit.empty?
73
+ to_emit.shift
74
+ end
75
+
76
+ def on_element(x)
77
+ self.current_set = Set[]
78
+ all_sets << current_set
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -1,197 +1,70 @@
1
1
  module Pacer
2
2
  module Routes
3
3
  module RouteOperations
4
- def key(&block)
5
- join(:key, &block)
4
+ def join(&block)
5
+ chain_route transform: Pacer::Transform::Join, block: block
6
6
  end
7
7
 
8
- def join(name = nil, options = {}, &block)
9
- args = {
10
- :transform => :join,
11
- element_type: :vertex,
12
- graph: options.fetch(:multi_graph, Pacer::MultiGraph.blank),
13
- from_graph: graph
14
- }
15
- args[:multi_graph] = options[:multi_graph] if options[:multi_graph]
16
- route = chain_route(args)
17
- route = route.key { |v| v } unless name == :key
18
- if block and name == :key
19
- route.key &block
20
- elsif block
21
- route.join(name || :values, &block)
22
- else
23
- route
24
- end
8
+ def unjoin
9
+ map { |g| g[:components] }.scatter extensions: extensions, graph: graph, element_type: element_type
25
10
  end
26
11
  end
27
12
  end
28
13
 
29
-
30
14
  module Transform
31
15
  module Join
32
- class CombinePipe < Pacer::Pipes::RubyPipe
33
- import com.tinkerpop.pipes.sideeffect.SideEffectPipe
34
- import java.util.ArrayList
35
- import java.util.LinkedList
16
+ attr_reader :key_block, :unique
36
17
 
37
- include SideEffectPipe rescue nil # may raise exception on reload.
18
+ def block=(block)
19
+ @key_block = block
20
+ end
38
21
 
39
- attr_accessor :multi_graph, :current_keys, :current_values, :join_on
40
- attr_reader :key_expando, :key_end, :values_pipes, :from_graph, :wrapper
22
+ def uniq
23
+ @unique = true
24
+ self
25
+ end
41
26
 
42
- def initialize(from_graph, multi_graph)
43
- super()
44
- @from_graph = from_graph
45
- @wrapper = Pacer::Wrappers::WrapperSelector.build from_graph
46
- @multi_graph = multi_graph || Pacer::MultiGraph.blank
47
- @values_pipes = []
48
- @current_keys = []
49
- @current_values = []
50
- end
27
+ protected
51
28
 
52
- def setKeyPipe(from_pipe, to_pipe)
53
- @key_expando, @key_end = prepare_aggregate_pipe(from_pipe, to_pipe)
54
- end
29
+ def attach_pipe(end_pipe)
30
+ pipe = JoinPipe.new(self, key_block, unique)
31
+ pipe.setStarts end_pipe if end_pipe
32
+ pipe
33
+ end
55
34
 
56
- def addValuesPipe(name, from_pipe, to_pipe)
57
- values_pipes << [name, *prepare_aggregate_pipe(from_pipe, to_pipe)]
58
- end
35
+ class JoinPipe < Pacer::Pipes::RubyPipe
36
+ attr_reader :block, :groups, :unique
37
+ attr_accessor:to_emit
59
38
 
60
- def getSideEffect
61
- multi_graph
39
+ def initialize(back, key_block, unique)
40
+ super()
41
+ @unique = unique
42
+ @block = Pacer::Wrappers::WrappingPipeFunction.new back, key_block
62
43
  end
63
44
 
64
- protected
65
-
66
45
  def processNextStart
67
- while true
68
- if current_keys.empty?
69
- element = wrapper.new from_graph, starts.next
70
- self.current_keys = get_keys(element)
71
- self.current_values = get_values(element) unless current_keys.empty?
72
- else
73
- key = current_keys.removeFirst
74
- if key
75
- combined = multi_graph.vertex(key) || multi_graph.create_vertex(key)
76
- else
77
- combined = multi_graph.create_vertex
78
- end
79
- combined.join_on join_on if join_on
80
- combined[:key] = key
81
- current_values.each do |key, values|
82
- combined.element.append_property_array key, values
83
- end
84
- return combined
46
+ unless to_emit
47
+ coll = unique ? Set : Array
48
+ groups = Hash.new { |h, k| h[k] = Pacer::GroupVertex.new k, block.graph, block.wrapper, coll.new }
49
+ while starts.hasNext
50
+ el = starts.next
51
+ groups[block.call(el)].add_component el
85
52
  end
53
+ self.to_emit = groups.values
86
54
  end
87
- end
88
-
89
- def get_keys(element)
90
- array = LinkedList.new
91
- if key_expando
92
- array.addAll next_results(key_expando, key_end, element)
55
+ if to_emit.empty?
56
+ raise Pacer::Pipes::EmptyPipe.instance
93
57
  else
94
- array.add nil
95
- end
96
- array
97
- end
98
-
99
- def get_values(element)
100
- values_pipes.map do |name, expando, to_pipe|
101
- [name, next_results(expando, to_pipe, element)]
102
- end
103
- end
104
-
105
- # doesn't need to be spun out because it's a capped aggregator
106
- def next_results(expando, pipe, element)
107
- pipe.reset
108
- expando.add element, ArrayList.new, nil
109
- array = pipe.next
110
- array.map do |element|
111
- if element.is_a? Pacer::Element
112
- wrapper.new from_graph, element
113
- else
114
- element
115
- end
58
+ to_emit.shift
116
59
  end
117
60
  end
118
61
 
119
- def prepare_aggregate_pipe(from_pipe, to_pipe)
120
- expando = Pacer::Pipes::ExpandablePipe.new
121
- expando.setStarts ArrayList.new.iterator
122
- from_pipe.setStarts(expando)
123
- agg_pipe = com.tinkerpop.pipes.sideeffect.AggregatePipe.new LinkedList.new
124
- cap_pipe = com.tinkerpop.pipes.transform.SideEffectCapPipe.new agg_pipe
125
- agg_pipe.setStarts to_pipe
126
- cap_pipe.setStarts to_pipe
127
- [expando, cap_pipe]
62
+ def reset
63
+ super
64
+ self.loaded = false
65
+ self.to_emit = nil
128
66
  end
129
67
  end
130
-
131
- include Pacer::Core::SideEffect
132
-
133
- attr_accessor :existing_multi_graph, :key_route, :values_routes, :from_graph
134
- attr_writer :join_on
135
-
136
- # FIXME: the pipe changes the graph. This does not fit with the idea of immutable routes.
137
- def graph
138
- @graph or super
139
- end
140
-
141
- def run!
142
- super
143
- @graph
144
- end
145
-
146
- def graph=(g)
147
- @graph = g
148
- end
149
-
150
- def key(&block)
151
- self.key_route = Pacer::Route.block_branch(self, block)
152
- self
153
- end
154
-
155
- def join(name = nil, &block)
156
- self.key_route = nil if name == :key
157
- if block
158
- values_routes << [(name || :values), Pacer::Route.block_branch(self, block)]
159
- else
160
- values_routes << [(name || :values), Pacer::Route.block_branch(self, proc { |v| v })]
161
- end
162
- self
163
- end
164
-
165
- def join_on(*keys)
166
- @join_on = keys
167
- self
168
- end
169
-
170
- def multigraph
171
- cap.first
172
- end
173
-
174
- protected
175
-
176
- def after_initialize
177
- @values_routes = []
178
- end
179
-
180
- def attach_pipe(end_pipe)
181
- pipe = CombinePipe.new(from_graph, existing_multi_graph)
182
- self.graph = pipe.multi_graph
183
- pipe.setKeyPipe *key_route.send(:build_pipeline) if key_route
184
- pipe.join_on = @join_on
185
- values_routes.each do |name, route|
186
- pipe.addValuesPipe name, *route.send(:build_pipeline)
187
- end
188
- pipe.setStarts end_pipe if end_pipe
189
- pipe
190
- end
191
-
192
- def inspect_string
193
- "#{ inspect_class_name }(#{ key_route.inspect }: #{ Hash[values_routes].inspect })"
194
- end
195
68
  end
196
69
  end
197
70
  end
@@ -0,0 +1,17 @@
1
+ module Pacer
2
+ module Routes
3
+ module RouteOperations
4
+ def parallel(opts = {}, &block)
5
+ threads = opts.fetch(:threads, 2)
6
+ branched = (0..threads).reduce(channel_cap buffer: opts.fetch(:in_buffer, threads)) do |r, n|
7
+ r.branch do |x|
8
+ b = block.call x.channel_reader
9
+ b.channel_cap
10
+ end
11
+ end
12
+ branched.merge_exhaustive.gather.channel_fan_in(buffer: opts.fetch(:out_buffer, threads),
13
+ based_on: block.call(self))
14
+ end
15
+ end
16
+ end
17
+ end
data/lib/pacer/version.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Pacer
2
2
  unless const_defined? :VERSION
3
- VERSION = "1.3.2"
3
+ VERSION = "1.3.3"
4
4
 
5
5
  JAR = "pacer-#{ VERSION }-standalone.jar"
6
6
  JAR_PATH = "lib/#{ JAR }"
data/pom.xml CHANGED
@@ -8,7 +8,7 @@
8
8
  <!-- NOTE: the following properties are automatically updated based on the values in lib/pacer-neo4j/version.rb -->
9
9
  <properties>
10
10
  <blueprints.version>2.3.0</blueprints.version>
11
- <gem.version>1.3.2</gem.version>
11
+ <gem.version>1.3.3</gem.version>
12
12
  <pipes.version>2.3.0</pipes.version>
13
13
  <gremlin.version>2.3.0</gremlin.version>
14
14
  </properties>
@@ -45,53 +45,8 @@ class RSpec::GraphRunner
45
45
  end
46
46
  end
47
47
 
48
- module RubyGraph
49
- def all(usage_style = :read_write, indices = true, &block)
50
- super
51
- rg(usage_style, indices, &block)
52
- end
53
-
54
- def rg(usage_style = :read_write, indices = true, &block)
55
- for_graph('rg', usage_style, indices, false, ruby_graph, ruby_graph2, nil, block)
56
- end
57
-
58
- protected
59
-
60
- def ruby_graph
61
- Pacer::PacerGraph.new Pacer::SimpleEncoder, proc { Pacer::RubyGraph.new }
62
- end
63
-
64
- def ruby_graph2
65
- Pacer::PacerGraph.new Pacer::SimpleEncoder, proc { Pacer::RubyGraph.new }
66
- end
67
- end
68
-
69
- module MultiGraph
70
- def all(usage_style = :read_write, indices = true, &block)
71
- super
72
- multigraph(usage_style, indices, &block)
73
- end
74
-
75
- def multigraph(usage_style = :read_write, indices = true, &block)
76
- for_graph('multigraph', usage_style, indices, false, multi_graph, multi_graph2, nil, block)
77
- end
78
-
79
- protected
80
-
81
- def multi_graph
82
- Pacer::MultiGraph.blank
83
- end
84
-
85
- def multi_graph2
86
- Pacer::MultiGraph.blank
87
- end
88
- end
89
-
90
-
91
48
  include Stubs
92
49
  include Tg
93
- #include RubyGraph
94
- #include MultiGraph
95
50
  include Neo4j if defined? Neo4j
96
51
  include Dex if defined? Dex
97
52
  include Orient if defined? Orient
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pacer
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.2
4
+ version: 1.3.3
5
5
  platform: java
6
6
  authors:
7
7
  - Darrick Wiebe
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-08-21 00:00:00.000000000 Z
11
+ date: 2013-08-27 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Pacer defines routes through a graph and then traverses them very quickly.
14
14
  email: darrick@innatesoftware.com
@@ -34,10 +34,10 @@ files:
34
34
  - bin/yard
35
35
  - bin/yardoc
36
36
  - blog/2012-09-18-pacer-1.0.md
37
+ - ideas.rb
37
38
  - lib/pacer.rb
38
- - lib/pacer/blueprints/multi_graph.rb
39
+ - lib/pacer/blueprints/group_vertex.rb
39
40
  - lib/pacer/blueprints/payload_elements.rb
40
- - lib/pacer/blueprints/ruby_graph.rb
41
41
  - lib/pacer/blueprints/tg.rb
42
42
  - lib/pacer/core/array_route.rb
43
43
  - lib/pacer/core/graph.rb
@@ -58,6 +58,7 @@ files:
58
58
  - lib/pacer/filter/empty_filter.rb
59
59
  - lib/pacer/filter/future_filter.rb
60
60
  - lib/pacer/filter/index_filter.rb
61
+ - lib/pacer/filter/limit_section_filter.rb
61
62
  - lib/pacer/filter/loop_filter.rb
62
63
  - lib/pacer/filter/object_filter.rb
63
64
  - lib/pacer/filter/property_filter.rb
@@ -129,10 +130,12 @@ files:
129
130
  - lib/pacer/transform/flat_map.rb
130
131
  - lib/pacer/transform/gather.rb
131
132
  - lib/pacer/transform/has_count_cap.rb
133
+ - lib/pacer/transform/intersect_sections.rb
132
134
  - lib/pacer/transform/join.rb
133
135
  - lib/pacer/transform/lookup_ids.rb
134
136
  - lib/pacer/transform/make_pairs.rb
135
137
  - lib/pacer/transform/map.rb
138
+ - lib/pacer/transform/parallel.rb
136
139
  - lib/pacer/transform/path.rb
137
140
  - lib/pacer/transform/path_tree.rb
138
141
  - lib/pacer/transform/payload.rb
@@ -200,7 +203,6 @@ files:
200
203
  - spec/pacer/side_effect/is_unique_spec.rb
201
204
  - spec/pacer/support/array_list_spec.rb
202
205
  - spec/pacer/support/enumerable_spec.rb
203
- - spec/pacer/transform/join_spec.rb
204
206
  - spec/pacer/transform/map_spec.rb
205
207
  - spec/pacer/transform/path_spec.rb
206
208
  - spec/pacer/transform/path_tree_spec.rb
@@ -218,7 +220,7 @@ files:
218
220
  - spec/support/use_transactions.rb
219
221
  - spec/tackle/simple_mixin.rb
220
222
  - spec/tackle/tinkerpop_graph_mixins.rb
221
- - lib/pacer-1.3.2-standalone.jar
223
+ - lib/pacer-1.3.3-standalone.jar
222
224
  homepage: http://github.com/pangloss/pacer
223
225
  licenses:
224
226
  - MIT
@@ -280,7 +282,6 @@ test_files:
280
282
  - spec/pacer/side_effect/is_unique_spec.rb
281
283
  - spec/pacer/support/array_list_spec.rb
282
284
  - spec/pacer/support/enumerable_spec.rb
283
- - spec/pacer/transform/join_spec.rb
284
285
  - spec/pacer/transform/map_spec.rb
285
286
  - spec/pacer/transform/path_spec.rb
286
287
  - spec/pacer/transform/path_tree_spec.rb
@@ -1,109 +0,0 @@
1
- module Pacer
2
- class MultiGraph < RubyGraph
3
- def self.blank
4
- PacerGraph.new SimpleEncoder, proc { MultiGraph.new }
5
- end
6
-
7
- protected
8
-
9
- def vertex_class
10
- MultiVertex
11
- end
12
-
13
- def edge_class
14
- RubyEdge
15
- end
16
- end
17
-
18
-
19
- class MultiVertex < RubyVertex
20
- import com.tinkerpop.pipes.util.iterators.MultiIterator
21
-
22
- def initialize(*args)
23
- super
24
- @vertex_keys = Set[]
25
- @join_keys = @vertex_keys
26
- end
27
-
28
- attr_accessor :vertex_keys, :join_keys
29
-
30
- def join_on(keys)
31
- if keys.is_a? Enumerable
32
- @join_keys = keys.map { |k| k.to_s }.to_set
33
- elsif keys
34
- @join_keys = Set[keys.to_s]
35
- else
36
- @join_keys = Set[]
37
- end
38
- end
39
-
40
- def vertices
41
- join_keys.flat_map do |key|
42
- @properties[key]
43
- end
44
- end
45
-
46
- def setProperty(key, value)
47
- case value
48
- when Pacer::Vertex
49
- vertex_keys << key.to_s
50
- super
51
- when Hash
52
- vertex_keys.delete key.to_s
53
- super
54
- when Enumerable
55
- values = value.to_a
56
- if values.any? and values.all? { |v| v.is_a? Pacer::Vertex }
57
- vertex_keys << key.to_s
58
- end
59
- super(key, values)
60
- else
61
- vertex_keys.delete key.to_s
62
- super
63
- end
64
- end
65
-
66
- def append_property_array(key, value)
67
- values = value.to_a
68
- existing_values = getProperty(key)
69
- if existing_values
70
- if vertex_keys.include? key and not values.all? { |v| v.is_a? Pacer::Vertex }
71
- vertex_keys.delete key.to_s
72
- end
73
- raise "Can't append to key #{ key } because it is not an Array" unless existing_values.is_a? Array
74
- else
75
- existing_values = []
76
- setProperty(key, existing_values)
77
- vertex_keys << key.to_s if values.all? { |v| v.is_a? Pacer::Vertex }
78
- end
79
- existing_values.concat values
80
- end
81
-
82
- def removeProperty(key)
83
- vertex_keys.delete key.to_s
84
- super
85
- end
86
-
87
- def getEdges(direction, *labels)
88
- vs = vertices
89
- if vs.any?
90
- labels = extract_varargs_strings(labels)
91
- p = Pacer::Pipes::IdentityPipe.new
92
- p.setStarts(MultiIterator.new super, *vs.map { |v| v.getEdges(direction, *labels).iterator })
93
- p
94
- else
95
- super
96
- end
97
- end
98
-
99
- def inspect
100
- s = super
101
- s[2] = 'M'
102
- s
103
- end
104
-
105
- def to_s
106
- "m[#{ element_id }]"
107
- end
108
- end
109
- end
@@ -1,223 +0,0 @@
1
- module Pacer
2
- class RubyGraph
3
- import com.tinkerpop.blueprints.Element
4
- import com.tinkerpop.blueprints.Graph
5
- import com.tinkerpop.blueprints.Features
6
-
7
- include Graph
8
-
9
- FEATURES = Features.new.tap do |features|
10
- features.supportsDuplicateEdges = true
11
- features.supportsSelfLoops = true
12
- features.supportsSerializableObjectProperty = true
13
- features.supportsBooleanProperty = true
14
- features.supportsDoubleProperty = true
15
- features.supportsFloatProperty = true
16
- features.supportsIntegerProperty = true
17
- features.supportsPrimitiveArrayProperty = true
18
- features.supportsUniformListProperty = true
19
- features.supportsMixedListProperty = true
20
- features.supportsLongProperty = true
21
- features.supportsMapProperty = true
22
- features.supportsStringProperty = true
23
-
24
- features.ignoresSuppliedIds = false
25
- features.isPersistent = false
26
- features.isWrapper = false
27
-
28
- features.supportsIndices = false
29
- features.supportsKeyIndices = false
30
- features.supportsVertexKeyIndex = false
31
- features.supportsEdgeKeyIndex = false
32
- features.supportsVertexIndex = false
33
- features.supportsEdgeIndex = false
34
- features.supportsTransactions = false
35
- features.supportsVertexIteration = true
36
- features.supportsEdgeIteration = true
37
- features.supportsEdgeRetrieval = true
38
- features.supportsVertexProperties = true
39
- features.supportsEdgeProperties = true
40
- features.supportsThreadedTransactions = false
41
- end
42
-
43
- def initialize
44
- clear
45
- end
46
-
47
- def addVertex(id)
48
- if id
49
- v_id = id
50
- else
51
- v_id = next_id
52
- end
53
- raise Pacer::ElementExists if @vertices.key? v_id
54
- @vertices[v_id] = vertex_class.new self, v_id
55
- end
56
-
57
- def getVertex(id)
58
- @vertices[id]
59
- end
60
-
61
- def removeVertex(vertex)
62
- vertex.getEdges(Pacer::Pipes::BOTH).each do |e|
63
- removeEdge e
64
- end
65
- @vertices.delete vertex.element_id
66
- end
67
-
68
- def getVertices
69
- @vertices.values.to_iterable
70
- end
71
-
72
- def addEdge(id, outVertex, inVertex, label)
73
- id ||= next_id
74
- raise Pacer::ElementExists if @edges.key? id
75
- @edges[id] = edge_class.new self, id, outVertex, inVertex, label
76
- end
77
-
78
- def getEdge(id)
79
- @edges[id]
80
- end
81
-
82
- def removeEdge(edge)
83
- @edges.delete edge.element_id
84
- end
85
-
86
- def getEdges
87
- @edges.values.to_iterable
88
- end
89
-
90
- def clear
91
- @vertices = {}
92
- @edges = {}
93
- @next_id = 0
94
- end
95
-
96
- def shutdown
97
- clear
98
- end
99
-
100
- def ==(other)
101
- other.equal? self
102
- end
103
-
104
- def features
105
- FEATURES
106
- end
107
-
108
- protected
109
-
110
- def vertex_class
111
- RubyVertex
112
- end
113
-
114
- def edge_class
115
- RubyEdge
116
- end
117
-
118
- def next_id
119
- @next_id += 1
120
- end
121
- end
122
-
123
- class RubyElement
124
- include com.tinkerpop.blueprints.Element
125
-
126
- def initialize(raw_graph, element_id)
127
- @raw_graph = raw_graph
128
- @element_id = element_id
129
- @properties = {}
130
- end
131
-
132
- def getPropertyKeys
133
- @properties.keys.to_hashset
134
- end
135
-
136
- def getProperty(key)
137
- v = @properties[key.to_s]
138
- if v.is_a? String
139
- v.dup
140
- else
141
- v
142
- end
143
- end
144
-
145
- def setProperty(key, value)
146
- @properties[key.to_s] = value
147
- end
148
-
149
- def removeProperty(key)
150
- @properties.delete key.to_s
151
- end
152
-
153
- def getId
154
- @element_id
155
- end
156
-
157
- protected
158
-
159
- attr_reader :raw_graph
160
-
161
- def extract_varargs_strings(labels)
162
- if labels.first.is_a? ArrayJavaProxy
163
- labels.first.map { |l| l.to_s }
164
- else
165
- labels
166
- end
167
- end
168
- end
169
-
170
-
171
- class RubyVertex < RubyElement
172
- include com.tinkerpop.blueprints.Vertex
173
- import com.tinkerpop.blueprints.util.VerticesFromEdgesIterable
174
-
175
- def getRawVertex
176
- self
177
- end
178
-
179
- def getVertices(direction, *labels)
180
- VerticesFromEdgesIterable.new self, direction, *labels
181
- end
182
-
183
- def getEdges(direction, *labels)
184
- labels = extract_varargs_strings(labels)
185
- if direction == Pacer::Pipes::BOTH
186
- edges = raw_graph.getEdges.select do |e|
187
- ( (e.getVertex(Pacer::Pipes::IN) == self or e.getVertex(Pacer::Pipes::OUT) == self) and
188
- (labels.empty? or labels.include? e.getLabel) )
189
- end
190
- else
191
- edges = raw_graph.getEdges.select { |e| e.getVertex(direction) == self and (labels.empty? or labels.include? e.getLabel) }
192
- end
193
- Pacer::Pipes::EnumerablePipe.new edges
194
- end
195
- end
196
-
197
- class RubyEdge < RubyElement
198
- include com.tinkerpop.blueprints.Edge
199
-
200
- def initialize(raw_graph, id, out_vertex, in_vertex, label)
201
- super(raw_graph, id)
202
- @out_vertex = out_vertex
203
- @in_vertex = in_vertex
204
- @label = label.to_s
205
- end
206
-
207
- def getRawEdge
208
- self
209
- end
210
-
211
- def getLabel()
212
- @label
213
- end
214
-
215
- def getVertex(direction)
216
- if direction == Pacer::Pipes::OUT
217
- @out_vertex
218
- else
219
- @in_vertex
220
- end
221
- end
222
- end
223
- end
@@ -1,139 +0,0 @@
1
- require 'spec_helper'
2
-
3
- Run.tg :read_only do
4
- use_pacer_graphml_data :read_only
5
-
6
- describe Pacer::Transform::Join do
7
- context 'with no key or value specified' do
8
- subject { graph.v.join }
9
- its(:count) { should == 7 }
10
- specify 'each element should be a node' do
11
- subject.each do |group|
12
- group[:key].should be_a Pacer::Vertex
13
- group.property_keys.to_a.should == ['key']
14
- end
15
- end
16
- end
17
-
18
- context 'with key_route only' do
19
- subject { graph.v.join(:key) { |r| r[:type] } }
20
-
21
- its(:count) { should == 7 }
22
- its(:to_a) { should_not be_empty }
23
- specify 'each result should have one value' do
24
- subject.each do |group|
25
- group[:key].should be_a String
26
- group.property_keys.to_a.should == ['key']
27
- end
28
- end
29
- end
30
-
31
- context 'with key_route and value route' do
32
- let(:route) { graph.v.join(:key) { |r| r[:type] }.join }
33
- subject { route }
34
-
35
- specify 'each result should reflect an element' do
36
- subject.each.zip(graph.v.to_a) do |group, e|
37
- group[:key].should == e[:type]
38
- group.property_keys.to_set.should == Set['key', 'values']
39
- group[:values].last.element_id.should == e.element_id
40
- end
41
- end
42
-
43
- context '#multigraph' do
44
- subject { route.multigraph }
45
- it { should be_a Pacer::PacerGraph }
46
- its(:blueprints_graph) { should be_a Pacer::MultiGraph }
47
-
48
- its('v.count') { should == 3 }
49
-
50
-
51
- context 'person' do
52
- subject { route.multigraph.vertex 'person' }
53
- it 'should hove 2 values' do
54
- subject[:values].length.should == 2
55
- end
56
- it { subject[:values].should == graph.v(:type => 'person').to_a }
57
- end
58
-
59
- context 'project' do
60
- subject { route.multigraph.vertex 'project' }
61
- it 'should hove 2 values' do
62
- subject[:values].length.should == 4
63
- end
64
- it { subject[:values].should == graph.v(:type => 'project').to_a }
65
- end
66
-
67
- context 'reduced to a count' do
68
- subject do
69
- route.multigraph.v.reduce({}) do |h, v|
70
- h[v.element_id] = v[:values].count
71
- h
72
- end
73
- end
74
- specify 'it should have a count for values' do
75
- subject['project'].should == 4
76
- subject['person'].should == 2
77
- subject['group'].should == 1
78
- end
79
- end
80
-
81
- context 'reduced to a string' do
82
- subject do
83
- route.multigraph.v.reduce({}) do |h, v|
84
- h[v.element_id] = v[:values].map { |v| v[:name] }.join ', '
85
- h
86
- end
87
- end
88
- specify do
89
- subject['project'].should == 'blueprints, pipes, pacer, gremlin'
90
- subject['person'].should == 'pangloss, okram'
91
- subject['group'].should == 'tinkerpop'
92
- end
93
- end
94
- end
95
- end
96
-
97
- context 'with a key block that returns a literal value' do
98
- subject { graph.v.join { |r| r[:type] }.key { |r| r[:type].length } }
99
- its(:count) { should == 7 }
100
- specify 'each value should have a numeric key' do
101
- subject.each do |v|
102
- v[:key].should == v.element_id
103
- v[:key].should == v[:values].first.length
104
- end
105
- end
106
- end
107
-
108
- context 'with values_maps' do
109
- let(:counted_group) do
110
- graph.v.join(:count) { |r| r.out_e.counted.cap }.
111
- join(:out_e, &:out_e).
112
- key { |r| r[:type] }
113
- end
114
- subject do
115
- counted_group.multigraph
116
- end
117
- its('v.count') { should == 3 }
118
- specify { counted_group.count.should == 7 }
119
- specify 'combine(:count) should group the counts in a hash' do
120
- hash = Hash[subject.v[[:key, :count]].to_a]
121
- hash.should == {"project"=>[0, 1, 3, 2], "person"=>[1, 3], "group"=>[4]}
122
- end
123
-
124
- specify 'reduce summarizes edge labels for each type' do
125
- result = Hash[subject.v.map { |v| [v.element_id, v[:out_e].group_count { |e| e.label }] }.to_a]
126
- result.should == {"project" => {"uses" => 5, "modelled_on" => 1},
127
- "person" => {"wrote" => 4},
128
- "group" => {"projects" => 3, "member" => 1}}
129
- end
130
-
131
- its(:blueprints_graph) { should be_a Pacer::MultiGraph }
132
-
133
- specify do
134
- counted_group.inspect.should ==
135
- "#<GraphV -> V-Join(#<V -> Obj(type) -> decode>: {:count=>#<V -> outE -> Obj-Cap(E-Counted)>, :out_e=>#<V -> outE>})>"
136
- end
137
- end
138
- end
139
- end