Implement database locking (needs to be debugged on windows and OSX)

This commit is contained in:
Kovid Goyal 2007-10-19 00:11:43 +00:00
parent 3af3b9c3d4
commit 8d46e046d4
2 changed files with 47 additions and 1 deletions

View File

@ -43,6 +43,8 @@ from libprs500.gui2.dialogs.lrf_single import LRFSingleDialog
from libprs500.gui2.dialogs.password import PasswordDialog
from libprs500.gui2.lrf_renderer.main import file_renderer
from libprs500.gui2.lrf_renderer.main import option_parser as lrfviewerop
from libprs500.library.database import DatabaseLocked
class Main(MainWindow, Ui_MainWindow):
@ -715,7 +717,12 @@ def main(args=sys.argv):
QCoreApplication.setOrganizationName(ORG_NAME)
QCoreApplication.setApplicationName(APP_UID)
initialize_file_icon_provider()
main = Main()
try:
main = Main()
except DatabaseLocked, err:
QMessageBox.critical(None, 'Cannot Start '+__appname__,
'Another program is using the database. Perhaps %s is already running?'%(__appname__,))
return 1
sys.excepthook = main.unhandled_exception
return app.exec_()
return 0

View File

@ -35,9 +35,42 @@ class Concatenate(object):
return self.ans[:-len(self.sep)]
return self.ans
_lock_file = None
class DatabaseLocked(Exception):
pass
def _lock(path):
path = os.path.join(os.path.dirname(path), '.'+os.path.basename(path)+'.lock')
global _lock_file
if _lock_file is not None:
raise DatabaseLocked('Database already locked in this instance.')
try:
_lock_file = open(path, 'wb')
except IOError:
raise DatabaseLocked('Database in use by another instance')
try:
import fcntl, errno
try:
fcntl.lockf(_lock_file.fileno(), fcntl.LOCK_EX|fcntl.LOCK_NB)
except IOError, err:
_lock_file = None
if err.errno in (errno.EACCES, errno.EAGAIN):
raise DatabaseLocked('Database in use by another instance')
except ImportError:
try:
import msvcrt
try:
msvcrt.locking(_lock_file.fileno(), msvcrt.LK_NBLCK, 1)
except IOError:
_lock_file = None
raise DatabaseLocked('Database in use by another instance')
except ImportError:
pass
def _connect(path):
if isinstance(path, unicode):
path = path.encode('utf-8')
_lock(path)
conn = sqlite.connect(path, detect_types=sqlite.PARSE_DECLTYPES|sqlite.PARSE_COLNAMES)
conn.row_factory = lambda cursor, row : list(row)
conn.create_aggregate('concat', 1, Concatenate)
@ -621,6 +654,12 @@ class LibraryDatabase(object):
conn.execute('pragma user_version=2')
conn.commit()
def __del__(self):
global _lock_file
import os
if _lock_file is not None and os.path.exists(_lock_file):
os.unlink(_lock_file)
def __init__(self, dbpath):
self.dbpath = dbpath
self.conn = _connect(dbpath)