perobs 4.4.0 → 4.6.0
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 +4 -4
- data/.github/workflows/ruby.yml +38 -0
- data/.gitignore +0 -1
- data/Gemfile +1 -0
- data/lib/perobs/Array.rb +25 -30
- data/lib/perobs/BigArray.rb +16 -29
- data/lib/perobs/BigArrayNode.rb +87 -99
- data/lib/perobs/BigHash.rb +14 -24
- data/lib/perobs/BigTree.rb +7 -17
- data/lib/perobs/BigTreeNode.rb +101 -122
- data/lib/perobs/Cache.rb +13 -0
- data/lib/perobs/ClassMap.rb +6 -0
- data/lib/perobs/DataBase.rb +19 -14
- data/lib/perobs/IDList.rb +2 -2
- data/lib/perobs/Log.rb +5 -0
- data/lib/perobs/Store.rb +17 -3
- data/lib/perobs/version.rb +1 -1
- data/perobs.gemspec +3 -2
- data/test/Array_spec.rb +55 -59
- data/test/BTreeDB_spec.rb +5 -1
- data/test/BigTreeNode_spec.rb +5 -8
- data/test/LegacyDBs/version_4.1/class_map.json +1 -0
- data/test/LegacyDBs/version_4.1/config.json +1 -0
- data/test/LegacyDBs/version_4.1/database.blobs +0 -0
- data/test/LegacyDBs/version_4.1/database_spaces.blobs +0 -0
- data/test/LegacyDBs/version_4.1/index.blobs +0 -0
- data/test/LegacyDBs/version_4.1/log +5 -0
- data/test/LegacyDBs/version_4.1/version +1 -0
- data/test/spec_helper.rb +1 -1
- metadata +38 -9
data/lib/perobs/BigArrayNode.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# # frozen_string_literal: true
|
|
2
2
|
#
|
|
3
3
|
# = BigArrayNode.rb -- Persistent Ruby Object Store
|
|
4
4
|
#
|
|
@@ -26,11 +26,10 @@
|
|
|
26
26
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
27
27
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
require_relative 'Object'
|
|
30
|
+
require_relative 'Array'
|
|
31
31
|
|
|
32
32
|
module PEROBS
|
|
33
|
-
|
|
34
33
|
# The BigArrayNode class provides the BTree nodes for the BigArray objects.
|
|
35
34
|
# A node can either be a branch node or a leaf node. Branch nodes don't
|
|
36
35
|
# store values, only offsets and references to child nodes. Leaf nodes don't
|
|
@@ -57,9 +56,8 @@ module PEROBS
|
|
|
57
56
|
# Index 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
|
58
57
|
#
|
|
59
58
|
class BigArrayNode < PEROBS::Object
|
|
60
|
-
|
|
61
59
|
attr_persist :tree, :parent, :offsets, :values, :children,
|
|
62
|
-
|
|
60
|
+
:prev_sibling, :next_sibling
|
|
63
61
|
|
|
64
62
|
# Internal constructor. Use Store.new(BigArrayNode, ...) instead.
|
|
65
63
|
# @param p [Handle]
|
|
@@ -118,16 +116,13 @@ module PEROBS
|
|
|
118
116
|
count = 0
|
|
119
117
|
node = self
|
|
120
118
|
while node
|
|
121
|
-
if node.is_leaf?
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
node = node.children.last
|
|
126
|
-
end
|
|
119
|
+
return count + node.values.size if node.is_leaf?
|
|
120
|
+
|
|
121
|
+
count += node.offsets.last
|
|
122
|
+
node = node.children.last
|
|
127
123
|
end
|
|
128
124
|
end
|
|
129
125
|
|
|
130
|
-
|
|
131
126
|
# Set the given value at the given index.
|
|
132
127
|
# @param index [Integer] Position to insert at
|
|
133
128
|
# @param value [Integer] value to insert
|
|
@@ -135,27 +130,29 @@ module PEROBS
|
|
|
135
130
|
node = self
|
|
136
131
|
|
|
137
132
|
# Traverse the tree to find the right node to add or replace the value.
|
|
138
|
-
|
|
133
|
+
idx = index
|
|
134
|
+
while node
|
|
139
135
|
# Once we have reached a leaf node we can insert or replace the value.
|
|
140
136
|
if node.is_leaf?
|
|
141
|
-
if
|
|
142
|
-
node.fatal "Set index (#{index}) larger than values array "
|
|
143
|
-
|
|
137
|
+
if idx >= node.values.size
|
|
138
|
+
node.fatal "Set index (#{index}) larger than values array " \
|
|
139
|
+
"(#{idx} >= #{node.values.size})."
|
|
144
140
|
end
|
|
145
|
-
node.values[
|
|
141
|
+
node.values[idx] = value
|
|
146
142
|
return
|
|
147
143
|
else
|
|
148
144
|
# Descend into the right child node to add the value to.
|
|
149
|
-
cidx = node.search_child_index(
|
|
150
|
-
if (
|
|
151
|
-
node.fatal "
|
|
145
|
+
cidx = node.search_child_index(idx)
|
|
146
|
+
if (idx -= node.offsets[cidx]).negative?
|
|
147
|
+
node.fatal "Idx (#{idx}) became negative while looking for " \
|
|
148
|
+
"index #{index}."
|
|
152
149
|
end
|
|
153
150
|
node = node.children[cidx]
|
|
154
151
|
end
|
|
155
152
|
end
|
|
156
153
|
|
|
157
|
-
node.fatal
|
|
158
|
-
|
|
154
|
+
node.fatal 'Could not find proper node to set the value while ' \
|
|
155
|
+
"looking for index #{index}."
|
|
159
156
|
end
|
|
160
157
|
|
|
161
158
|
# Insert the given value at the given index. All following values will be
|
|
@@ -167,7 +164,7 @@ module PEROBS
|
|
|
167
164
|
cidx = nil
|
|
168
165
|
|
|
169
166
|
# Traverse the tree to find the right node to add or replace the value.
|
|
170
|
-
while node
|
|
167
|
+
while node
|
|
171
168
|
# All nodes that we find on the way that are full will be split into
|
|
172
169
|
# two half-full nodes.
|
|
173
170
|
if node.size >= @tree.node_size
|
|
@@ -180,20 +177,20 @@ module PEROBS
|
|
|
180
177
|
# Once we have reached a leaf node we can insert or replace the value.
|
|
181
178
|
if node.is_leaf?
|
|
182
179
|
node.values.insert(index, value)
|
|
183
|
-
node.parent
|
|
180
|
+
node.parent&.adjust_offsets(node, 1)
|
|
184
181
|
return
|
|
185
182
|
else
|
|
186
183
|
# Descend into the right child node to add the value to.
|
|
187
184
|
cidx = node.search_child_index(index)
|
|
188
|
-
if (index -= node.offsets[cidx])
|
|
185
|
+
if (index -= node.offsets[cidx]).negative?
|
|
189
186
|
node.fatal "Index (#{index}) became negative"
|
|
190
187
|
end
|
|
191
188
|
node = node.children[cidx]
|
|
192
189
|
end
|
|
193
190
|
end
|
|
194
191
|
|
|
195
|
-
node.fatal
|
|
196
|
-
|
|
192
|
+
node.fatal 'Could not find proper node to insert the value while ' \
|
|
193
|
+
"looking for index #{index}"
|
|
197
194
|
end
|
|
198
195
|
|
|
199
196
|
# Return the value that matches the given key or return nil if they key is
|
|
@@ -204,23 +201,21 @@ module PEROBS
|
|
|
204
201
|
node = self
|
|
205
202
|
|
|
206
203
|
# Traverse the tree to find the right node to add or replace the value.
|
|
207
|
-
while node
|
|
204
|
+
while node
|
|
208
205
|
# Once we have reached a leaf node we can insert or replace the value.
|
|
209
|
-
if node.is_leaf?
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
node.fatal "Index (#{index}) became negative"
|
|
217
|
-
end
|
|
218
|
-
node = node.children[cidx]
|
|
206
|
+
return node.values[index] if node.is_leaf?
|
|
207
|
+
|
|
208
|
+
# Descend into the right child node to add the value to.
|
|
209
|
+
cidx = (node.offsets.bsearch_index { |o| o > index } ||
|
|
210
|
+
node.offsets.length) - 1
|
|
211
|
+
if (index -= node.offsets[cidx]).negative?
|
|
212
|
+
node.fatal "Index (#{index}) became negative"
|
|
219
213
|
end
|
|
214
|
+
node = node.children[cidx]
|
|
220
215
|
end
|
|
221
216
|
|
|
222
|
-
PEROBS.log.fatal
|
|
223
|
-
|
|
217
|
+
PEROBS.log.fatal 'Could not find proper node to get from while ' \
|
|
218
|
+
"looking for index #{index}"
|
|
224
219
|
end
|
|
225
220
|
|
|
226
221
|
# Delete the element at the specified index, returning that element, or
|
|
@@ -231,14 +226,12 @@ module PEROBS
|
|
|
231
226
|
node = self
|
|
232
227
|
deleted_value = nil
|
|
233
228
|
|
|
234
|
-
while node
|
|
229
|
+
while node
|
|
235
230
|
if node.is_leaf?
|
|
236
231
|
deleted_value = node.values.delete_at(index)
|
|
237
232
|
if node.parent
|
|
238
233
|
node.parent.adjust_offsets(node, -1)
|
|
239
|
-
if node.size < min_size
|
|
240
|
-
node.parent.consolidate_child_nodes(node)
|
|
241
|
-
end
|
|
234
|
+
node.parent.consolidate_child_nodes(node) if node.size < min_size
|
|
242
235
|
end
|
|
243
236
|
|
|
244
237
|
return deleted_value
|
|
@@ -246,15 +239,15 @@ module PEROBS
|
|
|
246
239
|
# Descend into the right child node to add the value to.
|
|
247
240
|
cidx = (node.offsets.bsearch_index { |o| o > index } ||
|
|
248
241
|
node.offsets.length) - 1
|
|
249
|
-
if (index -= node.offsets[cidx])
|
|
242
|
+
if (index -= node.offsets[cidx]).negative?
|
|
250
243
|
node.fatal "Index (#{index}) became negative"
|
|
251
244
|
end
|
|
252
245
|
node = node.children[cidx]
|
|
253
246
|
end
|
|
254
247
|
end
|
|
255
248
|
|
|
256
|
-
PEROBS.log.fatal
|
|
257
|
-
|
|
249
|
+
PEROBS.log.fatal 'Could not find proper node to delete from while ' \
|
|
250
|
+
"looking for index #{index}"
|
|
258
251
|
end
|
|
259
252
|
|
|
260
253
|
# Iterate over all the values of the node.
|
|
@@ -285,13 +278,13 @@ module PEROBS
|
|
|
285
278
|
branch_depth = nil
|
|
286
279
|
|
|
287
280
|
traverse do |node, position, stack|
|
|
288
|
-
if position
|
|
281
|
+
if position.zero?
|
|
289
282
|
# Nodes should have between min_size() and
|
|
290
283
|
# @tree.node_size children or values. Only the root node may have
|
|
291
284
|
# less.
|
|
292
285
|
if node.size > @tree.node_size
|
|
293
|
-
node.error "BigArray node #{node._id} is too large. It has "
|
|
294
|
-
|
|
286
|
+
node.error "BigArray node #{node._id} is too large. It has " \
|
|
287
|
+
"#{node.size} nodes instead of max. #{@tree.node_size}."
|
|
295
288
|
return false
|
|
296
289
|
end
|
|
297
290
|
if node.parent && node.size < min_size
|
|
@@ -303,7 +296,7 @@ module PEROBS
|
|
|
303
296
|
# All leaf nodes must have same distance from root node.
|
|
304
297
|
if branch_depth
|
|
305
298
|
unless branch_depth == stack.size
|
|
306
|
-
node.error
|
|
299
|
+
node.error 'All leaf nodes must have same distance from root'
|
|
307
300
|
return false
|
|
308
301
|
end
|
|
309
302
|
else
|
|
@@ -313,24 +306,24 @@ module PEROBS
|
|
|
313
306
|
return false unless node.check_leaf_node_links
|
|
314
307
|
|
|
315
308
|
if node.children
|
|
316
|
-
node.error
|
|
309
|
+
node.error 'children must be nil for a leaf node'
|
|
317
310
|
return false
|
|
318
311
|
end
|
|
319
312
|
else
|
|
320
313
|
unless node.children.size == node.offsets.size
|
|
321
|
-
node.error "Offset count (#{node.offsets.size}) must be equal "
|
|
322
|
-
|
|
323
|
-
|
|
314
|
+
node.error "Offset count (#{node.offsets.size}) must be equal " \
|
|
315
|
+
"to children count (#{node.children.size})"
|
|
316
|
+
return false
|
|
324
317
|
end
|
|
325
318
|
|
|
326
319
|
if node.values
|
|
327
|
-
node.error
|
|
320
|
+
node.error 'values must be nil for a branch node'
|
|
328
321
|
return false
|
|
329
322
|
end
|
|
330
323
|
|
|
331
324
|
unless @prev_sibling.nil? && @next_sibling.nil?
|
|
332
|
-
node.error
|
|
333
|
-
|
|
325
|
+
node.error 'prev_sibling and next_sibling must be nil for ' \
|
|
326
|
+
'branch nodes'
|
|
334
327
|
end
|
|
335
328
|
|
|
336
329
|
return false unless node.check_offsets
|
|
@@ -341,12 +334,10 @@ module PEROBS
|
|
|
341
334
|
# These checks are done after we have completed the respective child
|
|
342
335
|
# node with index 'position - 1'.
|
|
343
336
|
index = position - 1
|
|
344
|
-
if node.is_leaf?
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
node.values[index])
|
|
349
|
-
end
|
|
337
|
+
if node.is_leaf? && block_given?
|
|
338
|
+
# If a block was given, call this block with the key and value.
|
|
339
|
+
return false unless yield(node.first_index + index,
|
|
340
|
+
node.values[index])
|
|
350
341
|
end
|
|
351
342
|
end
|
|
352
343
|
end
|
|
@@ -357,25 +348,25 @@ module PEROBS
|
|
|
357
348
|
def check_leaf_node_links
|
|
358
349
|
if @prev_sibling.nil?
|
|
359
350
|
if @tree.first_leaf != self
|
|
360
|
-
error "Leaf node #{@_id} has no previous sibling "
|
|
361
|
-
|
|
351
|
+
error "Leaf node #{@_id} has no previous sibling " \
|
|
352
|
+
'but is not the first leaf of the tree'
|
|
362
353
|
return false
|
|
363
354
|
end
|
|
364
355
|
elsif @prev_sibling.next_sibling != self
|
|
365
|
-
error
|
|
366
|
-
|
|
356
|
+
error 'next_sibling of previous sibling does not point to ' \
|
|
357
|
+
'this node'
|
|
367
358
|
return false
|
|
368
359
|
end
|
|
369
360
|
|
|
370
361
|
if @next_sibling.nil?
|
|
371
362
|
if @tree.last_leaf != self
|
|
372
|
-
error "Leaf node #{@_id} has no next sibling "
|
|
373
|
-
|
|
363
|
+
error "Leaf node #{@_id} has no next sibling " \
|
|
364
|
+
'but is not the last leaf of the tree'
|
|
374
365
|
return false
|
|
375
366
|
end
|
|
376
367
|
elsif @next_sibling.prev_sibling != self
|
|
377
|
-
error
|
|
378
|
-
|
|
368
|
+
error 'previous_sibling of next sibling does not point to ' \
|
|
369
|
+
'this node'
|
|
379
370
|
return false
|
|
380
371
|
end
|
|
381
372
|
|
|
@@ -392,16 +383,16 @@ module PEROBS
|
|
|
392
383
|
|
|
393
384
|
last_offset = nil
|
|
394
385
|
@offsets.each_with_index do |offset, i|
|
|
395
|
-
if i
|
|
386
|
+
if i.positive?
|
|
396
387
|
if offset < last_offset
|
|
397
|
-
error
|
|
398
|
-
|
|
388
|
+
error 'Offsets are not strictly monotoneously ' \
|
|
389
|
+
"increasing: #{@offsets.inspect}"
|
|
399
390
|
return false
|
|
400
391
|
end
|
|
401
392
|
expected_offset = last_offset + @children[i - 1].values_count
|
|
402
393
|
if offset != expected_offset
|
|
403
|
-
error "Offset #{i} must be #{expected_offset} "
|
|
404
|
-
|
|
394
|
+
error "Offset #{i} must be #{expected_offset} " \
|
|
395
|
+
"but is #{offset}."
|
|
405
396
|
return false
|
|
406
397
|
end
|
|
407
398
|
end
|
|
@@ -420,20 +411,20 @@ module PEROBS
|
|
|
420
411
|
|
|
421
412
|
@children.each_with_index do |child, i|
|
|
422
413
|
unless child.is_a?(BigArrayNode)
|
|
423
|
-
error "Child #{@_id} is of class #{child.class} "
|
|
424
|
-
|
|
414
|
+
error "Child #{@_id} is of class #{child.class} " \
|
|
415
|
+
'instead of BigArrayNode'
|
|
425
416
|
return false
|
|
426
417
|
end
|
|
427
418
|
|
|
428
419
|
unless child.parent.is_a?(BigArrayNode)
|
|
429
|
-
error "Parent reference of child #{i} is of class "
|
|
430
|
-
|
|
420
|
+
error "Parent reference of child #{i} is of class " \
|
|
421
|
+
"#{child.class} instead of BigArrayNode"
|
|
431
422
|
return false
|
|
432
423
|
end
|
|
433
424
|
|
|
434
425
|
if child.parent != self
|
|
435
|
-
error "Child node #{child._id} has wrong parent "
|
|
436
|
-
|
|
426
|
+
error "Child node #{child._id} has wrong parent " \
|
|
427
|
+
"#{child.parent._id}. It should be #{@_id}."
|
|
437
428
|
return false
|
|
438
429
|
end
|
|
439
430
|
|
|
@@ -448,8 +439,8 @@ module PEROBS
|
|
|
448
439
|
end
|
|
449
440
|
|
|
450
441
|
unless child.parent == self
|
|
451
|
-
error "Child #{i} does not have parent pointing "
|
|
452
|
-
|
|
442
|
+
error "Child #{i} does not have parent pointing " \
|
|
443
|
+
'to this node'
|
|
453
444
|
return false
|
|
454
445
|
end
|
|
455
446
|
end
|
|
@@ -462,11 +453,11 @@ module PEROBS
|
|
|
462
453
|
str = ''
|
|
463
454
|
|
|
464
455
|
traverse do |node, position, stack|
|
|
465
|
-
if position
|
|
456
|
+
if position.zero?
|
|
466
457
|
begin
|
|
467
|
-
str += "#{node.parent ? node.parent.tree_prefix + ' +' : 'o'}"
|
|
468
|
-
|
|
469
|
-
|
|
458
|
+
str += "#{node.parent ? node.parent.tree_prefix + ' +' : 'o'}" \
|
|
459
|
+
"#{node.tree_branch_mark}-" \
|
|
460
|
+
"#{node.empty? ? '--' : 'v-'}#{node.tree_summary}\n"
|
|
470
461
|
rescue => e
|
|
471
462
|
str += "@@@@@@@@@@: #{e.message}\n"
|
|
472
463
|
end
|
|
@@ -474,11 +465,11 @@ module PEROBS
|
|
|
474
465
|
begin
|
|
475
466
|
if node.is_leaf?
|
|
476
467
|
if position <= node.size
|
|
477
|
-
str += "#{node.tree_prefix} "
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
468
|
+
str += "#{node.tree_prefix} " \
|
|
469
|
+
"#{position == node.size ? '-' : '|'} " \
|
|
470
|
+
"[ #{node.value_index(position - 1)}: " \
|
|
471
|
+
"#{node.values[position - 1].nil? ?
|
|
472
|
+
'nil' : node.values[position - 1]} ]\n"
|
|
482
473
|
end
|
|
483
474
|
end
|
|
484
475
|
rescue => e
|
|
@@ -811,7 +802,7 @@ module PEROBS
|
|
|
811
802
|
|
|
812
803
|
# Print and log an error message for the node.
|
|
813
804
|
def fatal(msg)
|
|
814
|
-
msg = "Fatal error in BigArray node @#{@_id}: #{msg}\n"
|
|
805
|
+
msg = "Fatal error in BigArray node @#{@_id}: #{msg}\n"
|
|
815
806
|
$stderr.puts msg
|
|
816
807
|
PEROBS.log.fatal msg
|
|
817
808
|
end
|
|
@@ -995,8 +986,5 @@ module PEROBS
|
|
|
995
986
|
@parent.consolidate_child_nodes(self)
|
|
996
987
|
end
|
|
997
988
|
end
|
|
998
|
-
|
|
999
989
|
end
|
|
1000
|
-
|
|
1001
990
|
end
|
|
1002
|
-
|
data/lib/perobs/BigHash.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# # frozen_string_literal: true
|
|
2
2
|
#
|
|
3
3
|
# = BigHash.rb -- Persistent Ruby Object Store
|
|
4
4
|
#
|
|
@@ -31,7 +31,6 @@ require 'perobs/Array'
|
|
|
31
31
|
require 'perobs/FNV_Hash_1a_64'
|
|
32
32
|
|
|
33
33
|
module PEROBS
|
|
34
|
-
|
|
35
34
|
# The BigHash is similar to the Hash object in that it provides a simple
|
|
36
35
|
# hash functionality. The difference is that this class scales to much
|
|
37
36
|
# larger data sets essentially limited to the amount of space available on
|
|
@@ -40,7 +39,6 @@ module PEROBS
|
|
|
40
39
|
# subset of the methods provided by the native Hash class that make sense
|
|
41
40
|
# for giant data sets.
|
|
42
41
|
class BigHash < PEROBS::Object
|
|
43
|
-
|
|
44
42
|
# Internally this class uses BigTree to store the values by the hashed
|
|
45
43
|
# key. We are using a 64 bit hash space so collisions are fairly unlikely
|
|
46
44
|
# but not impossible. Therefor we have to store the originial key with the
|
|
@@ -52,7 +50,6 @@ module PEROBS
|
|
|
52
50
|
# hashed key in a Collisions object instead of storing the Entry
|
|
53
51
|
# directly in the BigTree.
|
|
54
52
|
class Entry < PEROBS::Object
|
|
55
|
-
|
|
56
53
|
attr_persist :key, :value
|
|
57
54
|
|
|
58
55
|
def initialize(p, key, value)
|
|
@@ -60,7 +57,6 @@ module PEROBS
|
|
|
60
57
|
self.key = key
|
|
61
58
|
self.value = value
|
|
62
59
|
end
|
|
63
|
-
|
|
64
60
|
end
|
|
65
61
|
|
|
66
62
|
# Since the BigHash can also store PEROBS::Array values we need to
|
|
@@ -78,8 +74,7 @@ module PEROBS
|
|
|
78
74
|
self.btree = @store.new(PEROBS::BigTree)
|
|
79
75
|
end
|
|
80
76
|
|
|
81
|
-
def restore
|
|
82
|
-
end
|
|
77
|
+
def restore; end
|
|
83
78
|
|
|
84
79
|
# Insert a value that is associated with the given key. If a value for
|
|
85
80
|
# this key already exists, the value will be overwritten with the newly
|
|
@@ -139,8 +134,8 @@ module PEROBS
|
|
|
139
134
|
entry.each do |ae|
|
|
140
135
|
return ae.value if ae.key == key
|
|
141
136
|
end
|
|
142
|
-
|
|
143
|
-
return entry.value
|
|
137
|
+
elsif entry.key == key
|
|
138
|
+
return entry.value
|
|
144
139
|
end
|
|
145
140
|
|
|
146
141
|
nil
|
|
@@ -159,8 +154,8 @@ module PEROBS
|
|
|
159
154
|
entry.each do |ae|
|
|
160
155
|
return true if ae.key == key
|
|
161
156
|
end
|
|
162
|
-
|
|
163
|
-
return true
|
|
157
|
+
elsif entry.key == key
|
|
158
|
+
return true
|
|
164
159
|
end
|
|
165
160
|
|
|
166
161
|
false
|
|
@@ -180,12 +175,10 @@ module PEROBS
|
|
|
180
175
|
|
|
181
176
|
if entry.is_a?(PEROBS::Array)
|
|
182
177
|
entry.each_with_index do |ae, i|
|
|
183
|
-
if ae.key == key
|
|
184
|
-
return entry.delete_at(i).value
|
|
185
|
-
end
|
|
178
|
+
return entry.delete_at(i).value if ae.key == key
|
|
186
179
|
end
|
|
187
|
-
|
|
188
|
-
return entry.value
|
|
180
|
+
elsif entry.key == key
|
|
181
|
+
return entry.value
|
|
189
182
|
end
|
|
190
183
|
|
|
191
184
|
nil
|
|
@@ -202,13 +195,13 @@ module PEROBS
|
|
|
202
195
|
# Return true if hash is empty. False otherweise.
|
|
203
196
|
# @return [TrueClass, FalseClass]
|
|
204
197
|
def empty?
|
|
205
|
-
@btree.entry_counter
|
|
198
|
+
@btree.entry_counter.zero?
|
|
206
199
|
end
|
|
207
200
|
|
|
208
201
|
# Calls the given block for each key/value pair.
|
|
209
202
|
# @yield(key, value)
|
|
210
203
|
def each(&block)
|
|
211
|
-
@btree.each do |
|
|
204
|
+
@btree.each do |_, entry|
|
|
212
205
|
if entry.is_a?(Collisions)
|
|
213
206
|
break if entry.each do |c_entry|
|
|
214
207
|
yield(c_entry.key, c_entry.value)
|
|
@@ -224,23 +217,20 @@ module PEROBS
|
|
|
224
217
|
# @return [Array] A list of all keys
|
|
225
218
|
def keys
|
|
226
219
|
ks = []
|
|
227
|
-
each { |k,
|
|
220
|
+
each { |k, _| ks << k }
|
|
228
221
|
ks
|
|
229
222
|
end
|
|
230
223
|
|
|
231
224
|
# Check if the data structure contains any errors.
|
|
232
225
|
# @return [Boolean] true if no erros were found, false otherwise
|
|
233
226
|
def check
|
|
234
|
-
|
|
227
|
+
@btree.check
|
|
235
228
|
end
|
|
236
229
|
|
|
237
230
|
private
|
|
238
231
|
|
|
239
232
|
def hash_key(key)
|
|
240
|
-
FNV_Hash_1a_64
|
|
233
|
+
FNV_Hash_1a_64.digest(key)
|
|
241
234
|
end
|
|
242
|
-
|
|
243
235
|
end
|
|
244
|
-
|
|
245
236
|
end
|
|
246
|
-
|
data/lib/perobs/BigTree.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
#
|
|
3
3
|
# = BigTree.rb -- Persistent Ruby Object Store
|
|
4
4
|
#
|
|
@@ -35,10 +35,7 @@ module PEROBS
|
|
|
35
35
|
# entries is limited by the space on the backing store, not the main
|
|
36
36
|
# memory. Entries are addressed by a Integer key.
|
|
37
37
|
class BigTree < PEROBS::Object
|
|
38
|
-
|
|
39
|
-
class Stats < Struct.new(:leaf_nodes, :branch_nodes, :min_depth,
|
|
40
|
-
:max_depth)
|
|
41
|
-
end
|
|
38
|
+
Stats = Struct.new(:leaf_nodes, :branch_nodes, :min_depth, :max_depth)
|
|
42
39
|
|
|
43
40
|
attr_persist :node_size, :root, :first_leaf, :last_leaf, :entry_counter
|
|
44
41
|
|
|
@@ -118,9 +115,7 @@ module PEROBS
|
|
|
118
115
|
old_root = @root
|
|
119
116
|
clear
|
|
120
117
|
old_root.each do |k, v|
|
|
121
|
-
|
|
122
|
-
insert(k, v)
|
|
123
|
-
end
|
|
118
|
+
insert(k, v) unless yield(k, v)
|
|
124
119
|
end
|
|
125
120
|
end
|
|
126
121
|
|
|
@@ -131,7 +126,7 @@ module PEROBS
|
|
|
131
126
|
|
|
132
127
|
# Return true if the BigTree has no stored entries.
|
|
133
128
|
def empty?
|
|
134
|
-
@entry_counter
|
|
129
|
+
@entry_counter.zero?
|
|
135
130
|
end
|
|
136
131
|
|
|
137
132
|
# Iterate over all entries in the tree. Entries are always sorted by the
|
|
@@ -141,6 +136,7 @@ module PEROBS
|
|
|
141
136
|
node = @first_leaf
|
|
142
137
|
while node
|
|
143
138
|
break if node.each_element(&block).nil?
|
|
139
|
+
|
|
144
140
|
node = node.next_sibling
|
|
145
141
|
end
|
|
146
142
|
end
|
|
@@ -156,7 +152,6 @@ module PEROBS
|
|
|
156
152
|
end
|
|
157
153
|
end
|
|
158
154
|
|
|
159
|
-
|
|
160
155
|
# @return [String] Human reable form of the tree.
|
|
161
156
|
def to_s
|
|
162
157
|
@root.to_s
|
|
@@ -173,8 +168,8 @@ module PEROBS
|
|
|
173
168
|
end
|
|
174
169
|
|
|
175
170
|
unless @entry_counter == i
|
|
176
|
-
PEROBS.log.error "BigTree contains #{i} values but entry counter "
|
|
177
|
-
|
|
171
|
+
PEROBS.log.error "BigTree contains #{i} values but entry counter " \
|
|
172
|
+
"is #{@entry_counter}"
|
|
178
173
|
return false
|
|
179
174
|
end
|
|
180
175
|
|
|
@@ -188,10 +183,5 @@ module PEROBS
|
|
|
188
183
|
@root.statistics(stats)
|
|
189
184
|
stats
|
|
190
185
|
end
|
|
191
|
-
|
|
192
|
-
private
|
|
193
|
-
|
|
194
186
|
end
|
|
195
|
-
|
|
196
187
|
end
|
|
197
|
-
|