perobs 4.0.0 → 4.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +27 -16
  3. data/lib/perobs/Array.rb +66 -19
  4. data/lib/perobs/BTree.rb +106 -15
  5. data/lib/perobs/BTreeBlob.rb +4 -3
  6. data/lib/perobs/BTreeDB.rb +5 -4
  7. data/lib/perobs/BTreeNode.rb +482 -156
  8. data/lib/perobs/BTreeNodeLink.rb +10 -0
  9. data/lib/perobs/BigArray.rb +285 -0
  10. data/lib/perobs/BigArrayNode.rb +1002 -0
  11. data/lib/perobs/BigHash.rb +246 -0
  12. data/lib/perobs/BigTree.rb +197 -0
  13. data/lib/perobs/BigTreeNode.rb +873 -0
  14. data/lib/perobs/Cache.rb +48 -10
  15. data/lib/perobs/ConsoleProgressMeter.rb +61 -0
  16. data/lib/perobs/DataBase.rb +4 -3
  17. data/lib/perobs/DynamoDB.rb +57 -15
  18. data/lib/perobs/EquiBlobsFile.rb +155 -50
  19. data/lib/perobs/FNV_Hash_1a_64.rb +54 -0
  20. data/lib/perobs/FlatFile.rb +519 -227
  21. data/lib/perobs/FlatFileBlobHeader.rb +113 -54
  22. data/lib/perobs/FlatFileDB.rb +49 -23
  23. data/lib/perobs/FuzzyStringMatcher.rb +175 -0
  24. data/lib/perobs/Hash.rb +127 -33
  25. data/lib/perobs/IDList.rb +144 -0
  26. data/lib/perobs/IDListPage.rb +107 -0
  27. data/lib/perobs/IDListPageFile.rb +180 -0
  28. data/lib/perobs/IDListPageRecord.rb +142 -0
  29. data/lib/perobs/Object.rb +18 -15
  30. data/lib/perobs/ObjectBase.rb +46 -5
  31. data/lib/perobs/PersistentObjectCache.rb +57 -68
  32. data/lib/perobs/PersistentObjectCacheLine.rb +24 -12
  33. data/lib/perobs/ProgressMeter.rb +97 -0
  34. data/lib/perobs/SpaceManager.rb +273 -0
  35. data/lib/perobs/SpaceTree.rb +21 -12
  36. data/lib/perobs/SpaceTreeNode.rb +53 -61
  37. data/lib/perobs/Store.rb +264 -145
  38. data/lib/perobs/version.rb +1 -1
  39. data/lib/perobs.rb +2 -0
  40. data/perobs.gemspec +4 -4
  41. data/test/Array_spec.rb +15 -6
  42. data/test/BTree_spec.rb +6 -2
  43. data/test/BigArray_spec.rb +261 -0
  44. data/test/BigHash_spec.rb +152 -0
  45. data/test/BigTreeNode_spec.rb +153 -0
  46. data/test/BigTree_spec.rb +259 -0
  47. data/test/EquiBlobsFile_spec.rb +105 -1
  48. data/test/FNV_Hash_1a_64_spec.rb +59 -0
  49. data/test/FlatFileDB_spec.rb +198 -14
  50. data/test/FuzzyStringMatcher_spec.rb +261 -0
  51. data/test/Hash_spec.rb +13 -3
  52. data/test/IDList_spec.rb +77 -0
  53. data/test/LegacyDBs/LegacyDB.rb +155 -0
  54. data/test/LegacyDBs/version_3/class_map.json +1 -0
  55. data/test/LegacyDBs/version_3/config.json +1 -0
  56. data/test/LegacyDBs/version_3/database.blobs +0 -0
  57. data/test/LegacyDBs/version_3/database_spaces.blobs +0 -0
  58. data/test/LegacyDBs/version_3/index.blobs +0 -0
  59. data/test/LegacyDBs/version_3/version +1 -0
  60. data/test/LockFile_spec.rb +9 -6
  61. data/test/SpaceManager_spec.rb +176 -0
  62. data/test/SpaceTree_spec.rb +4 -1
  63. data/test/Store_spec.rb +305 -203
  64. data/test/spec_helper.rb +9 -4
  65. metadata +57 -16
  66. data/lib/perobs/BTreeNodeCache.rb +0 -109
  67. data/lib/perobs/TreeDB.rb +0 -277
data/test/spec_helper.rb CHANGED
@@ -41,15 +41,20 @@ def generate_db_name(caller_file)
41
41
  end
42
42
 
43
43
  def capture_io
44
- PEROBS.log.open(io = StringIO.new)
44
+ old_stdout = $stdout
45
+ $stdout = out = StringIO.new
46
+ PEROBS.log.open(log = StringIO.new)
47
+
45
48
  begin
46
49
  yield
47
50
  ensure
51
+ $stdout = old_stdout
48
52
  PEROBS.log.open($stderr)
49
53
  end
50
54
 
51
- io.rewind
52
- io.read
53
- end
55
+ out.rewind
56
+ log.rewind
54
57
 
58
+ Struct.new(:out, :log).new(out.read, log.read)
59
+ end
55
60
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: perobs
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.0
4
+ version: 4.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Schlaeger
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-11-05 00:00:00.000000000 Z
11
+ date: 2022-02-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -16,42 +16,42 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.6'
19
+ version: '2.3'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.6'
26
+ version: '2.3'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: yard
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.8.7
33
+ version: 0.9.12
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.8.7
40
+ version: 0.9.12
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '10.0'
47
+ version: 13.0.3
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '10.0'
54
+ version: 13.0.3
55
55
  description: Library to provide a persistent object store
56
56
  email:
57
57
  - chris@linux.com
@@ -70,31 +70,43 @@ files:
70
70
  - lib/perobs/BTreeBlob.rb
71
71
  - lib/perobs/BTreeDB.rb
72
72
  - lib/perobs/BTreeNode.rb
73
- - lib/perobs/BTreeNodeCache.rb
74
73
  - lib/perobs/BTreeNodeLink.rb
74
+ - lib/perobs/BigArray.rb
75
+ - lib/perobs/BigArrayNode.rb
76
+ - lib/perobs/BigHash.rb
77
+ - lib/perobs/BigTree.rb
78
+ - lib/perobs/BigTreeNode.rb
75
79
  - lib/perobs/Cache.rb
76
80
  - lib/perobs/ClassMap.rb
81
+ - lib/perobs/ConsoleProgressMeter.rb
77
82
  - lib/perobs/DataBase.rb
78
83
  - lib/perobs/DynamoDB.rb
79
84
  - lib/perobs/EquiBlobsFile.rb
85
+ - lib/perobs/FNV_Hash_1a_64.rb
80
86
  - lib/perobs/FlatFile.rb
81
87
  - lib/perobs/FlatFileBlobHeader.rb
82
88
  - lib/perobs/FlatFileDB.rb
89
+ - lib/perobs/FuzzyStringMatcher.rb
83
90
  - lib/perobs/Handle.rb
84
91
  - lib/perobs/Hash.rb
92
+ - lib/perobs/IDList.rb
93
+ - lib/perobs/IDListPage.rb
94
+ - lib/perobs/IDListPageFile.rb
95
+ - lib/perobs/IDListPageRecord.rb
85
96
  - lib/perobs/LockFile.rb
86
97
  - lib/perobs/Log.rb
87
98
  - lib/perobs/Object.rb
88
99
  - lib/perobs/ObjectBase.rb
89
100
  - lib/perobs/PersistentObjectCache.rb
90
101
  - lib/perobs/PersistentObjectCacheLine.rb
102
+ - lib/perobs/ProgressMeter.rb
91
103
  - lib/perobs/RobustFile.rb
104
+ - lib/perobs/SpaceManager.rb
92
105
  - lib/perobs/SpaceTree.rb
93
106
  - lib/perobs/SpaceTreeNode.rb
94
107
  - lib/perobs/SpaceTreeNodeLink.rb
95
108
  - lib/perobs/StackFile.rb
96
109
  - lib/perobs/Store.rb
97
- - lib/perobs/TreeDB.rb
98
110
  - lib/perobs/version.rb
99
111
  - perobs.gemspec
100
112
  - tasks/changelog.rake
@@ -104,12 +116,27 @@ files:
104
116
  - test/Array_spec.rb
105
117
  - test/BTreeDB_spec.rb
106
118
  - test/BTree_spec.rb
119
+ - test/BigArray_spec.rb
120
+ - test/BigHash_spec.rb
121
+ - test/BigTreeNode_spec.rb
122
+ - test/BigTree_spec.rb
107
123
  - test/ClassMap_spec.rb
108
124
  - test/EquiBlobsFile_spec.rb
125
+ - test/FNV_Hash_1a_64_spec.rb
109
126
  - test/FlatFileDB_spec.rb
127
+ - test/FuzzyStringMatcher_spec.rb
110
128
  - test/Hash_spec.rb
129
+ - test/IDList_spec.rb
130
+ - test/LegacyDBs/LegacyDB.rb
131
+ - test/LegacyDBs/version_3/class_map.json
132
+ - test/LegacyDBs/version_3/config.json
133
+ - test/LegacyDBs/version_3/database.blobs
134
+ - test/LegacyDBs/version_3/database_spaces.blobs
135
+ - test/LegacyDBs/version_3/index.blobs
136
+ - test/LegacyDBs/version_3/version
111
137
  - test/LockFile_spec.rb
112
138
  - test/Object_spec.rb
139
+ - test/SpaceManager_spec.rb
113
140
  - test/SpaceTree_spec.rb
114
141
  - test/StackFile_spec.rb
115
142
  - test/Store_spec.rb
@@ -119,7 +146,7 @@ homepage: https://github.com/scrapper/perobs
119
146
  licenses:
120
147
  - MIT
121
148
  metadata: {}
122
- post_install_message:
149
+ post_install_message:
123
150
  rdoc_options: []
124
151
  require_paths:
125
152
  - lib
@@ -127,28 +154,42 @@ required_ruby_version: !ruby/object:Gem::Requirement
127
154
  requirements:
128
155
  - - ">="
129
156
  - !ruby/object:Gem::Version
130
- version: '2.0'
157
+ version: '2.4'
131
158
  required_rubygems_version: !ruby/object:Gem::Requirement
132
159
  requirements:
133
160
  - - ">="
134
161
  - !ruby/object:Gem::Version
135
162
  version: '0'
136
163
  requirements: []
137
- rubyforge_project:
138
- rubygems_version: 2.2.5
139
- signing_key:
164
+ rubygems_version: 3.2.32
165
+ signing_key:
140
166
  specification_version: 4
141
167
  summary: Persistent Ruby Object Store
142
168
  test_files:
143
169
  - test/Array_spec.rb
144
170
  - test/BTreeDB_spec.rb
145
171
  - test/BTree_spec.rb
172
+ - test/BigArray_spec.rb
173
+ - test/BigHash_spec.rb
174
+ - test/BigTreeNode_spec.rb
175
+ - test/BigTree_spec.rb
146
176
  - test/ClassMap_spec.rb
147
177
  - test/EquiBlobsFile_spec.rb
178
+ - test/FNV_Hash_1a_64_spec.rb
148
179
  - test/FlatFileDB_spec.rb
180
+ - test/FuzzyStringMatcher_spec.rb
149
181
  - test/Hash_spec.rb
182
+ - test/IDList_spec.rb
183
+ - test/LegacyDBs/LegacyDB.rb
184
+ - test/LegacyDBs/version_3/class_map.json
185
+ - test/LegacyDBs/version_3/config.json
186
+ - test/LegacyDBs/version_3/database.blobs
187
+ - test/LegacyDBs/version_3/database_spaces.blobs
188
+ - test/LegacyDBs/version_3/index.blobs
189
+ - test/LegacyDBs/version_3/version
150
190
  - test/LockFile_spec.rb
151
191
  - test/Object_spec.rb
192
+ - test/SpaceManager_spec.rb
152
193
  - test/SpaceTree_spec.rb
153
194
  - test/StackFile_spec.rb
154
195
  - test/Store_spec.rb
@@ -1,109 +0,0 @@
1
- # encoding: UTF-8
2
- #
3
- # = BTree.rb -- Persistent Ruby Object Store
4
- #
5
- # Copyright (c) 2016, 2017 by Chris Schlaeger <chris@taskjuggler.org>
6
- #
7
- # MIT License
8
- #
9
- # Permission is hereby granted, free of charge, to any person obtaining
10
- # a copy of this software and associated documentation files (the
11
- # "Software"), to deal in the Software without restriction, including
12
- # without limitation the rights to use, copy, modify, merge, publish,
13
- # distribute, sublicense, and/or sell copies of the Software, and to
14
- # permit persons to whom the Software is furnished to do so, subject to
15
- # the following conditions:
16
- #
17
- # The above copyright notice and this permission notice shall be
18
- # included in all copies or substantial portions of the Software.
19
- #
20
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
-
28
- require 'perobs/BTreeNode'
29
-
30
- module PEROBS
31
-
32
- class BTreeNodeCache
33
-
34
- def initialize(tree)
35
- @tree = tree
36
- clear
37
- end
38
-
39
- def get(address)
40
- if (node = @modified_nodes[address])
41
- return node
42
- end
43
-
44
- if (node = @top_nodes[address])
45
- return node
46
- end
47
-
48
- if (node = @ephemeral_nodes[address])
49
- return node
50
- end
51
-
52
- BTreeNode::load(@tree, address)
53
- end
54
-
55
- def set_root(node)
56
- node = node.get_node if node.is_a?(BTreeNodeLink)
57
-
58
- @top_nodes = {}
59
- @top_nodes[node.node_address] = node
60
- end
61
-
62
- def insert(node, modified = true)
63
- unless node
64
- PEROBS.log.fatal "nil cannot be cached"
65
- end
66
- node = node.get_node if node.is_a?(BTreeNodeLink)
67
-
68
- if modified
69
- @modified_nodes[node.node_address] = node
70
- end
71
- @ephemeral_nodes[node.node_address] = node
72
-
73
- if !@top_nodes.include?(node) && node.is_top?
74
- @top_nodes[node.node_address] = node
75
- end
76
- end
77
-
78
- def _collect(address, ruby_object_id)
79
- # Just a dummy for now
80
- end
81
-
82
- # Remove a node from the cache.
83
- # @param address [Integer] address of node to remove.
84
- def delete(address)
85
- @ephemeral_nodes.delete(address)
86
- @top_nodes.delete(address)
87
- @modified_nodes.delete(address)
88
- end
89
-
90
- # Flush all dirty nodes into the backing store.
91
- def flush(now = false)
92
- if now || @modified_nodes.size > 1024
93
- @modified_nodes.each_value { |node| node.write_node }
94
- @modified_nodes = {}
95
- end
96
- @ephemeral_nodes = {}
97
- end
98
-
99
- # Remove all nodes from the cache.
100
- def clear
101
- @top_nodes = {}
102
- @ephemeral_nodes = {}
103
- @modified_nodes = {}
104
- end
105
-
106
- end
107
-
108
- end
109
-
data/lib/perobs/TreeDB.rb DELETED
@@ -1,277 +0,0 @@
1
- # encoding: UTF-8
2
- #
3
- # = BTreeDB.rb -- Persistent Ruby Object Store
4
- #
5
- # Copyright (c) 2015, 2016 by Chris Schlaeger <chris@taskjuggler.org>
6
- #
7
- # MIT License
8
- #
9
- # Permission is hereby granted, free of charge, to any person obtaining
10
- # a copy of this software and associated documentation files (the
11
- # "Software"), to deal in the Software without restriction, including
12
- # without limitation the rights to use, copy, modify, merge, publish,
13
- # distribute, sublicense, and/or sell copies of the Software, and to
14
- # permit persons to whom the Software is furnished to do so, subject to
15
- # the following conditions:
16
- #
17
- # The above copyright notice and this permission notice shall be
18
- # included in all copies or substantial portions of the Software.
19
- #
20
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
-
28
- require 'fileutils'
29
-
30
- require 'perobs/Log'
31
- require 'perobs/RobustFile'
32
- require 'perobs/DataBase'
33
- require 'perobs/BTreeBlob'
34
-
35
- module PEROBS
36
-
37
- # This class implements a BTree database using filesystem directories as
38
- # nodes and blob files as leafs. The BTree grows with the number of stored
39
- # entries. Each leaf node blob can hold a fixed number of entries. If more
40
- # entries need to be stored, the blob is replaced by a node with multiple
41
- # new leafs that store the entries of the previous node. The leafs are
42
- # implemented by the BTreeBlob class.
43
- class BTreeDB < DataBase
44
-
45
- attr_reader :max_blob_size
46
-
47
- # Create a new BTreeDB object.
48
- # @param db_name [String] name of the DB directory
49
- # @param options [Hash] options to customize the behavior. Currently only
50
- # the following options are supported:
51
- # :serializer : Can be :marshal, :json, :yaml
52
- # :dir_bits : The number of bits to use for the BTree nodes.
53
- # The value must be between 4 and 14. The larger
54
- # the number the more back-end directories are
55
- # being used. The default is 12 which results in
56
- # 4096 directories per node.
57
- # :max_blob_size : The maximum number of entries in the BTree leaf
58
- # nodes. The insert/find/delete time grows
59
- # linearly with the size.
60
- def initialize(db_name, options = {})
61
- super(options[:serializer] || :json)
62
-
63
- @db_dir = db_name
64
- # Create the database directory if it doesn't exist yet.
65
- ensure_dir_exists(@db_dir)
66
-
67
- # Read the existing DB config.
68
- @config = get_hash('config')
69
- check_option('serializer')
70
-
71
- # Check and set @dir_bits, the number of bits used for each tree level.
72
- @dir_bits = options[:dir_bits] || 12
73
- if @dir_bits < 4 || @dir_bits > 14
74
- PEROBS.log.fatal "dir_bits option (#{@dir_bits}) must be between 4 " +
75
- "and 12"
76
- end
77
- check_option('dir_bits')
78
-
79
- @max_blob_size = options[:max_blob_size] || 32
80
- if @max_blob_size < 4 || @max_blob_size > 128
81
- PEROBS.log.fatal "max_blob_size option (#{@max_blob_size}) must be " +
82
- "between 4 and 128"
83
- end
84
- check_option('max_blob_size')
85
-
86
- put_hash('config', @config)
87
-
88
- # This format string is used to create the directory name.
89
- @dir_format_string = "%0#{(@dir_bits / 4) +
90
- (@dir_bits % 4 == 0 ? 0 : 1)}X"
91
- # Bit mask to extract the dir_bits LSBs.
92
- @dir_mask = 2 ** @dir_bits - 1
93
- end
94
-
95
- # Delete the entire database. The database is no longer usable after this
96
- # method was called.
97
- def delete_database
98
- FileUtils.rm_rf(@db_dir)
99
- end
100
-
101
- def BTreeDB::delete_db(db_name)
102
- FileUtils.rm_rf(db_name)
103
- end
104
-
105
- # Return true if the object with given ID exists
106
- # @param id [Integer]
107
- def include?(id)
108
- !(blob = find_blob(id)).nil? && !blob.find(id).nil?
109
- end
110
-
111
- # Store a simple Hash as a JSON encoded file into the DB directory.
112
- # @param name [String] Name of the hash. Will be used as file name.
113
- # @param hash [Hash] A Hash that maps String objects to strings or
114
- # numbers.
115
- def put_hash(name, hash)
116
- file_name = File.join(@db_dir, name + '.json')
117
- begin
118
- RobustFile.write(file_name, hash.to_json)
119
- rescue IOError => e
120
- PEROBS.log.fatal "Cannot write hash file '#{file_name}': #{e.message}"
121
- end
122
- end
123
-
124
- # Load the Hash with the given name.
125
- # @param name [String] Name of the hash.
126
- # @return [Hash] A Hash that maps String objects to strings or numbers.
127
- def get_hash(name)
128
- file_name = File.join(@db_dir, name + '.json')
129
- return ::Hash.new unless File.exist?(file_name)
130
-
131
- begin
132
- json = File.read(file_name)
133
- rescue => e
134
- PEROBS.log.fatal "Cannot read hash file '#{file_name}': #{e.message}"
135
- end
136
- JSON.parse(json, :create_additions => true)
137
- end
138
-
139
- # Store the given object into the cluster files.
140
- # @param obj [Hash] Object as defined by PEROBS::ObjectBase
141
- def put_object(obj, id)
142
- find_blob(id, true).write_object(id, serialize(obj))
143
- end
144
-
145
- # Load the given object from the filesystem.
146
- # @param id [Integer] object ID
147
- # @return [Hash] Object as defined by PEROBS::ObjectBase or nil if ID does
148
- # not exist
149
- def get_object(id)
150
- return nil unless (blob = find_blob(id)) && (obj = blob.read_object(id))
151
- deserialize(obj)
152
- end
153
-
154
- # This method must be called to initiate the marking process.
155
- def clear_marks
156
- each_blob { |blob| blob.clear_marks }
157
- end
158
-
159
- # Permanently delete all objects that have not been marked. Those are
160
- # orphaned and are no longer referenced by any actively used object.
161
- # @return [Array] List of IDs that have been removed from the DB.
162
- def delete_unmarked_objects
163
- deleted_ids = []
164
- each_blob { |blob| deleted_ids += blob.delete_unmarked_entries }
165
- deleted_ids
166
- end
167
-
168
- # Mark an object.
169
- # @param id [Integer] ID of the object to mark
170
- def mark(id)
171
- (blob = find_blob(id)) && blob.mark(id)
172
- end
173
-
174
- # Check if the object is marked.
175
- # @param id [Integer] ID of the object to check
176
- # @param ignore_errors [Boolean] If set to true no errors will be raised
177
- # for non-existing objects.
178
- def is_marked?(id, ignore_errors = false)
179
- (blob = find_blob(id)) && blob.is_marked?(id, ignore_errors)
180
- end
181
-
182
- # Basic consistency check.
183
- # @param repair [TrueClass/FalseClass] True if found errors should be
184
- # repaired.
185
- def check_db(repair = false)
186
- each_blob { |blob| blob.check(repair) }
187
- end
188
-
189
- # Check if the stored object is syntactically correct.
190
- # @param id [Integer] Object ID
191
- # @param repair [TrueClass/FalseClass] True if an repair attempt should be
192
- # made.
193
- # @return [TrueClass/FalseClass] True if the object is OK, otherwise
194
- # false.
195
- def check(id, repair)
196
- begin
197
- get_object(id)
198
- rescue => e
199
- PEROBS.log.error "Cannot read object with ID #{id}: #{e.message}"
200
- return false
201
- end
202
-
203
- true
204
- end
205
-
206
- # Store the given serialized object into the cluster files. This method is
207
- # for internal use only!
208
- # @param raw [String] Serialized Object as defined by PEROBS::ObjectBase
209
- # @param id [Integer] Object ID
210
- def put_raw_object(raw, id)
211
- find_blob(id, true).write_object(id, raw)
212
- end
213
-
214
- private
215
-
216
- def find_blob(id, create_missing_blob = false, dir_name = @db_dir)
217
- dir_bits = id & @dir_mask
218
- sub_dir_name = File.join(dir_name, @dir_format_string % dir_bits)
219
-
220
- if Dir.exist?(sub_dir_name)
221
- if File.exist?(File.join(sub_dir_name, 'index'))
222
- # The directory is a blob directory and not a BTree node dir.
223
- return BTreeBlob.new(sub_dir_name, self)
224
- end
225
- else
226
- Dir.glob(File.join(dir_name, '*.index')).each do |fqfn|
227
- # Extract the 01-part of the filename
228
- lsb_string = File.basename(fqfn)[0..-6]
229
- # Convert the lsb_string into a Integer
230
- lsb = Integer('0b' + lsb_string)
231
- # Bit mask to match the LSBs
232
- mask = (2 ** lsb_string.length) - 1
233
- if (id & mask) == lsb
234
- return TreeBlob.new(sub_dir_name, lsb_string, self)
235
- end
236
- end
237
- if create_missing_blob
238
- # Create the new blob directory.
239
- Dir.mkdir(dir_name)
240
- # And initialize the blob DB.
241
- return BTreeBlob.new(dir_name, self)
242
- else
243
- return nil
244
- end
245
- end
246
-
247
- # Discard the least significant @dir_bits bits and start over again
248
- # with the directory that matches the @dir_bits LSBs of the new ID.
249
- id = id >> @dir_bits
250
- end
251
-
252
- def each_blob(&block)
253
- each_blob_r(@db_dir, &block)
254
- end
255
-
256
- def each_blob_r(dir, &block)
257
- Dir.glob(File.join(dir, '*')) do |dir_name|
258
- if is_blob_dir?(dir_name)
259
- block.call(BTreeBlob.new(dir_name, self))
260
- else
261
- each_blob_r(dir_name, &block)
262
- end
263
- end
264
- end
265
-
266
- def is_blob_dir?(dir_name)
267
- # A blob directory contains an 'index' and 'data' file. This is in
268
- # contrast to BTree node directories that only contain other
269
- # directories.
270
- index_file = File.join(dir_name, 'index')
271
- File.exist?(index_file)
272
- end
273
-
274
- end
275
-
276
- end
277
-