[PATCH 10/17] Automatically cache messages if needed

Sebastian Spaeth Sebastian at SSpaeth.de
Mon Nov 29 16:02:18 UTC 2010


Rather than forcing the user to cachemessagelist() before getmessagelist()
do it automatically.

Signed-off-by: Sebastian Spaeth <Sebastian at SSpaeth.de>
---
 offlineimap/folder/Base.py        |   26 +++++++++++++++----
 offlineimap/folder/IMAP.py        |    7 ++++-
 offlineimap/folder/LocalStatus.py |   24 ++++++++++--------
 offlineimap/folder/Maildir.py     |   49 +++++++++++++++++-------------------
 offlineimap/folder/UIDMaps.py     |    5 ++++
 5 files changed, 66 insertions(+), 45 deletions(-)

diff --git a/offlineimap/folder/Base.py b/offlineimap/folder/Base.py
index 35ab450..e7ad22d 100644
--- a/offlineimap/folder/Base.py
+++ b/offlineimap/folder/Base.py
@@ -26,7 +26,10 @@ import sys
 class BaseFolder:
     def __init__(self):
         self.uidlock = Lock()
-        
+        self.cachedMessageList = False
+        """whether we already got and cached the message list"""
+        self.messagelist = {}
+
     def getname(self):
         """Returns name"""
         return self.name
@@ -122,12 +125,20 @@ class BaseFolder:
     def cachemessagelist(self):
         """Reads the message list from disk or network and stores it in
         memory for later use.  This list will not be re-read from disk or
-        memory unless this function is called again."""
+        memory unless this function is called again.
+
+        Your implementation MUST set self.cachedMessageList = True
+        after successfull caching. Usually this function will be
+        automatically invoked by either method:`getmessagelist` or
+        method: `getmessageuidlist`"""
         raise NotImplementedException
 
     def getmessagelist(self):
         """Gets the current message list.
-        You must call cachemessagelist() before calling this function!"""
+        
+        Your implementation MUST call cachemessagelist() if
+        self.cachedMessageList = False and set
+        self.cachedMessageList = True afterwards."""
         raise NotImplementedException
 
     def uidexists(self,uid):
@@ -140,13 +151,16 @@ class BaseFolder:
 	return 0
 
     def getmessageuidlist(self):
-        """Gets a list of UIDs.
-        You may have to call cachemessagelist() before calling this function!"""
+        """Returns a list of UIDs.
+
+        Caches the list in if needed."""
+        if not self.cachedMessageList:
+            self.cachemessagelist()
 	return self.getmessagelist().keys()
 
     def getmessagecount(self):
         """Gets the number of messages."""
-        return len(self.getmessagelist().keys())
+        return len(self.getmessagelist())
 
     def getmessage(self, uid):
         """Returns the content of the specified message."""
diff --git a/offlineimap/folder/IMAP.py b/offlineimap/folder/IMAP.py
index 7569781..b4fa791 100644
--- a/offlineimap/folder/IMAP.py
+++ b/offlineimap/folder/IMAP.py
@@ -35,7 +35,6 @@ class IMAPFolder(BaseFolder):
         self.root = None # imapserver.root
         self.sep = imapserver.delim
         self.imapserver = imapserver
-        self.messagelist = None
         self.visiblename = visiblename
         self.accountname = accountname
         self.repository = repository
@@ -117,7 +116,8 @@ class IMAPFolder(BaseFolder):
 
         return False
 
-    # TODO: Make this so that it can define a date that would be the oldest messages etc.
+    # TODO: Make this so that it can define a date that would be
+    # the oldest messages etc.
     def cachemessagelist(self):
         imapobj = self.imapserver.acquireconnection()
         self.messagelist = {}
@@ -196,8 +196,11 @@ class IMAPFolder(BaseFolder):
                 flags = imaputil.flagsimap2maildir(options['FLAGS'])
                 rtime = imaplibutil.Internaldate2epoch(messagestr)
                 self.messagelist[uid] = {'uid': uid, 'flags': flags, 'time': rtime}
+        self.cachedMessageList = True
 
     def getmessagelist(self):
+        if not self.cachedMessageList:
+            self.cachemessagelist()
         return self.messagelist
 
     def getmessage(self, uid):
diff --git a/offlineimap/folder/LocalStatus.py b/offlineimap/folder/LocalStatus.py
index 0972a36..1c0a840 100644
--- a/offlineimap/folder/LocalStatus.py
+++ b/offlineimap/folder/LocalStatus.py
@@ -38,7 +38,6 @@ class LocalStatusFolder(BaseFolder):
         self.dofsync = config.getdefaultboolean("general", "fsync", True)
         self.filename = os.path.join(root, name)
         self.filename = repository.getfolderfilename(name)
-        self.messagelist = {}
         self.repository = repository
         self.savelock = threading.Lock()
         self.doautosave = 1
@@ -112,16 +111,6 @@ class LocalStatusFolder(BaseFolder):
             os.unlink(self.dbfilename)
 
     def cachemessagelist(self):
-        return
-
-    def autosave(self):
-        if self.doautosave:
-            self.save()
-
-    def save(self):
-        self.connection.commit()
-
-    def getmessagelist(self):
         if self.isnewfolder():
             self.messagelist = {}
             return
@@ -132,6 +121,19 @@ class LocalStatusFolder(BaseFolder):
             flags = [x for x in row[1]]
             self.messagelist[row[0]] = {'uid': row[0], 'flags': flags}
 
+        self.cachedMessageList = True
+        return self.messagelist
+
+    def autosave(self):
+        if self.doautosave:
+            self.save()
+
+    def save(self):
+        self.connection.commit()
+
+    def getmessagelist(self):
+        if not self.cachedMessageList:
+            self.cachemessagelist()
         return self.messagelist
 
     def uidexists(self,uid):
diff --git a/offlineimap/folder/Maildir.py b/offlineimap/folder/Maildir.py
index 49d4dae..c93fcc1 100644
--- a/offlineimap/folder/Maildir.py
+++ b/offlineimap/folder/Maildir.py
@@ -57,7 +57,6 @@ class MaildirFolder(BaseFolder):
         self.dofsync = config.getdefaultboolean("general", "fsync", True)
         self.root = root
         self.sep = sep
-        self.messagelist = None
         self.repository = repository
         self.accountname = accountname
         BaseFolder.__init__(self)
@@ -94,8 +93,20 @@ class MaildirFolder(BaseFolder):
         else:
             return True
 
+    def quickchanged(self, statusfolder):
+        if not self.cachedMessageList:
+            self.cachemessagelist()
+        savedmessages = statusfolder.getmessagelist()
+        if len(self.messagelist) != len(savedmessages):
+            return True
+        for uid in self.messagelist.keys():
+            if uid not in savedmessages:
+                return True
+            if self.messagelist[uid]['flags'] != savedmessages[uid]['flags']:
+                return True
+        return False
 
-    def _scanfolder(self):
+    def cachemessagelist(self):
         """Cache the message list.  Maildir flags are:
         R (replied)
         S (seen)
@@ -103,7 +114,7 @@ class MaildirFolder(BaseFolder):
         D (draft)
         F (flagged)
         and must occur in ASCII order."""
-        retval = {}
+        self.messagelist = {}
         files = []
         nouidcounter = -1               # Messages without UIDs get
                                         # negative UID numbers.
@@ -154,28 +165,15 @@ class MaildirFolder(BaseFolder):
             if flagmatch:
                 flags = [x for x in flagmatch.group(1)]
             flags.sort()
-            retval[uid] = {'uid': uid,
+            self.messagelist[uid] = {'uid': uid,
                            'flags': flags,
                            'filename': file}
-        return retval
-
-    def quickchanged(self, statusfolder):
-        self.cachemessagelist()
-        savedmessages = statusfolder.getmessagelist()
-        if len(self.messagelist) != len(savedmessages):
-            return True
-        for uid in self.messagelist.keys():
-            if uid not in savedmessages:
-                return True
-            if self.messagelist[uid]['flags'] != savedmessages[uid]['flags']:
-                return True
-        return False
 
-    def cachemessagelist(self):
-        if self.messagelist is None:
-            self.messagelist = self._scanfolder()
+        self.cachedMessageList = True
             
     def getmessagelist(self):
+        if not self.cachedMessageList:
+            self.cachemessagelist()
         return self.messagelist
 
     def getmessage(self, uid):
@@ -299,10 +297,9 @@ class MaildirFolder(BaseFolder):
         try:
             os.unlink(filename)
         except OSError:
-            # Can't find the file -- maybe already deleted?
-            newmsglist = self._scanfolder()
-            if uid in newmsglist:       # Nope, try new filename.
-                os.unlink(newmsglist[uid]['filename'])
-            # Yep -- return.
+            # Can't find the file -- maybe already deleted? Update cache.
+            self.cachemessagelist()
+            if self.uidexists(uid):       # Nope, try new filename.
+                os.unlink(self.messagelist[uid]['filename'])
+                # Yep -- return.
         del(self.messagelist[uid])
-        
diff --git a/offlineimap/folder/UIDMaps.py b/offlineimap/folder/UIDMaps.py
index 946f1f5..59fe570 100644
--- a/offlineimap/folder/UIDMaps.py
+++ b/offlineimap/folder/UIDMaps.py
@@ -102,10 +102,15 @@ class MappingFolderMixIn:
         finally:
             self.maplock.release()
 
+        self.cachedMessageList = True
+
     def getmessagelist(self):
         """Gets the current message list.
         You must call cachemessagelist() before calling this function!"""
 
+        if not self.cachedMessageList:
+            self.cachemessagelist()
+
         retval = {}
         localhash = self._mb.getmessagelist(self)
         self.maplock.acquire()
-- 
1.7.1




More information about the OfflineIMAP-project mailing list