]> code.delx.au - offlineimap/commitdiff
Added ability to disable fsync()
authorJohn Goerzen <jgoerzen@complete.org>
Sat, 2 Aug 2008 19:55:08 +0000 (14:55 -0500)
committerJohn Goerzen <jgoerzen@complete.org>
Sat, 2 Aug 2008 19:55:08 +0000 (14:55 -0500)
Passed config to LocalStatus and Maildir folders so they can look
up the fsync status

offlineimap.conf
offlineimap/folder/LocalStatus.py
offlineimap/folder/Maildir.py
offlineimap/repository/LocalStatus.py
offlineimap/repository/Maildir.py

index 996fe7a900131ef3e557f9658529471b8161b13a..de1a9d9c9bdc407e42172cce897395de8a5fc4e1 100644 (file)
@@ -98,6 +98,16 @@ ignore-readonly = no
 #
 # socktimeout = 60
 
+# By default, OfflineIMAP will use fsync() to force data out to disk at
+# opportune times to ensure consistency.  This can, however, reduce
+# performance.  Users where /home is on SSD (Flash) may also wish to reduce
+# write cycles.  Therefore, you can disable OfflineIMAP's use of fsync().
+# Doing so will come at the expense of greater risk of message duplication
+# in the event of a system crash or power loss.  Default is fsync = true.
+# Set fsync = false ot disable fsync.
+#
+# fsync = true
+
 ##################################################
 # Mailbox name recorder
 ##################################################
index 4bb83ee64784f5b74f789ddd08c861e1bcc106ca..c07c2b52b59f1ed8d5bdfdd4d9ef154f67259baf 100644 (file)
@@ -22,10 +22,12 @@ import os, threading
 magicline = "OFFLINEIMAP LocalStatus CACHE DATA - DO NOT MODIFY - FORMAT 1"
 
 class LocalStatusFolder(BaseFolder):
-    def __init__(self, root, name, repository, accountname):
+    def __init__(self, root, name, repository, accountname, config):
         self.name = name
         self.root = root
         self.sep = '.'
+        self.config = config
+        self.dofsync = config.getdefaultboolean("general", "fsync")        
         self.filename = os.path.join(root, name)
         self.filename = repository.getfolderfilename(name)
         self.messagelist = None
@@ -96,16 +98,18 @@ class LocalStatusFolder(BaseFolder):
                 flags = ''.join(flags)
                 file.write("%s:%s\n" % (msg['uid'], flags))
             file.flush()
-            os.fsync(file.fileno())
+            if self.dofsync:
+                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
+            if self.dofsync:
+                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 56a63e4306a1217469ec8bc232432df04d50597f..9b1b9ca3474b040dc2bc4421e3e4a5efe297f9a8 100644 (file)
@@ -45,8 +45,10 @@ def gettimeseq():
         timelock.release()
 
 class MaildirFolder(BaseFolder):
-    def __init__(self, root, name, sep, repository, accountname):
+    def __init__(self, root, name, sep, repository, accountname, config):
         self.name = name
+        self.config = config
+        self.dofsync = config.getdefaultboolean("general", "fsync")
         self.root = root
         self.sep = sep
         self.messagelist = None
@@ -183,7 +185,8 @@ class MaildirFolder(BaseFolder):
 
         # Make sure the data hits the disk
         file.flush()
-        os.fsync(file.fileno())
+        if self.dofsync:
+            os.fsync(file.fileno())
 
         file.close()
         if rtime != None:
index 8b7ac51d9f733ad00b941d658a417ae960bc1743..92e392d13cc5d8d4082be9393279f851bf5a7ed1 100644 (file)
@@ -54,12 +54,14 @@ class LocalStatusRepository(BaseRepository):
         retval = []
         for folder in os.listdir(self.directory):
             retval.append(folder.LocalStatus.LocalStatusFolder(self.directory,
-                                                               folder, self, self.accountname))
+                                                               folder, self, self.accountname, 
+                                                               self.config))
         return retval
 
     def getfolder(self, foldername):
         return folder.LocalStatus.LocalStatusFolder(self.directory, foldername,
-                                                    self, self.accountname)
+                                                    self, self.accountname,
+                                                    self.config)
 
 
     
index 291f35a7f9f375ff7608d32ea475a57c4dbc79c8..53edd63d09079e79f04a2dbcabc4a44afca3e855 100644 (file)
@@ -113,7 +113,8 @@ class MaildirRepository(BaseRepository):
        if self.config.has_option('Repository ' + self.name, 'restoreatime') and self.config.getboolean('Repository ' + self.name, 'restoreatime'):
            self._append_folder_atimes(foldername)
         return folder.Maildir.MaildirFolder(self.root, foldername,
-                                            self.getsep(), self, self.accountname)
+                                            self.getsep(), self, 
+                                            self.accountname, self.config)
     
     def _getfolders_scandir(self, root, extension = None):
         self.debug("_GETFOLDERS_SCANDIR STARTING. root = %s, extension = %s" \
@@ -159,7 +160,8 @@ class MaildirRepository(BaseRepository):
                if self.config.has_option('Repository ' + self.name, 'restoreatime') and self.config.getboolean('Repository ' + self.name, 'restoreatime'):
                    self._append_folder_atimes(foldername)
                 retval.append(folder.Maildir.MaildirFolder(self.root, foldername,
-                                                           self.getsep(), self, self.accountname))
+                                                           self.getsep(), self, self.accountname,
+                                                           self.config))
             if self.getsep() == '/' and dirname != '.':
                 # Check sub-directories for folders.
                 retval.extend(self._getfolders_scandir(root, foldername))