def _lock(self, lock_type='update', failhard=False):
        '''
        Place a lock file if (and only if) it does not already exist.
        '''
        try:
            fh_ = os.open(self._get_lock_file(lock_type),
                          os.O_CREAT | os.O_EXCL | os.O_WRONLY)
            with os.fdopen(fh_, 'wb'):
                # Write the lock file and close the filehandle
                os.write(fh_, salt.utils.stringutils.to_bytes(six.text_type(os.getpid())))
        except (OSError, IOError) as exc:
            if exc.errno == errno.EEXIST:
                with salt.utils.files.fopen(self._get_lock_file(lock_type), 'r') as fd_:
                    try:
                        pid = int(salt.utils.stringutils.to_unicode(fd_.readline()).rstrip())
                    except ValueError:
                        # Lock file is empty, set pid to 0 so it evaluates as
                        # False.
                        pid = 0
                global_lock_key = self.role + '_global_lock'
                lock_file = self._get_lock_file(lock_type=lock_type)
                if self.opts[global_lock_key]:
                    msg = (
                        '{0} is enabled and {1} lockfile {2} is present for '
                        '{3} remote \'{4}\'.'.format(
                            global_lock_key,
                            lock_type,
                            lock_file,
                            self.role,
                            self.id,
                        )
                    )
                    if pid:
                        msg += ' Process {0} obtained the lock'.format(pid)
                        if not pid_exists(pid):
                            msg += (' but this process is not running. The '
                                    'update may have been interrupted. If '
                                    'using multi-master with shared gitfs '
                                    'cache, the lock may have been obtained '
                                    'by another master.')
                    log.warning(msg)
                    if failhard:
                        raise exc
                    return
                elif pid and pid_exists(pid):
                    log.warning('Process %d has a %s %s lock (%s)',
                                pid, self.role, lock_type, lock_file)
                    if failhard:
                        raise
                    return
                else:
                    if pid:
                        log.warning(
                            'Process %d has a %s %s lock (%s), but this '
                            'process is not running. Cleaning up lock file.',
                            pid, self.role, lock_type, lock_file
                        )
                    success, fail = self.clear_lock()
                    if success:
                        return self._lock(lock_type='update',
                                          failhard=failhard)
                    elif failhard:
                        raise
                    return
            else:
                msg = 'Unable to set {0} lock for {1} ({2}): {3} '.format(
                    lock_type,
                    self.id,
                    self._get_lock_file(lock_type),
                    exc
                )
                log.error(msg, exc_info=True)
                raise GitLockError(exc.errno, msg)
        msg = 'Set {0} lock for {1} remote \'{2}\''.format(
            lock_type,
            self.role,
            self.id
        )
        log.debug(msg)
        return msg
def _lock ( self , lock_type = 'update' , failhard = False ) : try : fh_ = os . open ( self . _get_lock_file ( lock_type ) , os . O_CREAT | os . O_EXCL | os . O_WRONLY ) with os . fdopen ( fh_ , 'wb' ) : os . write ( fh_ , salt . utils . stringutils . to_bytes ( six . text_type ( os . getpid ( ) ) ) ) except ( OSError , IOError ) as exc : if exc . errno == errno . EEXIST : with salt . utils . files . fopen ( self . _get_lock_file ( lock_type ) , 'r' ) as fd_ : try : pid = int ( salt . utils . stringutils . to_unicode ( fd_ . readline ( ) ) . rstrip ( ) ) except ValueError : pid = 0 global_lock_key = self . role + '_global_lock' lock_file = self . _get_lock_file ( lock_type = lock_type ) if self . opts [ global_lock_key ] : msg = ( '{0} is enabled and {1} lockfile {2} is present for ' '{3} remote \'{4}\'.' . format ( global_lock_key , lock_type , lock_file , self . role , self . id , ) ) if pid : msg += ' Process {0} obtained the lock' . format ( pid ) if not pid_exists ( pid ) : msg += ( ' but this process is not running. The ' 'update may have been interrupted. If ' 'using multi-master with shared gitfs ' 'cache, the lock may have been obtained ' 'by another master.' ) log . warning ( msg ) if failhard : raise exc return elif pid and pid_exists ( pid ) : log . warning ( 'Process %d has a %s %s lock (%s)' , pid , self . role , lock_type , lock_file ) if failhard : raise return else : if pid : log . warning ( 'Process %d has a %s %s lock (%s), but this ' 'process is not running. Cleaning up lock file.' , pid , self . role , lock_type , lock_file ) success , fail = self . clear_lock ( ) if success : return self . _lock ( lock_type = 'update' , failhard = failhard ) elif failhard : raise return else : msg = 'Unable to set {0} lock for {1} ({2}): {3} ' . format ( lock_type , self . id , self . _get_lock_file ( lock_type ) , exc ) log . error ( msg , exc_info = True ) raise GitLockError ( exc . errno , msg ) msg = 'Set {0} lock for {1} remote \'{2}\'' . format ( lock_type , self . role , self . id ) log . debug ( msg ) return msg
Place a lock file if (and only if) it does not already exist.