comparison hgext/largefiles/remotestore.py @ 17127:9e1616307c4c

largefiles: batch statlfile requests when pushing a largefiles repo (issue3386) This implements a part of issue 3386. It batches the request for the status of all largefiles in the revisions that are about to be pushed into a single request, instead of doing N separate requests. In a real world test case, this change was verified to save 1,116 round-trips to the server. It only requires a client-side change; it is backwards-compatible with an older version of the server.
author Na'Tosha Bard <natosha@unity3d.com>
date Sun, 24 Jun 2012 20:36:22 +0200
parents 67d010779907
children e95ec38f86b0
comparison
equal deleted inserted replaced
17126:8fa8717b47b6 17127:9e1616307c4c
8 8
9 import urllib2 9 import urllib2
10 10
11 from mercurial import util 11 from mercurial import util
12 from mercurial.i18n import _ 12 from mercurial.i18n import _
13 from mercurial.wireproto import remotebatch
13 14
14 import lfutil 15 import lfutil
15 import basestore 16 import basestore
16 17
17 class remotestore(basestore.basestore): 18 class remotestore(basestore.basestore):
18 '''a largefile store accessed over a network''' 19 '''a largefile store accessed over a network'''
19 def __init__(self, ui, repo, url): 20 def __init__(self, ui, repo, url):
20 super(remotestore, self).__init__(ui, repo, url) 21 super(remotestore, self).__init__(ui, repo, url)
21 22
22 def put(self, source, hash): 23 def put(self, source, hash):
23 if self._verify(hash):
24 return
25 if self.sendfile(source, hash): 24 if self.sendfile(source, hash):
26 raise util.Abort( 25 raise util.Abort(
27 _('remotestore: could not put %s to remote store %s') 26 _('remotestore: could not put %s to remote store %s')
28 % (source, self.url)) 27 % (source, self.url))
29 self.ui.debug( 28 self.ui.debug(
30 _('remotestore: put %s to remote store %s') % (source, self.url)) 29 _('remotestore: put %s to remote store %s') % (source, self.url))
31 30
32 def exists(self, hash): 31 def exists(self, hashes):
33 return self._verify(hash) 32 return self._verify(hashes)
34 33
35 def sendfile(self, filename, hash): 34 def sendfile(self, filename, hash):
36 self.ui.debug('remotestore: sendfile(%s, %s)\n' % (filename, hash)) 35 self.ui.debug('remotestore: sendfile(%s, %s)\n' % (filename, hash))
37 fd = None 36 fd = None
38 try: 37 try:
72 # Mercurial does not close its SSH connections after writing a stream 71 # Mercurial does not close its SSH connections after writing a stream
73 if length is not None: 72 if length is not None:
74 infile = lfutil.limitreader(infile, length) 73 infile = lfutil.limitreader(infile, length)
75 return lfutil.copyandhash(lfutil.blockstream(infile), tmpfile) 74 return lfutil.copyandhash(lfutil.blockstream(infile), tmpfile)
76 75
77 def _verify(self, hash): 76 def _verify(self, hashes):
78 return not self._stat(hash) 77 return self._stat(hashes)
79 78
80 def _verifyfile(self, cctx, cset, contents, standin, verified): 79 def _verifyfile(self, cctx, cset, contents, standin, verified):
81 filename = lfutil.splitstandin(standin) 80 filename = lfutil.splitstandin(standin)
82 if not filename: 81 if not filename:
83 return False 82 return False
102 % (cset, filename)) 101 % (cset, filename))
103 return True # failed 102 return True # failed
104 else: 103 else:
105 raise RuntimeError('verify failed: unexpected response from ' 104 raise RuntimeError('verify failed: unexpected response from '
106 'statlfile (%r)' % stat) 105 'statlfile (%r)' % stat)
106
107 def batch(self):
108 '''Support for remote batching.'''
109 return remotebatch(self)
110