LocalStatusSQLite: code refactoring around database lock

Backported-from: 05e5b9c6bb
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
This commit is contained in:
Nicolas Sebrecht 2016-07-26 02:56:36 +02:00
parent 038a433f69
commit 77a6f9a7ba

View File

@ -90,23 +90,21 @@ class LocalStatusSQLiteFolder(BaseFolder):
dirname) dirname)
self.connection = None self.connection = None
# This lock protects against concurrent writes in same connection. # The lock serialize the writing/open/close of database accross threads.
self._dblock = Lock() if self.filename not in LocalStatusSQLiteFolder.locks:
LocalStatusSQLiteFolder.locks[self.filename] = DatabaseFileLock()
self._databaseFileLock = LocalStatusSQLiteFolder.locks[self.filename]
def openfiles(self): def openfiles(self):
# Make sure sqlite is in multithreading SERIALIZE mode. # Make sure sqlite is in multithreading SERIALIZE mode.
assert sqlite.threadsafety == 1, 'Your sqlite is not multithreading safe.' assert sqlite.threadsafety == 1, 'Your sqlite is not multithreading safe.'
# Protect the creation/upgrade of database accross threads. with self._databaseFileLock.getLock():
if self.filename not in LocalStatusSQLiteFolder.locks:
LocalStatusSQLiteFolder.locks[self.filename] = DatabaseFileLock()
databaseFileLock = LocalStatusSQLiteFolder.locks[self.filename]
with databaseFileLock.getLock():
# Try to establish connection, no need for threadsafety in __init__. # Try to establish connection, no need for threadsafety in __init__.
try: try:
self.connection = sqlite.connect(self.filename, self.connection = sqlite.connect(self.filename,
check_same_thread=False) check_same_thread=False)
databaseFileLock.registerNewUser() self._databaseFileLock.registerNewUser()
except sqlite.OperationalError as e: except sqlite.OperationalError as e:
# Operation had failed. # Operation had failed.
raise UserWarning("cannot open database file '%s': %s.\nYou might " raise UserWarning("cannot open database file '%s': %s.\nYou might "
@ -159,7 +157,7 @@ class LocalStatusSQLiteFolder(BaseFolder):
success = False success = False
while not success: while not success:
try: try:
with LocalStatusSQLiteFolder.locks[self.filename].getLock(): with self._databaseFileLock.getLock():
if args is None: if args is None:
if executemany: if executemany:
self.connection.executemany(sql) self.connection.executemany(sql)
@ -254,10 +252,9 @@ class LocalStatusSQLiteFolder(BaseFolder):
self.messagelist[uid]['mtime'] = row[2] self.messagelist[uid]['mtime'] = row[2]
def closefiles(self): def closefiles(self):
databaseFileLock = LocalStatusSQLiteFolder.locks[self.filename] with self._databaseFileLock.getLock():
with databaseFileLock.getLock(): self._databaseFileLock.removeOneUser()
databaseFileLock.removeOneUser() if self._databaseFileLock.shouldClose():
if databaseFileLock.shouldClose():
try: try:
self.connection.close() self.connection.close()
except: except: