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:
		@@ -1,5 +1,5 @@
 | 
			
		||||
# Local status cache virtual folder
 | 
			
		||||
# Copyright (C) 2002 - 2003 John Goerzen
 | 
			
		||||
# Copyright (C) 2002 - 2007 John Goerzen
 | 
			
		||||
# <jgoerzen@complete.org>
 | 
			
		||||
#
 | 
			
		||||
#    This program is free software; you can redistribute it and/or modify
 | 
			
		||||
@@ -90,8 +90,18 @@ class LocalStatusFolder(BaseFolder):
 | 
			
		||||
                flags.sort()
 | 
			
		||||
                flags = ''.join(flags)
 | 
			
		||||
                file.write("%s:%s\n" % (msg['uid'], flags))
 | 
			
		||||
            file.flush()
 | 
			
		||||
            os.fsync(file.fileno())
 | 
			
		||||
            file.close()
 | 
			
		||||
            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:
 | 
			
		||||
            self.savelock.release()
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
# Maildir folder support
 | 
			
		||||
# Copyright (C) 2002 - 2006 John Goerzen
 | 
			
		||||
# Copyright (C) 2002 - 2007 John Goerzen
 | 
			
		||||
# <jgoerzen@complete.org>
 | 
			
		||||
#
 | 
			
		||||
#    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)
 | 
			
		||||
        file = open(os.path.join(tmpdir, tmpmessagename), "wt")
 | 
			
		||||
        file.write(content)
 | 
			
		||||
 | 
			
		||||
        # Make sure the data hits the disk
 | 
			
		||||
        file.flush()
 | 
			
		||||
        os.fsync(file.fileno())
 | 
			
		||||
 | 
			
		||||
        file.close()
 | 
			
		||||
        if rtime != None:
 | 
			
		||||
            os.utime(os.path.join(tmpdir,tmpmessagename), (rtime,rtime))
 | 
			
		||||
@@ -177,6 +182,15 @@ class MaildirFolder(BaseFolder):
 | 
			
		||||
        os.link(os.path.join(tmpdir, tmpmessagename),
 | 
			
		||||
                os.path.join(newdir, messagename))
 | 
			
		||||
        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': [],
 | 
			
		||||
                                 'filename': os.path.join(newdir, messagename)}
 | 
			
		||||
        self.savemessageflags(uid, flags)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user