Mercurial > public > mercurial-scm > hg
comparison mercurial/localrepo.py @ 14930:372d9d8b1da4
localrepo: decorate dirstate() with filecache
We refresh the stat info when releasing repo.wlock(), right after writing it.
Also, invalidate the dirstate by deleting its attribute. This will force a
stat by the decorator that actually checks if anything changed, rather than
reading it again every time.
Note that prior to this, there was a single dirstate instance created for a
localrepo. It was invalidated by calling dirstate.invalidated(), clearing
its internal attributes.
As a consequence, the following construct is no longer safe:
ds = repo.dirstate # keep a reference to the repo's dirstate
wlock = repo.wlock()
try:
ds.setparents(...)
finally:
wlock.release() # dirstate should be written here
Since it's possible that the dirstate was modified between lines #1 and #2,
therefore changes to the old dirstate won't get written when the lock releases,
because a new instance was created by the decorator.
author | Idan Kamara <idankk86@gmail.com> |
---|---|
date | Mon, 25 Jul 2011 15:08:37 +0300 |
parents | 4bf9493e7b07 |
children | a710936c3037 |
comparison
equal
deleted
inserted
replaced
14929:4bf9493e7b07 | 14930:372d9d8b1da4 |
---|---|
15 import merge as mergemod | 15 import merge as mergemod |
16 import tags as tagsmod | 16 import tags as tagsmod |
17 from lock import release | 17 from lock import release |
18 import weakref, errno, os, time, inspect | 18 import weakref, errno, os, time, inspect |
19 propertycache = util.propertycache | 19 propertycache = util.propertycache |
20 filecache = scmutil.filecache | |
20 | 21 |
21 class localrepository(repo.repository): | 22 class localrepository(repo.repository): |
22 capabilities = set(('lookup', 'changegroupsubset', 'branchmap', 'pushkey', | 23 capabilities = set(('lookup', 'changegroupsubset', 'branchmap', 'pushkey', |
23 'known', 'getbundle')) | 24 'known', 'getbundle')) |
24 supportedformats = set(('revlogv1', 'generaldelta')) | 25 supportedformats = set(('revlogv1', 'generaldelta')) |
185 | 186 |
186 @propertycache | 187 @propertycache |
187 def manifest(self): | 188 def manifest(self): |
188 return manifest.manifest(self.sopener) | 189 return manifest.manifest(self.sopener) |
189 | 190 |
190 @propertycache | 191 @filecache('dirstate') |
191 def dirstate(self): | 192 def dirstate(self): |
192 warned = [0] | 193 warned = [0] |
193 def validate(node): | 194 def validate(node): |
194 try: | 195 try: |
195 self.changelog.rev(node) | 196 self.changelog.rev(node) |
795 self._tagtypes = None | 796 self._tagtypes = None |
796 self.nodetagscache = None | 797 self.nodetagscache = None |
797 self._branchcache = None # in UTF-8 | 798 self._branchcache = None # in UTF-8 |
798 self._branchcachetip = None | 799 self._branchcachetip = None |
799 | 800 |
801 def invalidatedirstate(self): | |
802 '''Invalidates the dirstate, causing the next call to dirstate | |
803 to check if it was modified since the last time it was read, | |
804 rereading it if it has. | |
805 | |
806 This is different to dirstate.invalidate() that it doesn't always | |
807 rereads the dirstate. Use dirstate.invalidate() if you want to | |
808 explicitly read the dirstate again (i.e. restoring it to a previous | |
809 known good state).''' | |
810 try: | |
811 delattr(self, 'dirstate') | |
812 except AttributeError: | |
813 pass | |
814 | |
800 def invalidate(self): | 815 def invalidate(self): |
801 for a in ("changelog", "manifest", "_bookmarks", "_bookmarkcurrent"): | 816 for a in ("changelog", "manifest", "_bookmarks", "_bookmarkcurrent"): |
802 if a in self.__dict__: | 817 if a in self.__dict__: |
803 delattr(self, a) | 818 delattr(self, a) |
804 self.invalidatecaches() | 819 self.invalidatecaches() |
839 l = self._wlockref and self._wlockref() | 854 l = self._wlockref and self._wlockref() |
840 if l is not None and l.held: | 855 if l is not None and l.held: |
841 l.lock() | 856 l.lock() |
842 return l | 857 return l |
843 | 858 |
844 l = self._lock(self.join("wlock"), wait, self.dirstate.write, | 859 def unlock(): |
845 self.dirstate.invalidate, _('working directory of %s') % | 860 self.dirstate.write() |
861 ce = self._filecache.get('dirstate') | |
862 if ce: | |
863 ce.refresh() | |
864 | |
865 l = self._lock(self.join("wlock"), wait, unlock, | |
866 self.invalidatedirstate, _('working directory of %s') % | |
846 self.origroot) | 867 self.origroot) |
847 self._wlockref = weakref.ref(l) | 868 self._wlockref = weakref.ref(l) |
848 return l | 869 return l |
849 | 870 |
850 def _filecommit(self, fctx, manifest1, manifest2, linkrev, tr, changelist): | 871 def _filecommit(self, fctx, manifest1, manifest2, linkrev, tr, changelist): |