@@ -309,6 +309,7 @@ def get(self):
309309 with self ._lock :
310310 return self ._value
311311
312+
312313class _MmapedDict (object ):
313314 """A dict of doubles, backed by an mmapped file.
314315
@@ -317,9 +318,10 @@ class _MmapedDict(object):
317318 There's then a number of entries, consisting of a 4 byte int which is the
318319 size of the next field, a utf-8 encoded string key, padding to a 8 byte
319320 alignment, and then a 8 byte float which is the value.
321+
322+ Not thread safe.
320323 """
321324 def __init__ (self , filename ):
322- self ._lock = Lock ()
323325 self ._f = open (filename , 'a+b' )
324326 if os .fstat (self ._f .fileno ()).st_size == 0 :
325327 self ._f .truncate (_INITIAL_MMAP_SIZE )
@@ -371,17 +373,15 @@ def read_all_values(self):
371373 yield k , v
372374
373375 def read_value (self , key ):
374- with self ._lock :
375- if key not in self ._positions :
376- self ._init_value (key )
376+ if key not in self ._positions :
377+ self ._init_value (key )
377378 pos = self ._positions [key ]
378379 # We assume that reading from an 8 byte aligned value is atomic
379380 return struct .unpack_from (b'd' , self ._m , pos )[0 ]
380381
381382 def write_value (self , key , value ):
382- with self ._lock :
383- if key not in self ._positions :
384- self ._init_value (key )
383+ if key not in self ._positions :
384+ self ._init_value (key )
385385 pos = self ._positions [key ]
386386 # We assume that writing to an 8 byte aligned value is atomic
387387 struct .pack_into (b'd' , self ._m , pos , value )
@@ -395,7 +395,10 @@ def close(self):
395395def _MultiProcessValue (__pid = os .getpid ()):
396396 pid = __pid
397397 files = {}
398- files_lock = Lock ()
398+ # Use a single global lock when in multi-processing mode
399+ # as we presume this means there is no threading going on.
400+ # This avoids the need to also have mutexes in __MmapDict.
401+ lock = Lock ()
399402
400403 class _MmapedValue (object ):
401404 '''A float protected by a mutex backed by a per-process mmaped file.'''
@@ -407,28 +410,27 @@ def __init__(self, typ, metric_name, name, labelnames, labelvalues, multiprocess
407410 file_prefix = typ + '_' + multiprocess_mode
408411 else :
409412 file_prefix = typ
410- with files_lock :
413+ with lock :
411414 if file_prefix not in files :
412415 filename = os .path .join (
413416 os .environ ['prometheus_multiproc_dir' ], '{0}_{1}.db' .format (file_prefix , pid ))
414417 files [file_prefix ] = _MmapedDict (filename )
415418 self ._file = files [file_prefix ]
416419 self ._key = json .dumps ((metric_name , name , labelnames , labelvalues ))
417420 self ._value = self ._file .read_value (self ._key )
418- self ._lock = Lock ()
419421
420422 def inc (self , amount ):
421- with self . _lock :
423+ with lock :
422424 self ._value += amount
423425 self ._file .write_value (self ._key , self ._value )
424426
425427 def set (self , value ):
426- with self . _lock :
428+ with lock :
427429 self ._value = value
428430 self ._file .write_value (self ._key , self ._value )
429431
430432 def get (self ):
431- with self . _lock :
433+ with lock :
432434 return self ._value
433435
434436 return _MmapedValue
0 commit comments