SQLite: avoid concurrent writes on backend migration

The saveall() method must acquire the lock to make writes.

Reported-and-tested-by: Julien Cubizolles <j.cubizolles@free.fr>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
This commit is contained in:
Nicolas Sebrecht 2017-01-31 01:41:26 +01:00
parent 23b497d191
commit 4df06d57c3
2 changed files with 13 additions and 11 deletions

View File

@ -1,5 +1,5 @@
# Local status cache virtual folder: SQLite backend
# Copyright (C) 2009-2016 Stewart Smith and contributors.
# Copyright (C) 2009-2017 Stewart Smith and contributors.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -282,16 +282,17 @@ class LocalStatusSQLiteFolder(BaseFolder):
def saveall(self):
"""Saves the entire messagelist to the database."""
data = []
for uid, msg in self.messagelist.items():
mtime = msg['mtime']
flags = ''.join(sorted(msg['flags']))
labels = ', '.join(sorted(msg['labels']))
data.append((uid, flags, mtime, labels))
with self._databaseFileLock.getLock():
data = []
for uid, msg in self.messagelist.items():
mtime = msg['mtime']
flags = ''.join(sorted(msg['flags']))
labels = ', '.join(sorted(msg['labels']))
data.append((uid, flags, mtime, labels))
self.__sql_write('INSERT OR REPLACE INTO status '
'(id,flags,mtime,labels) VALUES (?,?,?,?)',
data, executemany=True)
self.__sql_write('INSERT OR REPLACE INTO status '
'(id,flags,mtime,labels) VALUES (?,?,?,?)',
data, executemany=True)
# Following some pure SQLite functions, where we chose to use

View File

@ -1,5 +1,5 @@
# Local status cache repository support
# Copyright (C) 2002-2016 John Goerzen & contributors
# Copyright (C) 2002-2017 John Goerzen & contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -21,6 +21,7 @@ from offlineimap.folder.LocalStatus import LocalStatusFolder
from offlineimap.folder.LocalStatusSQLite import LocalStatusSQLiteFolder
from offlineimap.repository.Base import BaseRepository
class LocalStatusRepository(BaseRepository):
def __init__(self, reposname, account):
BaseRepository.__init__(self, reposname, account)