diff -r b4a85ddadcb9 -r cbbdd085c991 mercurial/wireproto.py --- a/mercurial/wireproto.py Mon Aug 03 06:13:05 2015 -0700 +++ b/mercurial/wireproto.py Wed Aug 05 14:51:34 2015 -0400 @@ -58,48 +58,12 @@ Some protocols may have compressed the contents.""" raise NotImplementedError() -# abstract batching support - -class future(object): - '''placeholder for a value to be set later''' - def set(self, value): - if util.safehasattr(self, 'value'): - raise error.RepoError("future is already set") - self.value = value - -class batcher(object): - '''base class for batches of commands submittable in a single request - - All methods invoked on instances of this class are simply queued and - return a a future for the result. Once you call submit(), all the queued - calls are performed and the results set in their respective futures. - ''' - def __init__(self): - self.calls = [] - def __getattr__(self, name): - def call(*args, **opts): - resref = future() - self.calls.append((name, args, opts, resref,)) - return resref - return call - def submit(self): - pass - -class localbatch(batcher): - '''performs the queued calls directly''' - def __init__(self, local): - batcher.__init__(self) - self.local = local - def submit(self): - for name, args, opts, resref in self.calls: - resref.set(getattr(self.local, name)(*args, **opts)) - -class remotebatch(batcher): +class remotebatch(peer.batcher): '''batches the queued calls; uses as few roundtrips as possible''' def __init__(self, remote): '''remote must support _submitbatch(encbatch) and _submitone(op, encargs)''' - batcher.__init__(self) + peer.batcher.__init__(self) self.remote = remote def submit(self): req, rsp = [], [] @@ -128,41 +92,10 @@ encresref.set(encres) resref.set(batchable.next()) -def batchable(f): - '''annotation for batchable methods - - Such methods must implement a coroutine as follows: - - @batchable - def sample(self, one, two=None): - # Handle locally computable results first: - if not one: - yield "a local result", None - # Build list of encoded arguments suitable for your wire protocol: - encargs = [('one', encode(one),), ('two', encode(two),)] - # Create future for injection of encoded result: - encresref = future() - # Return encoded arguments and future: - yield encargs, encresref - # Assuming the future to be filled with the result from the batched - # request now. Decode it: - yield decode(encresref.value) - - The decorator returns a function which wraps this coroutine as a plain - method, but adds the original method as an attribute called "batchable", - which is used by remotebatch to split the call into separate encoding and - decoding phases. - ''' - def plain(*args, **opts): - batchable = f(*args, **opts) - encargsorres, encresref = batchable.next() - if not encresref: - return encargsorres # a local result in this case - self = args[0] - encresref.set(self._submitone(f.func_name, encargsorres)) - return batchable.next() - setattr(plain, 'batchable', f) - return plain +# Forward a couple of names from peer to make wireproto interactions +# slightly more sensible. +batchable = peer.batchable +future = peer.future # list of nodes encoding / decoding