pacer 1.3.2-java → 1.3.3-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 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