New locking idea (was Re: [PATCH 0 of 2] new log option --tolerant)

Jason Harris jason.f.harris at gmail.com
Mon Dec 13 10:06:53 CST 2010


On Dec 13, 2010, at 7:01 AM, Matt Mackall wrote:

> On Sun, 2010-12-12 at 04:19 +0100, Jason Harris wrote:
>> Ok I have come across the following issue in MacHg. (The issue is general to GUI
>> clients but I will use MacHg in the description below. Substitute your favorite
>> other GUI client which does things in a multithreaded way.)
>> 
>> I need Mercurial to treat the revision ranges I pass it tolerantly. The
>> situation arises in MacHg because of its ubiquitous use of multi-threaded-ness
>> and some history altering operations, like strip, histedit, collapse, rebase
>> with --collapse, etc. These history editing operations can decrease the number
>> of changesets after an operation. Now just after the operation the "hg tip"
>> command might be still loading and yet MacHg might need to also fire off some
>> "hg log" commands to update the history view of the repository. Ie we might be
>> issuing in essence a command like hg log --rev "0:23" --template "<stuff>" but
>> maybe after the operation the repository only has 19 changesets in it. We don't
>> want this 'hg log' command we just issued to fail with an abort: unknown
>> revision '23'!
> 
> I'm not thrilled with this approach, but you've got me thinking about
> alternatives to fix this long-standing issue.
> 
> To have complete locking for strip and friends, we need to satisfy the
> following
> 
> - any number of simultaneous readers
> - appenders exclude other appenders, but not readers
> - destroyers exclude readers and appenders
> 
> Mercurial currently handles the first two, but not the last (limited to
> extensions and the rollback command). To add appenders to the mix, we
> need to be able to do the following:
> 
> - keep track of an arbitrary number of readers efficiently
> - atomically exclude new readers
> - keep destroyers from waiting forever
> 
> My thought is we can accomplish this with a new reader/ lock directory
> in .hg/store. When the directory exists, readers just need to create a
> uniquely-named lock file in the directory to indicate they're in the
> process of reading and delete it when they're done. This obviously isn't
> as fast as doing nothing, but should still be pretty fast.
> 
> When a destroyer wants to take over, it first takes the write lock to
> exclude appenders and other destroyers. It then attempts to delete the
> reader directory. If there are no read locks in the directory, rmdir
> will succeed. If rmdir fails, it loops until it succeeds. To unlock, it
> recreates the reader directory, and releases the write lock.
> 
> However, a destroyer may wait forever if new readers keep appearing. To
> prevent this, it renames the reader directory to reader-blocked. New
> readers will wait for the reader directory to reappear, while old
> readers will try deleting their read locks from both locations.
> 
> This relies on atomicity of rmdir vs file creation, which is a pretty
> reasonable requirement as failing it would mean a filesystem could
> 'leak' files.
> 
> In addition to fixing Jason's problem, this will also let us safely do
> things like running strip on a repo that's being served by hgweb.

Such a change would be great for me :)

Thanks!,
  Jas


More information about the Mercurial-devel mailing list