connectionpool.py
86 lines
| 2.3 KiB
| text/x-python
|
PythonLexer
Augie Fackler
|
r40530 | # 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 ( | ||||
hg, | ||||
sshpeer, | ||||
) | ||||
_sshv1peer = sshpeer.sshv1peer | ||||
Augie Fackler
|
r43346 | |||
Gregory Szorc
|
r49801 | class connectionpool: | ||
Augie Fackler
|
r40530 | 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: | ||||
Augie Fackler
|
r43346 | |||
Valentin Gatien-Baron
|
r47417 | peer = hg.peer(self._repo.ui, {}, path) | ||
r51821 | if hasattr(peer, '_cleanup'): | |||
Augie Fackler
|
r40530 | |||
Valentin Gatien-Baron
|
r47417 | class mypeer(peer.__class__): | ||
Valentin Gatien-Baron
|
r47418 | def _cleanup(self, warn=None): | ||
Valentin Gatien-Baron
|
r47417 | # close pipee first so peer.cleanup reading it won't | ||
# deadlock, if there are other processes with pipeo | ||||
# open (i.e. us). | ||||
r51821 | if hasattr(self, 'pipee'): | |||
Valentin Gatien-Baron
|
r47417 | self.pipee.close() | ||
return super(mypeer, self)._cleanup() | ||||
peer.__class__ = mypeer | ||||
Augie Fackler
|
r40530 | |||
conn = connection(pathpool, peer) | ||||
return conn | ||||
def close(self): | ||||
Gregory Szorc
|
r49790 | for pathpool in self._pool.values(): | ||
Augie Fackler
|
r40530 | for conn in pathpool: | ||
conn.close() | ||||
del pathpool[:] | ||||
Augie Fackler
|
r43346 | |||
Gregory Szorc
|
r49801 | class connection: | ||
Augie Fackler
|
r40530 | 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): | ||||
r51821 | if hasattr(self.peer, 'cleanup'): | |||
Augie Fackler
|
r40530 | self.peer.cleanup() | ||