annotate mercurial/wireprotov2peer.py @ 39486:43d92d68ac88

wireprotov2peer: properly format errors formatrichmessage() expects an iterable containing dicts with well-defined keys. We were passing in something else. This caused an exception. Change the code to call formatrichmessage() with the proper argument. And add a TODO to potentially emit the proper data structure from the server in the first place. Differential Revision: https://phab.mercurial-scm.org/D4441
author Gregory Szorc <gregory.szorc@gmail.com>
date Wed, 05 Sep 2018 09:04:40 -0700
parents 42bc1c70a6b8
children 07b58266bce3
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
1 # wireprotov2peer.py - client side code for wire protocol version 2
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
2 #
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
3 # Copyright 2018 Gregory Szorc <gregory.szorc@gmail.com>
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
4 #
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
5 # This software may be used and distributed according to the terms of the
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
6 # GNU General Public License version 2 or any later version.
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
7
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
8 from __future__ import absolute_import
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
9
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
10 from .i18n import _
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
11 from . import (
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
12 encoding,
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
13 error,
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
14 util,
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
15 wireprotoframing,
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
16 )
39450
9f51fd22ed50 wireprotov2peer: use our CBOR decoder
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39438
diff changeset
17 from .utils import (
9f51fd22ed50 wireprotov2peer: use our CBOR decoder
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39438
diff changeset
18 cborutil,
9f51fd22ed50 wireprotov2peer: use our CBOR decoder
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39438
diff changeset
19 )
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
20
37725
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
21 def formatrichmessage(atoms):
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
22 """Format an encoded message from the framing protocol."""
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
23
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
24 chunks = []
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
25
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
26 for atom in atoms:
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
27 msg = _(atom[b'msg'])
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
28
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
29 if b'args' in atom:
39486
43d92d68ac88 wireprotov2peer: properly format errors
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39485
diff changeset
30 msg = msg % tuple(atom[b'args'])
37725
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
31
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
32 chunks.append(msg)
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
33
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
34 return b''.join(chunks)
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
35
37720
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
36 class commandresponse(object):
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
37 """Represents the response to a command request."""
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
38
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
39 def __init__(self, requestid, command):
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
40 self.requestid = requestid
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
41 self.command = command
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
42
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
43 self.b = util.bytesio()
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
44
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
45 def cborobjects(self):
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
46 """Obtain decoded CBOR objects from this response."""
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
47 self.b.seek(0)
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
48
39450
9f51fd22ed50 wireprotov2peer: use our CBOR decoder
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39438
diff changeset
49 for v in cborutil.decodeall(self.b.getvalue()):
9f51fd22ed50 wireprotov2peer: use our CBOR decoder
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39438
diff changeset
50 yield v
37720
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
51
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
52 class clienthandler(object):
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
53 """Object to handle higher-level client activities.
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
54
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
55 The ``clientreactor`` is used to hold low-level state about the frame-based
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
56 protocol, such as which requests and streams are active. This type is used
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
57 for higher-level operations, such as reading frames from a socket, exposing
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
58 and managing a higher-level primitive for representing command responses,
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
59 etc. This class is what peers should probably use to bridge wire activity
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
60 with the higher-level peer API.
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
61 """
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
62
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
63 def __init__(self, ui, clientreactor):
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
64 self._ui = ui
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
65 self._reactor = clientreactor
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
66 self._requests = {}
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
67 self._futures = {}
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
68 self._responses = {}
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
69
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
70 def callcommand(self, command, args, f):
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
71 """Register a request to call a command.
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
72
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
73 Returns an iterable of frames that should be sent over the wire.
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
74 """
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
75 request, action, meta = self._reactor.callcommand(command, args)
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
76
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
77 if action != 'noop':
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
78 raise error.ProgrammingError('%s not yet supported' % action)
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
79
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
80 rid = request.requestid
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
81 self._requests[rid] = request
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
82 self._futures[rid] = f
37720
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
83 self._responses[rid] = commandresponse(rid, command)
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
84
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
85 return iter(())
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
86
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
87 def flushcommands(self):
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
88 """Flush all queued commands.
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
89
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
90 Returns an iterable of frames that should be sent over the wire.
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
91 """
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
92 action, meta = self._reactor.flushcommands()
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
93
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
94 if action != 'sendframes':
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
95 raise error.ProgrammingError('%s not yet supported' % action)
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
96
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
97 return meta['framegen']
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
98
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
99 def readframe(self, fh):
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
100 """Attempt to read and process a frame.
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
101
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
102 Returns None if no frame was read. Presumably this means EOF.
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
103 """
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
104 frame = wireprotoframing.readframe(fh)
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
105 if frame is None:
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
106 # TODO tell reactor?
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
107 return
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
108
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
109 self._ui.note(_('received %r\n') % frame)
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
110 self._processframe(frame)
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
111
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
112 return True
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
113
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
114 def _processframe(self, frame):
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
115 """Process a single read frame."""
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
116
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
117 action, meta = self._reactor.onframerecv(frame)
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
118
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
119 if action == 'error':
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
120 e = error.RepoError(meta['message'])
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
121
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
122 if frame.requestid in self._futures:
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
123 self._futures[frame.requestid].set_exception(e)
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
124 else:
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
125 raise e
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
126
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
127 if frame.requestid not in self._requests:
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
128 raise error.ProgrammingError(
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
129 'received frame for unknown request; this is either a bug in '
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
130 'the clientreactor not screening for this or this instance was '
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
131 'never told about this request: %r' % frame)
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
132
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
133 response = self._responses[frame.requestid]
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
134
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
135 if action == 'responsedata':
39485
42bc1c70a6b8 wireprotov2peer: report exceptions in frame handling against request future
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39450
diff changeset
136 # Any failures processing this frame should bubble up to the
42bc1c70a6b8 wireprotov2peer: report exceptions in frame handling against request future
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39450
diff changeset
137 # future tracking the request.
42bc1c70a6b8 wireprotov2peer: report exceptions in frame handling against request future
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39450
diff changeset
138 try:
42bc1c70a6b8 wireprotov2peer: report exceptions in frame handling against request future
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39450
diff changeset
139 self._processresponsedata(frame, meta, response)
42bc1c70a6b8 wireprotov2peer: report exceptions in frame handling against request future
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39450
diff changeset
140 except BaseException as e:
42bc1c70a6b8 wireprotov2peer: report exceptions in frame handling against request future
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39450
diff changeset
141 self._futures[frame.requestid].set_exception(e)
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
142 else:
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
143 raise error.ProgrammingError(
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
144 'unhandled action from clientreactor: %s' % action)
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
145
39438
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
146 def _processresponsedata(self, frame, meta, response):
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
147 # This buffers all data until end of stream is received. This
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
148 # is bad for performance.
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
149 # TODO make response data streamable
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
150 response.b.write(meta['data'])
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
151
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
152 if meta['eos']:
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
153 # If the command has a decoder, resolve the future to the
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
154 # decoded value. Otherwise resolve to the rich response object.
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
155 decoder = COMMAND_DECODERS.get(response.command)
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
156
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
157 # TODO consider always resolving the overall status map.
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
158 if decoder:
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
159 objs = response.cborobjects()
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
160
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
161 overall = next(objs)
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
162
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
163 if overall['status'] == 'ok':
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
164 self._futures[frame.requestid].set_result(decoder(objs))
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
165 else:
39486
43d92d68ac88 wireprotov2peer: properly format errors
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39485
diff changeset
166 atoms = [{'msg': overall['error']['message']}]
43d92d68ac88 wireprotov2peer: properly format errors
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39485
diff changeset
167 if 'args' in overall['error']:
43d92d68ac88 wireprotov2peer: properly format errors
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39485
diff changeset
168 atoms[0]['args'] = overall['error']['args']
43d92d68ac88 wireprotov2peer: properly format errors
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39485
diff changeset
169 e = error.RepoError(formatrichmessage(atoms))
39438
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
170 self._futures[frame.requestid].set_exception(e)
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
171 else:
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
172 self._futures[frame.requestid].set_result(response)
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
173
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
174 del self._requests[frame.requestid]
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
175 del self._futures[frame.requestid]
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
176
37725
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
177 def decodebranchmap(objs):
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
178 # Response should be a single CBOR map of branch name to array of nodes.
37725
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
179 bm = next(objs)
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
180
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
181 return {encoding.tolocal(k): v for k, v in bm.items()}
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
182
37725
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
183 def decodeheads(objs):
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
184 # Array of node bytestrings.
37725
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
185 return next(objs)
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
186
37725
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
187 def decodeknown(objs):
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
188 # Bytestring where each byte is a 0 or 1.
37725
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
189 raw = next(objs)
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
190
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
191 return [True if c == '1' else False for c in raw]
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
192
37725
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
193 def decodelistkeys(objs):
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
194 # Map with bytestring keys and values.
37725
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
195 return next(objs)
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
196
37725
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
197 def decodelookup(objs):
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
198 return next(objs)
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
199
37725
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
200 def decodepushkey(objs):
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
201 return next(objs)
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
202
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
203 COMMAND_DECODERS = {
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
204 'branchmap': decodebranchmap,
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
205 'heads': decodeheads,
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
206 'known': decodeknown,
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
207 'listkeys': decodelistkeys,
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
208 'lookup': decodelookup,
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
209 'pushkey': decodepushkey,
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
210 }