<s> import contextlib <EOL> import errno <EOL> import functools <EOL> import os <EOL> import shutil <EOL> import subprocess <EOL> import sys <EOL> import tempfile <EOL> import threading <EOL> import time <EOL> import weakref <EOL> from oslo_config import cfg <EOL> from solum . openstack . common import fileutils <EOL> from solum . openstack . common . gettextutils import _ <EOL> from solum . openstack . common import log as logging <EOL> LOG = logging . getLogger ( __name__ ) <EOL> util_opts = [ <EOL> cfg . BoolOpt ( '<STR_LIT>' , default = False , <EOL> help = '<STR_LIT>' ) , <EOL> cfg . StrOpt ( '<STR_LIT>' , <EOL> default = os . environ . get ( "<STR_LIT>" ) , <EOL> help = ( '<STR_LIT>' ) ) <EOL> ] <EOL> CONF = cfg . CONF <EOL> CONF . register_opts ( util_opts ) <EOL> def set_defaults ( lock_path ) : <EOL> cfg . set_defaults ( util_opts , lock_path = lock_path ) <EOL> class _InterProcessLock ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , name ) : <EOL> self . lockfile = None <EOL> self . fname = name <EOL> def acquire ( self ) : <EOL> basedir = os . path . dirname ( self . fname ) <EOL> if not os . path . exists ( basedir ) : <EOL> fileutils . ensure_tree ( basedir ) <EOL> LOG . info ( _ ( '<STR_LIT>' ) , basedir ) <EOL> self . lockfile = open ( self . fname , '<STR_LIT:w>' ) <EOL> while True : <EOL> try : <EOL> self . trylock ( ) <EOL> LOG . debug ( _ ( '<STR_LIT>' ) , self . fname ) <EOL> return True <EOL> except IOError as e : <EOL> if e . errno in ( errno . EACCES , errno . EAGAIN ) : <EOL> time . sleep ( <NUM_LIT> ) <EOL> else : <EOL> raise threading . ThreadError ( _ ( "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" ) % <EOL> { <EOL> '<STR_LIT:filename>' : self . fname , <EOL> '<STR_LIT>' : e , <EOL> } ) <EOL> def __enter__ ( self ) : <EOL> self . acquire ( ) <EOL> return self <EOL> def release ( self ) : <EOL> try : <EOL> self . unlock ( ) <EOL> self . lockfile . close ( ) <EOL> except IOError : <EOL> LOG . exception ( _ ( "<STR_LIT>" ) , <EOL> self . fname ) <EOL> LOG . debug ( _ ( '<STR_LIT>' ) , self . fname ) <EOL> def __exit__ ( self , exc_type , exc_val , exc_tb ) : <EOL> self . release ( ) <EOL> def trylock ( self ) : <EOL> raise NotImplementedError ( ) <EOL> def unlock ( self ) : <EOL> raise NotImplementedError ( ) <EOL> class _WindowsLock ( _InterProcessLock ) : <EOL> def trylock ( self ) : <EOL> msvcrt . locking ( self . lockfile . fileno ( ) , msvcrt . LK_NBLCK , <NUM_LIT:1> ) <EOL> def unlock ( self ) : <EOL> msvcrt . locking ( self . lockfile . fileno ( ) , msvcrt . LK_UNLCK , <NUM_LIT:1> ) <EOL> class _PosixLock ( _InterProcessLock ) : <EOL> def trylock ( self ) : <EOL> fcntl . lockf ( self . lockfile , fcntl . LOCK_EX | fcntl . LOCK_NB ) <EOL> def unlock ( self ) : <EOL> fcntl . lockf ( self . lockfile , fcntl . LOCK_UN ) <EOL> if os . name == '<STR_LIT>' : <EOL> import msvcrt <EOL> InterProcessLock = _WindowsLock <EOL> else : <EOL> import fcntl <EOL> InterProcessLock = _PosixLock <EOL> _semaphores = weakref . WeakValueDictionary ( ) <EOL> _semaphores_lock = threading . Lock ( ) <EOL> def external_lock ( name , lock_file_prefix = None ) : <EOL> with internal_lock ( name ) : <EOL> LOG . debug ( _ ( '<STR_LIT>' ) , <EOL> { '<STR_LIT>' : name } ) <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> if not CONF . lock_path : <EOL> raise cfg . RequiredOptError ( '<STR_LIT>' ) <EOL> lock_file_path = os . path . join ( CONF . lock_path , name ) <EOL> return InterProcessLock ( lock_file_path ) <EOL> def internal_lock ( name ) : <EOL> with _semaphores_lock : <EOL> try : <EOL> sem = _semaphores [ name ] <EOL> except KeyError : <EOL> sem = threading . Semaphore ( ) <EOL> _semaphores [ name ] = sem <EOL> LOG . debug ( _ ( '<STR_LIT>' ) , { '<STR_LIT>' : name } ) <EOL> return sem <EOL> @ contextlib . contextmanager <EOL> def lock ( name , lock_file_prefix = None , external = False ) : <EOL> """<STR_LIT>""" <EOL> if external and not CONF . disable_process_locking : <EOL> lock = external_lock ( name , lock_file_prefix ) <EOL> else : <EOL> lock = internal_lock ( name ) <EOL> with lock : <EOL> yield lock <EOL> def synchronized ( name , lock_file_prefix = None , external = False ) : <EOL> """<STR_LIT>""" <EOL> def wrap ( f ) : <EOL> @ functools . wraps ( f ) <EOL> def inner ( * args , ** kwargs ) : <EOL> try : <EOL> with lock ( name , lock_file_prefix , external ) : <EOL> LOG . debug ( _ ( '<STR_LIT>' ) , <EOL> { '<STR_LIT>' : f . __name__ } ) <EOL> return f ( * args , ** kwargs ) <EOL> finally : <EOL> LOG . debug ( _ ( '<STR_LIT>' ) , <EOL> { '<STR_LIT>' : f . __name__ } ) <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 main ( 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> if __name__ == '<STR_LIT:__main__>' : <EOL> sys . exit ( main ( sys . argv ) ) </s>
