annotate mercurial/wireprotov2peer.py @ 38128:1cba497491be

narrow: only wrap dirstate functions once, instead of per-reposetup chg will call reposetup multiple times, and we would end up double-wrapping (or worse) the dirstate functions; this can cause issues like OSError 'No such file or directory' during rebase operations, when we go to double-delete our narrowspec backup file. Differential Revision: https://phab.mercurial-scm.org/D3559
author Kyle Lippincott <spectral@google.com>
date Wed, 16 May 2018 14:59:32 -0700
parents 3ea8323d6f95
children 1467b6c27ff9
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 .thirdparty import (
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
12 cbor,
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
13 )
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
14 from . import (
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
15 encoding,
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
16 error,
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
17 util,
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
18 wireprotoframing,
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
19 )
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:
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
30 msg = msg % atom[b'args']
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 size = self.b.tell()
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
48 self.b.seek(0)
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
49
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
50 decoder = cbor.CBORDecoder(self.b)
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
51
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
52 while self.b.tell() < size:
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
53 yield decoder.decode()
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
54
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
55 class clienthandler(object):
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
56 """Object to handle higher-level client activities.
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
57
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
58 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
59 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
60 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
61 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
62 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
63 with the higher-level peer API.
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
64 """
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
65
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
66 def __init__(self, ui, clientreactor):
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
67 self._ui = ui
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
68 self._reactor = clientreactor
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
69 self._requests = {}
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
70 self._futures = {}
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
71 self._responses = {}
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 def callcommand(self, command, args, f):
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
74 """Register a request to call a command.
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
75
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
76 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
77 """
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
78 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
79
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
80 if action != 'noop':
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
81 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
82
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
83 rid = request.requestid
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
84 self._requests[rid] = request
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
85 self._futures[rid] = f
37720
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
86 self._responses[rid] = commandresponse(rid, command)
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
87
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
88 return iter(())
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 def flushcommands(self):
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
91 """Flush all queued commands.
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
92
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
93 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
94 """
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
95 action, meta = self._reactor.flushcommands()
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 if action != 'sendframes':
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
98 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
99
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
100 return meta['framegen']
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 def readframe(self, fh):
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
103 """Attempt to read and process a frame.
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
104
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
105 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
106 """
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
107 frame = wireprotoframing.readframe(fh)
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
108 if frame is None:
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
109 # TODO tell reactor?
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
110 return
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 self._ui.note(_('received %r\n') % frame)
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
113 self._processframe(frame)
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
114
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
115 return True
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 def _processframe(self, frame):
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
118 """Process a single read frame."""
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
119
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
120 action, meta = self._reactor.onframerecv(frame)
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 action == 'error':
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
123 e = error.RepoError(meta['message'])
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
124
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
125 if frame.requestid in self._futures:
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
126 self._futures[frame.requestid].set_exception(e)
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
127 else:
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
128 raise e
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
129
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
130 if frame.requestid not in self._requests:
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
131 raise error.ProgrammingError(
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
132 '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
133 '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
134 'never told about this request: %r' % frame)
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
135
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
136 response = self._responses[frame.requestid]
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
137
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
138 if action == 'responsedata':
37720
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
139 response.b.write(meta['data'])
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
140
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
141 if meta['eos']:
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
142 # If the command has a decoder, resolve the future to the
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
143 # decoded value. Otherwise resolve to the rich response object.
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
144 decoder = COMMAND_DECODERS.get(response.command)
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
145
37725
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
146 # TODO consider always resolving the overall status map.
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
147 if decoder:
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
148 objs = response.cborobjects()
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
149
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
150 overall = next(objs)
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
151
37725
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
152 if overall['status'] == 'ok':
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
153 self._futures[frame.requestid].set_result(decoder(objs))
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
154 else:
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
155 e = error.RepoError(
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
156 formatrichmessage(overall['error']['message']))
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
157 self._futures[frame.requestid].set_exception(e)
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
158 else:
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
159 self._futures[frame.requestid].set_result(response)
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
160
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
161 del self._requests[frame.requestid]
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
162 del self._futures[frame.requestid]
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
163
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
164 else:
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
165 raise error.ProgrammingError(
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
166 '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
167
37725
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
168 def decodebranchmap(objs):
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
169 # 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
170 bm = next(objs)
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
171
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
172 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
173
37725
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
174 def decodeheads(objs):
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
175 # 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
176 return next(objs)
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
177
37725
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
178 def decodeknown(objs):
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
179 # 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
180 raw = next(objs)
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
181
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
182 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
183
37725
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
184 def decodelistkeys(objs):
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
185 # 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
186 return next(objs)
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
187
37725
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
188 def decodelookup(objs):
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
189 return next(objs)
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
190
37725
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
191 def decodepushkey(objs):
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
192 return next(objs)
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
193
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
194 COMMAND_DECODERS = {
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
195 'branchmap': decodebranchmap,
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
196 'heads': decodeheads,
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
197 'known': decodeknown,
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
198 'listkeys': decodelistkeys,
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
199 'lookup': decodelookup,
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
200 'pushkey': decodepushkey,
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
201 }