[jhbuild/desrt/master: 34/35] packagedb: move safe file writing to fileutils



commit 1c87fb26d99c44d59d294abc0e3faad7e9be82ff
Author: Ryan Lortie <desrt desrt ca>
Date:   Sat Jan 3 23:16:13 2015 -0500

    packagedb: move safe file writing to fileutils
    
    Add a SafeWriter class to fileutils that handles the usual dance of
    creating a tmpfile, writing to it, flushing it, fsyncing it, closing it
    and renaming it.
    
    Use it from the two locations that were doing this in packagedb.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=742298

 jhbuild/utils/fileutils.py |   20 ++++++++++++++++++++
 jhbuild/utils/packagedb.py |   27 ++++++++-------------------
 2 files changed, 28 insertions(+), 19 deletions(-)
---
diff --git a/jhbuild/utils/fileutils.py b/jhbuild/utils/fileutils.py
index b57d062..15d5191 100644
--- a/jhbuild/utils/fileutils.py
+++ b/jhbuild/utils/fileutils.py
@@ -107,3 +107,23 @@ if os.name == 'nt':
     rename = _windows_rename
 else:
     rename = os.rename
+
+class SafeWriter(object):
+    def __init__(self, filename):
+        self.filename = filename
+        self.tmpname = filename + '.tmp'
+        self.fp = open(self.tmpname, 'w')
+
+    def commit(self):
+        self.fp.flush()
+        if hasattr(os, 'fdatasync'):
+            os.fdatasync(self.fp.fileno())
+        else:
+            os.fsync(self.fp.fileno())
+        self.fp.close()
+
+        rename(self.tmpname, self.filename)
+
+    def abandon(self):
+        self.fp.close()
+        os.unlink(self.tmpname)
diff --git a/jhbuild/utils/packagedb.py b/jhbuild/utils/packagedb.py
index 79f5771..9c2d95d 100644
--- a/jhbuild/utils/packagedb.py
+++ b/jhbuild/utils/packagedb.py
@@ -94,15 +94,9 @@ class PackageEntry:
         return dbentry
 
     def write(self):
-        fd = file(os.path.join(self.manifests_dir, self.package + '.tmp'), 'w')
-        fd.write('\n'.join(self.manifest) + '\n')
-        if hasattr(os, 'fdatasync'):
-            os.fdatasync(fd.fileno())
-        else:
-            os.fsync(fd.fileno())
-        fd.close()
-        fileutils.rename(os.path.join(self.manifests_dir, self.package + '.tmp'),
-                         os.path.join(self.manifests_dir, self.package))
+        writer = fileutils.SafeWriter(os.path.join(self.manifests_dir, self.package))
+        writer.fp.write('\n'.join(self.manifest) + '\n')
+        writer.commit()
 
     def remove(self):
         os.unlink(os.path.join(self.manifests_dir, self.package))
@@ -176,9 +170,8 @@ class PackageDB:
             node = entry.to_xml(doc)
             pkgdb_node.append(node)
 
-        tmp_dbfile_path = self.dbfile + '.tmp'
-        tmp_dbfile = open(tmp_dbfile_path, 'w')
-        
+        writer = fileutils.SafeWriter(self.dbfile)
+
         # Because ElementTree can't pretty-print, we convert it to a string
         # and then read it back with DOM, then write it out again.  Yes, this
         # is lame.
@@ -187,15 +180,11 @@ class PackageDB:
         doc.write(buf, encoding='UTF-8')
         dom_doc = DOM.parseString(buf.getvalue())
         try:
-            dom_doc.writexml(tmp_dbfile, addindent='  ', newl='\n', encoding='UTF-8')
+            dom_doc.writexml(writer.fp, addindent='  ', newl='\n', encoding='UTF-8')
         except:
-            tmp_dbfile.close()
-            os.unlink(tmp_dbfile_path)
+            writer.abandon()
             raise
-        tmp_dbfile.flush()
-        os.fsync(tmp_dbfile.fileno())
-        tmp_dbfile.close()
-        fileutils.rename(tmp_dbfile_path, self.dbfile)
+        writer.commit()
         # Ensure we don't reread what we already have cached
         self._entries_stat = os.stat(self.dbfile)
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]