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):