~ubuntu-branches/ubuntu/karmic/calibre/karmic

« back to all changes in this revision

Viewing changes to src/calibre/utils/lock.py

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2009-07-30 12:49:41 UTC
  • mfrom: (1.3.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20090730124941-qjdsmri25zt8zocn
Tags: 0.6.3+dfsg-0ubuntu1
* New upstream release. Please see http://calibre.kovidgoyal.net/new_in_6/
  for the list of new features and changes.
* remove_postinstall.patch: Update for new version.
* build_debug.patch: Does not apply any more, disable for now. Might not be
  necessary any more.
* debian/copyright: Fix reference to versionless GPL.
* debian/rules: Drop obsolete dh_desktop call.
* debian/rules: Add workaround for weird Python 2.6 setuptools behaviour of
  putting compiled .so files into src/calibre/plugins/calibre/plugins
  instead of src/calibre/plugins.
* debian/rules: Drop hal fdi moving, new upstream version does not use hal
  any more. Drop hal dependency, too.
* debian/rules: Install udev rules into /lib/udev/rules.d.
* Add debian/calibre.preinst: Remove unmodified
  /etc/udev/rules.d/95-calibre.rules on upgrade.
* debian/control: Bump Python dependencies to 2.6, since upstream needs
  it now.

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
class LockError(Exception):
14
14
    pass
15
15
 
 
16
class WindowsExclFile(object):
 
17
 
 
18
    def __init__(self, path, timeout=20):
 
19
        self.name = path
 
20
        import win32file as w
 
21
        import pywintypes
 
22
 
 
23
        while timeout > 0:
 
24
            timeout -= 1
 
25
            try:
 
26
                self._handle = w.CreateFile(path,
 
27
                    w.GENERIC_READ|w.GENERIC_WRITE, # Open for reading and writing
 
28
                    0, # Open exclusive
 
29
                    None, # No security attributes
 
30
                    w.OPEN_ALWAYS, # If file does not exist, create it
 
31
                    w.FILE_ATTRIBUTE_NORMAL, #Normal attributes
 
32
                    None, #No template file
 
33
                )
 
34
                break
 
35
            except pywintypes.error, err:
 
36
                if getattr(err, 'args', [-1])[0] in (0x20, 0x21):
 
37
                    time.sleep(1)
 
38
                    continue
 
39
                else:
 
40
                    raise
 
41
 
 
42
    def seek(self, amt, frm=0):
 
43
        import win32file as w
 
44
        if frm not in (0, 1, 2):
 
45
            raise ValueError('Invalid from for seek: %s'%frm)
 
46
        frm = {0:w.FILE_BEGIN, 1: w.FILE_CURRENT, 2:w.FILE_END}[frm]
 
47
        if frm is w.FILE_END:
 
48
            amt = 0 - amt
 
49
        w.SetFilePointer(self._handle, amt, frm)
 
50
 
 
51
    def tell(self):
 
52
        import win32file as w
 
53
        return w.SetFilePointer(self._handle, 0, w.FILE_CURRENT)
 
54
 
 
55
    def flush(self):
 
56
        import win32file as w
 
57
        w.FlushFileBuffers(self._handle)
 
58
 
 
59
    def close(self):
 
60
        if self._handle is not None:
 
61
            import win32file as w
 
62
            self.flush()
 
63
            w.CloseHandle(self._handle)
 
64
            self._handle = None
 
65
 
 
66
    def read(self, bytes=-1):
 
67
        import win32file as w
 
68
        sz = w.GetFileSize(self._handle)
 
69
        max = sz - self.tell()
 
70
        if bytes < 0: bytes = max
 
71
        bytes = min(max, bytes)
 
72
        if bytes < 1:
 
73
            return ''
 
74
        hr, ans = w.ReadFile(self._handle, bytes, None)
 
75
        if hr != 0:
 
76
            raise IOError('Error reading file: %s'%hr)
 
77
        return ans
 
78
 
 
79
    def readlines(self, sizehint=-1):
 
80
        return self.read().splitlines()
 
81
 
 
82
    def write(self, bytes):
 
83
        if isinstance(bytes, unicode):
 
84
            bytes = bytes.encode('utf-8')
 
85
        import win32file as w
 
86
        w.WriteFile(self._handle, bytes, None)
 
87
 
 
88
    def truncate(self, size=None):
 
89
        import win32file as w
 
90
        pos = self.tell()
 
91
        if size is None:
 
92
            size = pos
 
93
        t = min(size, pos)
 
94
        self.seek(t)
 
95
        w.SetEndOfFile(self._handle)
 
96
        self.seek(pos)
 
97
 
 
98
    def isatty(self):
 
99
        return False
 
100
 
 
101
    @property
 
102
    def closed(self):
 
103
        return self._handle is None
 
104
 
 
105
 
16
106
class ExclusiveFile(object):
17
 
    
18
 
    def __init__(self, path, timeout=10):
 
107
 
 
108
    def __init__(self, path, timeout=15):
19
109
        self.path = path
20
110
        self.timeout = timeout
21
 
        
 
111
 
22
112
    def __enter__(self):
23
 
        self.file  = open(self.path, 'a+b')
 
113
        self.file  =  WindowsExclFile(self.path, self.timeout) if iswindows else open(self.path, 'a+b')
24
114
        self.file.seek(0)
25
115
        timeout = self.timeout
26
 
        if iswindows:
27
 
            name = ('Local\\'+(__appname__+self.file.name).replace('\\', '_'))[:201]
28
 
            while self.timeout < 0 or timeout >= 0:
29
 
                self.mutex = win32event.CreateMutex(None, False, name)
30
 
                if win32api.GetLastError() != winerror.ERROR_ALREADY_EXISTS: break
31
 
                time.sleep(1)
32
 
                timeout -= 1
33
 
        else:
 
116
        if not iswindows:
34
117
            while self.timeout < 0 or timeout >= 0:
35
118
                try:
36
119
                    fcntl.lockf(self.file.fileno(), fcntl.LOCK_EX|fcntl.LOCK_NB)
38
121
                except IOError:
39
122
                    time.sleep(1)
40
123
                    timeout -= 1
41
 
        if timeout < 0 and self.timeout >= 0:
42
 
            self.file.close()
43
 
            raise LockError
 
124
            if timeout < 0 and self.timeout >= 0:
 
125
                self.file.close()
 
126
                raise LockError('Failed to lock')
44
127
        return self.file
45
 
                
 
128
 
46
129
    def __exit__(self, type, value, traceback):
47
130
        self.file.close()
48
 
        if iswindows:
49
 
            win32api.CloseHandle(self.mutex)
50
 
 
51
131
 
52
132
def _clean_lock_file(file):
53
133
    try:
62
142
 
63
143
def singleinstance(name):
64
144
    '''
65
 
    Return True if no other instance of the application identified by name is running, 
 
145
    Return True if no other instance of the application identified by name is running,
66
146
    False otherwise.
67
147
    @param name: The name to lock.
68
 
    @type name: string 
 
148
    @type name: string
69
149
    '''
70
150
    if iswindows:
71
151
        mutexname = 'mutexforsingleinstanceof'+__appname__+name
82
162
            return True
83
163
        except IOError:
84
164
            return False
85
 
        
 
165
 
86
166
    return False