flockdb 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/VERSION +1 -1
  2. data/flockdb.gemspec +1 -1
  3. data/lib/flock/mock_service.rb +109 -91
  4. metadata +2 -2
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.1
1
+ 0.3.2
data/flockdb.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{flockdb}
8
- s.version = "0.3.1"
8
+ s.version = "0.3.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Matt Freels", "Rael Dornfest", "Nick Kallen"]
@@ -2,10 +2,17 @@ module Flock
2
2
  module MockService
3
3
  extend self
4
4
 
5
+ EXEC_OPS = {
6
+ Edges::ExecuteOperationType::Add => :add,
7
+ Edges::ExecuteOperationType::Remove => :remove,
8
+ Edges::ExecuteOperationType::Archive => :archive
9
+ }
10
+
5
11
  attr_accessor :timeout, :fixtures
6
12
 
7
13
  def clear
8
- @sources = @destinations = nil
14
+ @forward_edges = nil
15
+ @backward_edges = nil
9
16
  end
10
17
 
11
18
  def load(fixtures = nil)
@@ -14,71 +21,28 @@ module Flock
14
21
  clear
15
22
 
16
23
  fixtures.each do |fixture|
17
- file, graph_id, source, destination = fixture.values_at(:file, :graph, :source, :destination)
24
+ file, graph, source, dest = fixture.values_at(:file, :graph, :source, :destination)
18
25
 
19
- fixtures_data = YAML::load(ERB.new(File.open(file, 'r').read).result(binding)).sort
20
- fixtures_data.each do |key, value|
21
- sources[[value[destination], graph_id]] << value[source]
22
- destinations[[value[source], graph_id]] << value[destination]
26
+ YAML::load(ERB.new(File.open(file, 'r').read).result(binding)).sort.each do |key, row|
27
+ add(row[source], graph, row[dest])
23
28
  end
24
29
  end
25
30
  end
26
31
 
27
32
  def inspect
28
- "Flock::MockService: " + @sources.inspect + " - " + @destinations.inspect
33
+ "Flock::MockService: ( #{@forward_edges.inspect} - #{@backward_edges.inspect} )"
29
34
  end
30
35
 
31
36
  def execute(operations)
32
37
  operations = operations.operations
33
38
  operations.each do |operation|
34
39
  term = operation.term
35
- backward_data_source, forward_data_source = term.is_forward ? [sources, destinations] : [destinations, sources]
36
- backward_archived_data_source, forward_archived_data_source = term.is_forward ? [archived_sources, archived_destinations] : [archived_destinations, archived_sources]
37
- source_id, graph_id = term.source_id, term.graph_id
38
- destination_ids = term.destination_ids && term.destination_ids.unpack("Q*")
39
- case operation.operation_type
40
- when Edges::ExecuteOperationType::Add
41
- if destination_ids.nil?
42
- backward_archived_data_source.delete([source_id, graph_id]).to_a.each do |n|
43
- (forward_data_source[[n, graph_id]] << source_id).uniq!
44
- (backward_data_source[[source_id, graph_id]] << n).uniq!
45
- forward_archived_data_source[[n, graph_id]].delete(source_id)
46
- end
47
- else
48
- destination_ids.each do |destination_id|
49
- backward_data_source[[destination_id, graph_id]] << source_id
50
- forward_data_source[[source_id, graph_id]] << destination_id
51
- end
52
- end
53
- when Edges::ExecuteOperationType::Remove
54
- if destination_ids.nil?
55
- backward_data_source.delete([source_id, graph_id]).to_a.each do |n|
56
- forward_data_source[[n, graph_id]].delete(source_id)
57
- end
58
- else
59
- destination_ids.each do |destination_id|
60
- backward_data_source[[destination_id, graph_id]].delete(source_id)
61
- forward_data_source[[source_id, graph_id]].delete(destination_id)
62
- end
63
- end
64
- when Edges::ExecuteOperationType::Archive
65
- if destination_ids.nil?
66
- backward_data_source.delete([source_id, graph_id]).to_a.each do |n|
67
- forward_archived_data_source[[n, graph_id]] << source_id
68
- backward_archived_data_source[[source_id, graph_id]] << n
69
- forward_data_source[[n, graph_id]].delete(source_id)
70
- end
71
- else
72
- destination_ids.each do |destination_id|
73
- if backward_data_source[[destination_id, graph_id]].delete(source_id)
74
- backward_archived_data_source[[destination_id, graph_id]] << source_id
75
- end
76
- if forward_data_source[[source_id, graph_id]].delete(destination_id)
77
- forward_archived_data_source[[source_id, graph_id]] << destination_id
78
- end
79
- end
80
- end
81
- end
40
+ graph, source = term.graph_id, term.source_id
41
+ dest = term.destination_ids && term.destination_ids.unpack('Q*')
42
+
43
+ source, dest = dest, source unless term.is_forward
44
+
45
+ self.send(EXEC_OPS[operation.operation_type], source, graph, dest)
82
46
  end
83
47
  end
84
48
 
@@ -86,8 +50,8 @@ module Flock
86
50
  iterate(select_query(select_operations), page)
87
51
  end
88
52
 
89
- def contains(source_id, graph_id, destination_id)
90
- !!destinations[[source_id, graph_id]].detect {|i| i == destination_id}
53
+ def contains(source, graph, dest)
54
+ forward_edges[graph][:normal][source].include?(dest)
91
55
  end
92
56
 
93
57
  def count(select_operations)
@@ -95,18 +59,16 @@ module Flock
95
59
  end
96
60
 
97
61
  private
62
+
98
63
  def select_query(select_operations)
99
64
  stack = []
100
65
  select_operations.each do |select_operation|
101
66
  case select_operation.operation_type
102
67
  when Edges::SelectOperationType::SimpleQuery
103
- query_term = select_operation.term
104
- data_source = query_term.is_forward ? destinations : sources
105
- data = data_source[[query_term.source_id, query_term.graph_id]]
106
- if query_term.destination_ids
107
- data &= query_term.destination_ids.unpack("Q*")
108
- end
109
- stack.push(data)
68
+ term = select_operation.term
69
+ source = term.is_forward ? forward_edges : backward_edges
70
+ data = source[term.graph_id][:normal][term.source_id]
71
+ stack.push(term.destination_ids ? (term.destination_ids.unpack('Q*') & data) : data)
110
72
  when Edges::SelectOperationType::Intersection
111
73
  stack.push(stack.pop & stack.pop)
112
74
  when Edges::SelectOperationType::Union
@@ -120,16 +82,15 @@ module Flock
120
82
  stack.pop
121
83
  end
122
84
 
123
- private
124
-
125
85
  def iterate(data, page)
126
86
  return empty_result if page.cursor == Flock::CursorEnd
127
87
 
128
- start = if page.cursor < Flock::CursorStart
129
- [-page.cursor - page.count, 0].max
130
- else
131
- page.cursor == Flock::CursorStart ? 0 : page.cursor
132
- end
88
+ start =
89
+ if page.cursor < Flock::CursorStart
90
+ [-page.cursor - page.count, 0].max
91
+ else
92
+ page.cursor == Flock::CursorStart ? 0 : page.cursor
93
+ end
133
94
  rv = data.slice(start, page.count)
134
95
  next_cursor = (start + page.count >= data.size) ? Flock::CursorEnd : start + page.count
135
96
  prev_cursor = (start <= 0) ? Flock::CursorEnd : -start
@@ -142,36 +103,93 @@ module Flock
142
103
  end
143
104
 
144
105
  def empty_result
145
- @empty_result ||= begin
146
- empty_result = Flock::Results.new
147
- empty_result.ids = ""
148
- empty_result.next_cursor = Flock::CursorEnd
149
- empty_result.prev_cursor = Flock::CursorEnd
150
- empty_result
151
- end
152
- end
153
-
154
- def sources
155
- @sources ||= Hash.new do |h, k|
156
- h[k] = []
106
+ @empty_result ||=
107
+ begin
108
+ empty_result = Flock::Results.new
109
+ empty_result.ids = ""
110
+ empty_result.next_cursor = Flock::CursorEnd
111
+ empty_result.prev_cursor = Flock::CursorEnd
112
+ empty_result
113
+ end
114
+ end
115
+
116
+
117
+ [:forward_edges, :backward_edges].each do |name|
118
+ class_eval("def #{name}; @#{name} ||= new_edges_hash end")
119
+ end
120
+
121
+ def new_edges_hash
122
+ Hash.new { |h,k| h[k] = Hash.new { |h,k| h[k] = Hash.new { |h2,k2| h2[k2] = [] } } }
123
+ end
124
+
125
+ def add_row(store, source, dest)
126
+ (store[source] << dest).uniq!
127
+ end
128
+
129
+ def add_edge(source, graph, dest, state)
130
+ add_row(forward_edges[graph][state], source, dest)
131
+ add_row(backward_edges[graph][state], dest, source)
132
+ [source, graph, dest]
133
+ end
134
+
135
+ def remove_row(store, source, dest)
136
+ store[source].delete(dest).tap do
137
+ store.delete(source) if store[source].empty?
157
138
  end
158
139
  end
159
140
 
160
- def destinations
161
- @destinations ||= Hash.new do |h, k|
162
- h[k] = []
141
+ def remove_edge(source, graph, dest, state)
142
+ forward = remove_row(forward_edges[graph][state], source, dest)
143
+ backward = remove_row(backward_edges[graph][state], dest, source)
144
+
145
+ [source, graph, dest] if forward and backward
146
+ end
147
+
148
+ def remove_node(source, graph, dest, state)
149
+ raise unless source or dest
150
+
151
+ sources, dests = Array(source), Array(dest)
152
+
153
+ sources = dests.map{|dest| backward_edges[graph][state][dest] }.inject([]) {|a,b| a.concat b } if sources.empty?
154
+ dests = sources.map{|source| forward_edges[graph][state][source] }.inject([]) {|a,b| a.concat b } if dests.empty?
155
+
156
+ [].tap do |deleted|
157
+ sources.each {|s| dests.each {|d| deleted << remove_edge(s, graph, d, state) } }
158
+ end.compact
159
+ end
160
+
161
+ def unarchive_node(source, graph, dest)
162
+ remove_node(source, graph, dest, :archived).tap do |deleted|
163
+ deleted.each {|d| add_edge(source, graph, dest, :normal) }
163
164
  end
164
165
  end
165
166
 
166
- def archived_sources
167
- @archived_sources ||= Hash.new do |h, k|
168
- h[k] = []
167
+ # actual graph helpers
168
+
169
+ def add(source, graph, dest)
170
+ if source.nil? or dest.nil?
171
+ unarchive_node(source, graph, dest)
172
+ else
173
+ sources, dests = Array(source), Array(dest)
174
+
175
+ sources.each do |s|
176
+ dests.each do |d|
177
+ add_edge(s, graph, d, :normal)
178
+ remove_edge(s, graph, d, :archived)
179
+ end
180
+ end
169
181
  end
170
182
  end
171
183
 
172
- def archived_destinations
173
- @archived_destinations ||= Hash.new do |h, k|
174
- h[k] = []
184
+ def remove(source, graph, dest)
185
+ remove_node(source, graph, dest, :archived)
186
+ remove_node(source, graph, dest, :normal)
187
+ end
188
+
189
+ def archive(source, graph, dest)
190
+ remove_node(source, graph, dest, :normal).tap do |deleted|
191
+ p deleted
192
+ deleted.each {|source, graph, dest| add_edge(source, graph, dest, :archived) }
175
193
  end
176
194
  end
177
195
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 3
8
- - 1
9
- version: 0.3.1
8
+ - 2
9
+ version: 0.3.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - Matt Freels