biliarchiver/_uploadingLock.py

86 lines
2.6 KiB
Python
Raw Normal View History

2023-06-03 07:36:24 -07:00
import os
import sys
import importlib.util
class AlreadyRunningError(Exception):
def __init__(self, message: str=""):
self.message = message
super().__init__(self.message)
def __str__(self):
return self.message
LOCK_FILENAME = '_uploading.lock'
class UploadLock_Basic:
def __init__(self, lock_dir):
self.lock_file = os.path.join(lock_dir, LOCK_FILENAME)
def __enter__(self):
if os.path.exists(self.lock_file):
with open(self.lock_file, 'r', encoding='utf-8') as f:
print(f.read())
print("Another instance is already running.")
raise AlreadyRunningError('Another instance is already running.')
else:
with open(self.lock_file, 'w', encoding='utf-8') as f:
f.write(f'PID: {os.getpid()}: Running')
2023-06-03 08:49:58 -07:00
# print("Acquired lock, continuing.")
2023-06-03 07:36:24 -07:00
def __exit__(self, exc_type, exc_val, exc_tb):
os.remove(self.lock_file)
2023-06-03 08:49:58 -07:00
# print("Released lock.")
2023-06-03 07:36:24 -07:00
# decorator
def __call__(self, func):
def wrapper(*args, **kwargs):
with self:
return func(*args, **kwargs)
return wrapper
class UploadLock_Fcntl():
fcntl = None
try:
import fcntl
except ModuleNotFoundError:
pass
def __init__(self, lock_dir):
if self.fcntl is None:
raise(ModuleNotFoundError("No module named 'fcntl'", name='fcntl'))
self.lock_file = os.path.join(lock_dir, LOCK_FILENAME)
self.lock_file_fd = None
def __enter__(self):
self.lock_file_fd = open(self.lock_file, 'w')
try:
self.fcntl.lockf(self.lock_file_fd, self.fcntl.LOCK_EX | self.fcntl.LOCK_NB)
2023-06-03 08:49:58 -07:00
# print("Acquired lock, continuing.")
2023-06-03 07:36:24 -07:00
except IOError:
raise AlreadyRunningError("Another instance is already running.")
def __exit__(self, exc_type, exc_val, exc_tb):
if self.lock_file_fd is None:
raise IOError("Lock file not opened.")
self.fcntl.lockf(self.lock_file_fd, self.fcntl.LOCK_UN)
self.lock_file_fd.close()
os.remove(self.lock_file)
2023-06-03 08:49:58 -07:00
# print("Released lock.")
2023-06-03 07:36:24 -07:00
# decorator
def __call__(self, func):
def wrapper(*args, **kwargs):
with self:
return func(*args, **kwargs)
return wrapper
class UploadLock():
def __new__(cls, lock_dir):
fcntl_avaivable = importlib.util.find_spec('fcntl')
if fcntl_avaivable is not None:
return UploadLock_Fcntl(lock_dir)
else:
return UploadLock_Basic(lock_dir)