Mercurial > hg > cc > cirrus_home
annotate lib/python/lock.py @ 134:d3ef00af2064
add usage/help info
author | Henry S. Thompson <ht@inf.ed.ac.uk> |
---|---|
date | Wed, 14 Jul 2021 16:49:54 +0000 |
parents | b6a5999d8e06 |
children |
rev | line source |
---|---|
87
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
1 # Courtesy of https://stackoverflow.com/a/46407326 |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
2 import fcntl, os |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
3 def lock_file(f): |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
4 if f.writable(): fcntl.lockf(f, fcntl.LOCK_EX) |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
5 def unlock_file(f): |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
6 if f.writable(): fcntl.lockf(f, fcntl.LOCK_UN) |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
7 |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
8 # Class for ensuring that all file operations are atomic, treat |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
9 # initialization like a standard call to 'open' that happens to be atomic. |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
10 # This file opener *must* be used in a "with" block. |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
11 class AtomicOpen: |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
12 # Open the file with arguments provided by user. Then acquire |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
13 # a lock on that file object (WARNING: Advisory locking). |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
14 def __init__(self, path, *args, **kwargs): |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
15 # Open the file and acquire a lock on the file before operating |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
16 self.file = open(path,*args, **kwargs) |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
17 # Lock the opened file |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
18 lock_file(self.file) |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
19 |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
20 # Return the opened file object (knowing a lock has been obtained). |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
21 def __enter__(self, *args, **kwargs): return self.file |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
22 |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
23 # Unlock the file and close the file object. |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
24 def __exit__(self, exc_type=None, exc_value=None, traceback=None): |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
25 # Flush to make sure all buffered contents are written to file. |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
26 self.file.flush() |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
27 os.fsync(self.file.fileno()) |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
28 # Release the lock on the file. |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
29 unlock_file(self.file) |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
30 self.file.close() |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
31 # Handle exceptions that may have come up during execution, by |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
32 # default any exceptions are raised to the user. |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
33 if (exc_type != None): return False |
b6a5999d8e06
working with locking and copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff
changeset
|
34 else: return True |