summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohan Dahlin <johan@async.com.br>2008-12-08 16:29:33 +0000
committerJohan Dahlin <johan@src.gnome.org>2008-12-08 16:29:33 +0000
commitd05de46ddec10d4b7f9968320d2cb5f54d14d2f4 (patch)
tree92bcd7013972925ef7dfeef5e422e13dc7b03e36
parent645cc555cce7b6c1252e19f70d5083f30b40c03e (diff)
downloadgobject-introspection-d05de46ddec10d4b7f9968320d2cb5f54d14d2f4.tar.gz
Dump the cache file to a temporary file and rename it the expected
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. svn path=/trunk/; revision=985
-rw-r--r--ChangeLog8
-rw-r--r--giscanner/cachestore.py26
2 files changed, 27 insertions, 7 deletions
diff --git a/ChangeLog b/ChangeLog
index b5d6ba3c..ba52604a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+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.
+
2008-12-03 Christophe Fergeau <teuf@gnome.org>
Bug 562971 – g-ir-scanner failure on libgpod headers
diff --git a/giscanner/cachestore.py b/giscanner/cachestore.py
index 4629e622..d9163464 100644
--- a/giscanner/cachestore.py
+++ b/giscanner/cachestore.py
@@ -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 @@ class CacheStore(object):
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 @@ class CacheStore(object):
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 @@ class CacheStore(object):
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