[jhbuild] packagedb: move safe file writing to fileutils



commit 62a7097d8db25a6f7e668b274193f23f645d75ac
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 |   19 +++++++++++++++++++
 jhbuild/utils/packagedb.py |   27 ++++++++-------------------
 2 files changed, 27 insertions(+), 19 deletions(-)
---
diff --git a/jhbuild/utils/fileutils.py b/jhbuild/utils/fileutils.py
index 95def68..eb66f18 100644
--- a/jhbuild/utils/fileutils.py
+++ b/jhbuild/utils/fileutils.py
@@ -114,3 +114,22 @@ def ensure_unlinked(filename):
     except OSError as e:
         if e.errno != os.errno.ENOENT:
             raise
+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 29cf1e7..483f7e6 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):
         fileutils.ensure_unlinked(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]