[PATCH 9/9] Create LocalStatus or LocalStatusSQLite folders

Sebastian Spaeth Sebastian at SSpaeth.de
Tue Apr 26 11:31:40 BST 2011


Depending on the configuration we use the plain text or the new
experimental sqlite backend for the LocalStatus cache. Make plain text
the default status backend but allow people to configure
status_backend=sqlite in their [Account ...] section.

Signed-off-by: Sebastian Spaeth <Sebastian at SSpaeth.de>
---
 Changelog.draft.rst                   |   12 +++-------
 offlineimap.conf                      |   12 +++++++++++
 offlineimap/repository/LocalStatus.py |   36 ++++++++++++++++++++++++++------
 3 files changed, 45 insertions(+), 15 deletions(-)

diff --git a/Changelog.draft.rst b/Changelog.draft.rst
index 0a85888..79f9cd1 100644
--- a/Changelog.draft.rst
+++ b/Changelog.draft.rst
@@ -13,6 +13,10 @@ others.
 New Features
 ------------
 
+* optional: experimental SQLite-based backend for the LocalStatus
+  cache. Plain text remains the default. Enable by setting
+  status_backend=sqlite in the [Account ...] section
+
 Changes
 -------
 
@@ -25,11 +29,3 @@ Pending for the next major release
 
 * UIs get shorter and nicer names. (API changing)
 * Implement IDLE feature. (delayed until next major release)
-
-
-Stalled
-=======
-
-* Learn Sqlite support.
-    Stalled: it would need to learn the ability to choose between the current
-    format and SQL to help testing the long term.
diff --git a/offlineimap.conf b/offlineimap.conf
index 7018090..da92a30 100644
--- a/offlineimap.conf
+++ b/offlineimap.conf
@@ -197,6 +197,18 @@ remoterepository = RemoteExample
 # You can also specify parameters to the commands
 # presynchook = imapfilter -c someotherconfig.lua
 
+# OfflineImap caches the status of your mails to e.g. be able to
+# determine if a mail has been deleted on one side or added on the
+# other. The default backend is 'plain' which writes out the status in
+# plain text files. On Repositories with large numbers of mails, the
+# performance might not be optimal, as we write out the complete file
+# for each change. Another backend 'sqlite' is available which stores
+# the status in sqlite databased. If you switch the backend, you will
+# have to delete the old cache directory in
+# ~/.offlineimap/Account-<account>/LocalStatus[-sqlite] manually.
+
+status_backend = plain
+
 # If you have a limited amount of bandwidth available you can exclude larger
 # messages (e.g. those with large attachments etc).  If you do this it
 # will appear to offlineimap that these messages do not exist at all.  They
diff --git a/offlineimap/repository/LocalStatus.py b/offlineimap/repository/LocalStatus.py
index 722f6c3..7d38596 100644
--- a/offlineimap/repository/LocalStatus.py
+++ b/offlineimap/repository/LocalStatus.py
@@ -18,7 +18,8 @@
 
 from Base import BaseRepository
 from offlineimap import folder
-import offlineimap.folder.LocalStatus
+from offlineimap.folder.LocalStatus import LocalStatusFolder
+from offlineimap.folder.LocalStatusSQLite import LocalStatusSQLiteFolder
 import os
 import re
 
@@ -26,9 +27,25 @@ class LocalStatusRepository(BaseRepository):
     def __init__(self, reposname, account):
         BaseRepository.__init__(self, reposname, account)
         self.directory = os.path.join(account.getaccountmeta(), 'LocalStatus')
+
+        #statusbackend can be 'plain' or 'sqlite'
+        backend = self.account.getconf('status_backend', 'plain')
+        if backend == 'sqlite':
+            self._backend = 'sqlite'
+            self.LocalStatusFolderClass = LocalStatusSQLiteFolder
+            self.directory += '-sqlite'
+        elif backend == 'plain':
+            self._backend = 'plain'
+            self.LocalStatusFolderClass = LocalStatusFolder
+        else:
+            raise SyntaxWarning("Unknown status_backend '%s' for account '%s'" \
+                                % (backend, account.name))
+
         if not os.path.exists(self.directory):
             os.mkdir(self.directory, 0700)
-        self.folders = None
+
+        # self._folders is a list of LocalStatusFolders()
+        self._folders = None
 
     def getsep(self):
         return '.'
@@ -40,16 +57,22 @@ class LocalStatusRepository(BaseRepository):
         return os.path.join(self.directory, foldername)
 
     def makefolder(self, foldername):
-        # "touch" the file, truncating it.
+        """Create a LocalStatus Folder
+
+        Empty Folder for plain backend. NoOp for sqlite backend as those
+        are created on demand."""
+        # Invalidate the cache.
+        self._folders = None
+        if self._backend == 'sqlite':
+            return
+
         filename = self.getfolderfilename(foldername)
         file = open(filename + ".tmp", "wt")
         file.write(offlineimap.folder.LocalStatus.magicline + '\n')
-        file.flush()
-        os.fsync(file.fileno())
         file.close()
         os.rename(filename + ".tmp", filename)
         # Invalidate the cache.
-        self.folders = None
+        self._folders = None
 
     def getfolder(self, foldername):
         """Return the Folder() object for a foldername"""
@@ -72,4 +95,3 @@ class LocalStatusRepository(BaseRepository):
         """Forgets the cached list of folders, if any.  Useful to run
         after a sync run."""
         self._folders = None
-
-- 
1.7.4.1





More information about the OfflineIMAP-project mailing list