@@ -309,6 +309,7 @@ def get(self):
309
309
with self ._lock :
310
310
return self ._value
311
311
312
+
312
313
class _MmapedDict (object ):
313
314
"""A dict of doubles, backed by an mmapped file.
314
315
@@ -317,9 +318,10 @@ class _MmapedDict(object):
317
318
There's then a number of entries, consisting of a 4 byte int which is the
318
319
size of the next field, a utf-8 encoded string key, padding to a 8 byte
319
320
alignment, and then a 8 byte float which is the value.
321
+
322
+ Not thread safe.
320
323
"""
321
324
def __init__ (self , filename ):
322
- self ._lock = Lock ()
323
325
self ._f = open (filename , 'a+b' )
324
326
if os .fstat (self ._f .fileno ()).st_size == 0 :
325
327
self ._f .truncate (_INITIAL_MMAP_SIZE )
@@ -371,17 +373,15 @@ def read_all_values(self):
371
373
yield k , v
372
374
373
375
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 )
377
378
pos = self ._positions [key ]
378
379
# We assume that reading from an 8 byte aligned value is atomic
379
380
return struct .unpack_from (b'd' , self ._m , pos )[0 ]
380
381
381
382
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 )
385
385
pos = self ._positions [key ]
386
386
# We assume that writing to an 8 byte aligned value is atomic
387
387
struct .pack_into (b'd' , self ._m , pos , value )
@@ -395,7 +395,10 @@ def close(self):
395
395
def _MultiProcessValue (__pid = os .getpid ()):
396
396
pid = __pid
397
397
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 ()
399
402
400
403
class _MmapedValue (object ):
401
404
'''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
407
410
file_prefix = typ + '_' + multiprocess_mode
408
411
else :
409
412
file_prefix = typ
410
- with files_lock :
413
+ with lock :
411
414
if file_prefix not in files :
412
415
filename = os .path .join (
413
416
os .environ ['prometheus_multiproc_dir' ], '{0}_{1}.db' .format (file_prefix , pid ))
414
417
files [file_prefix ] = _MmapedDict (filename )
415
418
self ._file = files [file_prefix ]
416
419
self ._key = json .dumps ((metric_name , name , labelnames , labelvalues ))
417
420
self ._value = self ._file .read_value (self ._key )
418
- self ._lock = Lock ()
419
421
420
422
def inc (self , amount ):
421
- with self . _lock :
423
+ with lock :
422
424
self ._value += amount
423
425
self ._file .write_value (self ._key , self ._value )
424
426
425
427
def set (self , value ):
426
- with self . _lock :
428
+ with lock :
427
429
self ._value = value
428
430
self ._file .write_value (self ._key , self ._value )
429
431
430
432
def get (self ):
431
- with self . _lock :
433
+ with lock :
432
434
return self ._value
433
435
434
436
return _MmapedValue
0 commit comments