[jhbuild] packagedb: Use a lock file around modifications, reread after external changes
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [jhbuild] packagedb: Use a lock file around modifications, reread after external changes
- Date: Fri, 30 Sep 2011 18:12:01 +0000 (UTC)
commit 08c2f07bf2580af5ae543b0e33d6c0b1e2269f88
Author: Colin Walters <walters verbum org>
Date: Sun Jul 31 17:38:04 2011 -0400
packagedb: Use a lock file around modifications, reread after external changes
To somewhat support concurrent operation like "jhbuild buildone foo",
"jhbuild buildone bar" in separate terminals for speed, we need to at
least avoid corrupting the packagedb.xml file.
Note this does NOT provide safety against building/installing the same
module twice.
https://bugzilla.gnome.org/show_bug.cgi?id=312910
jhbuild/utils/packagedb.py | 37 +++++++++++++++++++++++++++++++++++--
1 files changed, 35 insertions(+), 2 deletions(-)
---
diff --git a/jhbuild/utils/packagedb.py b/jhbuild/utils/packagedb.py
index 9f47ec0..f610e71 100644
--- a/jhbuild/utils/packagedb.py
+++ b/jhbuild/utils/packagedb.py
@@ -19,10 +19,13 @@
import os
import sys
+import stat
import time
import logging
import xml.dom.minidom as DOM
+from . import lockfile
+
try:
import xml.etree.ElementTree as ET
except ImportError:
@@ -114,21 +117,37 @@ class PackageEntry:
class PackageDB:
def __init__(self, dbfile, config):
self.dbfile = dbfile
- self.manifests_dir = os.path.join(os.path.dirname(dbfile), 'manifests')
+ dirname = os.path.dirname(dbfile)
+ self.manifests_dir = os.path.join(dirname, 'manifests')
if not os.path.exists(self.manifests_dir):
os.makedirs(self.manifests_dir)
self.config = config
- self._entries = None
+ self._lock = lockfile.LockFile.get(os.path.join(dirname, 'packagedb.xml.lock'))
+ self._entries = None # hash
+ self._entries_stat = None # os.stat structure
def _ensure_cache(function):
def decorate(self, *args, **kwargs):
if self._entries is None:
self._read_cache()
+ elif self._entries_stat is None:
+ # It didn't exist before, see if it does now
+ self._read_cache()
+ else:
+ try:
+ stbuf = os.stat(self.dbfile)
+ except OSError, e:
+ pass
+ if not (self._entries_stat[stat.ST_INO] == stbuf[stat.ST_INO]
+ and self._entries_stat[stat.ST_MTIME] == stbuf[stat.ST_MTIME]):
+ logging.info(_('Package DB modified externally, rereading'))
+ self._read_cache()
function(self, *args, **kwargs)
return decorate
def _read_cache(self):
self._entries = {}
+ self._entries_stat = None
try:
f = open(self.dbfile)
except OSError, e:
@@ -144,6 +163,7 @@ class PackageDB:
continue
entry = PackageEntry.from_xml(node, self.manifests_dir)
self._entries[entry.package] = entry
+ self._entries_stat = os.fstat(f.fileno())
def _write_cache(self):
pkgdb_node = ET.Element('packagedb')
@@ -172,6 +192,8 @@ class PackageDB:
os.fsync(tmp_dbfile.fileno())
tmp_dbfile.close()
os.rename(tmp_dbfile_path, self.dbfile)
+ # Ensure we don't reread what we already have cached
+ self._entries_stat = os.stat(self.dbfile)
def _accumulate_dirtree_contents_recurse(self, path, contents):
assert os.path.isdir(path)
@@ -196,12 +218,22 @@ class PackageDB:
contents[i] = '/' + subpath[pathlen:]
return contents
+ def _locked(function):
+ def decorate(self, *args, **kwargs):
+ self._lock.lock()
+ try:
+ function(self, *args, **kwargs)
+ finally:
+ self._lock.unlock()
+ return decorate
+
@_ensure_cache
def get(self, package):
'''Return entry if package is installed, otherwise return None.'''
return self._entries.get(package)
@_ensure_cache
+ @_locked
def add(self, package, version, destdir):
'''Add a module to the install cache.'''
now = time.time()
@@ -229,6 +261,7 @@ class PackageDB:
return entry.metadata['installed-date']
@_ensure_cache
+ @_locked
def uninstall(self, package_name):
'''Remove a module from the install cache.'''
entry = self._entries[package_name]
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]