]> code.delx.au - offlineimap/commitdiff
Improve filesystem flushing semantics
authorJohn Goerzen <jgoerzen@complete.org>
Wed, 28 Mar 2007 20:23:18 +0000 (21:23 +0100)
committerJohn Goerzen <jgoerzen@complete.org>
Wed, 28 Mar 2007 20:23:18 +0000 (21:23 +0100)
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

offlineimap/folder/LocalStatus.py
offlineimap/folder/Maildir.py

index 937825d5ba66c200147016e5d4c082679dc6702a..bace7df9e8b77881c8c50273828c9fcc9ce50bac 100644 (file)
@@ -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()
 
index 74019cb658331a8338fac0e73559b5068ec15d16..a4dbdba1030e7d712dfb2c7757a32ca01ed4d10a 100644 (file)
@@ -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)