Show More
@@ -120,7 +120,6 b' from mercurial import (' | |||
|
120 | 120 | extensions, |
|
121 | 121 | hg, |
|
122 | 122 | localrepo, |
|
123 | peer, | |
|
124 | 123 | phases, |
|
125 | 124 | pushkey, |
|
126 | 125 | pycompat, |
@@ -354,11 +353,11 b' def localrepolistkeys(orig, self, namesp' | |||
|
354 | 353 | else: |
|
355 | 354 | return orig(self, namespace) |
|
356 | 355 | |
|
357 | @peer.batchable | |
|
356 | @wireprotov1peer.batchable | |
|
358 | 357 | def listkeyspatterns(self, namespace, patterns): |
|
359 | 358 | if not self.capable('pushkey'): |
|
360 | 359 | yield {}, None |
|
361 | f = peer.future() | |
|
360 | f = wireprotov1peer.future() | |
|
362 | 361 | self.ui.debug('preparing listkeys for "%s" with pattern "%s"\n' % |
|
363 | 362 | (namespace, patterns)) |
|
364 | 363 | yield { |
@@ -49,7 +49,6 b' from . import (' | |||
|
49 | 49 | narrowspec, |
|
50 | 50 | obsolete, |
|
51 | 51 | pathutil, |
|
52 | peer, | |
|
53 | 52 | phases, |
|
54 | 53 | pushkey, |
|
55 | 54 | pycompat, |
@@ -66,6 +65,7 b' from . import (' | |||
|
66 | 65 | txnutil, |
|
67 | 66 | util, |
|
68 | 67 | vfs as vfsmod, |
|
68 | wireprotov1peer, | |
|
69 | 69 | ) |
|
70 | 70 | from .utils import ( |
|
71 | 71 | procutil, |
@@ -153,6 +153,20 b" moderncaps = {'lookup', 'branchmap', 'pu" | |||
|
153 | 153 | 'unbundle'} |
|
154 | 154 | legacycaps = moderncaps.union({'changegroupsubset'}) |
|
155 | 155 | |
|
156 | class localiterbatcher(wireprotov1peer.iterbatcher): | |
|
157 | def __init__(self, local): | |
|
158 | super(localiterbatcher, self).__init__() | |
|
159 | self.local = local | |
|
160 | ||
|
161 | def submit(self): | |
|
162 | # submit for a local iter batcher is a noop | |
|
163 | pass | |
|
164 | ||
|
165 | def results(self): | |
|
166 | for name, args, opts, resref in self.calls: | |
|
167 | resref.set(getattr(self.local, name)(*args, **opts)) | |
|
168 | yield resref.value | |
|
169 | ||
|
156 | 170 | class localpeer(repository.peer): |
|
157 | 171 | '''peer for a local repo; reflects only the most recent API''' |
|
158 | 172 | |
@@ -273,7 +287,7 b' class localpeer(repository.peer):' | |||
|
273 | 287 | # Begin of peer interface. |
|
274 | 288 | |
|
275 | 289 | def iterbatch(self): |
|
276 |
return |
|
|
290 | return localiterbatcher(self) | |
|
277 | 291 | |
|
278 | 292 | # End of peer interface. |
|
279 | 293 |
@@ -19,7 +19,6 b' from . import (' | |||
|
19 | 19 | changegroup as changegroupmod, |
|
20 | 20 | encoding, |
|
21 | 21 | error, |
|
22 | peer, | |
|
23 | 22 | pushkey as pushkeymod, |
|
24 | 23 | pycompat, |
|
25 | 24 | repository, |
@@ -29,7 +28,76 b' from . import (' | |||
|
29 | 28 | |
|
30 | 29 | urlreq = util.urlreq |
|
31 | 30 | |
|
32 | class remoteiterbatcher(peer.iterbatcher): | |
|
31 | def batchable(f): | |
|
32 | '''annotation for batchable methods | |
|
33 | ||
|
34 | Such methods must implement a coroutine as follows: | |
|
35 | ||
|
36 | @batchable | |
|
37 | def sample(self, one, two=None): | |
|
38 | # Build list of encoded arguments suitable for your wire protocol: | |
|
39 | encargs = [('one', encode(one),), ('two', encode(two),)] | |
|
40 | # Create future for injection of encoded result: | |
|
41 | encresref = future() | |
|
42 | # Return encoded arguments and future: | |
|
43 | yield encargs, encresref | |
|
44 | # Assuming the future to be filled with the result from the batched | |
|
45 | # request now. Decode it: | |
|
46 | yield decode(encresref.value) | |
|
47 | ||
|
48 | The decorator returns a function which wraps this coroutine as a plain | |
|
49 | method, but adds the original method as an attribute called "batchable", | |
|
50 | which is used by remotebatch to split the call into separate encoding and | |
|
51 | decoding phases. | |
|
52 | ''' | |
|
53 | def plain(*args, **opts): | |
|
54 | batchable = f(*args, **opts) | |
|
55 | encargsorres, encresref = next(batchable) | |
|
56 | if not encresref: | |
|
57 | return encargsorres # a local result in this case | |
|
58 | self = args[0] | |
|
59 | cmd = pycompat.bytesurl(f.__name__) # ensure cmd is ascii bytestr | |
|
60 | encresref.set(self._submitone(cmd, encargsorres)) | |
|
61 | return next(batchable) | |
|
62 | setattr(plain, 'batchable', f) | |
|
63 | return plain | |
|
64 | ||
|
65 | class future(object): | |
|
66 | '''placeholder for a value to be set later''' | |
|
67 | def set(self, value): | |
|
68 | if util.safehasattr(self, 'value'): | |
|
69 | raise error.RepoError("future is already set") | |
|
70 | self.value = value | |
|
71 | ||
|
72 | class batcher(object): | |
|
73 | '''base class for batches of commands submittable in a single request | |
|
74 | ||
|
75 | All methods invoked on instances of this class are simply queued and | |
|
76 | return a a future for the result. Once you call submit(), all the queued | |
|
77 | calls are performed and the results set in their respective futures. | |
|
78 | ''' | |
|
79 | def __init__(self): | |
|
80 | self.calls = [] | |
|
81 | def __getattr__(self, name): | |
|
82 | def call(*args, **opts): | |
|
83 | resref = future() | |
|
84 | # Please don't invent non-ascii method names, or you will | |
|
85 | # give core hg a very sad time. | |
|
86 | self.calls.append((name.encode('ascii'), args, opts, resref,)) | |
|
87 | return resref | |
|
88 | return call | |
|
89 | def submit(self): | |
|
90 | raise NotImplementedError() | |
|
91 | ||
|
92 | class iterbatcher(batcher): | |
|
93 | ||
|
94 | def submit(self): | |
|
95 | raise NotImplementedError() | |
|
96 | ||
|
97 | def results(self): | |
|
98 | raise NotImplementedError() | |
|
99 | ||
|
100 | class remoteiterbatcher(iterbatcher): | |
|
33 | 101 | def __init__(self, remote): |
|
34 | 102 | super(remoteiterbatcher, self).__init__() |
|
35 | 103 | self._remote = remote |
@@ -92,11 +160,6 b' class remoteiterbatcher(peer.iterbatcher' | |||
|
92 | 160 | |
|
93 | 161 | yield finalfuture.value |
|
94 | 162 | |
|
95 | # Forward a couple of names from peer to make wireproto interactions | |
|
96 | # slightly more sensible. | |
|
97 | batchable = peer.batchable | |
|
98 | future = peer.future | |
|
99 | ||
|
100 | 163 | def encodebatchcmds(req): |
|
101 | 164 | """Return a ``cmds`` argument value for the ``batch`` command.""" |
|
102 | 165 | escapearg = wireprototypes.escapebatcharg |
@@ -9,9 +9,10 b' from __future__ import absolute_import, ' | |||
|
9 | 9 | |
|
10 | 10 | from mercurial import ( |
|
11 | 11 | error, |
|
12 | peer, | |
|
12 | localrepo, | |
|
13 | 13 | util, |
|
14 | 14 | wireprotov1peer, |
|
15 | ||
|
15 | 16 | ) |
|
16 | 17 | |
|
17 | 18 | # equivalent of repo.repository |
@@ -31,7 +32,7 b' class localthing(thing):' | |||
|
31 | 32 | return "Hello, %s" % name |
|
32 | 33 | def batchiter(self): |
|
33 | 34 | '''Support for local batching.''' |
|
34 |
return |
|
|
35 | return localrepo.localiterbatcher(self) | |
|
35 | 36 | |
|
36 | 37 | # usage of "thing" interface |
|
37 | 38 | def use(it): |
@@ -51,7 +52,7 b' def use(it):' | |||
|
51 | 52 | bar2 = batch.bar(b="Uno", a="Due") |
|
52 | 53 | |
|
53 | 54 | # Future shouldn't be set until we submit(). |
|
54 | assert isinstance(foo, peer.future) | |
|
55 | assert isinstance(foo, wireprotov1peer.future) | |
|
55 | 56 | assert not util.safehasattr(foo, 'value') |
|
56 | 57 | assert not util.safehasattr(bar, 'value') |
|
57 | 58 | batch.submit() |
@@ -179,16 +180,16 b' class remotething(thing):' | |||
|
179 | 180 | def batchiter(self): |
|
180 | 181 | return wireprotov1peer.remoteiterbatcher(self) |
|
181 | 182 | |
|
182 | @peer.batchable | |
|
183 | @wireprotov1peer.batchable | |
|
183 | 184 | def foo(self, one, two=None): |
|
184 | 185 | encargs = [('one', mangle(one),), ('two', mangle(two),)] |
|
185 | encresref = peer.future() | |
|
186 | encresref = wireprotov1peer.future() | |
|
186 | 187 | yield encargs, encresref |
|
187 | 188 | yield unmangle(encresref.value) |
|
188 | 189 | |
|
189 | @peer.batchable | |
|
190 | @wireprotov1peer.batchable | |
|
190 | 191 | def bar(self, b, a): |
|
191 | encresref = peer.future() | |
|
192 | encresref = wireprotov1peer.future() | |
|
192 | 193 | yield [('b', mangle(b),), ('a', mangle(a),)], encresref |
|
193 | 194 | yield unmangle(encresref.value) |
|
194 | 195 |
|
1 | NO CONTENT: file was removed |
General Comments 0
You need to be logged in to leave comments.
Login now