Ejemplo n.º 1
0
        def __init__(self, filename):
            super(_fcntl_WriteLock, self).__init__()
            # Check we can grab a lock before we actually open the file.
            self.filename = osutils.realpath(filename)
            if self.filename in _fcntl_WriteLock._open_locks:
                self._clear_f()
                raise errors.LockContention(self.filename)
            if self.filename in _fcntl_ReadLock._open_locks:
                if 'strict_locks' in debug.debug_flags:
                    self._clear_f()
                    raise errors.LockContention(self.filename)
                else:
                    trace.mutter(
                        'Write lock taken w/ an open read lock on: %s' %
                        (self.filename, ))

            self._open(self.filename, 'rb+')
            # reserve a slot for this lock - even if the lockf call fails,
            # at this point unlock() will be called, because self.f is set.
            # TODO: make this fully threadsafe, if we decide we care.
            _fcntl_WriteLock._open_locks.add(self.filename)
            try:
                # LOCK_NB will cause IOError to be raised if we can't grab a
                # lock right away.
                fcntl.lockf(self.f, fcntl.LOCK_EX | fcntl.LOCK_NB)
            except IOError, e:
                if e.errno in (errno.EAGAIN, errno.EACCES):
                    # We couldn't grab the lock
                    self.unlock()
                # we should be more precise about whats a locking
                # error and whats a random-other error
                raise errors.LockContention(self.filename, e)
Ejemplo n.º 2
0
        def __init__(self, read_lock):
            super(_fcntl_TemporaryWriteLock, self).__init__()
            self._read_lock = read_lock
            self.filename = read_lock.filename

            count = _fcntl_ReadLock._open_locks[self.filename]
            if count > 1:
                # Something else also has a read-lock, so we cannot grab a
                # write lock.
                raise errors.LockContention(self.filename)

            if self.filename in _fcntl_WriteLock._open_locks:
                raise AssertionError('file already locked: %r' %
                                     (self.filename, ))

            # See if we can open the file for writing. Another process might
            # have a read lock. We don't use self._open() because we don't want
            # to create the file if it exists. That would have already been
            # done by _fcntl_ReadLock
            try:
                new_f = open(self.filename, 'rb+')
            except IOError, e:
                if e.errno in (errno.EACCES, errno.EPERM):
                    raise errors.LockFailed(self.filename, str(e))
                raise
Ejemplo n.º 3
0
 def unlock(self):
     overlapped = pywintypes.OVERLAPPED()
     try:
         win32file.UnlockFileEx(self.hfile, 0, 0x7fff0000, overlapped)
         self._clear_f()
     except Exception, e:
         raise errors.LockContention(e)
Ejemplo n.º 4
0
        def _lock(self, filename, openmode, lockmode):
            self._open(filename, openmode)

            self.hfile = msvcrt.get_osfhandle(self.f.fileno())
            overlapped = OVERLAPPED()
            result = _LockFileEx(
                self.hfile,  # HANDLE hFile
                lockmode,  # DWORD dwFlags
                0,  # DWORD dwReserved
                0x7fffffff,  # DWORD nNumberOfBytesToLockLow
                0x00000000,  # DWORD nNumberOfBytesToLockHigh
                ctypes.byref(overlapped),  # lpOverlapped
            )
            if result == 0:
                self._clear_f()
                last_err = _GetLastError()
                if last_err in (ERROR_LOCK_VIOLATION, ):
                    raise errors.LockContention(filename)
                raise errors.LockContention('Unknown locking error: %s' %
                                            (last_err, ))
Ejemplo n.º 5
0
 def _open(self, filename, access, share, cflags, pymode):
     self.filename = osutils.realpath(filename)
     try:
         self._handle = win32file_CreateFile(
             filename, access, share, None, win32file.OPEN_ALWAYS,
             win32file.FILE_ATTRIBUTE_NORMAL, None)
     except pywintypes.error, e:
         if e.args[0] == winerror.ERROR_ACCESS_DENIED:
             raise errors.LockFailed(filename, e)
         if e.args[0] == winerror.ERROR_SHARING_VIOLATION:
             raise errors.LockContention(filename, e)
         raise
Ejemplo n.º 6
0
 def _open(self, filename, access, share, cflags, pymode):
     self.filename = osutils.realpath(filename)
     handle = _CreateFile(filename, access, share, None, OPEN_ALWAYS,
                          FILE_ATTRIBUTE_NORMAL, 0)
     if handle in (INVALID_HANDLE_VALUE, 0):
         e = ctypes.WinError()
         if e.args[0] == ERROR_ACCESS_DENIED:
             raise errors.LockFailed(filename, e)
         if e.args[0] == ERROR_SHARING_VIOLATION:
             raise errors.LockContention(filename, e)
         raise e
     fd = msvcrt.open_osfhandle(handle, cflags)
     self.f = os.fdopen(fd, pymode)
     return self.f
Ejemplo n.º 7
0
 def __init__(self, filename):
     super(_fcntl_ReadLock, self).__init__()
     self.filename = osutils.realpath(filename)
     if self.filename in _fcntl_WriteLock._open_locks:
         if 'strict_locks' in debug.debug_flags:
             # We raise before calling _open so we don't need to
             # _clear_f
             raise errors.LockContention(self.filename)
         else:
             trace.mutter(
                 'Read lock taken w/ an open write lock on: %s' %
                 (self.filename, ))
     _fcntl_ReadLock._open_locks.setdefault(self.filename, 0)
     _fcntl_ReadLock._open_locks[self.filename] += 1
     self._open(filename, 'rb')
     try:
         # LOCK_NB will cause IOError to be raised if we can't grab a
         # lock right away.
         fcntl.lockf(self.f, fcntl.LOCK_SH | fcntl.LOCK_NB)
     except IOError, e:
         # we should be more precise about whats a locking
         # error and whats a random-other error
         raise errors.LockContention(self.filename, e)
Ejemplo n.º 8
0
def _translate_error(error_tuple):
    # Many exceptions need some state from the requestor to be properly
    # translated (e.g. they need a branch object).  So this only translates a
    # few errors, and the rest are turned into a generic ErrorFromSmartServer.
    error_name = error_tuple[0]
    error_args = error_tuple[1:]
    if error_name == 'UnknownMethod':
        raise errors.UnknownSmartMethod(error_args[0])
    if error_name == 'LockContention':
        raise errors.LockContention('(remote lock)')
    elif error_name == 'LockFailed':
        raise errors.LockFailed(*error_args[:2])
    else:
        raise errors.ErrorFromSmartServer(error_tuple)
Ejemplo n.º 9
0
        def _lock(self, filename, openmode, lockmode):
            self._open(filename, openmode)

            self.hfile = msvcrt.get_osfhandle(self.f.fileno())
            overlapped = pywintypes.OVERLAPPED()
            try:
                win32file.LockFileEx(self.hfile, lockmode, 0, 0x7fff0000,
                                     overlapped)
            except pywintypes.error, e:
                self._clear_f()
                if e.args[0] in (winerror.ERROR_LOCK_VIOLATION, ):
                    raise errors.LockContention(filename)
                ## import pdb; pdb.set_trace()
                raise
Ejemplo n.º 10
0
 def __init__(self, filename):
     super(_fcntl_ReadLock, self).__init__()
     self.filename = osutils.realpath(filename)
     _fcntl_ReadLock._open_locks.setdefault(self.filename, 0)
     _fcntl_ReadLock._open_locks[self.filename] += 1
     self._open(filename, 'rb')
     try:
         # LOCK_NB will cause IOError to be raised if we can't grab a
         # lock right away.
         fcntl.lockf(self.f, fcntl.LOCK_SH | fcntl.LOCK_NB)
     except IOError, e:
         # we should be more precise about whats a locking
         # error and whats a random-other error
         raise errors.LockContention(e)
Ejemplo n.º 11
0
 def unlock(self):
     overlapped = OVERLAPPED()
     result = _UnlockFileEx(
         self.hfile,  # HANDLE hFile
         0,  # DWORD dwReserved
         0x7fffffff,  # DWORD nNumberOfBytesToLockLow
         0x00000000,  # DWORD nNumberOfBytesToLockHigh
         ctypes.byref(overlapped),  # lpOverlapped
     )
     self._clear_f()
     if result == 0:
         self._clear_f()
         last_err = _GetLastError()
         raise errors.LockContention('Unknown unlocking error: %s' %
                                     (last_err, ))
Ejemplo n.º 12
0
    class _fcntl_TemporaryWriteLock(_OSLock):
        """A token used when grabbing a temporary_write_lock.

        Call restore_read_lock() when you are done with the write lock.
        """
        def __init__(self, read_lock):
            super(_fcntl_TemporaryWriteLock, self).__init__()
            self._read_lock = read_lock
            self.filename = read_lock.filename

            count = _fcntl_ReadLock._open_locks[self.filename]
            if count > 1:
                # Something else also has a read-lock, so we cannot grab a
                # write lock.
                raise errors.LockContention(self.filename)

            if self.filename in _fcntl_WriteLock._open_locks:
                raise AssertionError('file already locked: %r' %
                                     (self.filename, ))

            # See if we can open the file for writing. Another process might
            # have a read lock. We don't use self._open() because we don't want
            # to create the file if it exists. That would have already been
            # done by _fcntl_ReadLock
            try:
                new_f = open(self.filename, 'rb+')
            except IOError, e:
                if e.errno in (errno.EACCES, errno.EPERM):
                    raise errors.LockFailed(self.filename, str(e))
                raise
            try:
                # LOCK_NB will cause IOError to be raised if we can't grab a
                # lock right away.
                fcntl.lockf(new_f, fcntl.LOCK_EX | fcntl.LOCK_NB)
            except IOError, e:
                # TODO: Raise a more specific error based on the type of error
                raise errors.LockContention(self.filename, e)
 def test_LockContention(self):
     # For now, LockContentions are always transmitted with no details.
     # Eventually they should include a relpath or url or something else to
     # identify which lock is busy.
     self.assertTranslationEqual(('LockContention', ),
                                 errors.LockContention('lock', 'msg'))