Show More
@@ -1,90 +1,89 b'' | |||||
1 | # connectionpool.py - class for pooling peer connections for reuse |
|
1 | # connectionpool.py - class for pooling peer connections for reuse | |
2 | # |
|
2 | # | |
3 | # Copyright 2017 Facebook, Inc. |
|
3 | # Copyright 2017 Facebook, Inc. | |
4 | # |
|
4 | # | |
5 | # This software may be used and distributed according to the terms of the |
|
5 | # This software may be used and distributed according to the terms of the | |
6 | # GNU General Public License version 2 or any later version. |
|
6 | # GNU General Public License version 2 or any later version. | |
7 |
|
7 | |||
8 | from __future__ import absolute_import |
|
8 | from __future__ import absolute_import | |
9 |
|
9 | |||
10 | from mercurial import ( |
|
10 | from mercurial import ( | |
11 | extensions, |
|
|||
12 | hg, |
|
11 | hg, | |
13 | pycompat, |
|
12 | pycompat, | |
14 | sshpeer, |
|
13 | sshpeer, | |
15 | util, |
|
14 | util, | |
16 | ) |
|
15 | ) | |
17 |
|
16 | |||
18 | _sshv1peer = sshpeer.sshv1peer |
|
17 | _sshv1peer = sshpeer.sshv1peer | |
19 |
|
18 | |||
20 |
|
19 | |||
21 | class connectionpool(object): |
|
20 | class connectionpool(object): | |
22 | def __init__(self, repo): |
|
21 | def __init__(self, repo): | |
23 | self._repo = repo |
|
22 | self._repo = repo | |
24 | self._pool = dict() |
|
23 | self._pool = dict() | |
25 |
|
24 | |||
26 | def get(self, path): |
|
25 | def get(self, path): | |
27 | pathpool = self._pool.get(path) |
|
26 | pathpool = self._pool.get(path) | |
28 | if pathpool is None: |
|
27 | if pathpool is None: | |
29 | pathpool = list() |
|
28 | pathpool = list() | |
30 | self._pool[path] = pathpool |
|
29 | self._pool[path] = pathpool | |
31 |
|
30 | |||
32 | conn = None |
|
31 | conn = None | |
33 | if len(pathpool) > 0: |
|
32 | if len(pathpool) > 0: | |
34 | try: |
|
33 | try: | |
35 | conn = pathpool.pop() |
|
34 | conn = pathpool.pop() | |
36 | peer = conn.peer |
|
35 | peer = conn.peer | |
37 | # If the connection has died, drop it |
|
36 | # If the connection has died, drop it | |
38 | if isinstance(peer, _sshv1peer): |
|
37 | if isinstance(peer, _sshv1peer): | |
39 | if peer._subprocess.poll() is not None: |
|
38 | if peer._subprocess.poll() is not None: | |
40 | conn = None |
|
39 | conn = None | |
41 | except IndexError: |
|
40 | except IndexError: | |
42 | pass |
|
41 | pass | |
43 |
|
42 | |||
44 | if conn is None: |
|
43 | if conn is None: | |
45 |
|
44 | |||
46 | peer = hg.peer(self._repo.ui, {}, path) |
|
45 | peer = hg.peer(self._repo.ui, {}, path) | |
47 | if util.safehasattr(peer, '_cleanup'): |
|
46 | if util.safehasattr(peer, '_cleanup'): | |
48 |
|
47 | |||
49 | class mypeer(peer.__class__): |
|
48 | class mypeer(peer.__class__): | |
50 | def _cleanup(self, warn=None): |
|
49 | def _cleanup(self, warn=None): | |
51 | # close pipee first so peer.cleanup reading it won't |
|
50 | # close pipee first so peer.cleanup reading it won't | |
52 | # deadlock, if there are other processes with pipeo |
|
51 | # deadlock, if there are other processes with pipeo | |
53 | # open (i.e. us). |
|
52 | # open (i.e. us). | |
54 | if util.safehasattr(self, 'pipee'): |
|
53 | if util.safehasattr(self, 'pipee'): | |
55 | self.pipee.close() |
|
54 | self.pipee.close() | |
56 | return super(mypeer, self)._cleanup() |
|
55 | return super(mypeer, self)._cleanup() | |
57 |
|
56 | |||
58 | peer.__class__ = mypeer |
|
57 | peer.__class__ = mypeer | |
59 |
|
58 | |||
60 | conn = connection(pathpool, peer) |
|
59 | conn = connection(pathpool, peer) | |
61 |
|
60 | |||
62 | return conn |
|
61 | return conn | |
63 |
|
62 | |||
64 | def close(self): |
|
63 | def close(self): | |
65 | for pathpool in pycompat.itervalues(self._pool): |
|
64 | for pathpool in pycompat.itervalues(self._pool): | |
66 | for conn in pathpool: |
|
65 | for conn in pathpool: | |
67 | conn.close() |
|
66 | conn.close() | |
68 | del pathpool[:] |
|
67 | del pathpool[:] | |
69 |
|
68 | |||
70 |
|
69 | |||
71 | class connection(object): |
|
70 | class connection(object): | |
72 | def __init__(self, pool, peer): |
|
71 | def __init__(self, pool, peer): | |
73 | self._pool = pool |
|
72 | self._pool = pool | |
74 | self.peer = peer |
|
73 | self.peer = peer | |
75 |
|
74 | |||
76 | def __enter__(self): |
|
75 | def __enter__(self): | |
77 | return self |
|
76 | return self | |
78 |
|
77 | |||
79 | def __exit__(self, type, value, traceback): |
|
78 | def __exit__(self, type, value, traceback): | |
80 | # Only add the connection back to the pool if there was no exception, |
|
79 | # Only add the connection back to the pool if there was no exception, | |
81 | # since an exception could mean the connection is not in a reusable |
|
80 | # since an exception could mean the connection is not in a reusable | |
82 | # state. |
|
81 | # state. | |
83 | if type is None: |
|
82 | if type is None: | |
84 | self._pool.append(self) |
|
83 | self._pool.append(self) | |
85 | else: |
|
84 | else: | |
86 | self.close() |
|
85 | self.close() | |
87 |
|
86 | |||
88 | def close(self): |
|
87 | def close(self): | |
89 | if util.safehasattr(self.peer, 'cleanup'): |
|
88 | if util.safehasattr(self.peer, 'cleanup'): | |
90 | self.peer.cleanup() |
|
89 | self.peer.cleanup() |
General Comments 0
You need to be logged in to leave comments.
Login now