chgserver: mangle server address to include confighash
authorJun Wu <quark@fb.com>
Wed, 02 Mar 2016 10:10:06 +0000
changeset 28326 ea400a4f32e6
parent 28325 9fec3cb8d128
child 28327 3ab370f84a23
chgserver: mangle server address to include confighash Before this patch, chgserver will use the address provided by the client. The new design is one server per confighash. This patch appends "-$confighash" to the address the client provides. To maintain the compatibility and make sure the client can connect to the server, a symbolic link is created at the original address pointing to the new address. The address is intentionally mangled at the server, instead of being pre- calculated by some other process (eg. a previous server). In this way, we can avoid file system race conditions.
hgext/chgserver.py
--- a/hgext/chgserver.py	Mon Feb 29 14:05:45 2016 +0000
+++ b/hgext/chgserver.py	Wed Mar 02 10:10:06 2016 +0000
@@ -35,6 +35,7 @@
 
   [chgserver]
   idletimeout = 3600 # seconds, after which an idle server will exit
+  skiphash = False   # whether to skip config or env change checks
 """
 
 from __future__ import absolute_import
@@ -516,6 +517,9 @@
 def _tempaddress(address):
     return '%s.%d.tmp' % (address, os.getpid())
 
+def _hashaddress(address, hashstr):
+    return '%s-%s' % (address, hashstr)
+
 class AutoExitMixIn:  # use old-style to comply with SocketServer design
     lastactive = time.time()
     idletimeout = 3600  # default 1 hour
@@ -581,6 +585,7 @@
         # drop options set for "hg serve --cmdserver" command
         self.ui.setconfig('progress', 'assume-tty', None)
         signal.signal(signal.SIGHUP, self._reloadconfig)
+        self._inithashstate()
         class cls(AutoExitMixIn, SocketServer.ForkingMixIn,
                   SocketServer.UnixStreamServer):
             ui = self.ui
@@ -589,9 +594,25 @@
         self.server.idletimeout = self.ui.configint(
             'chgserver', 'idletimeout', self.server.idletimeout)
         self.server.startautoexitthread()
+        self._createsymlink()
         # avoid writing "listening at" message to stdout before attachio
         # request, which calls setvbuf()
 
+    def _inithashstate(self):
+        self.baseaddress = self.address
+        if self.ui.configbool('chgserver', 'skiphash', False):
+            self.hashstate = None
+            return
+        self.hashstate = hashstate.fromui(self.ui)
+        self.address = _hashaddress(self.address, self.hashstate.confighash)
+
+    def _createsymlink(self):
+        if self.baseaddress == self.address:
+            return
+        tempaddress = _tempaddress(self.baseaddress)
+        os.symlink(self.address, tempaddress)
+        util.rename(tempaddress, self.baseaddress)
+
     def _reloadconfig(self, signum, frame):
         self.ui = self.server.ui = _renewui(self.ui)