class Prometheus::Client::DataStores::DirectFileStore::FileMappedDict
A dict of doubles, backed by an file we access directly a a byte array.
The file starts with a 4 byte int, indicating how much of it is used. Then 4 bytes of padding. There's then a number of entries, consisting of a 4 byte int which is the size of the next field, a utf-8 encoded string key, padding to an 8 byte alignment, and then a 8 byte float which is the value.
Constants
- INITIAL_FILE_SIZE
Attributes
capacity[R]
positions[R]
used[R]
Public Class Methods
new(filename, readonly = false)
click to toggle source
# File lib/prometheus/client/data_stores/direct_file_store.rb, line 213 def initialize(filename, readonly = false) @positions = {} @used = 0 open_file(filename, readonly) @used = @f.read(4).unpack('l')[0] if @capacity > 0 if @used > 0 # File already has data. Read the existing values with_file_lock { populate_positions } else # File is empty. Init the `used` counter, if we're in write mode if !readonly @used = 8 @f.seek(0) @f.write([@used].pack('l')) end end end
Public Instance Methods
all_values()
click to toggle source
Return a list of key-value pairs
# File lib/prometheus/client/data_stores/direct_file_store.rb, line 234 def all_values with_file_lock do @positions.map do |key, pos| @f.seek(pos) value = @f.read(8).unpack('d')[0] [key, value] end end end
close()
click to toggle source
# File lib/prometheus/client/data_stores/direct_file_store.rb, line 265 def close @f.close end
read_value(key)
click to toggle source
# File lib/prometheus/client/data_stores/direct_file_store.rb, line 244 def read_value(key) if !@positions.has_key?(key) init_value(key) end pos = @positions[key] @f.seek(pos) @f.read(8).unpack('d')[0] end
with_file_lock() { || ... }
click to toggle source
# File lib/prometheus/client/data_stores/direct_file_store.rb, line 269 def with_file_lock @f.flock(File::LOCK_EX) yield ensure @f.flock(File::LOCK_UN) end
write_value(key, value)
click to toggle source
# File lib/prometheus/client/data_stores/direct_file_store.rb, line 254 def write_value(key, value) if !@positions.has_key?(key) init_value(key) end pos = @positions[key] @f.seek(pos) @f.write([value].pack('d')) @f.flush end
Private Instance Methods
init_value(key)
click to toggle source
Initialize a value. Lock must be held by caller.
# File lib/prometheus/client/data_stores/direct_file_store.rb, line 299 def init_value(key) # Pad to be 8-byte aligned. padded = key + (' ' * (8 - (key.length + 4) % 8)) value = [padded.length, padded, 0.0].pack("lA#{padded.length}d") while @used + value.length > @capacity @capacity *= 2 resize_file(@capacity) end @f.seek(@used) @f.write(value) @used += value.length @f.seek(0) @f.write([@used].pack('l')) @f.flush @positions[key] = @used - 8 end
open_file(filename, readonly)
click to toggle source
# File lib/prometheus/client/data_stores/direct_file_store.rb, line 278 def open_file(filename, readonly) mode = if readonly "r" elsif File.exist?(filename) "r+b" else "w+b" end @f = File.open(filename, mode) if @f.size == 0 && !readonly resize_file(INITIAL_FILE_SIZE) end @capacity = @f.size end
populate_positions()
click to toggle source
Read position of all keys. No locking is performed.
# File lib/prometheus/client/data_stores/direct_file_store.rb, line 317 def populate_positions @f.seek(8) while @f.pos < @used padded_len = @f.read(4).unpack('l')[0] key = @f.read(padded_len).unpack("A#{padded_len}")[0].strip @positions[key] = @f.pos @f.seek(8, :CUR) end end
resize_file(new_capacity)
click to toggle source
# File lib/prometheus/client/data_stores/direct_file_store.rb, line 294 def resize_file(new_capacity) @f.truncate(new_capacity) end