##// END OF EJS Templates
peer: when collecting method names for batch calls, bytes-ify __name__...
Augie Fackler -
r34728:a652b776 default
parent child Browse files
Show More
@@ -1,96 +1,98 b''
1 # peer.py - repository base classes for mercurial
1 # peer.py - repository base classes for mercurial
2 #
2 #
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
5 #
5 #
6 # This software may be used and distributed according to the terms of the
6 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2 or any later version.
7 # GNU General Public License version 2 or any later version.
8
8
9 from __future__ import absolute_import
9 from __future__ import absolute_import
10
10
11 from . import (
11 from . import (
12 error,
12 error,
13 util,
13 util,
14 )
14 )
15
15
16 # abstract batching support
16 # abstract batching support
17
17
18 class future(object):
18 class future(object):
19 '''placeholder for a value to be set later'''
19 '''placeholder for a value to be set later'''
20 def set(self, value):
20 def set(self, value):
21 if util.safehasattr(self, 'value'):
21 if util.safehasattr(self, 'value'):
22 raise error.RepoError("future is already set")
22 raise error.RepoError("future is already set")
23 self.value = value
23 self.value = value
24
24
25 class batcher(object):
25 class batcher(object):
26 '''base class for batches of commands submittable in a single request
26 '''base class for batches of commands submittable in a single request
27
27
28 All methods invoked on instances of this class are simply queued and
28 All methods invoked on instances of this class are simply queued and
29 return a a future for the result. Once you call submit(), all the queued
29 return a a future for the result. Once you call submit(), all the queued
30 calls are performed and the results set in their respective futures.
30 calls are performed and the results set in their respective futures.
31 '''
31 '''
32 def __init__(self):
32 def __init__(self):
33 self.calls = []
33 self.calls = []
34 def __getattr__(self, name):
34 def __getattr__(self, name):
35 def call(*args, **opts):
35 def call(*args, **opts):
36 resref = future()
36 resref = future()
37 self.calls.append((name, args, opts, resref,))
37 # Please don't invent non-ascii method names, or you will
38 # give core hg a very sad time.
39 self.calls.append((name.encode('ascii'), args, opts, resref,))
38 return resref
40 return resref
39 return call
41 return call
40 def submit(self):
42 def submit(self):
41 raise NotImplementedError()
43 raise NotImplementedError()
42
44
43 class iterbatcher(batcher):
45 class iterbatcher(batcher):
44
46
45 def submit(self):
47 def submit(self):
46 raise NotImplementedError()
48 raise NotImplementedError()
47
49
48 def results(self):
50 def results(self):
49 raise NotImplementedError()
51 raise NotImplementedError()
50
52
51 class localiterbatcher(iterbatcher):
53 class localiterbatcher(iterbatcher):
52 def __init__(self, local):
54 def __init__(self, local):
53 super(iterbatcher, self).__init__()
55 super(iterbatcher, self).__init__()
54 self.local = local
56 self.local = local
55
57
56 def submit(self):
58 def submit(self):
57 # submit for a local iter batcher is a noop
59 # submit for a local iter batcher is a noop
58 pass
60 pass
59
61
60 def results(self):
62 def results(self):
61 for name, args, opts, resref in self.calls:
63 for name, args, opts, resref in self.calls:
62 resref.set(getattr(self.local, name)(*args, **opts))
64 resref.set(getattr(self.local, name)(*args, **opts))
63 yield resref.value
65 yield resref.value
64
66
65 def batchable(f):
67 def batchable(f):
66 '''annotation for batchable methods
68 '''annotation for batchable methods
67
69
68 Such methods must implement a coroutine as follows:
70 Such methods must implement a coroutine as follows:
69
71
70 @batchable
72 @batchable
71 def sample(self, one, two=None):
73 def sample(self, one, two=None):
72 # Build list of encoded arguments suitable for your wire protocol:
74 # Build list of encoded arguments suitable for your wire protocol:
73 encargs = [('one', encode(one),), ('two', encode(two),)]
75 encargs = [('one', encode(one),), ('two', encode(two),)]
74 # Create future for injection of encoded result:
76 # Create future for injection of encoded result:
75 encresref = future()
77 encresref = future()
76 # Return encoded arguments and future:
78 # Return encoded arguments and future:
77 yield encargs, encresref
79 yield encargs, encresref
78 # Assuming the future to be filled with the result from the batched
80 # Assuming the future to be filled with the result from the batched
79 # request now. Decode it:
81 # request now. Decode it:
80 yield decode(encresref.value)
82 yield decode(encresref.value)
81
83
82 The decorator returns a function which wraps this coroutine as a plain
84 The decorator returns a function which wraps this coroutine as a plain
83 method, but adds the original method as an attribute called "batchable",
85 method, but adds the original method as an attribute called "batchable",
84 which is used by remotebatch to split the call into separate encoding and
86 which is used by remotebatch to split the call into separate encoding and
85 decoding phases.
87 decoding phases.
86 '''
88 '''
87 def plain(*args, **opts):
89 def plain(*args, **opts):
88 batchable = f(*args, **opts)
90 batchable = f(*args, **opts)
89 encargsorres, encresref = next(batchable)
91 encargsorres, encresref = next(batchable)
90 if not encresref:
92 if not encresref:
91 return encargsorres # a local result in this case
93 return encargsorres # a local result in this case
92 self = args[0]
94 self = args[0]
93 encresref.set(self._submitone(f.__name__, encargsorres))
95 encresref.set(self._submitone(f.__name__, encargsorres))
94 return next(batchable)
96 return next(batchable)
95 setattr(plain, 'batchable', f)
97 setattr(plain, 'batchable', f)
96 return plain
98 return plain
General Comments 0
You need to be logged in to leave comments. Login now