[PATCH 3/9] Experimental LocalStatus stored in SQLite database
Sebastian Spaeth
Sebastian at SSpaeth.de
Tue Apr 26 11:31:34 BST 2011
Based on patches by Stewart Smith, updated by Rob Browning.
This adds the file without using it yet.
Signed-off-by: Sebastian Spaeth <Sebastian at SSpaeth.de>
---
offlineimap/folder/LocalStatusSQLite.py | 202 +++++++++++++++++++++++++++++++
1 files changed, 202 insertions(+), 0 deletions(-)
create mode 100644 offlineimap/folder/LocalStatusSQLite.py
diff --git a/offlineimap/folder/LocalStatusSQLite.py b/offlineimap/folder/LocalStatusSQLite.py
new file mode 100644
index 0000000..974baf4
--- /dev/null
+++ b/offlineimap/folder/LocalStatusSQLite.py
@@ -0,0 +1,202 @@
+# Local status cache virtual folder: SQLite backend
+# Copyright (C) 2009-2011 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
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+from Base import BaseFolder
+import os, threading
+
+from pysqlite2 import dbapi2 as sqlite
+
+magicline = "OFFLINEIMAP LocalStatus CACHE DATA - DO NOT MODIFY - FORMAT 1"
+newmagicline = "OFFLINEIMAP LocalStatus NOW IN SQLITE, DO NOT MODIFY"
+
+class LocalStatusFolder(BaseFolder):
+ """LocalStatus backend implemented with an SQLite database"""
+ def __deinit__(self):
+ self.save()
+ self.cursor.close()
+ self.connection.close()
+
+ def __init__(self, root, name, repository, accountname, config):
+ self.name = name
+ self.root = root
+ self.sep = '.'
+ self.config = config
+ self.dofsync = config.getdefaultboolean("general", "fsync", True)
+ self.filename = repository.getfolderfilename(name)
+ self.messagelist = {}
+ self.repository = repository
+ self.savelock = threading.Lock()
+ self.doautosave = 1
+ self.accountname = accountname
+ BaseFolder.__init__(self)
+ self.dbfilename = self.filename + '.sqlite'
+
+ # MIGRATE
+ if os.path.exists(self.filename):
+ self.connection = sqlite.connect(self.dbfilename)
+ self.cursor = self.connection.cursor()
+ self.cursor.execute('CREATE TABLE status (id INTEGER PRIMARY KEY, flags VARCHAR(50))')
+ if self.isnewfolder():
+ self.messagelist = {}
+ return
+ file = open(self.filename, "rt")
+ self.messagelist = {}
+ line = file.readline().strip()
+ assert(line == magicline)
+ for line in file.xreadlines():
+ line = line.strip()
+ uid, flags = line.split(':')
+ uid = long(uid)
+ flags = [x for x in flags]
+ flags.sort()
+ flags = ''.join(flags)
+ self.cursor.execute('INSERT INTO status (id,flags) VALUES (?,?)',
+ (uid,flags))
+ file.close()
+ self.connection.commit()
+ os.rename(self.filename, self.filename + ".old")
+ self.cursor.close()
+ self.connection.close()
+
+ # create new
+ if not os.path.exists(self.dbfilename):
+ self.connection = sqlite.connect(self.dbfilename)
+ self.cursor = self.connection.cursor()
+ self.cursor.execute('CREATE TABLE status (id INTEGER PRIMARY KEY, flags VARCHAR(50))')
+ else:
+ self.connection = sqlite.connect(self.dbfilename)
+ self.cursor = self.connection.cursor()
+
+
+
+ def getaccountname(self):
+ return self.accountname
+
+ def storesmessages(self):
+ return 0
+
+ def isnewfolder(self):
+ return not os.path.exists(self.dbfilename)
+
+ def getname(self):
+ return self.name
+
+ def getroot(self):
+ return self.root
+
+ def getsep(self):
+ return self.sep
+
+ def getfullname(self):
+ return self.filename
+
+ def deletemessagelist(self):
+ if not self.isnewfolder():
+ self.cursor.close()
+ self.connection.close()
+ 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
+
+ self.messagelist = {}
+ self.cursor.execute('SELECT id,flags from status')
+ for row in self.cursor:
+ flags = [x for x in row[1]]
+ self.messagelist[row[0]] = {'uid': row[0], 'flags': flags}
+
+ return self.messagelist
+
+ def uidexists(self,uid):
+ self.cursor.execute('SELECT id FROM status WHERE id=:id',{'id': uid})
+ for row in self.cursor:
+ if(row[0]==uid):
+ return 1
+ return 0
+
+ def getmessageuidlist(self):
+ self.cursor.execute('SELECT id from status')
+ r = []
+ for row in self.cursor:
+ r.append(row[0])
+ return r
+
+ def getmessagecount(self):
+ self.cursor.execute('SELECT count(id) from status');
+ row = self.cursor.fetchone()
+ return row[0]
+
+ def savemessage(self, uid, content, flags, rtime):
+ if uid < 0:
+ # We cannot assign a uid.
+ return uid
+
+ if self.uidexists(uid): # already have it
+ self.savemessageflags(uid, flags)
+ return uid
+
+ self.messagelist[uid] = {'uid': uid, 'flags': flags, 'time': rtime}
+ flags.sort()
+ flags = ''.join(flags)
+ self.cursor.execute('INSERT INTO status (id,flags) VALUES (?,?)',
+ (uid,flags))
+ self.autosave()
+ return uid
+
+ def getmessageflags(self, uid):
+ self.cursor.execute('SELECT flags FROM status WHERE id=:id',
+ {'id': uid})
+ for row in self.cursor:
+ flags = [x for x in row[0]]
+ return flags
+ assert False,"getmessageflags() called on non-existing message"
+
+ def getmessagetime(self, uid):
+ return self.messagelist[uid]['time']
+
+ def savemessageflags(self, uid, flags):
+ self.messagelist[uid] = {'uid': uid, 'flags': flags}
+ flags.sort()
+ flags = ''.join(flags)
+ self.cursor.execute('UPDATE status SET flags=? WHERE id=?',(flags,uid))
+ self.autosave()
+
+ def deletemessage(self, uid):
+ self.deletemessages([uid])
+
+ def deletemessages(self, uidlist):
+ # Weed out ones not in self.messagelist
+ uidlist = [uid for uid in uidlist if uid in self.messagelist]
+ if not len(uidlist):
+ return
+
+ for uid in uidlist:
+ del(self.messagelist[uid])
+ #if self.uidexists(uid):
+ self.cursor.execute('DELETE FROM status WHERE id=:id', {'id': uid})
--
1.7.4.1
More information about the OfflineIMAP-project
mailing list