File: process_mechanism.py

package info (click to toggle)
python-fasteners 0.19-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 284 kB
  • sloc: python: 1,626; makefile: 5
file content (154 lines) | stat: -rw-r--r-- 4,030 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
from abc import ABC
from abc import abstractmethod
import errno
import os


class _InterProcessReaderWriterLockMechanism(ABC):

    @staticmethod
    @abstractmethod
    def trylock(lockfile, exclusive):
        ...

    @staticmethod
    @abstractmethod
    def unlock(lockfile):
        ...

    @staticmethod
    @abstractmethod
    def get_handle(path):
        ...

    @staticmethod
    @abstractmethod
    def close_handle(lockfile):
        ...


class _InterProcessMechanism(ABC):
    @staticmethod
    @abstractmethod
    def trylock(lockfile):
        ...

    @staticmethod
    @abstractmethod
    def unlock(lockfile):
        ...


class _WindowsInterProcessMechanism(_InterProcessMechanism):
    """Interprocess lock implementation that works on windows systems."""

    @staticmethod
    def trylock(lockfile):
        fileno = lockfile.fileno()
        msvcrt.locking(fileno, msvcrt.LK_NBLCK, 1)

    @staticmethod
    def unlock(lockfile):
        fileno = lockfile.fileno()
        msvcrt.locking(fileno, msvcrt.LK_UNLCK, 1)


class _FcntlInterProcessMechanism(_InterProcessMechanism):
    """Interprocess lock implementation that works on posix systems."""

    @staticmethod
    def trylock(lockfile):
        fcntl.lockf(lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB)

    @staticmethod
    def unlock(lockfile):
        fcntl.lockf(lockfile, fcntl.LOCK_UN)


class _WindowsInterProcessReaderWriterLockMechanism(_InterProcessReaderWriterLockMechanism):
    """Interprocess readers writer lock implementation that works on windows
    systems."""

    @staticmethod
    def trylock(lockfile, exclusive):

        if exclusive:
            flags = win32con.LOCKFILE_FAIL_IMMEDIATELY | win32con.LOCKFILE_EXCLUSIVE_LOCK
        else:
            flags = win32con.LOCKFILE_FAIL_IMMEDIATELY

        handle = msvcrt.get_osfhandle(lockfile.fileno())
        ok = win32file.LockFileEx(handle, flags, 0, 1, 0, win32file.pointer(pywintypes.OVERLAPPED()))
        if ok:
            return True
        else:
            last_error = win32file.GetLastError()
            if last_error == win32file.ERROR_LOCK_VIOLATION:
                return False
            else:
                raise OSError(last_error)

    @staticmethod
    def unlock(lockfile):
        handle = msvcrt.get_osfhandle(lockfile.fileno())
        ok = win32file.UnlockFileEx(handle, 0, 1, 0, win32file.pointer(pywintypes.OVERLAPPED()))
        if not ok:
            raise OSError(win32file.GetLastError())

    @staticmethod
    def get_handle(path):
        return open(path, 'a+')

    @staticmethod
    def close_handle(lockfile):
        lockfile.close()


class _FcntlInterProcessReaderWriterLockMechanism(_InterProcessReaderWriterLockMechanism):
    """Interprocess readers writer lock implementation that works on posix
    systems."""

    @staticmethod
    def trylock(lockfile, exclusive):

        if exclusive:
            flags = fcntl.LOCK_EX | fcntl.LOCK_NB
        else:
            flags = fcntl.LOCK_SH | fcntl.LOCK_NB

        try:
            fcntl.lockf(lockfile, flags)
            return True
        except (IOError, OSError) as e:
            if e.errno in (errno.EACCES, errno.EAGAIN):
                return False
            else:
                raise e

    @staticmethod
    def unlock(lockfile):
        fcntl.lockf(lockfile, fcntl.LOCK_UN)

    @staticmethod
    def get_handle(path):
        return open(path, 'a+')

    @staticmethod
    def close_handle(lockfile):
        lockfile.close()


if os.name == 'nt':
    import msvcrt
    import fasteners.pywin32.pywintypes as pywintypes
    import fasteners.pywin32.win32con as win32con
    import fasteners.pywin32.win32file as win32file

    _interprocess_reader_writer_mechanism = _WindowsInterProcessReaderWriterLockMechanism()
    _interprocess_mechanism = _WindowsInterProcessMechanism()

else:
    import fcntl

    _interprocess_reader_writer_mechanism = _FcntlInterProcessReaderWriterLockMechanism()
    _interprocess_mechanism = _FcntlInterProcessMechanism()