mirror of
https://github.com/facebook/sapling.git
synced 2024-10-11 17:27:53 +03:00
55f677869b
Summary: Previously remotefilelog would open a connection and leave the getfiles command running on that connection, so it didn't have to reopen the ssh connection each time. We want to reuse this ssh connection for treemanifest and fastannotate, so let's switch it to a pool model where the connection is kept open but the getfiles command is not left open. If an exception happens while the connection is out of the pool, it is discarded instead of being added back to the pool. Test Plan: Ran the tests. The fastannotate tests changed to reflect the new way the connectionpool allows use. Reviewers: quark, #mercurial, mitrandir Reviewed By: mitrandir Subscribers: mitrandir, medson, mjpieters Differential Revision: https://phabricator.intern.facebook.com/D5280323 Signature: t1:5280323:1497975420:e3ae1ee854a1afc90816502543a19ff36f59b497
81 lines
2.3 KiB
Python
81 lines
2.3 KiB
Python
# 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 mercurial import (
|
|
extensions,
|
|
hg,
|
|
sshpeer,
|
|
util,
|
|
)
|
|
|
|
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, sshpeer.sshpeer) and
|
|
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, 'cleanup', _cleanup)
|
|
|
|
conn = connection(pathpool, peer)
|
|
|
|
return conn
|
|
|
|
def close(self):
|
|
for pathpool in self._pool.itervalues():
|
|
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()
|