~justin-fathomdb/nova/justinsb-openstack-api-volumes

« back to all changes in this revision

Viewing changes to vendor/lockfile/lockfile/linklockfile.py

  • Committer: Jesse Andrews
  • Date: 2010-05-28 06:05:26 UTC
  • Revision ID: git-v1:bf6e6e718cdc7488e2da87b21e258ccc065fe499
initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from __future__ import absolute_import
 
2
 
 
3
import time
 
4
import os
 
5
 
 
6
from . import (LockBase, LockFailed, NotLocked, NotMyLock, LockTimeout,
 
7
               AlreadyLocked)
 
8
 
 
9
class LinkLockFile(LockBase):
 
10
    """Lock access to a file using atomic property of link(2).
 
11
 
 
12
    >>> lock = LinkLockFile('somefile')
 
13
    >>> lock = LinkLockFile('somefile', threaded=False)
 
14
    """
 
15
 
 
16
    def acquire(self, timeout=None):
 
17
        try:
 
18
            open(self.unique_name, "wb").close()
 
19
        except IOError:
 
20
            raise LockFailed("failed to create %s" % self.unique_name)
 
21
 
 
22
        end_time = time.time()
 
23
        if timeout is not None and timeout > 0:
 
24
            end_time += timeout
 
25
 
 
26
        while True:
 
27
            # Try and create a hard link to it.
 
28
            try:
 
29
                print 'making a hard link %s to %s' % (self.unique_name,
 
30
                                                       self.lock_file)
 
31
                os.link(self.unique_name, self.lock_file)
 
32
            except OSError:
 
33
                # Link creation failed.  Maybe we've double-locked?
 
34
                nlinks = os.stat(self.unique_name).st_nlink
 
35
                if nlinks == 2:
 
36
                    # The original link plus the one I created == 2.  We're
 
37
                    # good to go.
 
38
                    return
 
39
                else:
 
40
                    # Otherwise the lock creation failed.
 
41
                    if timeout is not None and time.time() > end_time:
 
42
                        os.unlink(self.unique_name)
 
43
                        if timeout > 0:
 
44
                            raise LockTimeout
 
45
                        else:
 
46
                            raise AlreadyLocked
 
47
                    time.sleep(timeout is not None and timeout/10 or 0.1)
 
48
            else:
 
49
                # Link creation succeeded.  We're good to go.
 
50
                return
 
51
 
 
52
    def release(self):
 
53
        if not self.is_locked():
 
54
            raise NotLocked
 
55
        elif not os.path.exists(self.unique_name):
 
56
            raise NotMyLock
 
57
        os.unlink(self.unique_name)
 
58
        os.unlink(self.lock_file)
 
59
 
 
60
    def is_locked(self):
 
61
        return os.path.exists(self.lock_file)
 
62
 
 
63
    def i_am_locking(self):
 
64
        return (self.is_locked() and
 
65
                os.path.exists(self.unique_name) and
 
66
                os.stat(self.unique_name).st_nlink == 2)
 
67
 
 
68
    def break_lock(self):
 
69
        if os.path.exists(self.lock_file):
 
70
            os.unlink(self.lock_file)
 
71