Patchwork [1,of,3,V2] chgserver: truncate base address at "." for hash address

login
register
mail settings
Submitter Jun Wu
Date Dec. 19, 2016, 10:19 p.m.
Message ID <c543f9fd1a5b7657d411.1482185963@x1c>
Download mbox | patch
Permalink /patch/17969/
State Accepted
Headers show

Comments

Jun Wu - Dec. 19, 2016, 10:19 p.m.
# HG changeset patch
# User Jun Wu <quark@fb.com>
# Date 1482185261 0
#      Mon Dec 19 22:07:41 2016 +0000
# Node ID c543f9fd1a5b7657d4114e61e87a8d9bc32f7617
# Parent  935092e525b0ee5656d0830162a1c2adf8248de3
# Available At https://bitbucket.org/quark-zju/hg-draft
#              hg pull https://bitbucket.org/quark-zju/hg-draft -r c543f9fd1a5b
chgserver: truncate base address at "." for hash address

Previously, the hash address is just appending "-$HASH" to base address.
This patch makes it truncate the basename address at "." before appending
"-$HASH".

This makes it possible to spawn new servers in a racy situation and the
client could be sure the server it connects is the new server just spawned.

This is a step towards removing the lock.

One of the functionalities of the lock is to make sure the connect will
connect to a server it just created:

  1. start server --address foo
  2. connect to foo # wish "foo" is the server just started

With this change, the client could do:

  1. start server --address foo.tmp$PID
  2. connect to foo.tmp$PID # is the serer just started
     (note: if it is not, it does not affect correctness - linux pid
      namespace is not a concern here)
  3. rename foo.tmp$PID to foo

Another functionality of the lock is to avoid starting multiple servers with
a same confighash in parallel. But that also prevents starting multiple
servers with different confighashes in parallel.

Patch

diff --git a/mercurial/chgserver.py b/mercurial/chgserver.py
--- a/mercurial/chgserver.py
+++ b/mercurial/chgserver.py
@@ -530,5 +530,10 @@  def _tempaddress(address):
 
 def _hashaddress(address, hashstr):
-    return '%s-%s' % (address, hashstr)
+    # if the basename of address contains '.', use only the left part. this
+    # makes it possible for the client to pass 'server.tmp$PID' and follow by
+    # an atomic rename to avoid locking when spawning new servers.
+    dirname, basename = os.path.split(address)
+    basename = basename.split('.', 1)[0]
+    return '%s-%s' % (os.path.join(dirname, basename), hashstr)
 
 class chgunixservicehandler(object):