# HG changeset patch # User Adrian Buehlmann # Date 2011-01-28 12:38:34 # Node ID d00bbff8600e5dc6bc1ab6c51896eb1f6711c7ad # Parent 327719a44b6a1ef4d35ba9166e39a0186b72f1d1 fncachestore: defer updating the fncache file to a single file open Defers updating the fncache file with newly added entries to the end of the transaction (on e.g. pull), doing a single open call on the fncache file, instead of opening and closing it each time a new entry is added to the store. Implemented by adding a new abstract write() function on store.basicstore and registering it as a release function on the store lock in localrepo.lock (compare with dirstate.write). store.fncachestore overrides write() from basicstore and calls a new write function on the fncache object, which writes all entries to the fncache file if it's dirty. store.fncache.add() now just marks itself as dirty if a new name is added. diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -781,8 +781,8 @@ class localrepository(repo.repository): l.lock() return l - l = self._lock(self.sjoin("lock"), wait, None, self.invalidate, - _('repository %s') % self.origroot) + l = self._lock(self.sjoin("lock"), wait, self.store.write, + self.invalidate, _('repository %s') % self.origroot) self._lockref = weakref.ref(l) return l diff --git a/mercurial/store.py b/mercurial/store.py --- a/mercurial/store.py +++ b/mercurial/store.py @@ -213,6 +213,9 @@ class basicstore(object): def copylist(self): return ['requires'] + _data.split() + def write(self): + pass + class encodedstore(basicstore): def __init__(self, path, opener, pathjoiner): self.pathjoiner = pathjoiner @@ -243,10 +246,12 @@ class fncache(object): def __init__(self, opener): self.opener = opener self.entries = None + self._dirty = False def _load(self): '''fill the entries from the fncache file''' self.entries = set() + self._dirty = False try: fp = self.opener('fncache', mode='rb') except IOError: @@ -265,12 +270,22 @@ class fncache(object): fp.write(encodedir(p) + '\n') fp.close() self.entries = set(files) + self._dirty = False + + def write(self): + if not self._dirty: + return + fp = self.opener('fncache', mode='wb', atomictemp=True) + for p in self.entries: + fp.write(encodedir(p) + '\n') + fp.rename() + self._dirty = False def add(self, fn): if self.entries is None: self._load() if fn not in self.entries: - self.opener('fncache', 'ab').write(encodedir(fn) + '\n') + self._dirty = True self.entries.add(fn) def __contains__(self, fn): @@ -328,6 +343,9 @@ class fncachestore(basicstore): return (['requires', '00changelog.i'] + [self.pathjoiner('store', f) for f in d.split()]) + def write(self): + self.fncache.write() + def store(requirements, path, opener, pathjoiner=None): pathjoiner = pathjoiner or os.path.join if 'store' in requirements: