perobs 4.0.0 → 4.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/perobs.rb +1 -0
- data/lib/perobs/Array.rb +66 -19
- data/lib/perobs/BTree.rb +83 -12
- data/lib/perobs/BTreeBlob.rb +1 -1
- data/lib/perobs/BTreeDB.rb +2 -2
- data/lib/perobs/BTreeNode.rb +365 -85
- data/lib/perobs/BigArray.rb +267 -0
- data/lib/perobs/BigArrayNode.rb +998 -0
- data/lib/perobs/BigHash.rb +262 -0
- data/lib/perobs/BigTree.rb +184 -0
- data/lib/perobs/BigTreeNode.rb +873 -0
- data/lib/perobs/ConsoleProgressMeter.rb +61 -0
- data/lib/perobs/DataBase.rb +4 -3
- data/lib/perobs/DynamoDB.rb +57 -15
- data/lib/perobs/EquiBlobsFile.rb +143 -51
- data/lib/perobs/FNV_Hash_1a_64.rb +54 -0
- data/lib/perobs/FlatFile.rb +363 -203
- data/lib/perobs/FlatFileBlobHeader.rb +98 -54
- data/lib/perobs/FlatFileDB.rb +42 -20
- data/lib/perobs/Hash.rb +58 -13
- data/lib/perobs/IDList.rb +144 -0
- data/lib/perobs/IDListPage.rb +107 -0
- data/lib/perobs/IDListPageFile.rb +180 -0
- data/lib/perobs/IDListPageRecord.rb +142 -0
- data/lib/perobs/Object.rb +18 -15
- data/lib/perobs/ObjectBase.rb +38 -4
- data/lib/perobs/PersistentObjectCache.rb +53 -67
- data/lib/perobs/PersistentObjectCacheLine.rb +24 -12
- data/lib/perobs/ProgressMeter.rb +97 -0
- data/lib/perobs/SpaceTree.rb +21 -12
- data/lib/perobs/SpaceTreeNode.rb +53 -61
- data/lib/perobs/Store.rb +71 -32
- data/lib/perobs/version.rb +1 -1
- data/perobs.gemspec +4 -4
- data/test/Array_spec.rb +15 -6
- data/test/BTree_spec.rb +5 -2
- data/test/BigArray_spec.rb +214 -0
- data/test/BigHash_spec.rb +144 -0
- data/test/BigTreeNode_spec.rb +153 -0
- data/test/BigTree_spec.rb +259 -0
- data/test/EquiBlobsFile_spec.rb +105 -1
- data/test/FNV_Hash_1a_64_spec.rb +59 -0
- data/test/FlatFileDB_spec.rb +63 -14
- data/test/Hash_spec.rb +1 -2
- data/test/IDList_spec.rb +77 -0
- data/test/LegacyDBs/LegacyDB.rb +151 -0
- data/test/LegacyDBs/version_3/class_map.json +1 -0
- data/test/LegacyDBs/version_3/config.json +1 -0
- data/test/LegacyDBs/version_3/database.blobs +0 -0
- data/test/LegacyDBs/version_3/database_spaces.blobs +0 -0
- data/test/LegacyDBs/version_3/index.blobs +0 -0
- data/test/LegacyDBs/version_3/version +1 -0
- data/test/LockFile_spec.rb +9 -6
- data/test/SpaceTree_spec.rb +4 -1
- data/test/Store_spec.rb +290 -199
- data/test/spec_helper.rb +9 -4
- metadata +47 -10
- data/lib/perobs/TreeDB.rb +0 -277
data/lib/perobs/SpaceTree.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
#
|
3
3
|
# = SpaceTree.rb -- Persistent Ruby Object Store
|
4
4
|
#
|
5
|
-
# Copyright (c) 2016, 2017 by Chris Schlaeger <chris@taskjuggler.org>
|
5
|
+
# Copyright (c) 2016, 2017, 2018 by Chris Schlaeger <chris@taskjuggler.org>
|
6
6
|
#
|
7
7
|
# MIT License
|
8
8
|
#
|
@@ -40,20 +40,21 @@ module PEROBS
|
|
40
40
|
# size which drastically simplifies the backing store operation.
|
41
41
|
class SpaceTree
|
42
42
|
|
43
|
-
attr_reader :nodes, :cache
|
43
|
+
attr_reader :nodes, :cache, :progressmeter
|
44
44
|
|
45
45
|
# Manage the free spaces tree in the specified directory
|
46
46
|
# @param dir [String] directory path of an existing directory
|
47
|
-
def initialize(dir)
|
47
|
+
def initialize(dir, progressmeter)
|
48
48
|
@dir = dir
|
49
|
+
@progressmeter = progressmeter
|
49
50
|
|
50
51
|
# This EquiBlobsFile contains the nodes of the SpaceTree.
|
51
|
-
@nodes = EquiBlobsFile.new(@dir, 'database_spaces',
|
52
|
+
@nodes = EquiBlobsFile.new(@dir, 'database_spaces', progressmeter,
|
52
53
|
SpaceTreeNode::NODE_BYTES, 1)
|
53
54
|
|
54
55
|
# Benchmark runs showed a cache size of 128 to be a good compromise
|
55
56
|
# between read and write performance trade-offs and memory consumption.
|
56
|
-
@cache = PersistentObjectCache.new(128, SpaceTreeNode, self)
|
57
|
+
@cache = PersistentObjectCache.new(128, 5000, SpaceTreeNode, self)
|
57
58
|
end
|
58
59
|
|
59
60
|
# Open the SpaceTree file.
|
@@ -74,9 +75,14 @@ module PEROBS
|
|
74
75
|
@cache.clear
|
75
76
|
end
|
76
77
|
|
78
|
+
# @return true if file is currently open.
|
79
|
+
def is_open?
|
80
|
+
!@root_address.nil?
|
81
|
+
end
|
82
|
+
|
77
83
|
# Flush all pending writes to the file system.
|
78
84
|
def sync
|
79
|
-
@cache.flush
|
85
|
+
@cache.flush(true)
|
80
86
|
@nodes.sync
|
81
87
|
end
|
82
88
|
|
@@ -105,10 +111,12 @@ module PEROBS
|
|
105
111
|
if size <= 0
|
106
112
|
PEROBS.log.fatal "Size (#{size}) must be larger than 0."
|
107
113
|
end
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
114
|
+
# The following check is fairly costly and should never trigger unless
|
115
|
+
# there is a bug in the PEROBS code. Only use this for debugging.
|
116
|
+
#if has_space?(address, size)
|
117
|
+
# PEROBS.log.fatal "The space with address #{address} and size " +
|
118
|
+
# "#{size} can't be added twice."
|
119
|
+
#end
|
112
120
|
root.add_space(address, size)
|
113
121
|
end
|
114
122
|
|
@@ -157,8 +165,9 @@ module PEROBS
|
|
157
165
|
# @param flat_file [FlatFile] Flat file to compare with
|
158
166
|
# @return True if space list matches, flase otherwise
|
159
167
|
def check(flat_file = nil)
|
160
|
-
|
161
|
-
|
168
|
+
sync
|
169
|
+
return false unless @nodes.check
|
170
|
+
root.check(flat_file, @nodes.total_entries)
|
162
171
|
end
|
163
172
|
|
164
173
|
# Iterate over all entries and yield address and size.
|
data/lib/perobs/SpaceTreeNode.rb
CHANGED
@@ -74,24 +74,11 @@ module PEROBS
|
|
74
74
|
@smaller = smaller
|
75
75
|
@equal = equal
|
76
76
|
@larger = larger
|
77
|
-
|
78
|
-
ObjectSpace.define_finalizer(
|
79
|
-
self, SpaceTreeNode._finalize(@tree, @node_address, object_id))
|
80
|
-
@tree.cache.insert(self, false)
|
81
|
-
end
|
82
|
-
|
83
|
-
# This method generates the destructor for the objects of this class. It
|
84
|
-
# is done this way to prevent the Proc object hanging on to a reference to
|
85
|
-
# self which would prevent the object from being collected. This internal
|
86
|
-
# method is not intended for users to call.
|
87
|
-
def SpaceTreeNode._finalize(tree, node_address, ruby_object_id)
|
88
|
-
proc { tree.cache._collect(node_address, ruby_object_id) }
|
89
77
|
end
|
90
78
|
|
91
79
|
# Create a new SpaceTreeNode. This method should be used for the creation
|
92
80
|
# of new nodes instead of calling the constructor directly.
|
93
81
|
# @param tree [SpaceTree] The tree the node should belong to
|
94
|
-
# @param node_address [Integer] Address of the node in the file
|
95
82
|
# @param blob_address [Integer] Address of the free space blob
|
96
83
|
# @param size [Integer] Size of the free space blob
|
97
84
|
# @param parent [SpaceTreeNode] Parent node in the tree
|
@@ -99,7 +86,7 @@ module PEROBS
|
|
99
86
|
node_address = tree.nodes.free_address
|
100
87
|
|
101
88
|
node = SpaceTreeNode.new(tree, node_address, blob_address, size, parent)
|
102
|
-
node
|
89
|
+
tree.cache.insert(node)
|
103
90
|
|
104
91
|
node
|
105
92
|
end
|
@@ -107,7 +94,7 @@ module PEROBS
|
|
107
94
|
# Restore a node from the backing store at the given address and tree.
|
108
95
|
# @param tree [SpaceTree] The tree the node belongs to
|
109
96
|
# @param node_address [Integer] The address in the file.
|
110
|
-
def SpaceTreeNode::load(tree, node_address)
|
97
|
+
def SpaceTreeNode::load(tree, node_address, unused = nil)
|
111
98
|
unless node_address > 0
|
112
99
|
PEROBS.log.fatal "node_address (#{node_address}) must be larger than 0"
|
113
100
|
end
|
@@ -132,6 +119,8 @@ module PEROBS
|
|
132
119
|
node = SpaceTreeNode.new(tree, node_address, blob_address, size,
|
133
120
|
parent, smaller, equal, larger)
|
134
121
|
|
122
|
+
tree.cache.insert(node, false)
|
123
|
+
|
135
124
|
node
|
136
125
|
end
|
137
126
|
|
@@ -529,62 +518,65 @@ module PEROBS
|
|
529
518
|
# errors.
|
530
519
|
# @param flat_file [FlatFile] If given, check that the space is also
|
531
520
|
# present in the given flat file.
|
521
|
+
# @param count [Integer] The total number of entries in the tree
|
532
522
|
# @return [false,true] True if OK, false otherwise
|
533
|
-
def check(flat_file)
|
523
|
+
def check(flat_file, count)
|
534
524
|
node_counter = 0
|
535
525
|
max_depth = 0
|
536
526
|
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
"
|
548
|
-
|
527
|
+
@tree.progressmeter.start('Checking space list entries', count) do |pm|
|
528
|
+
each do |node, mode, stack|
|
529
|
+
max_depth = stack.size if stack.size > max_depth
|
530
|
+
|
531
|
+
case mode
|
532
|
+
when :smaller
|
533
|
+
if node.smaller
|
534
|
+
return false unless node.check_node_link('smaller', stack)
|
535
|
+
smaller_node = node.smaller
|
536
|
+
if smaller_node.size >= node.size
|
537
|
+
PEROBS.log.error "Smaller SpaceTreeNode size " +
|
538
|
+
"(#{smaller_node}) is not smaller than #{node}"
|
539
|
+
return false
|
540
|
+
end
|
549
541
|
end
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
542
|
+
when :equal
|
543
|
+
if node.equal
|
544
|
+
return false unless node.check_node_link('equal', stack)
|
545
|
+
equal_node = node.equal
|
546
|
+
|
547
|
+
if equal_node.smaller || equal_node.larger
|
548
|
+
PEROBS.log.error "Equal node #{equal_node} must not have " +
|
549
|
+
"smaller/larger childs"
|
550
|
+
return false
|
551
|
+
end
|
552
|
+
|
553
|
+
if node.size != equal_node.size
|
554
|
+
PEROBS.log.error "Equal SpaceTreeNode size (#{equal_node}) " +
|
555
|
+
"is not equal parent node #{node}"
|
556
|
+
return false
|
557
|
+
end
|
560
558
|
end
|
561
|
-
|
562
|
-
if node.
|
563
|
-
|
564
|
-
|
565
|
-
|
559
|
+
when :larger
|
560
|
+
if node.larger
|
561
|
+
return false unless node.check_node_link('larger', stack)
|
562
|
+
larger_node = node.larger
|
563
|
+
if larger_node.size <= node.size
|
564
|
+
PEROBS.log.error "Larger SpaceTreeNode size " +
|
565
|
+
"(#{larger_node}) is not larger than #{node}"
|
566
|
+
return false
|
567
|
+
end
|
566
568
|
end
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
PEROBS.log.error "Larger SpaceTreeNode size " +
|
574
|
-
"(#{larger_node}) is not larger than #{node}"
|
569
|
+
when :on_exit
|
570
|
+
if flat_file &&
|
571
|
+
!flat_file.has_space?(node.blob_address, node.size)
|
572
|
+
PEROBS.log.error "SpaceTreeNode has space at offset " +
|
573
|
+
"#{node.blob_address} of size #{node.size} that isn't " +
|
574
|
+
"available in the FlatFile."
|
575
575
|
return false
|
576
576
|
end
|
577
|
-
end
|
578
|
-
when :on_exit
|
579
|
-
if flat_file &&
|
580
|
-
!flat_file.has_space?(node.blob_address, node.size)
|
581
|
-
PEROBS.log.error "SpaceTreeNode has space at offset " +
|
582
|
-
"#{node.blob_address} of size #{node.size} that isn't " +
|
583
|
-
"available in the FlatFile."
|
584
|
-
return false
|
585
|
-
end
|
586
577
|
|
587
|
-
|
578
|
+
pm.update(node_counter += 1)
|
579
|
+
end
|
588
580
|
end
|
589
581
|
end
|
590
582
|
PEROBS.log.debug "#{node_counter} SpaceTree nodes checked"
|
data/lib/perobs/Store.rb
CHANGED
@@ -2,7 +2,8 @@
|
|
2
2
|
#
|
3
3
|
# = Store.rb -- Persistent Ruby Object Store
|
4
4
|
#
|
5
|
-
# Copyright (c) 2015, 2016
|
5
|
+
# Copyright (c) 2015, 2016, 2017, 2018, 2019
|
6
|
+
# by Chris Schlaeger <chris@taskjuggler.org>
|
6
7
|
#
|
7
8
|
# MIT License
|
8
9
|
#
|
@@ -36,6 +37,11 @@ require 'perobs/FlatFileDB'
|
|
36
37
|
require 'perobs/Object'
|
37
38
|
require 'perobs/Hash'
|
38
39
|
require 'perobs/Array'
|
40
|
+
require 'perobs/BigTree'
|
41
|
+
require 'perobs/BigHash'
|
42
|
+
require 'perobs/BigArray'
|
43
|
+
require 'perobs/ProgressMeter'
|
44
|
+
require 'perobs/ConsoleProgressMeter'
|
39
45
|
|
40
46
|
# PErsistent Ruby OBject Store
|
41
47
|
module PEROBS
|
@@ -132,8 +138,14 @@ module PEROBS
|
|
132
138
|
# :yaml : Can also handle most Ruby data types and is
|
133
139
|
# portable between Ruby versions (1.9 and later).
|
134
140
|
# Unfortunately, it is 10x slower than marshal.
|
141
|
+
# :progressmeter : reference to a ProgressMeter object that receives
|
142
|
+
# progress information during longer running tasks.
|
143
|
+
# It defaults to ProgressMeter which only logs into
|
144
|
+
# the log. Use ConsoleProgressMeter or a derived
|
145
|
+
# class for more fancy progress reporting.
|
135
146
|
def initialize(data_base, options = {})
|
136
147
|
# Create a backing store handler
|
148
|
+
@progressmeter = (options[:progressmeter] ||= ProgressMeter.new)
|
137
149
|
@db = (options[:engine] || FlatFileDB).new(data_base, options)
|
138
150
|
@db.open
|
139
151
|
# Create a map that can translate classes to numerical IDs and vice
|
@@ -197,7 +209,10 @@ module PEROBS
|
|
197
209
|
# method was called.
|
198
210
|
def exit
|
199
211
|
if @cache && @cache.in_transaction?
|
200
|
-
|
212
|
+
@cache.abort_transaction
|
213
|
+
@cache.flush
|
214
|
+
@db.close if @db
|
215
|
+
PEROBS.log.fatal "You cannot call exit() during a transaction: #{Kernel.caller}"
|
201
216
|
end
|
202
217
|
@cache.flush if @cache
|
203
218
|
@db.close if @db
|
@@ -297,20 +312,30 @@ module PEROBS
|
|
297
312
|
# needed.
|
298
313
|
def sync
|
299
314
|
if @cache.in_transaction?
|
300
|
-
|
315
|
+
@cache.abort_transaction
|
316
|
+
@cache.flush
|
317
|
+
PEROBS.log.fatal "You cannot call sync() during a transaction: \n" +
|
318
|
+
Kernel.caller.join("\n")
|
301
319
|
end
|
302
320
|
@cache.flush
|
303
321
|
end
|
304
322
|
|
323
|
+
# Return the number of object stored in the store. CAVEAT: This method
|
324
|
+
# will only return correct values when it is separated from any mutating
|
325
|
+
# call by a call to sync().
|
326
|
+
# @return [Integer] Number of persistently stored objects in the Store.
|
327
|
+
def size
|
328
|
+
# We don't include the Hash that stores the root objects into the object
|
329
|
+
# count.
|
330
|
+
@db.item_counter - 1
|
331
|
+
end
|
332
|
+
|
305
333
|
# Discard all objects that are not somehow connected to the root objects
|
306
334
|
# from the back-end storage. The garbage collector is not invoked
|
307
335
|
# automatically. Depending on your usage pattern, you need to call this
|
308
336
|
# method periodically.
|
309
337
|
# @return [Integer] The number of collected objects
|
310
338
|
def gc
|
311
|
-
if @cache.in_transaction?
|
312
|
-
PEROBS.log.fatal 'You cannot call gc() during a transaction'
|
313
|
-
end
|
314
339
|
sync
|
315
340
|
mark
|
316
341
|
sweep
|
@@ -354,10 +379,6 @@ module PEROBS
|
|
354
379
|
return obj
|
355
380
|
end
|
356
381
|
|
357
|
-
#if (obj = @db.search_object(id))
|
358
|
-
# PEROBS.log.fatal "Object was not in index but in DB"
|
359
|
-
#end
|
360
|
-
|
361
382
|
# The requested object does not exist. Return nil.
|
362
383
|
nil
|
363
384
|
end
|
@@ -370,38 +391,42 @@ module PEROBS
|
|
370
391
|
# made.
|
371
392
|
# @return [Integer] The number of references to bad objects found.
|
372
393
|
def check(repair = false)
|
394
|
+
stats = { :errors => 0, :object_cnt => 0 }
|
395
|
+
|
373
396
|
# All objects must have in-db version.
|
374
397
|
sync
|
375
398
|
# Run basic consistency checks first.
|
376
|
-
errors
|
399
|
+
stats[:errors] += @db.check_db(repair)
|
377
400
|
|
378
401
|
# We will use the mark to mark all objects that we have checked already.
|
379
402
|
# Before we start, we need to clear all marks.
|
380
403
|
@db.clear_marks
|
381
404
|
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
405
|
+
@progressmeter.start("Checking object link structure",
|
406
|
+
@db.item_counter) do
|
407
|
+
@root_objects.each do |name, id|
|
408
|
+
check_object(id, repair, stats)
|
409
|
+
end
|
386
410
|
end
|
387
411
|
|
388
412
|
# Delete all broken root objects.
|
389
413
|
if repair
|
390
414
|
@root_objects.delete_if do |name, id|
|
391
|
-
unless
|
415
|
+
unless @db.check(id, repair)
|
392
416
|
PEROBS.log.error "Discarding broken root object '#{name}' " +
|
393
417
|
"with ID #{id}"
|
394
|
-
errors += 1
|
418
|
+
stats[:errors] += 1
|
395
419
|
end
|
396
|
-
!res
|
397
420
|
end
|
398
421
|
end
|
399
422
|
|
400
|
-
if errors > 0
|
423
|
+
if stats[:errors] > 0
|
401
424
|
if repair
|
402
|
-
PEROBS.log.error "#{errors} errors found in
|
425
|
+
PEROBS.log.error "#{stats[:errors]} errors found in " +
|
426
|
+
"#{stats[:object_cnt]} objects"
|
403
427
|
else
|
404
|
-
PEROBS.log.fatal "#{errors} errors found in
|
428
|
+
PEROBS.log.fatal "#{stats[:errors]} errors found in " +
|
429
|
+
"#{stats[:object_cnt]} objects"
|
405
430
|
end
|
406
431
|
else
|
407
432
|
PEROBS.log.debug "No errors found"
|
@@ -410,7 +435,7 @@ module PEROBS
|
|
410
435
|
# Ensure that any fixes are written into the DB.
|
411
436
|
sync if repair
|
412
437
|
|
413
|
-
errors
|
438
|
+
stats[:errors]
|
414
439
|
end
|
415
440
|
|
416
441
|
# This method will execute the provided block as an atomic transaction
|
@@ -439,7 +464,10 @@ module PEROBS
|
|
439
464
|
stack = [ 0 ] + @root_objects.values
|
440
465
|
while !stack.empty?
|
441
466
|
# Get an object index from the stack.
|
442
|
-
|
467
|
+
id = stack.pop
|
468
|
+
next if @db.is_marked?(id)
|
469
|
+
|
470
|
+
unless (obj = object_by_id(id))
|
443
471
|
PEROBS.log.fatal "Database is corrupted. Object with ID #{id} " +
|
444
472
|
"not found."
|
445
473
|
end
|
@@ -510,19 +538,25 @@ module PEROBS
|
|
510
538
|
def mark
|
511
539
|
classes = Set.new
|
512
540
|
marked_objects = 0
|
513
|
-
|
541
|
+
@progressmeter.start("Marking linked objects", @db.item_counter) do
|
542
|
+
each do |obj|
|
543
|
+
classes.add(obj.class)
|
544
|
+
@progressmeter.update(marked_objects += 1)
|
545
|
+
end
|
546
|
+
end
|
514
547
|
@class_map.keep(classes.map { |c| c.to_s })
|
515
548
|
|
516
549
|
# The root_objects object is included in the count, but we only want to
|
517
550
|
# count user objects here.
|
518
|
-
PEROBS.log.debug "#{marked_objects - 1}
|
551
|
+
PEROBS.log.debug "#{marked_objects - 1} of #{@db.item_counter} " +
|
552
|
+
"objects marked"
|
519
553
|
@stats.marked_objects = marked_objects - 1
|
520
554
|
end
|
521
555
|
|
522
556
|
# Sweep phase of a mark-and-sweep garbage collector. It will remove all
|
523
557
|
# unmarked objects from the store.
|
524
558
|
def sweep
|
525
|
-
@stats.swept_objects = @db.delete_unmarked_objects
|
559
|
+
@stats.swept_objects = @db.delete_unmarked_objects
|
526
560
|
@cache.reset
|
527
561
|
PEROBS.log.debug "#{@stats.swept_objects} objects collected"
|
528
562
|
@stats.swept_objects
|
@@ -534,8 +568,7 @@ module PEROBS
|
|
534
568
|
# with
|
535
569
|
# @param repair [Boolean] Delete refernces to broken objects if true
|
536
570
|
# @return [Integer] The number of references to bad objects.
|
537
|
-
def check_object(start_id, repair)
|
538
|
-
errors = 0
|
571
|
+
def check_object(start_id, repair, stats)
|
539
572
|
@db.mark(start_id)
|
540
573
|
# The todo list holds a touple for each object that still needs to be
|
541
574
|
# checked. The first item is the referring object and the second is the
|
@@ -546,7 +579,13 @@ module PEROBS
|
|
546
579
|
# Get the next PEROBS object to check
|
547
580
|
ref_obj, id = todo_list.pop
|
548
581
|
|
549
|
-
|
582
|
+
begin
|
583
|
+
obj = object_by_id(id)
|
584
|
+
rescue PEROBS::FatalError
|
585
|
+
obj = nil
|
586
|
+
end
|
587
|
+
|
588
|
+
if obj
|
550
589
|
# The object exists and is OK. Mark is as checked.
|
551
590
|
@db.mark(id)
|
552
591
|
# Now look at all other objects referenced by this object.
|
@@ -569,11 +608,11 @@ module PEROBS
|
|
569
608
|
ref_obj.inspect
|
570
609
|
end
|
571
610
|
end
|
572
|
-
errors += 1
|
611
|
+
stats[:errors] += 1
|
573
612
|
end
|
574
|
-
end
|
575
613
|
|
576
|
-
|
614
|
+
@progressmeter.update(stats[:object_cnt] += 1)
|
615
|
+
end
|
577
616
|
end
|
578
617
|
|
579
618
|
end
|