Class: PEROBS::BTreeBlob
- Inherits:
-
Object
- Object
- PEROBS::BTreeBlob
- Defined in:
- lib/perobs/BTreeBlob.rb
Overview
This class manages the usage of the data blobs in the corresponding HashedBlobsDB object.
Constant Summary collapse
- ID =
For performance reasons we use an Array for the entries instead of a Hash. These constants specify the Array index for the corresponding value.
0- BYTES =
Number of bytes
1- START =
Start Address
2- MARKED =
Mark/Unmarked flag
3
Instance Method Summary collapse
-
#check(repair = false) ⇒ TrueClass/FalseClass
Run a basic consistency check.
-
#clear_marks ⇒ Object
Clear the mark on all entries in the index.
-
#delete_unmarked_entries ⇒ Array
Remove all entries from the index that have not been marked.
-
#find(id) ⇒ Array
Find the data for the object with given id.
-
#initialize(dir, btreedb) ⇒ BTreeBlob
constructor
Create a new BTreeBlob object.
-
#is_marked?(id) ⇒ TrueClass or FalseClass
Check if the entry for a given ID is marked.
-
#mark(id) ⇒ Object
Set a mark on the entry with the given ID.
-
#read_object(id) ⇒ String
Read the entry for the given ID and return it as bytes.
-
#write_object(id, raw) ⇒ Object
Write the given bytes with the given ID into the DB.
Constructor Details
#initialize(dir, btreedb) ⇒ BTreeBlob
Create a new BTreeBlob object.
49 50 51 52 53 54 55 56 |
# File 'lib/perobs/BTreeBlob.rb', line 49 def initialize(dir, btreedb) @dir = dir @btreedb = btreedb @index_file_name = File.join(dir, 'index') @blobs_file_name = File.join(dir, 'data') read_index end |
Instance Method Details
#check(repair = false) ⇒ TrueClass/FalseClass
Run a basic consistency check.
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
# File 'lib/perobs/BTreeBlob.rb', line 162 def check(repair = false) # Determine size of the data blobs file. data_file_size = File.exists?(@blobs_file_name) ? File.size(@blobs_file_name) : 0 next_start = 0 prev_entry = nil @entries.each do |entry| # Entries should never overlap if prev_entry && next_start > entry[START] raise RuntimeError, "#{@dir}: Index entries are overlapping\n" + "ID: #{'%016X' % prev_entry[ID]} " + "Start: #{prev_entry[START]} " + "Bytes: #{prev_entry[BYTES]}\n" + "ID: #{'%016X' % entry[ID]} Start: #{entry[START]} " + "Bytes: #{entry[BYTES]}" end next_start = entry[START] + entry[BYTES] # Entries must fit within the data file if next_start > data_file_size raise RuntimeError, "#{@dir}: Entry for ID #{'%016X' % entry[ID]} " + "goes beyond 'data' file " + "size (#{data_file_size})\n" + "ID: #{'%016X' % entry[ID]} Start: #{entry[START]} " + "Bytes: #{entry[BYTES]}" end prev_entry = entry end true end |
#clear_marks ⇒ Object
Clear the mark on all entries in the index.
102 103 104 105 |
# File 'lib/perobs/BTreeBlob.rb', line 102 def clear_marks @entries.each { |e| e[MARKED] = 0 } write_index end |
#delete_unmarked_entries ⇒ Array
Remove all entries from the index that have not been marked.
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/perobs/BTreeBlob.rb', line 141 def delete_unmarked_entries deleted_ids = [] # First remove the entry from the hash table. @entries_by_id.delete_if do |id, e| if e[MARKED] == 0 deleted_ids << id true else false end end # Then delete the entry itself. @entries.delete_if { |e| e[MARKED] == 0 } write_index deleted_ids end |
#find(id) ⇒ Array
Find the data for the object with given id.
93 94 95 96 97 98 99 |
# File 'lib/perobs/BTreeBlob.rb', line 93 def find(id) if (entry = @entries_by_id[id]) return [ entry[BYTES], entry[START] ] end nil end |
#is_marked?(id) ⇒ TrueClass or FalseClass
Check if the entry for a given ID is marked.
130 131 132 133 134 135 136 137 |
# File 'lib/perobs/BTreeBlob.rb', line 130 def is_marked?(id) @entries.each do |entry| return entry[MARKED] != 0 if entry[ID] == id end raise ArgumentError, "Cannot find an entry for ID #{'%016X' % id} to check" end |
#mark(id) ⇒ Object
Set a mark on the entry with the given ID.
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/perobs/BTreeBlob.rb', line 109 def mark(id) found = false @entries.each do |entry| if entry[ID] == id entry[MARKED] = 1 found = true break end end unless found raise ArgumentError, "Cannot find an entry for ID #{'%016X' % id} to mark" end write_index end |
#read_object(id) ⇒ String
Read the entry for the given ID and return it as bytes.
82 83 84 85 |
# File 'lib/perobs/BTreeBlob.rb', line 82 def read_object(id) return nil unless (bytes_and_start = find(id)) read_from_blobs_file(*bytes_and_start) end |
#write_object(id, raw) ⇒ Object
Write the given bytes with the given ID into the DB.
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/perobs/BTreeBlob.rb', line 61 def write_object(id, raw) if @entries.length > @btreedb.max_blob_size # The blob has reached the maximum size. Replace the blob with a BTree # node directory and distribute the blob entires into the sub-blobs of # the new BTree node. split_blob # Insert the passed object into the newly created BTree node. @btreedb.put_raw_object(raw, id) else bytes = raw.bytesize start_address = reserve_bytes(id, bytes) if write_to_blobs_file(raw, start_address) != bytes raise RuntimeError, 'Object length does not match written bytes' end write_index end end |