[PATCH 3 of 3] localrepo: pass args and command running as store/write lock metadata

Jun Wu quark at fb.com
Tue Mar 21 12:40:45 EDT 2017


Excerpts from Ryan McElroy's message of 2017-03-20 12:39:11 +0000:
> Overall, I like the functionality this series adds, but I'm less 
> convinced on the specific implementation. Adding more stuff to the 
> junkyard that is the "ui" class doesn't feel awesome, and I'm concerned 
> with how it will interact with chg and a future direction of ui 
> immutability.
> 
> I have an alternate suggestion for how to achieve this visibility into 
> what is going on in a repo:
> 
> Instead of having this information inside of a lock, what if every 
> process that started up in a repo tried to create a file in 
> .hg/processes/ (or something) of the form "info.<pid>". Then you 
> wouldn't need to pass this data through to the lock command, wouldn't 
> need to plumb it through the ui class, and combining the lock info with 
> the processes info would still be straightforward.
>
> This would allow you to touch only the dispatch logic and achieve 
> something even cooler: you'd be able to see all of the processes running 
> in a repo (even read processes, as long as the reader has write access 
> to the repo's .hg/).
> 
> Thoughts on this alternate approach?

Two questions:

1. Who is responsible for garbage collecting those pid files, in case of
   crashes?
2. Linux has pid namespace, pid could conflict.

I think it's better to just rely on whatever the operating system provides
to convert pid to args.

> 
> Some nitpicks inline as well.
> 
> On 3/20/17 7:49 AM, Phil Cohen wrote:
> > # HG changeset patch
> > # User Phil Cohen <phillco at fb.com>
> > # Date 1489996027 25200
> > #      Mon Mar 20 00:47:07 2017 -0700
> > # Node ID f37121209a2bbcde572e986f2b038bf2da7f954a
> > # Parent  1ca023fb02cbe4747e2b5b625866cfa538cbebd3
> > localrepo: pass args and command running as store/write lock metadata
> >
> > diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
> > --- a/mercurial/localrepo.py
> > +++ b/mercurial/localrepo.py
> > @@ -10,6 +10,7 @@
> >   import errno
> >   import hashlib
> >   import inspect
> > +import json
> >   import os
> >   import random
> >   import time
> > @@ -1355,10 +1356,15 @@
> >           if parentenvvar is not None:
> >               parentlock = encoding.environ.get(parentenvvar)
> >           try:
> > +            metadata = json.dumps({
> > +                'cmd': self.ui.commandname,
> > +                'args': self.ui.args
> > +            })
> >               l = lockmod.lock(vfs, lockname, 0, releasefn=releasefn,
> >                                acquirefn=acquirefn, desc=desc,
> >                                inheritchecker=inheritchecker,
> > -                             parentlock=parentlock)
> > +                             parentlock=parentlock,
> > +                             metadata=metadata)
> 
> It wasn't clear to me that metadata should be a string and not arbitrary 
> data that would be "somehow" serialized. It might be good to name (in 
> the previous patch) the variable "infostring" rather than "metadata" so 
> that this is more self-documenting.
> 
> Alternatively, have the lock code do the JSON serialization, and allow 
> metadata to be a list of dict of data that the lock will do the 
> serialization for, if present. That help's guarantee that lock.info will 
> always contain JSON serialized data.
> 
> >           except error.LockHeld as inst:
> >               if not wait:
> >                   raise
> > diff --git a/tests/test-repo-lock-writes-metadata.t b/tests/test-repo-lock-writes-metadata.t
> > new file mode 100644
> > --- /dev/null
> > +++ b/tests/test-repo-lock-writes-metadata.t
> > @@ -0,0 +1,38 @@
> > +Make a repo
> > +
> > +  $ hg init test
> > +  $ cd test
> > +  $ echo file > file
> > +  $ hg commit -Aqm initial
> 
> Nit-pick: I'd love some whitespace after the previous test instead of 
> before the next test.
> 
> > +Make an extension
> > +
> > +  $ cat << EOT > lockinfo.py
> > +  > from contextlib import nested
> > +  > from mercurial import (cmdutil, extensions)
> > +  > cmdtable = {}
> > +  > command = cmdutil.command(cmdtable)
> > +  > @command('locktest')
> > +  > def locktest(ui, repo, *args, **opts):
> > +  >   def readf(path):
> > +  >      try:
> > +  >        with open(path, "r") as f:
> > +  >           return f.read()
> > +  >      except IOError as e:
> > +  >         return "<not found>"
> > +  >   def status(str):
> > +  >     print(str, readf(".hg/wlock.info"), readf(".hg/store/lock.info"))
> > +  >   status("No lock, shouldn't have either file:")
> > +  >   with repo.wlock():
> > +  >       status("Have the write lock:")
> > +  >       with repo.lock():
> > +  >         status("Also have the store lock:")
> > +  >       status("Just the write lock:")
> > +  >   status("Neither:")
> > +  > EOT
> > +Test store and write lock
> > +  $ hg locktest -v --config extensions.x=lockinfo.py
> > +  ("No lock, shouldn't have either file:", '<not found>', '<not found>')
> > +  ('Have the write lock:', '{"cmd": "locktest", "args": ["locktest", "-v"]}', '<not found>')
> > +  ('Also have the store lock:', '{"cmd": "locktest", "args": ["locktest", "-v"]}', '{"cmd": "locktest", "args": ["locktest", "-v"]}')
> > +  ('Just the write lock:', '{"cmd": "locktest", "args": ["locktest", "-v"]}', '<not found>')
> > +  ('Neither:', '<not found>', '<not found>')
> >
> 


More information about the Mercurial-devel mailing list