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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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