Mercurial > hg
view hgext/remotefilelog/connectionpool.py @ 44682:9ce613d648de
rust-chg: add config validation and process returned instructions
This is the reimplementation of runinstructions() and main() in chg.c.
In Rust version, we only pass in early arguments to the server as the locator
doesn't know the full arguments. This should be fine since these arguments
are just passed in to _earlyparseopts() and _parseconfig(), which means the
server doesn't need full arguments.
Another difference is the handling of the "exit <code>" instruction. In Rust
version, we can simply reuse the connection instead of "exit(code)" as the
command error isn't displayed yet. That's because the client-side stdio is not
attached until the connection is validated. This behavior is cleaner than C,
but it also means that the early server exception wouldn't be propagated to
client because stderr isn't attached. So we might have to reconsider when to
attach/detach the server stdio.
Differential Revision: https://phab.mercurial-scm.org/D8381
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Sun, 07 Oct 2018 16:14:21 +0900 |
parents | 4aa72cdf616f |
children | 0509cee38757 |
line wrap: on
line source
# connectionpool.py - class for pooling peer connections for reuse # # Copyright 2017 Facebook, Inc. # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. from __future__ import absolute_import from mercurial import ( extensions, hg, pycompat, sshpeer, util, ) _sshv1peer = sshpeer.sshv1peer class connectionpool(object): def __init__(self, repo): self._repo = repo self._pool = dict() def get(self, path): pathpool = self._pool.get(path) if pathpool is None: pathpool = list() self._pool[path] = pathpool conn = None if len(pathpool) > 0: try: conn = pathpool.pop() peer = conn.peer # If the connection has died, drop it if isinstance(peer, _sshv1peer): if peer._subprocess.poll() is not None: conn = None except IndexError: pass if conn is None: def _cleanup(orig): # close pipee first so peer.cleanup reading it won't deadlock, # if there are other processes with pipeo open (i.e. us). peer = orig.im_self if util.safehasattr(peer, 'pipee'): peer.pipee.close() return orig() peer = hg.peer(self._repo.ui, {}, path) if util.safehasattr(peer, 'cleanup'): extensions.wrapfunction(peer, b'cleanup', _cleanup) conn = connection(pathpool, peer) return conn def close(self): for pathpool in pycompat.itervalues(self._pool): for conn in pathpool: conn.close() del pathpool[:] class connection(object): def __init__(self, pool, peer): self._pool = pool self.peer = peer def __enter__(self): return self def __exit__(self, type, value, traceback): # Only add the connection back to the pool if there was no exception, # since an exception could mean the connection is not in a reusable # state. if type is None: self._pool.append(self) else: self.close() def close(self): if util.safehasattr(self.peer, 'cleanup'): self.peer.cleanup()