perobs 4.5.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 +82 -96
- data/lib/perobs/BigHash.rb +14 -24
- data/lib/perobs/BigTree.rb +7 -17
- data/lib/perobs/BigTreeNode.rb +101 -122
- data/lib/perobs/ClassMap.rb +6 -0
- data/lib/perobs/DataBase.rb +19 -14
- data/lib/perobs/IDList.rb +2 -2
- data/lib/perobs/Store.rb +1 -1
- 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/BigTreeNode.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
3
|
# = BigTreeNode.rb -- Persistent Ruby Object Store
|
4
4
|
#
|
5
5
|
# Copyright (c) 2016, 2017 by Chris Schlaeger <chris@taskjuggler.org>
|
@@ -25,11 +25,10 @@
|
|
25
25
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
26
26
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
27
27
|
|
28
|
-
|
29
|
-
|
28
|
+
require_relative 'Object'
|
29
|
+
require_relative 'Array'
|
30
30
|
|
31
31
|
module PEROBS
|
32
|
-
|
33
32
|
# The BigTreeNode class provides the BTree nodes for the BigTree objects.
|
34
33
|
# A node can either be a branch node or a leaf node. Branch nodes don't
|
35
34
|
# store values, only references to child nodes. Leaf nodes don't have child
|
@@ -38,9 +37,8 @@ module PEROBS
|
|
38
37
|
# associated with a value or determines the lower key boundary for the
|
39
38
|
# following child node.
|
40
39
|
class BigTreeNode < PEROBS::Object
|
41
|
-
|
42
40
|
attr_persist :tree, :parent, :keys, :values, :children,
|
43
|
-
|
41
|
+
:prev_sibling, :next_sibling
|
44
42
|
|
45
43
|
# Internal constructor. Use Store.new(BigTreeNode, ...) instead.
|
46
44
|
# @param p [Handle]
|
@@ -94,23 +92,19 @@ module PEROBS
|
|
94
92
|
node = myself
|
95
93
|
|
96
94
|
# Traverse the tree to find the right node to add or replace the value.
|
97
|
-
while node
|
95
|
+
while node
|
98
96
|
# All nodes that we find on the way that are full will be split into
|
99
97
|
# two half-full nodes.
|
100
|
-
if node.keys.size >= @tree.node_size
|
101
|
-
node = node.split_node
|
102
|
-
end
|
98
|
+
node = node.split_node if node.keys.size >= @tree.node_size
|
103
99
|
|
104
100
|
# Once we have reached a leaf node we can insert or replace the value.
|
105
|
-
if node.is_leaf?
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
node = node.children[node.search_key_index(key)]
|
110
|
-
end
|
101
|
+
return node.insert_element(key, value) if node.is_leaf?
|
102
|
+
|
103
|
+
# Descend into the right child node to add the value to.
|
104
|
+
node = node.children[node.search_key_index(key)]
|
111
105
|
end
|
112
106
|
|
113
|
-
PEROBS.log.fatal
|
107
|
+
PEROBS.log.fatal 'Could not find proper node to insert into'
|
114
108
|
end
|
115
109
|
|
116
110
|
# Return the value that matches the given key or return nil if they key is
|
@@ -120,7 +114,7 @@ module PEROBS
|
|
120
114
|
def get(key)
|
121
115
|
node = self
|
122
116
|
|
123
|
-
while node
|
117
|
+
while node
|
124
118
|
# Find index of the entry that best fits the key.
|
125
119
|
i = node.search_key_index(key)
|
126
120
|
if node.is_leaf?
|
@@ -133,8 +127,8 @@ module PEROBS
|
|
133
127
|
node = node.children[i]
|
134
128
|
end
|
135
129
|
|
136
|
-
PEROBS.log.fatal
|
137
|
-
|
130
|
+
PEROBS.log.fatal 'Could not find proper node to get from while ' \
|
131
|
+
"looking for key #{key}"
|
138
132
|
end
|
139
133
|
|
140
134
|
# Return the node chain from the root to the leaf node storing the
|
@@ -143,9 +137,9 @@ module PEROBS
|
|
143
137
|
# @return [Array of BigTreeNode] node list (may be empty)
|
144
138
|
def node_chain(key)
|
145
139
|
node = myself
|
146
|
-
list = [
|
140
|
+
list = [node]
|
147
141
|
|
148
|
-
while node
|
142
|
+
while node
|
149
143
|
# Find index of the entry that best fits the key.
|
150
144
|
i = node.search_key_index(key)
|
151
145
|
if node.is_leaf?
|
@@ -169,7 +163,7 @@ module PEROBS
|
|
169
163
|
def has_key?(key)
|
170
164
|
node = self
|
171
165
|
|
172
|
-
while node
|
166
|
+
while node
|
173
167
|
# Find index of the entry that best fits the key.
|
174
168
|
i = node.search_key_index(key)
|
175
169
|
if node.is_leaf?
|
@@ -182,8 +176,8 @@ module PEROBS
|
|
182
176
|
node = node.children[i]
|
183
177
|
end
|
184
178
|
|
185
|
-
PEROBS.log.fatal
|
186
|
-
|
179
|
+
PEROBS.log.fatal 'Could not find proper node to get from while ' \
|
180
|
+
"looking for key #{key}"
|
187
181
|
end
|
188
182
|
|
189
183
|
# Return the value that matches the given key and remove the value from
|
@@ -193,18 +187,16 @@ module PEROBS
|
|
193
187
|
def remove(key)
|
194
188
|
node = self
|
195
189
|
|
196
|
-
while node
|
190
|
+
while node
|
197
191
|
# Find index of the entry that best fits the key.
|
198
192
|
i = node.search_key_index(key)
|
199
193
|
if node.is_leaf?
|
200
194
|
# This is a leaf node. Check if there is an exact match for the
|
201
195
|
# given key and return the corresponding value or nil.
|
202
|
-
if node.keys[i]
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
return nil
|
207
|
-
end
|
196
|
+
return nil if node.keys[i] != key
|
197
|
+
|
198
|
+
@tree.entry_counter -= 1
|
199
|
+
return node.remove_element(i)
|
208
200
|
end
|
209
201
|
|
210
202
|
# Descend into the right child node to continue the search.
|
@@ -217,10 +209,9 @@ module PEROBS
|
|
217
209
|
# Iterate over all the key/value pairs in this node and all sub-nodes.
|
218
210
|
# @yield [key, value]
|
219
211
|
def each
|
220
|
-
traverse do |node, position,
|
221
|
-
|
212
|
+
traverse do |node, position, _|
|
213
|
+
node.is_leaf? && position < node.keys.size &&
|
222
214
|
yield(node.keys[position], node.values[position])
|
223
|
-
end
|
224
215
|
end
|
225
216
|
end
|
226
217
|
|
@@ -252,7 +243,7 @@ module PEROBS
|
|
252
243
|
branch_depth = nil
|
253
244
|
|
254
245
|
traverse do |node, position, stack|
|
255
|
-
if position
|
246
|
+
if position.zero?
|
256
247
|
if node.parent
|
257
248
|
# After a split the nodes will only have half the maximum keys.
|
258
249
|
# For branch nodes one of the split nodes will have even 1 key
|
@@ -264,16 +255,16 @@ module PEROBS
|
|
264
255
|
end
|
265
256
|
|
266
257
|
if node.keys.size > @tree.node_size
|
267
|
-
node.error
|
268
|
-
|
258
|
+
node.error 'BigTree node must not have more then ' \
|
259
|
+
"#{@tree.node_size} keys, but has #{node.keys.size} keys"
|
269
260
|
return false
|
270
261
|
end
|
271
262
|
|
272
263
|
last_key = nil
|
273
264
|
node.keys.each do |key|
|
274
265
|
if last_key && key < last_key
|
275
|
-
node.error
|
276
|
-
|
266
|
+
node.error 'Keys are not increasing monotoneously: ' \
|
267
|
+
"#{node.keys.inspect}"
|
277
268
|
return false
|
278
269
|
end
|
279
270
|
last_key = key
|
@@ -282,7 +273,7 @@ module PEROBS
|
|
282
273
|
if node.is_leaf?
|
283
274
|
if branch_depth
|
284
275
|
unless branch_depth == stack.size
|
285
|
-
node.error
|
276
|
+
node.error 'All leaf nodes must have same distance from root'
|
286
277
|
return false
|
287
278
|
end
|
288
279
|
else
|
@@ -290,54 +281,54 @@ module PEROBS
|
|
290
281
|
end
|
291
282
|
if node.prev_sibling.nil?
|
292
283
|
if @tree.first_leaf != node
|
293
|
-
node.error "Leaf node #{node._id} has no previous sibling "
|
294
|
-
|
284
|
+
node.error "Leaf node #{node._id} has no previous sibling " \
|
285
|
+
'but is not the first leaf of the tree'
|
295
286
|
return false
|
296
287
|
end
|
297
288
|
elsif node.prev_sibling.next_sibling != node
|
298
|
-
node.error
|
299
|
-
|
289
|
+
node.error 'next_sibling of previous sibling does not point to ' \
|
290
|
+
'this node'
|
300
291
|
return false
|
301
292
|
end
|
302
293
|
if node.next_sibling.nil?
|
303
294
|
if @tree.last_leaf != node
|
304
|
-
node.error "Leaf node #{node._id} has no next sibling "
|
305
|
-
|
295
|
+
node.error "Leaf node #{node._id} has no next sibling " \
|
296
|
+
'but is not the last leaf of the tree'
|
306
297
|
return false
|
307
298
|
end
|
308
299
|
elsif node.next_sibling.prev_sibling != node
|
309
|
-
node.error
|
310
|
-
|
300
|
+
node.error 'previous_sibling of next sibling does not point to ' \
|
301
|
+
'this node'
|
311
302
|
return false
|
312
303
|
end
|
313
304
|
unless node.keys.size == node.values.size
|
314
|
-
node.error "Key count (#{node.keys.size}) and value "
|
315
|
-
|
316
|
-
|
305
|
+
node.error "Key count (#{node.keys.size}) and value " \
|
306
|
+
"count (#{node.values.size}) don't match"
|
307
|
+
return false
|
317
308
|
end
|
318
309
|
if node.children
|
319
|
-
node.error
|
310
|
+
node.error 'children must be nil for a leaf node'
|
320
311
|
return false
|
321
312
|
end
|
322
313
|
else
|
323
314
|
if node.values
|
324
|
-
node.error
|
315
|
+
node.error 'values must be nil for a branch node'
|
325
316
|
return false
|
326
317
|
end
|
327
318
|
unless node.children.size == node.keys.size + 1
|
328
|
-
node.error "Key count (#{node.keys.size}) must be one "
|
329
|
-
|
330
|
-
|
319
|
+
node.error "Key count (#{node.keys.size}) must be one " \
|
320
|
+
"less than children count (#{node.children.size})"
|
321
|
+
return false
|
331
322
|
end
|
332
323
|
node.children.each_with_index do |child, i|
|
333
324
|
unless child.is_a?(BigTreeNode)
|
334
|
-
node.error "Child #{i} is of class #{child.class} "
|
335
|
-
|
325
|
+
node.error "Child #{i} is of class #{child.class} " \
|
326
|
+
'instead of BigTreeNode'
|
336
327
|
return false
|
337
328
|
end
|
338
329
|
unless child.parent.is_a?(BigTreeNode)
|
339
|
-
node.error "Parent reference of child #{i} is of class "
|
340
|
-
|
330
|
+
node.error "Parent reference of child #{i} is of class " \
|
331
|
+
"#{child.class} instead of BigTreeNode"
|
341
332
|
return false
|
342
333
|
end
|
343
334
|
if child == node
|
@@ -349,25 +340,22 @@ module PEROBS
|
|
349
340
|
return false
|
350
341
|
end
|
351
342
|
unless child.parent == node
|
352
|
-
node.error "Child #{i} does not have parent pointing "
|
353
|
-
|
343
|
+
node.error "Child #{i} does not have parent pointing " \
|
344
|
+
'to this node'
|
354
345
|
return false
|
355
346
|
end
|
356
|
-
if i
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
return false
|
362
|
-
end
|
347
|
+
if i.positive? && node.children[i - 1].next_sibling != child
|
348
|
+
node.error 'next_sibling of node ' \
|
349
|
+
"#{node.children[i - 1]._id} " \
|
350
|
+
"must point to node #{child._id}"
|
351
|
+
return false
|
363
352
|
end
|
364
|
-
if i < node.children.length - 1
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
end
|
353
|
+
if i < node.children.length - 1 &&
|
354
|
+
child != node.children[i + 1].prev_sibling
|
355
|
+
node.error 'prev_sibling of node ' \
|
356
|
+
"#{node.children[i + 1]._id} " \
|
357
|
+
"must point to node #{child._id}"
|
358
|
+
return false
|
371
359
|
end
|
372
360
|
end
|
373
361
|
end
|
@@ -382,15 +370,15 @@ module PEROBS
|
|
382
370
|
end
|
383
371
|
else
|
384
372
|
unless node.children[index].keys.last < node.keys[index]
|
385
|
-
node.error "Child #{node.children[index]._id} "
|
386
|
-
|
387
|
-
|
373
|
+
node.error "Child #{node.children[index]._id} " \
|
374
|
+
"has too large key #{node.children[index].keys.last}. " \
|
375
|
+
"Must be smaller than #{node.keys[index]}."
|
388
376
|
return false
|
389
377
|
end
|
390
378
|
unless node.children[position].keys.first >= node.keys[index]
|
391
|
-
node.error "Child #{node.children[position]._id} "
|
392
|
-
|
393
|
-
|
379
|
+
node.error "Child #{node.children[position]._id} " \
|
380
|
+
"has too small key #{node.children[position].keys.first}. " \
|
381
|
+
"Must be larger than or equal to #{node.keys[index]}."
|
394
382
|
return false
|
395
383
|
end
|
396
384
|
end
|
@@ -404,12 +392,12 @@ module PEROBS
|
|
404
392
|
def to_s
|
405
393
|
str = ''
|
406
394
|
|
407
|
-
traverse do |node, position,
|
408
|
-
if position
|
395
|
+
traverse do |node, position, _|
|
396
|
+
if position.zero?
|
409
397
|
begin
|
410
|
-
str += "#{node.parent ? node.parent.tree_prefix + ' +' : 'o'}"
|
411
|
-
|
412
|
-
|
398
|
+
str += "#{node.parent ? node.parent.tree_prefix + ' +' : 'o'}" \
|
399
|
+
"#{node.tree_branch_mark}-" \
|
400
|
+
"#{node.keys.first.nil? ? '--' : 'v-'}#{node.tree_summary}\n"
|
413
401
|
rescue => e
|
414
402
|
str += "@@@@@@@@@@: #{e.message}\n"
|
415
403
|
end
|
@@ -417,14 +405,12 @@ module PEROBS
|
|
417
405
|
begin
|
418
406
|
if node.is_leaf?
|
419
407
|
if node.keys[position - 1]
|
420
|
-
str += "#{node.tree_prefix} |"
|
421
|
-
"[#{node.keys[position - 1]}, "
|
408
|
+
str += "#{node.tree_prefix} |" \
|
409
|
+
"[#{node.keys[position - 1]}, " \
|
422
410
|
"#{node.values[position - 1]}]\n"
|
423
411
|
end
|
424
|
-
|
425
|
-
|
426
|
-
str += "#{node.tree_prefix} #{node.keys[position - 1]}\n"
|
427
|
-
end
|
412
|
+
elsif node.keys[position - 1]
|
413
|
+
str += "#{node.tree_prefix} #{node.keys[position - 1]}\n"
|
428
414
|
end
|
429
415
|
rescue => e
|
430
416
|
str += "@@@@@@@@@@: #{e.message}\n"
|
@@ -518,10 +504,9 @@ module PEROBS
|
|
518
504
|
def remove_element(index)
|
519
505
|
# Delete the key at the specified index.
|
520
506
|
unless (key = @keys.delete_at(index))
|
521
|
-
PEROBS.log.fatal "Could not remove element #{index} from BigTreeNode "
|
522
|
-
"@#{@_id}"
|
507
|
+
PEROBS.log.fatal "Could not remove element #{index} from BigTreeNode @#{@_id}"
|
523
508
|
end
|
524
|
-
update_branch_key(key) if index
|
509
|
+
update_branch_key(key) if index.zero?
|
525
510
|
|
526
511
|
# Delete the corresponding value.
|
527
512
|
removed_value = @values.delete_at(index)
|
@@ -533,7 +518,7 @@ module PEROBS
|
|
533
518
|
borrow_from_next_sibling(@next_sibling) ||
|
534
519
|
merge_with_leaf_node(@next_sibling)
|
535
520
|
elsif @parent
|
536
|
-
PEROBS.log.fatal
|
521
|
+
PEROBS.log.fatal 'Cannot not find adjecent leaf siblings'
|
537
522
|
end
|
538
523
|
end
|
539
524
|
|
@@ -549,7 +534,7 @@ module PEROBS
|
|
549
534
|
PEROBS.log.fatal "Cannot remove child #{node._id} from node #{@_id}"
|
550
535
|
end
|
551
536
|
|
552
|
-
if index
|
537
|
+
if index.zero?
|
553
538
|
# Removing the first child is a bit more complicated as the
|
554
539
|
# corresponding branch key is in a parent node.
|
555
540
|
key = @keys.shift
|
@@ -592,7 +577,7 @@ module PEROBS
|
|
592
577
|
|
593
578
|
def merge_with_leaf_node(node)
|
594
579
|
if @keys.length + node.keys.length > @tree.node_size
|
595
|
-
PEROBS.log.fatal
|
580
|
+
PEROBS.log.fatal 'Leaf nodes are too big to merge'
|
596
581
|
end
|
597
582
|
|
598
583
|
self.keys += node.keys
|
@@ -603,7 +588,7 @@ module PEROBS
|
|
603
588
|
|
604
589
|
def merge_with_branch_node(node)
|
605
590
|
if @keys.length + 1 + node.keys.length > @tree.node_size
|
606
|
-
PEROBS.log.fatal
|
591
|
+
PEROBS.log.fatal 'Branch nodes are too big to merge'
|
607
592
|
end
|
608
593
|
|
609
594
|
index = @parent.search_node_index(node) - 1
|
@@ -670,9 +655,9 @@ module PEROBS
|
|
670
655
|
def traverse
|
671
656
|
# We use a non-recursive implementation to traverse the tree. This stack
|
672
657
|
# keeps track of all the known still to be checked nodes.
|
673
|
-
stack = [
|
658
|
+
stack = [[self, 0]]
|
674
659
|
|
675
|
-
|
660
|
+
until stack.empty?
|
676
661
|
node, position = stack.pop
|
677
662
|
|
678
663
|
# Call the payload method. The position marks where we are in the node
|
@@ -684,15 +669,15 @@ module PEROBS
|
|
684
669
|
# to return to the parent node.
|
685
670
|
yield(node, position, stack)
|
686
671
|
|
687
|
-
|
688
|
-
# Push the next position for this node onto the stack.
|
689
|
-
stack.push([ node, position + 1 ])
|
672
|
+
next unless position <= node.keys.size
|
690
673
|
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
674
|
+
# Push the next position for this node onto the stack.
|
675
|
+
stack.push([node, position + 1])
|
676
|
+
|
677
|
+
if !node.is_leaf? && node.children[position]
|
678
|
+
# If we have a child node for this position, push the linked node
|
679
|
+
# and the starting position onto the stack.
|
680
|
+
stack.push([node.children[position], 0])
|
696
681
|
end
|
697
682
|
end
|
698
683
|
end
|
@@ -701,16 +686,12 @@ module PEROBS
|
|
701
686
|
# @param stats [Stats] Data structure that stores the gathered data
|
702
687
|
def statistics(stats)
|
703
688
|
traverse do |node, position, stack|
|
704
|
-
if position
|
689
|
+
if position.zero?
|
705
690
|
if node.is_leaf?
|
706
691
|
stats.leaf_nodes += 1
|
707
692
|
depth = stack.size + 1
|
708
|
-
if stats.min_depth.nil? || stats.min_depth < depth
|
709
|
-
|
710
|
-
end
|
711
|
-
if stats.max_depth.nil? || stats.max_depth > depth
|
712
|
-
stats.max_depth = depth
|
713
|
-
end
|
693
|
+
stats.min_depth = depth if stats.min_depth.nil? || stats.min_depth < depth
|
694
|
+
stats.max_depth = depth if stats.max_depth.nil? || stats.max_depth > depth
|
714
695
|
else
|
715
696
|
stats.branch_nodes += 1
|
716
697
|
end
|
@@ -743,6 +724,7 @@ module PEROBS
|
|
743
724
|
# Branch node decoration for the inspection method.
|
744
725
|
def tree_branch_mark
|
745
726
|
return '' unless @parent
|
727
|
+
|
746
728
|
'-'
|
747
729
|
end
|
748
730
|
|
@@ -866,8 +848,5 @@ module PEROBS
|
|
866
848
|
|
867
849
|
# The smallest element has no branch key.
|
868
850
|
end
|
869
|
-
|
870
851
|
end
|
871
|
-
|
872
852
|
end
|
873
|
-
|
data/lib/perobs/ClassMap.rb
CHANGED
@@ -60,6 +60,12 @@ module PEROBS
|
|
60
60
|
@by_id[id]
|
61
61
|
end
|
62
62
|
|
63
|
+
# Get a list of all classes used in the Store.
|
64
|
+
# @return [Array] list of Ruby classes
|
65
|
+
def classes
|
66
|
+
@by_class.keys
|
67
|
+
end
|
68
|
+
|
63
69
|
# Rename a set of classes to new names.
|
64
70
|
# @param rename_map [Hash] Hash that maps old names to new names
|
65
71
|
def rename(rename_map)
|
data/lib/perobs/DataBase.rb
CHANGED
@@ -34,18 +34,23 @@ require 'fileutils'
|
|
34
34
|
|
35
35
|
require 'perobs/Log'
|
36
36
|
require 'perobs/ObjectBase'
|
37
|
+
require_relative 'ProgressMeter'
|
37
38
|
|
38
39
|
module PEROBS
|
39
|
-
|
40
40
|
# Base class for all storage back-ends.
|
41
41
|
class DataBase
|
42
|
-
|
43
42
|
# Create a new DataBase object. This method must be overwritten by the
|
44
43
|
# deriving classes and then called via their constructor.
|
45
44
|
def initialize(options)
|
46
45
|
@serializer = options[:serializer] || :json
|
47
46
|
@progressmeter = options[:progressmeter] || ProgressMeter.new
|
48
47
|
@config = {}
|
48
|
+
@class_map = nil
|
49
|
+
end
|
50
|
+
|
51
|
+
# Register the class map object needed to de-serialize objects.
|
52
|
+
def register_class_map(class_map)
|
53
|
+
@class_map = class_map
|
49
54
|
end
|
50
55
|
|
51
56
|
# A dummy open method. Deriving classes must overload them to insert their
|
@@ -81,19 +86,21 @@ module PEROBS
|
|
81
86
|
# @param raw [String]
|
82
87
|
# @return [Hash] Deserialized version
|
83
88
|
def deserialize(raw)
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
89
|
+
case @serializer
|
90
|
+
when :marshal
|
91
|
+
Marshal.load(raw)
|
92
|
+
when :json
|
93
|
+
JSON.parse(raw, create_additions: true)
|
94
|
+
when :yaml
|
95
|
+
if RUBY_VERSION < '3.2'
|
91
96
|
YAML.load(raw)
|
97
|
+
else
|
98
|
+
YAML.load(raw, permitted_classes: [Symbol, POReference] + @class_map.classes)
|
92
99
|
end
|
93
|
-
rescue => e
|
94
|
-
PEROBS.log.fatal "Cannot de-serialize object with #{@serializer} " +
|
95
|
-
"parser: " + e.message
|
96
100
|
end
|
101
|
+
rescue => e
|
102
|
+
PEROBS.log.fatal "Cannot de-serialize object with #{@serializer} " +
|
103
|
+
"parser: " + e.message
|
97
104
|
end
|
98
105
|
|
99
106
|
# Check a config option and adjust it if needed.
|
@@ -127,7 +134,5 @@ module PEROBS
|
|
127
134
|
end
|
128
135
|
end
|
129
136
|
end
|
130
|
-
|
131
137
|
end
|
132
|
-
|
133
138
|
end
|
data/lib/perobs/IDList.rb
CHANGED
@@ -46,7 +46,7 @@ module PEROBS
|
|
46
46
|
# that will be kept in memory. If the list is larger, values will
|
47
47
|
# be cached in the specified file.
|
48
48
|
# @param page_size [Integer] The number of values per page. The default
|
49
|
-
# value is 32 which was found the best performing config in
|
49
|
+
# value is 32 which was found the best performing config in tests.
|
50
50
|
def initialize(dir, name, max_in_memory, page_size = 32)
|
51
51
|
# The page_file manages the pages that store the values.
|
52
52
|
@page_file = IDListPageFile.new(self, dir, name,
|
@@ -63,7 +63,7 @@ module PEROBS
|
|
63
63
|
page = @page_records[index]
|
64
64
|
|
65
65
|
# In case the page is already full we'll have to create a new page.
|
66
|
-
# There is no guarantee that a split will yield
|
66
|
+
# There is no guarantee that a split will yield a page with space as we
|
67
67
|
# split by ID range, not by distributing the values evenly across the
|
68
68
|
# two pages.
|
69
69
|
while page.is_full?
|
data/lib/perobs/Store.rb
CHANGED
@@ -157,6 +157,7 @@ module PEROBS
|
|
157
157
|
# Create a map that can translate classes to numerical IDs and vice
|
158
158
|
# versa.
|
159
159
|
@class_map = ClassMap.new(@db)
|
160
|
+
@db.register_class_map(@class_map)
|
160
161
|
|
161
162
|
# List of PEROBS objects that are currently available as Ruby objects
|
162
163
|
# hashed by their ID.
|
@@ -712,4 +713,3 @@ module PEROBS
|
|
712
713
|
end
|
713
714
|
|
714
715
|
end
|
715
|
-
|
data/lib/perobs/version.rb
CHANGED
data/perobs.gemspec
CHANGED
@@ -16,9 +16,10 @@ GEM_SPEC = Gem::Specification.new do |spec|
|
|
16
16
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
17
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
18
|
spec.require_paths = ["lib"]
|
19
|
-
spec.required_ruby_version = '>=2.
|
19
|
+
spec.required_ruby_version = '>=2.5'
|
20
20
|
|
21
|
-
spec.add_development_dependency 'bundler', '~> 2.
|
21
|
+
spec.add_development_dependency 'bundler', '~> 2.2'
|
22
22
|
spec.add_development_dependency 'yard', '~>0.9.12'
|
23
23
|
spec.add_development_dependency 'rake', '~> 13.0.3'
|
24
|
+
spec.add_development_dependency 'rspec', '~> 3.12'
|
24
25
|
end
|