##// END OF EJS Templates
largefiles: batch statlfile requests when pushing a largefiles repo (issue3386)...
Na'Tosha Bard -
r17127:9e161630 default
parent child Browse files
Show More
@@ -48,8 +48,8 b' class basestore(object):'
48 '''Put source file into the store under <filename>/<hash>.'''
48 '''Put source file into the store under <filename>/<hash>.'''
49 raise NotImplementedError('abstract method')
49 raise NotImplementedError('abstract method')
50
50
51 def exists(self, hash):
51 def exists(self, hashes):
52 '''Check to see if the store contains the given hash.'''
52 '''Check to see if the store contains the given hashes.'''
53 raise NotImplementedError('abstract method')
53 raise NotImplementedError('abstract method')
54
54
55 def get(self, files):
55 def get(self, files):
@@ -340,7 +340,11 b' def uploadlfiles(ui, rsrc, rdst, files):'
340 store = basestore._openstore(rsrc, rdst, put=True)
340 store = basestore._openstore(rsrc, rdst, put=True)
341
341
342 at = 0
342 at = 0
343 files = filter(lambda h: not store.exists(h), files)
343 ui.debug("sending statlfile command for %d largefiles\n" % len(files))
344 retval = store.exists(files)
345 files = filter(lambda h: not retval[h], files)
346 ui.debug("%d largefiles need to be uploaded\n" % len(files))
347
344 for hash in files:
348 for hash in files:
345 ui.progress(_('uploading largefiles'), at, unit='largefile',
349 ui.progress(_('uploading largefiles'), at, unit='largefile',
346 total=len(files))
350 total=len(files))
@@ -7,6 +7,7 b' import os'
7 import urllib2
7 import urllib2
8
8
9 from mercurial import error, httprepo, util, wireproto
9 from mercurial import error, httprepo, util, wireproto
10 from mercurial.wireproto import batchable, future
10 from mercurial.i18n import _
11 from mercurial.i18n import _
11
12
12 import lfutil
13 import lfutil
@@ -119,15 +120,19 b' def wirereposetup(ui, repo):'
119 length))
120 length))
120 return (length, stream)
121 return (length, stream)
121
122
123 @batchable
122 def statlfile(self, sha):
124 def statlfile(self, sha):
125 f = future()
126 result = {'sha': sha}
127 yield result, f
123 try:
128 try:
124 return int(self._call("statlfile", sha=sha))
129 yield int(f.value)
125 except (ValueError, urllib2.HTTPError):
130 except (ValueError, urllib2.HTTPError):
126 # If the server returns anything but an integer followed by a
131 # If the server returns anything but an integer followed by a
127 # newline, newline, it's not speaking our language; if we get
132 # newline, newline, it's not speaking our language; if we get
128 # an HTTP error, we can't be sure the largefile is present;
133 # an HTTP error, we can't be sure the largefile is present;
129 # either way, consider it missing.
134 # either way, consider it missing.
130 return 2
135 yield 2
131
136
132 repo.__class__ = lfileswirerepository
137 repo.__class__ = lfileswirerepository
133
138
@@ -10,6 +10,7 b' 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
@@ -20,8 +21,6 b' class remotestore(basestore.basestore):'
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')
@@ -29,8 +28,8 b' class remotestore(basestore.basestore):'
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))
@@ -74,8 +73,8 b' class remotestore(basestore.basestore):'
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)
@@ -104,3 +103,8 b' class remotestore(basestore.basestore):'
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
@@ -25,5 +25,13 b' class wirestore(remotestore.remotestore)'
25 def _get(self, hash):
25 def _get(self, hash):
26 return self.remote.getlfile(hash)
26 return self.remote.getlfile(hash)
27
27
28 def _stat(self, hash):
28 def _stat(self, hashes):
29 return self.remote.statlfile(hash)
29 batch = self.remote.batch()
30 futures = {}
31 for hash in hashes:
32 futures[hash] = batch.statlfile(hash)
33 batch.submit()
34 retval = {}
35 for hash in hashes:
36 retval[hash] = not futures[hash].value
37 return retval
General Comments 0
You need to be logged in to leave comments. Login now