[PATCH V6] dirstate: avoid a race with multiple commits in the same process
Greg Ward
greg at gerg.ca
Mon Mar 21 20:09:11 CDT 2011
On 21 March 2011, Adrian Buehlmann said:
> def normal(self, f):
> '''Mark a file normal and clean.'''
> self._dirty = True
> self._addpath(f)
> s = os.lstat(self._join(f))
> self._map[f] = ('n', s.st_mode, s.st_size, int(s.st_mtime))
> if f in self._copymap:
> del self._copymap[f]
>
> # Right now, this file is clean: but if some code in this
> # process modifies it without changing its size before the clock
> # ticks over to the next second, then it won't be clean anymore.
> # So make sure that status() will look harder at it.
> self._lastnormal.add(f)
>
> Hmmm.
>
> local.status does a full compare for files that need to be looked into,
> which IIUC now includes the files in self._lastnormal (see
> dirstate.status() ).
The set "files that need to be looked into" *may* include files in
self._lastnormal. If one of them has changed size or mtime, it takes
the fast path to M status.
> localrepo.status calls self.dirstate.normal(f) for the files that
> content-compare equal (list "fixup").
>
> Maybe there should be a way to say "this file is *really* normal, we've
> even compared file contents". I think such files shouldn't be added to
> _lastnormal, so they are not content-compared again and again on every
> localrepo.status() call.
_lastnormal isn't really a record of current state -- that's what
dirstate._map is. It's more of a reminder to dirstate in the near
future. Even if localrepository.status() really compares contents and
*knows* the file is normal, it's still possible there will be another
size-preserving change in the same second before the next call to
status(). So the invocation of localrepository.status() that *knows*
the file is normal now does not know the file will still be normal in
(say) 700 ms.
Greg
More information about the Mercurial-devel
mailing list