2019-07-31 14:30:06 +00:00
|
|
|
from os import remove
|
2019-07-31 14:59:08 +00:00
|
|
|
from contextlib import contextmanager
|
2019-07-31 14:30:06 +00:00
|
|
|
from fcntl import flock, LOCK_EX, LOCK_UN
|
|
|
|
|
|
|
|
|
|
|
|
class RefCounter:
|
|
|
|
def __init__(self, lockpath):
|
|
|
|
self.lockpath = lockpath
|
|
|
|
self._lockfile = open(self.lockpath, 'a+')
|
2019-07-31 14:59:08 +00:00
|
|
|
with self.locked():
|
|
|
|
counter = self._read_counter()
|
|
|
|
self._write_counter(counter+1)
|
|
|
|
|
|
|
|
@contextmanager
|
|
|
|
def locked(self):
|
2019-07-31 14:30:06 +00:00
|
|
|
flock(self._lockfile, LOCK_EX)
|
2019-07-31 14:59:08 +00:00
|
|
|
yield
|
2019-07-31 14:30:06 +00:00
|
|
|
flock(self._lockfile, LOCK_UN)
|
|
|
|
|
|
|
|
def _read_counter(self):
|
|
|
|
self._lockfile.seek(0)
|
|
|
|
try:
|
|
|
|
counter = int(self._lockfile.read())
|
|
|
|
except ValueError:
|
|
|
|
counter = 0
|
|
|
|
return counter
|
|
|
|
|
|
|
|
def _write_counter(self, counter):
|
|
|
|
self._lockfile.seek(0)
|
|
|
|
self._lockfile.truncate()
|
|
|
|
self._lockfile.write(str(counter))
|
|
|
|
self._lockfile.flush()
|
|
|
|
|
|
|
|
def teardown_instance(self):
|
2019-07-31 14:59:08 +00:00
|
|
|
with self.locked():
|
|
|
|
counter = self._read_counter()
|
|
|
|
if counter <= 1:
|
|
|
|
remove(self.lockpath)
|
|
|
|
self.deallocate()
|
|
|
|
else:
|
|
|
|
self._write_counter(counter-1)
|
2019-07-31 14:30:06 +00:00
|
|
|
self._lockfile.close()
|
|
|
|
|
|
|
|
def deallocate(self):
|
|
|
|
pass
|