lib/prometheus/client/mmaped_dict.rb in prometheus-client-mmap-0.7.0.beta12 vs lib/prometheus/client/mmaped_dict.rb in prometheus-client-mmap-0.7.0.beta13
- old
+ new
@@ -1,11 +1,12 @@
require 'prometheus/client'
require 'mmap'
module Prometheus
module Client
- class ParsingError < StandardError; end
+ class ParsingError < StandardError
+ end
# A dict of doubles, backed by an mmapped file.
#
# The file starts with a 4 byte int, indicating how much of it is used.
# Then 4 bytes of padding.
@@ -21,34 +22,49 @@
def initialize(filename)
@mutex = Mutex.new
@f = File.open(filename, 'a+b')
process_file
rescue StandardError => e
- raise ParsingError.new("exception #{e} while processing metrics file #{@f.path}")
+ raise ParsingError, "exception #{e} while processing metrics file #{@f.path}"
end
- # Yield (key, value, pos). No locking is performed.
- def all_values
- read_all_values.map { |k, v, p| [k, v] }
+ # Yield (key, value). No locking is performed.
+ def self.read_all_values(f)
+ m = Mmap.new(f, 'rw', Mmap::MAP_SHARED)
+ used, = m[0..3].unpack('l')
+ pos = 8
+ values = []
+ while pos < used
+ data = m.slice(pos..-1)
+ encoded_len, = data.unpack('l')
+ value_offset = 4 + encoded_len + (8 - (encoded_len + 4) % 8)
+
+ encoded, value = data.unpack(format('@4A%d@%dd', encoded_len, value_offset))
+ values << [encoded, value]
+ pos += value_offset + 8
+ end
+ values
+ ensure
+ m.munmap
end
def read_value(key)
@mutex.synchronize do
- init_value(key) unless @positions.has_key?(key)
+ init_value(key) unless @positions.key?(key)
end
pos = @positions[key]
# We assume that reading from an 8 byte aligned value is atomic.
- @m[pos..pos+7].unpack('d')[0]
+ @m[pos..pos + 7].unpack('d')[0]
end
def write_value(key, value)
@mutex.synchronize do
- init_value(key) unless @positions.has_key?(key)
+ init_value(key) unless @positions.key?(key)
end
pos = @positions[key]
# We assume that writing to an 8 byte aligned value is atomic.
- @m[pos..pos+7] = [value].pack('d')
+ @m[pos..pos + 7] = [value].pack('d')
end
def close
@m.munmap
rescue TypeError => e
@@ -62,13 +78,11 @@
end
private
def process_file
- if @f.size < MINIMUM_SIZE
- @f.truncate(initial_mmap_file_size)
- end
+ @f.truncate(initial_mmap_file_size) if @f.size < MINIMUM_SIZE
@capacity = @f.size
@m = Mmap.new(@f.path, 'rw', Mmap::MAP_SHARED)
# @m.mlock # TODO: Why does this raise an error?
@@ -76,11 +90,11 @@
@used = @m[0..3].unpack('l')[0]
if @used == 0
@used = 8
@m[0..3] = [@used].pack('l')
else
- read_all_values.each do |key, _, pos|
+ read_all_positions.each do |key, _, pos|
@positions[key] = pos
end
end
end
@@ -102,23 +116,22 @@
@m[0..3] = [@used].pack('l')
@positions[key] = @used - 8
end
# Yield (key, value, pos). No locking is performed.
- def read_all_values
+ def read_all_positions
pos = 8
values = []
while pos < @used
- encoded_len = @m[pos..-1].unpack('l')[0]
- pos += 4
- encoded = @m[pos..-1].unpack("A#{encoded_len}")[0]
- padded_len = encoded_len + (8 - (encoded_len + 4) % 8)
- pos += padded_len
- value = @m[pos..-1].unpack('d')[0]
- values << [encoded, value, pos]
+ data = @m.slice(pos..-1)
+ encoded_len = data.unpack('l')[0]
+ padding_len = 8 - (encoded_len + 4) % 8
+ encoded = data.unpack(format('@4A%d', encoded_len))
+ pos += 4 + encoded_len + padding_len
+ values << [encoded, pos]
pos += 8
end
values
end
end
end
-end
\ No newline at end of file
+end