Improve filesystem flushing semantics

fsync the Maildir file, its final directory when writing a new message.

fsync the localstatus file and its final directory when writing the 
local status cache.

This should reduce duplication in the event of hardware trouble.

fixes #8

see thread at http://lists.complete.org/offlineimap@complete.org/2007/03/threads.html.gz
This commit is contained in:
John Goerzen 2007-03-28 21:23:18 +01:00
parent 4b564bd568
commit 4f54887265
2 changed files with 26 additions and 2 deletions

View File

@ -1,5 +1,5 @@
# Local status cache virtual folder # Local status cache virtual folder
# Copyright (C) 2002 - 2003 John Goerzen # Copyright (C) 2002 - 2007 John Goerzen
# <jgoerzen@complete.org> # <jgoerzen@complete.org>
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
@ -90,8 +90,18 @@ class LocalStatusFolder(BaseFolder):
flags.sort() flags.sort()
flags = ''.join(flags) flags = ''.join(flags)
file.write("%s:%s\n" % (msg['uid'], flags)) file.write("%s:%s\n" % (msg['uid'], flags))
file.flush()
os.fsync(file.fileno())
file.close() file.close()
os.rename(self.filename + ".tmp", self.filename) os.rename(self.filename + ".tmp", self.filename)
try:
fd = os.open(os.path.dirname(self.filename), os.O_RDONLY)
os.fsync(fd)
os.close(fd)
except:
pass
finally: finally:
self.savelock.release() self.savelock.release()

View File

@ -1,5 +1,5 @@
# Maildir folder support # Maildir folder support
# Copyright (C) 2002 - 2006 John Goerzen # Copyright (C) 2002 - 2007 John Goerzen
# <jgoerzen@complete.org> # <jgoerzen@complete.org>
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
@ -169,6 +169,11 @@ class MaildirFolder(BaseFolder):
ui.debug('maildir', 'savemessage: using temporary name %s' % tmpmessagename) 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)
# Make sure the data hits the disk
file.flush()
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))
@ -177,6 +182,15 @@ class MaildirFolder(BaseFolder):
os.link(os.path.join(tmpdir, tmpmessagename), os.link(os.path.join(tmpdir, tmpmessagename),
os.path.join(newdir, messagename)) os.path.join(newdir, messagename))
os.unlink(os.path.join(tmpdir, tmpmessagename)) os.unlink(os.path.join(tmpdir, tmpmessagename))
try:
# fsync the directory (safer semantics in Linux)
fd = os.open(newdir, os.O_RDONLY)
os.fsync(fd)
os.close(fd)
except:
pass
self.messagelist[uid] = {'uid': uid, 'flags': [], self.messagelist[uid] = {'uid': uid, 'flags': [],
'filename': os.path.join(newdir, messagename)} 'filename': os.path.join(newdir, messagename)}
self.savemessageflags(uid, flags) self.savemessageflags(uid, flags)