<s> import contextlib <EOL> import functools <EOL> import logging <EOL> import os <EOL> import shutil <EOL> import subprocess <EOL> import sys <EOL> import tempfile <EOL> import threading <EOL> import weakref <EOL> import fasteners <EOL> from oslo_config import cfg <EOL> from oslo_utils import reflection <EOL> from oslo_utils import timeutils <EOL> import six <EOL> from oslo_concurrency . _i18n import _ , _LI <EOL> LOG = logging . getLogger ( __name__ ) <EOL> _opts = [ <EOL> cfg . BoolOpt ( '<STR_LIT>' , default = False , <EOL> help = '<STR_LIT>' , <EOL> deprecated_group = '<STR_LIT>' ) , <EOL> cfg . StrOpt ( '<STR_LIT>' , <EOL> default = os . environ . get ( "<STR_LIT>" ) , <EOL> help = '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' , <EOL> deprecated_group = '<STR_LIT>' ) <EOL> ] <EOL> def _register_opts ( conf ) : <EOL> conf . register_opts ( _opts , group = '<STR_LIT>' ) <EOL> CONF = cfg . CONF <EOL> _register_opts ( CONF ) <EOL> def set_defaults ( lock_path ) : <EOL> """<STR_LIT>""" <EOL> cfg . set_defaults ( _opts , lock_path = lock_path ) <EOL> def get_lock_path ( conf ) : <EOL> """<STR_LIT>""" <EOL> _register_opts ( conf ) <EOL> return conf . oslo_concurrency . lock_path <EOL> InterProcessLock = fasteners . InterProcessLock <EOL> ReaderWriterLock = fasteners . ReaderWriterLock <EOL> """<STR_LIT>""" <EOL> class Semaphores ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self ) : <EOL> self . _semaphores = weakref . WeakValueDictionary ( ) <EOL> self . _lock = threading . Lock ( ) <EOL> def get ( self , name ) : <EOL> """<STR_LIT>""" <EOL> with self . _lock : <EOL> try : <EOL> return self . _semaphores [ name ] <EOL> except KeyError : <EOL> sem = threading . Semaphore ( ) <EOL> self . _semaphores [ name ] = sem <EOL> return sem <EOL> def __len__ ( self ) : <EOL> """<STR_LIT>""" <EOL> return len ( self . _semaphores ) <EOL> _semaphores = Semaphores ( ) <EOL> def _get_lock_path ( name , lock_file_prefix , lock_path = None ) : <EOL> name = name . replace ( os . sep , '<STR_LIT:_>' ) <EOL> if lock_file_prefix : <EOL> sep = '<STR_LIT>' if lock_file_prefix . endswith ( '<STR_LIT:->' ) else '<STR_LIT:->' <EOL> name = '<STR_LIT>' % ( lock_file_prefix , sep , name ) <EOL> local_lock_path = lock_path or CONF . oslo_concurrency . lock_path <EOL> if not local_lock_path : <EOL> raise cfg . RequiredOptError ( '<STR_LIT>' ) <EOL> return os . path . join ( local_lock_path , name ) <EOL> def external_lock ( name , lock_file_prefix = None , lock_path = None ) : <EOL> lock_file_path = _get_lock_path ( name , lock_file_prefix , lock_path ) <EOL> return InterProcessLock ( lock_file_path ) <EOL> def remove_external_lock_file ( name , lock_file_prefix = None , lock_path = None , <EOL> semaphores = None ) : <EOL> """<STR_LIT>""" <EOL> with internal_lock ( name , semaphores = semaphores ) : <EOL> lock_file_path = _get_lock_path ( name , lock_file_prefix , lock_path ) <EOL> try : <EOL> os . remove ( lock_file_path ) <EOL> except OSError : <EOL> LOG . info ( _LI ( '<STR_LIT>' ) , <EOL> { '<STR_LIT:file>' : lock_file_path } ) <EOL> def internal_lock ( name , semaphores = None ) : <EOL> if semaphores is None : <EOL> semaphores = _semaphores <EOL> return semaphores . get ( name ) <EOL> @ contextlib . contextmanager <EOL> def lock ( name , lock_file_prefix = None , external = False , lock_path = None , <EOL> do_log = True , semaphores = None , delay = <NUM_LIT> ) : <EOL> """<STR_LIT>""" <EOL> int_lock = internal_lock ( name , semaphores = semaphores ) <EOL> with int_lock : <EOL> if do_log : <EOL> LOG . debug ( '<STR_LIT>' , { '<STR_LIT>' : name } ) <EOL> try : <EOL> if external and not CONF . oslo_concurrency . disable_process_locking : <EOL> ext_lock = external_lock ( name , lock_file_prefix , lock_path ) <EOL> ext_lock . acquire ( delay = delay ) <EOL> try : <EOL> yield ext_lock <EOL> finally : <EOL> ext_lock . release ( ) <EOL> else : <EOL> yield int_lock <EOL> finally : <EOL> if do_log : <EOL> LOG . debug ( '<STR_LIT>' , { '<STR_LIT>' : name } ) <EOL> def synchronized ( name , lock_file_prefix = None , external = False , lock_path = None , <EOL> semaphores = None , delay = <NUM_LIT> ) : <EOL> """<STR_LIT>""" <EOL> def wrap ( f ) : <EOL> @ six . wraps ( f ) <EOL> def inner ( * args , ** kwargs ) : <EOL> t1 = timeutils . now ( ) <EOL> t2 = None <EOL> try : <EOL> with lock ( name , lock_file_prefix , external , lock_path , <EOL> do_log = False , semaphores = semaphores , delay = delay ) : <EOL> t2 = timeutils . now ( ) <EOL> LOG . debug ( '<STR_LIT>' <EOL> '<STR_LIT>' , <EOL> { '<STR_LIT:name>' : name , <EOL> '<STR_LIT>' : reflection . get_callable_name ( f ) , <EOL> '<STR_LIT>' : ( t2 - t1 ) } ) <EOL> return f ( * args , ** kwargs ) <EOL> finally : <EOL> t3 = timeutils . now ( ) <EOL> if t2 is None : <EOL> held_secs = "<STR_LIT>" <EOL> else : <EOL> held_secs = "<STR_LIT>" % ( t3 - t2 ) <EOL> LOG . debug ( '<STR_LIT>' <EOL> '<STR_LIT>' , <EOL> { '<STR_LIT:name>' : name , <EOL> '<STR_LIT>' : reflection . get_callable_name ( f ) , <EOL> '<STR_LIT>' : held_secs } ) <EOL> return inner <EOL> return wrap <EOL> def synchronized_with_prefix ( lock_file_prefix ) : <EOL> """<STR_LIT>""" <EOL> return functools . partial ( synchronized , lock_file_prefix = lock_file_prefix ) <EOL> def remove_external_lock_file_with_prefix ( lock_file_prefix ) : <EOL> """<STR_LIT>""" <EOL> return functools . partial ( remove_external_lock_file , <EOL> lock_file_prefix = lock_file_prefix ) <EOL> def _lock_wrapper ( argv ) : <EOL> """<STR_LIT>""" <EOL> lock_dir = tempfile . mkdtemp ( ) <EOL> os . environ [ "<STR_LIT>" ] = lock_dir <EOL> try : <EOL> ret_val = subprocess . call ( argv [ <NUM_LIT:1> : ] ) <EOL> finally : <EOL> shutil . rmtree ( lock_dir , ignore_errors = True ) <EOL> return ret_val <EOL> def main ( ) : <EOL> sys . exit ( _lock_wrapper ( sys . argv ) ) <EOL> if __name__ == '<STR_LIT:__main__>' : <EOL> raise NotImplementedError ( _ ( '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' ) ) </s>
