[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