]> code.delx.au - offlineimap/blob - offlineimap/folder/LocalStatus.py
90ad3c8c1a043cf43f0ebce780459ba869b9cc86
[offlineimap] / offlineimap / folder / LocalStatus.py
1 # Local status cache virtual folder
2 # Copyright (C) 2002 - 2008 John Goerzen
3 # <jgoerzen@complete.org>
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 from Base import BaseFolder
20 import os, threading
21
22 from pysqlite2 import dbapi2 as sqlite
23
24 magicline = "OFFLINEIMAP LocalStatus CACHE DATA - DO NOT MODIFY - FORMAT 1"
25 newmagicline = "OFFLINEIMAP LocalStatus NOW IN SQLITE, DO NOT MODIFY"
26
27 class LocalStatusFolder(BaseFolder):
28 def __deinit__(self):
29 self.save()
30 self.cursor.close()
31 self.connection.close()
32
33 def __init__(self, root, name, repository, accountname):
34 self.name = name
35 self.root = root
36 self.sep = '.'
37 self.filename = os.path.join(root, name)
38 self.filename = repository.getfolderfilename(name)
39 self.messagelist = {}
40 self.repository = repository
41 self.savelock = threading.Lock()
42 self.doautosave = 1
43 self.accountname = accountname
44 BaseFolder.__init__(self)
45 self.dbfilename = self.filename + '.sqlite'
46
47 # MIGRATE
48 if os.path.exists(self.filename):
49 self.connection = sqlite.connect(self.dbfilename)
50 self.cursor = self.connection.cursor()
51 self.cursor.execute('CREATE TABLE status (id INTEGER PRIMARY KEY, flags VARCHAR(50))')
52 if self.isnewfolder():
53 self.messagelist = {}
54 return
55 file = open(self.filename, "rt")
56 self.messagelist = {}
57 line = file.readline().strip()
58 assert(line == magicline)
59 for line in file.xreadlines():
60 line = line.strip()
61 uid, flags = line.split(':')
62 uid = long(uid)
63 flags = [x for x in flags]
64 flags.sort()
65 flags = ''.join(flags)
66 self.cursor.execute('INSERT INTO status (id,flags) VALUES (?,?)',
67 (uid,flags))
68 file.close()
69 self.connection.commit()
70 os.rename(self.filename, self.filename + ".old")
71 self.cursor.close()
72 self.connection.close()
73
74 # create new
75 if not os.path.exists(self.dbfilename):
76 self.connection = sqlite.connect(self.dbfilename)
77 self.cursor = self.connection.cursor()
78 self.cursor.execute('CREATE TABLE status (id INTEGER PRIMARY KEY, flags VARCHAR(50))')
79 else:
80 self.connection = sqlite.connect(self.dbfilename)
81 self.cursor = self.connection.cursor()
82
83
84
85 def getaccountname(self):
86 return self.accountname
87
88 def storesmessages(self):
89 return 0
90
91 def isnewfolder(self):
92 return not os.path.exists(self.dbfilename)
93
94 def getname(self):
95 return self.name
96
97 def getroot(self):
98 return self.root
99
100 def getsep(self):
101 return self.sep
102
103 def getfullname(self):
104 return self.filename
105
106 def deletemessagelist(self):
107 if not self.isnewfolder():
108 self.cursor.close()
109 self.connection.close()
110 os.unlink(self.dbfilename)
111
112 def cachemessagelist(self):
113 return
114
115 def autosave(self):
116 if self.doautosave:
117 self.save()
118
119 def save(self):
120 self.connection.commit()
121
122 def getmessagelist(self):
123 if self.isnewfolder():
124 self.messagelist = {}
125 return
126
127 self.messagelist = {}
128 self.cursor.execute('SELECT id,flags from status')
129 for row in self.cursor:
130 flags = [x for x in row[1]]
131 self.messagelist[row[0]] = {'uid': row[0], 'flags': flags}
132
133 return self.messagelist
134
135 def uidexists(self,uid):
136 self.cursor.execute('SELECT id FROM status WHERE id=:id',{'id': uid})
137 for row in self.cursor:
138 if(row[0]==uid):
139 return 1
140 return 0
141
142 def getmessageuidlist(self):
143 self.cursor.execute('SELECT id from status')
144 r = []
145 for row in self.cursor:
146 r.append(row[0])
147 return r
148
149 def getmessagecount(self):
150 self.cursor.execute('SELECT count(id) from status');
151 row = self.cursor.fetchone()
152 return row[0]
153
154 def savemessage(self, uid, content, flags, rtime):
155 if uid < 0:
156 # We cannot assign a uid.
157 return uid
158
159 if self.uidexists(uid): # already have it
160 self.savemessageflags(uid, flags)
161 return uid
162
163 self.messagelist[uid] = {'uid': uid, 'flags': flags, 'time': rtime}
164 flags.sort()
165 flags = ''.join(flags)
166 self.cursor.execute('INSERT INTO status (id,flags) VALUES (?,?)',
167 (uid,flags))
168 self.autosave()
169 return uid
170
171 def getmessageflags(self, uid):
172 self.cursor.execute('SELECT flags FROM status WHERE id=:id',
173 {'id': uid})
174 for row in self.cursor:
175 flags = [x for x in row[0]]
176 return flags
177 return flags
178
179 def getmessagetime(self, uid):
180 return self.messagelist[uid]['time']
181
182 def savemessageflags(self, uid, flags):
183 self.messagelist[uid] = {'uid': uid, 'flags': flags}
184 flags.sort()
185 flags = ''.join(flags)
186 self.cursor.execute('UPDATE status SET flags=? WHERE id=?',(flags,uid))
187 self.autosave()
188
189 def deletemessage(self, uid):
190 if not self.uidexists(uid):
191 return
192
193 if uid in self.messagelist:
194 del(self.messagelist[uid])
195
196 self.cursor.execute('DELETE FROM status WHERE id=:id', {'id': uid})
197 return