[PATCH] SQLite: avoid concurrent writes on backend migration

Nicolas Sebrecht nicolas.s-dev at laposte.net
Tue Jan 31 00:46:47 GMT 2017


I think the following patch should fix this bug. Please, try it from

 https://github.com/nicolas33/offlineimap/tree/bug/database-closed


-- >% --
From: Nicolas Sebrecht <nicolas.s-dev at laposte.net>
Subject: [PATCH] SQLite: avoid concurrent writes on backend migration

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

Reported-by: Julien Cubizolles <j.cubizolles at free.fr>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev at laposte.net>
---
 offlineimap/folder/LocalStatusSQLite.py | 23 ++++++++++++-----------
 offlineimap/repository/LocalStatus.py   |  3 ++-
 2 files changed, 14 insertions(+), 12 deletions(-)

diff --git a/offlineimap/folder/LocalStatusSQLite.py b/offlineimap/folder/LocalStatusSQLite.py
index 47c7144..1047345 100644
--- a/offlineimap/folder/LocalStatusSQLite.py
+++ b/offlineimap/folder/LocalStatusSQLite.py
@@ -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))
-
-        self.__sql_write('INSERT OR REPLACE INTO status '
-            '(id,flags,mtime,labels) VALUES (?,?,?,?)',
-            data, executemany=True)
+        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)
 
 
     # Following some pure SQLite functions, where we chose to use
diff --git a/offlineimap/repository/LocalStatus.py b/offlineimap/repository/LocalStatus.py
index f23020f..ff99eab 100644
--- a/offlineimap/repository/LocalStatus.py
+++ b/offlineimap/repository/LocalStatus.py
@@ -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)
-- 
2.11.0





More information about the OfflineIMAP-project mailing list