treemanifest: use a connectionpool

remotefilelog and fastannotate already use a connection pool to share and reuse
connections. Treemanifest often does ondemand downloading of trees, such as
during hg log -p, and would greatly benefit from reusing connections as well.

This patch makes the connectionpool and attribute of the repo object, instead of
the fileserverclient object, which allows treemanifest to make use of it easily.

Differential Revision: https://phab.mercurial-scm.org/D1454
This commit is contained in:
Durham Goode 2017-11-21 06:52:51 -08:00
parent 818f7dee74
commit 02afbac4e7
4 changed files with 35 additions and 14 deletions

View File

@ -138,7 +138,7 @@ def annotatepeer(repo):
if sharepeer and fileservice: if sharepeer and fileservice:
ui.debug('fastannotate: using remotefilelog connection pool\n') ui.debug('fastannotate: using remotefilelog connection pool\n')
conn = fileservice.connpool.get(repo.fallbackpath) conn = repo.connectionpool.get(repo.fallbackpath)
peer = conn.peer peer = conn.peer
stolen = True stolen = True
else: else:

View File

@ -22,7 +22,6 @@ from mercurial import (
) )
from . import ( from . import (
connectionpool,
constants, constants,
shallowutil, shallowutil,
wirepack, wirepack,
@ -258,7 +257,6 @@ class fileserverclient(object):
if self.cacheprocess: if self.cacheprocess:
self.cacheprocess = util.expandpath(self.cacheprocess) self.cacheprocess = util.expandpath(self.cacheprocess)
# This option causes remotefilelog to pass the full file path to the # This option causes remotefilelog to pass the full file path to the
# cacheprocess instead of a hashed key. # cacheprocess instead of a hashed key.
self.cacheprocesspasspath = ui.configbool( self.cacheprocesspasspath = ui.configbool(
@ -267,7 +265,6 @@ class fileserverclient(object):
self.debugoutput = ui.configbool("remotefilelog", "debug") self.debugoutput = ui.configbool("remotefilelog", "debug")
self.remotecache = cacheconnection() self.remotecache = cacheconnection()
self.connpool = connectionpool.connectionpool(repo)
def setstore(self, datastore, historystore, writedata, writehistory): def setstore(self, datastore, historystore, writedata, writehistory):
self.datastore = datastore self.datastore = datastore
@ -276,7 +273,7 @@ class fileserverclient(object):
self.writehistory = writehistory self.writehistory = writehistory
def _connect(self): def _connect(self):
return self.connpool.get(self.repo.fallbackpath) return self.repo.connectionpool.get(self.repo.fallbackpath)
def request(self, fileids): def request(self, fileids):
"""Takes a list of filename/node pairs and fetches them from the """Takes a list of filename/node pairs and fetches them from the
@ -526,8 +523,6 @@ class fileserverclient(object):
if self.remotecache.connected: if self.remotecache.connected:
self.remotecache.close() self.remotecache.close()
self.connpool.close()
def prefetch(self, fileids, force=False, fetchdata=True, def prefetch(self, fileids, force=False, fetchdata=True,
fetchhistory=False): fetchhistory=False):
"""downloads the given file versions to the cache """downloads the given file versions to the cache

View File

@ -9,7 +9,12 @@ from hgext3rd.extutil import runshellcommand
from mercurial.i18n import _ from mercurial.i18n import _
from mercurial.node import hex, nullid, nullrev from mercurial.node import hex, nullid, nullrev
from mercurial import error, localrepo, util, match, scmutil from mercurial import error, localrepo, util, match, scmutil
from . import remotefilelog, remotefilectx, fileserverclient from . import (
connectionpool,
fileserverclient,
remotefilelog,
remotefilectx,
)
import constants, shallowutil import constants, shallowutil
from contentstore import remotefilelogcontentstore, unioncontentstore from contentstore import remotefilelogcontentstore, unioncontentstore
from contentstore import remotecontentstore from contentstore import remotecontentstore
@ -271,6 +276,10 @@ def wraprepo(repo):
results = [(path, hex(fnode)) for (path, fnode) in files] results = [(path, hex(fnode)) for (path, fnode) in files]
repo.fileservice.prefetch(results) repo.fileservice.prefetch(results)
def close(self):
super(shallowrepository, self).close()
self.connectionpool.close()
repo.__class__ = shallowrepository repo.__class__ = shallowrepository
repo.shallowmatch = match.always(repo.root, '') repo.shallowmatch = match.always(repo.root, '')
@ -281,6 +290,9 @@ def wraprepo(repo):
None) None)
repo.excludepattern = repo.ui.configlist("remotefilelog", "excludepattern", repo.excludepattern = repo.ui.configlist("remotefilelog", "excludepattern",
None) None)
if not util.safehasattr(repo, 'connectionpool'):
repo.connectionpool = connectionpool.connectionpool(repo)
if repo.includepattern or repo.excludepattern: if repo.includepattern or repo.excludepattern:
repo.shallowmatch = match.match(repo.root, '', None, repo.shallowmatch = match.match(repo.root, '', None,
repo.includepattern, repo.excludepattern) repo.includepattern, repo.excludepattern)

View File

@ -73,7 +73,6 @@ from mercurial import (
error, error,
exchange, exchange,
extensions, extensions,
hg,
localrepo, localrepo,
manifest, manifest,
mdiff, mdiff,
@ -113,7 +112,12 @@ from remotefilelog.historypack import (
historypackstore, historypackstore,
mutablehistorypack, mutablehistorypack,
) )
from remotefilelog import shallowrepo, shallowutil, wirepack from remotefilelog import (
connectionpool,
shallowrepo,
shallowutil,
wirepack,
)
from remotefilelog.repack import ( from remotefilelog.repack import (
_computeincrementaldatapack, _computeincrementaldatapack,
_computeincrementalhistorypack, _computeincrementalhistorypack,
@ -256,6 +260,9 @@ def clientreposetup(repo):
except KeyError: except KeyError:
raise error.Abort(_("cannot use treemanifest without fastmanifest")) raise error.Abort(_("cannot use treemanifest without fastmanifest"))
if not util.safehasattr(repo, 'connectionpool'):
repo.connectionpool = connectionpool.connectionpool(repo)
def setuptreestores(repo, mfl): def setuptreestores(repo, mfl):
if repo.ui.configbool("treemanifest", "server"): if repo.ui.configbool("treemanifest", "server"):
packpath = repo.vfs.join('cache/packs/%s' % PACK_CATEGORY) packpath = repo.vfs.join('cache/packs/%s' % PACK_CATEGORY)
@ -1070,7 +1077,12 @@ def _prefetchtrees(repo, rootdir, mfnodes, basemfnodes, directories):
fallbackpath = repo.ui.config('paths', 'default') fallbackpath = repo.ui.config('paths', 'default')
start = time.time() start = time.time()
remote = hg.peer(repo.ui, {}, fallbackpath) with repo.connectionpool.get(fallbackpath) as conn:
remote = conn.peer
_gettrees(repo, remote, rootdir, mfnodes, basemfnodes, directories,
start)
def _gettrees(repo, remote, rootdir, mfnodes, basemfnodes, directories, start):
if 'gettreepack' not in shallowutil.peercapabilities(remote): if 'gettreepack' not in shallowutil.peercapabilities(remote):
raise error.Abort(_("missing gettreepack capability on remote")) raise error.Abort(_("missing gettreepack capability on remote"))
remote.ui.pushbuffer() remote.ui.pushbuffer()
@ -1100,14 +1112,16 @@ def _prefetchtrees(repo, rootdir, mfnodes, basemfnodes, directories):
nodestr = '\n'.join(hexnodes[:10]) nodestr = '\n'.join(hexnodes[:10])
if len(hexnodes) > 10: if len(hexnodes) > 10:
nodestr += '\n...' nodestr += '\n...'
# Give stderr some time to reach the client, so we can read it into the
# currently pushed ui buffer, instead of it randomly showing up in a
# future ui read.
time.sleep(0.1)
raise error.Abort(_('unable to download the following trees from the ' raise error.Abort(_('unable to download the following trees from the '
'server:\n%s') % nodestr, hint=exc.hint) 'server:\n%s') % nodestr, hint=exc.hint)
except error.BundleValueError as exc: except error.BundleValueError as exc:
raise error.Abort(_('missing support for %s') % exc) raise error.Abort(_('missing support for %s') % exc)
finally: finally:
# Manually destruct the peer, so we can collect any error output remote._readerr()
remote._cleanup()
output = remote.ui.popbuffer() output = remote.ui.popbuffer()
if output: if output:
repo.ui.debug(output) repo.ui.debug(output)