gobject-introspection r985 - in trunk: . giscanner



Author: johan
Date: Mon Dec  8 16:29:33 2008
New Revision: 985
URL: http://svn.gnome.org/viewvc/gobject-introspection?rev=985&view=rev

Log:
2008-12-08  Johan Dahlin  <johan async com br>

	* giscanner/cachestore.py (CacheStore.store): Dump the cache
	file to a temporary file and rename it the expected filename
	only when it's completely written.
	This should make the cache more roboust when run in parallel,
	and hopefully avoid triggering bugs in Python.



Modified:
   trunk/ChangeLog
   trunk/giscanner/cachestore.py

Modified: trunk/giscanner/cachestore.py
==============================================================================
--- trunk/giscanner/cachestore.py	(original)
+++ trunk/giscanner/cachestore.py	Mon Dec  8 16:29:33 2008
@@ -18,11 +18,11 @@
 # Boston, MA 02111-1307, USA.
 #
 
+import errno
 import cPickle
 import hashlib
 import os
-import errno
-
+import tempfile
 
 def _get_cachedir():
     cachedir = os.path.join(os.environ['HOME'], '.cache')
@@ -61,7 +61,7 @@
         return (os.stat(store_filename).st_mtime >=
                 os.stat(filename).st_mtime)
 
-    def _purge_cache(self, filename):
+    def _remove_filename(filename):
         try:
             os.unlink(filename)
         except IOError, e:
@@ -81,19 +81,31 @@
         store_filename = self._get_filename(filename)
         if store_filename is None:
             return
+
         if (os.path.exists(store_filename) and
             self._cache_is_valid(store_filename, filename)):
             return None
-        fd = open(store_filename, 'w')
+
+        tmp_fd, tmp_filename = tempfile.mkstemp(prefix='g-ir-scanner-cache-')
         try:
-            cPickle.dump(data, fd)
+            cPickle.dump(data, os.fdopen(tmp_fd, 'w'))
         except IOError, e:
             # No space left on device
-            if e.errno == e.ENOSPC:
+            if e.errno == errno.ENOSPC:
+                self._remove_filename(tmp_filename)
                 return
             else:
                 raise
 
+        try:
+            os.rename(tmp_filename, store_filename)
+        except OSError, e:
+            # Permission denied
+            if e.errno == errno.EACCES:
+                self._remove_filename(tmp_filename)
+            else:
+                raise
+
     def load(self, filename):
         store_filename = self._get_filename(filename)
         if store_filename is None:
@@ -111,6 +123,6 @@
             data = cPickle.load(fd)
         except (EOFError, ValueError, cPickle.BadPickleGet):
             # Broken cache entry, remove it
-            self._purge_cache(store_filename)
+            self._remove_filename(store_filename)
             data = None
         return data



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