folder/Maildir: Store only relative filename components
MaildirFolder.messagelist[*]['filename'] was storing the absolute file paths for all stored emails. While this is convenient, it wastes much space, as the folder prefix is always the same and it is known to the MaildirFolder. Just 40 chars in a folder with 100k mails waste >4MB of space. Adapt the few locations where we need the full path to construct it dynamically. Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de> Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
This commit is contained in:
parent
c1c200a487
commit
e023f190b0
@ -185,27 +185,32 @@ class MaildirFolder(BaseFolder):
|
|||||||
return self.messagelist
|
return self.messagelist
|
||||||
|
|
||||||
def getmessage(self, uid):
|
def getmessage(self, uid):
|
||||||
|
"""Return the content of the message"""
|
||||||
filename = self.messagelist[uid]['filename']
|
filename = self.messagelist[uid]['filename']
|
||||||
file = open(filename, 'rt')
|
filepath = os.path.join(self.getfullname(), filename)
|
||||||
|
file = open(filepath, 'rt')
|
||||||
retval = file.read()
|
retval = file.read()
|
||||||
file.close()
|
file.close()
|
||||||
|
#TODO: WHY are we replacing \r\n with \n here? And why do we
|
||||||
|
# read it as text?
|
||||||
return retval.replace("\r\n", "\n")
|
return retval.replace("\r\n", "\n")
|
||||||
|
|
||||||
def getmessagetime( self, uid ):
|
def getmessagetime( self, uid ):
|
||||||
filename = self.messagelist[uid]['filename']
|
filename = self.messagelist[uid]['filename']
|
||||||
st = os.stat(filename)
|
filepath = os.path.join(self.getfullname(), filename)
|
||||||
|
st = os.stat(filepath)
|
||||||
return st.st_mtime
|
return st.st_mtime
|
||||||
|
|
||||||
def savemessage(self, uid, content, flags, rtime):
|
def savemessage(self, uid, content, flags, rtime):
|
||||||
# This function only ever saves to tmp/,
|
# This function only ever saves to tmp/,
|
||||||
# but it calls savemessageflags() to actually save to cur/ or new/.
|
# but it calls savemessageflags() to actually save to cur/ or new/.
|
||||||
self.ui.debug('maildir', 'savemessage: called to write with flags %s and content %s' % \
|
self.ui.debug('maildir', 'savemessage: called to write with flags %s '
|
||||||
(repr(flags), repr(content)))
|
'and content %s' % (repr(flags), repr(content)))
|
||||||
if uid < 0:
|
if uid < 0:
|
||||||
# We cannot assign a new uid.
|
# We cannot assign a new uid.
|
||||||
return uid
|
return uid
|
||||||
if uid in self.messagelist:
|
if uid in self.messagelist:
|
||||||
# We already have it.
|
# We already have it, just update flags.
|
||||||
self.savemessageflags(uid, flags)
|
self.savemessageflags(uid, flags)
|
||||||
return uid
|
return uid
|
||||||
|
|
||||||
@ -231,7 +236,8 @@ class MaildirFolder(BaseFolder):
|
|||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
tmpmessagename = messagename.split(',')[0]
|
tmpmessagename = messagename.split(',')[0]
|
||||||
self.ui.debug('maildir', 'savemessage: using temporary name %s' % tmpmessagename)
|
self.ui.debug('maildir', 'savemessage: using temporary name %s' %\
|
||||||
|
tmpmessagename)
|
||||||
file = open(os.path.join(tmpdir, tmpmessagename), "wt")
|
file = open(os.path.join(tmpdir, tmpmessagename), "wt")
|
||||||
file.write(content)
|
file.write(content)
|
||||||
|
|
||||||
@ -239,10 +245,10 @@ class MaildirFolder(BaseFolder):
|
|||||||
file.flush()
|
file.flush()
|
||||||
if self.dofsync:
|
if self.dofsync:
|
||||||
os.fsync(file.fileno())
|
os.fsync(file.fileno())
|
||||||
|
|
||||||
file.close()
|
file.close()
|
||||||
|
|
||||||
if rtime != None:
|
if rtime != None:
|
||||||
os.utime(os.path.join(tmpdir,tmpmessagename), (rtime,rtime))
|
os.utime(os.path.join(tmpdir, tmpmessagename), (rtime, rtime))
|
||||||
self.ui.debug('maildir', 'savemessage: moving from %s to %s' % \
|
self.ui.debug('maildir', 'savemessage: moving from %s to %s' % \
|
||||||
(tmpmessagename, messagename))
|
(tmpmessagename, messagename))
|
||||||
if tmpmessagename != messagename: # then rename it
|
if tmpmessagename != messagename: # then rename it
|
||||||
@ -259,7 +265,8 @@ class MaildirFolder(BaseFolder):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
self.messagelist[uid] = {'uid': uid, 'flags': [],
|
self.messagelist[uid] = {'uid': uid, 'flags': [],
|
||||||
'filename': os.path.join(tmpdir, messagename)}
|
'filename': os.path.join('tmp', messagename)}
|
||||||
|
# savemessageflags moves msg to 'cur' or 'new' as appropriate
|
||||||
self.savemessageflags(uid, flags)
|
self.savemessageflags(uid, flags)
|
||||||
self.ui.debug('maildir', 'savemessage: returning uid %d' % uid)
|
self.ui.debug('maildir', 'savemessage: returning uid %d' % uid)
|
||||||
return uid
|
return uid
|
||||||
@ -269,14 +276,14 @@ class MaildirFolder(BaseFolder):
|
|||||||
|
|
||||||
def savemessageflags(self, uid, flags):
|
def savemessageflags(self, uid, flags):
|
||||||
oldfilename = self.messagelist[uid]['filename']
|
oldfilename = self.messagelist[uid]['filename']
|
||||||
newpath, newname = os.path.split(oldfilename)
|
dir_prefix, newname = os.path.split(oldfilename)
|
||||||
tmpdir = os.path.join(self.getfullname(), 'tmp')
|
tmpdir = os.path.join(self.getfullname(), 'tmp')
|
||||||
if 'S' in flags:
|
if 'S' in flags:
|
||||||
# If a message has been seen, it goes into the cur
|
# If a message has been seen, it goes into the cur
|
||||||
# directory. CR debian#152482, [complete.org #4]
|
# directory. CR debian#152482
|
||||||
newpath = os.path.join(self.getfullname(), 'cur')
|
dir_prefix = 'cur'
|
||||||
else:
|
else:
|
||||||
newpath = os.path.join(self.getfullname(), 'new')
|
dir_prefix = 'new'
|
||||||
infostr = ':'
|
infostr = ':'
|
||||||
infomatch = re.search('(:.*)$', newname)
|
infomatch = re.search('(:.*)$', newname)
|
||||||
if infomatch: # If the info string is present..
|
if infomatch: # If the info string is present..
|
||||||
@ -287,15 +294,16 @@ class MaildirFolder(BaseFolder):
|
|||||||
infostr += '2,' + ''.join(flags)
|
infostr += '2,' + ''.join(flags)
|
||||||
newname += infostr
|
newname += infostr
|
||||||
|
|
||||||
newfilename = os.path.join(newpath, newname)
|
newfilename = os.path.join(dir_prefix, newname)
|
||||||
if (newfilename != oldfilename):
|
if (newfilename != oldfilename):
|
||||||
os.rename(oldfilename, newfilename)
|
os.rename(os.path.join(self.getfullname(), oldfilename),
|
||||||
|
os.path.join(self.getfullname(), newfilename))
|
||||||
self.messagelist[uid]['flags'] = flags
|
self.messagelist[uid]['flags'] = flags
|
||||||
self.messagelist[uid]['filename'] = newfilename
|
self.messagelist[uid]['filename'] = newfilename
|
||||||
|
|
||||||
# By now, the message had better not be in tmp/ land!
|
# By now, the message had better not be in tmp/ land!
|
||||||
final_dir, final_name = os.path.split(self.messagelist[uid]['filename'])
|
final_dir, final_name = os.path.split(self.messagelist[uid]['filename'])
|
||||||
assert final_dir != tmpdir
|
assert final_dir != 'tmp'
|
||||||
|
|
||||||
def deletemessage(self, uid):
|
def deletemessage(self, uid):
|
||||||
"""Unlinks a message file from the Maildir.
|
"""Unlinks a message file from the Maildir.
|
||||||
@ -309,13 +317,16 @@ class MaildirFolder(BaseFolder):
|
|||||||
return
|
return
|
||||||
|
|
||||||
filename = self.messagelist[uid]['filename']
|
filename = self.messagelist[uid]['filename']
|
||||||
|
filepath = os.path.join(self.getfullname(), filename)
|
||||||
try:
|
try:
|
||||||
os.unlink(filename)
|
os.unlink(filepath)
|
||||||
except OSError:
|
except OSError:
|
||||||
# Can't find the file -- maybe already deleted?
|
# Can't find the file -- maybe already deleted?
|
||||||
newmsglist = self._scanfolder()
|
newmsglist = self._scanfolder()
|
||||||
if uid in newmsglist: # Nope, try new filename.
|
if uid in newmsglist: # Nope, try new filename.
|
||||||
os.unlink(newmsglist[uid]['filename'])
|
filename = newmsglist[uid]['filename']
|
||||||
|
filepath = os.path.join(self.getfullname(), filename)
|
||||||
|
os.unlink(filepath)
|
||||||
# Yep -- return.
|
# Yep -- return.
|
||||||
del(self.messagelist[uid])
|
del(self.messagelist[uid])
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user