Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(118)

Side by Side Diff: runtime/observatory/lib/service_common.dart

Issue 1120133002: Rework error handling in the service protocol and in Observatory. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library service_common; 5 library service_common;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:convert'; 8 import 'dart:convert';
9 import 'dart:typed_data'; 9 import 'dart:typed_data';
10 10
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 void _notifyDisconnect(String reason) { 109 void _notifyDisconnect(String reason) {
110 if (!_hasFinishedConnect) { 110 if (!_hasFinishedConnect) {
111 return; 111 return;
112 } 112 }
113 if (!_disconnected.isCompleted) { 113 if (!_disconnected.isCompleted) {
114 Logger.root.info('WebSocketVM connection error: ${target.networkAddress}') ; 114 Logger.root.info('WebSocketVM connection error: ${target.networkAddress}') ;
115 _disconnected.complete(reason); 115 _disconnected.complete(reason);
116 } 116 }
117 } 117 }
118 Future get onDisconnect => _disconnected.future; 118 Future get onDisconnect => _disconnected.future;
119 bool get isDisconnected => _disconnected.isCompleted;
119 120
120 void disconnect({String reason : 'WebSocket closed'}) { 121 void disconnect({String reason : 'WebSocket closed'}) {
121 if (_hasInitiatedConnect) { 122 if (_hasInitiatedConnect) {
122 _webSocket.close(); 123 _webSocket.close();
123 } 124 }
124 // We don't need to cancel requests and notify here. These 125 // We don't need to cancel requests and notify here. These
125 // functions will be called again when the onClose callback 126 // functions will be called again when the onClose callback
126 // fires. However, we may have a better 'reason' string now, so 127 // fires. However, we may have a better 'reason' string now, so
127 // let's take care of business. 128 // let's take care of business.
128 _cancelAllRequests(reason); 129 _cancelAllRequests(reason);
129 _notifyDisconnect(reason); 130 _notifyDisconnect(reason);
130 } 131 }
131 132
132 Future<Map> invokeRpcRaw(String method, Map params) { 133 Future<Map> invokeRpcRaw(String method, Map params) {
133 if (!_hasInitiatedConnect) { 134 if (!_hasInitiatedConnect) {
134 _hasInitiatedConnect = true; 135 _hasInitiatedConnect = true;
135 _webSocket.connect( 136 _webSocket.connect(
136 target.networkAddress, _onOpen, _onMessage, _onError, _onClose); 137 target.networkAddress, _onOpen, _onMessage, _onError, _onClose);
137 } 138 }
139 if (_disconnected.isCompleted) {
140 // This connection was closed already.
141 var exception = new NetworkRpcException('WebSocket closed');
142 return new Future.error(exception);
143 }
138 String serial = (_requestSerial++).toString(); 144 String serial = (_requestSerial++).toString();
139 var request = new _WebSocketRequest(method, params); 145 var request = new _WebSocketRequest(method, params);
140 if (_webSocket.isOpen) { 146 if (_webSocket.isOpen) {
141 // Already connected, send request immediately. 147 // Already connected, send request immediately.
142 _sendRequest(serial, request); 148 _sendRequest(serial, request);
143 } else { 149 } else {
144 // Not connected yet, add to delayed requests. 150 // Not connected yet, add to delayed requests.
145 _delayedRequests[serial] = request; 151 _delayedRequests[serial] = request;
146 } 152 }
147 return request.completer.future; 153 return request.completer.future;
(...skipping 18 matching lines...) Expand all
166 _sendAllDelayedRequests(); 172 _sendAllDelayedRequests();
167 _notifyConnect(); 173 _notifyConnect();
168 } 174 }
169 175
170 Map _parseJSON(String message) { 176 Map _parseJSON(String message) {
171 var map; 177 var map;
172 try { 178 try {
173 map = JSON.decode(message); 179 map = JSON.decode(message);
174 } catch (e, st) { 180 } catch (e, st) {
175 Logger.root.severe('Disconnecting: Error decoding message: $e\n$st'); 181 Logger.root.severe('Disconnecting: Error decoding message: $e\n$st');
176 disconnect(reason:'Error decoding JSON message: $e'); 182 disconnect(reason:'Connection saw corrupt JSON message: $e');
177 return null; 183 return null;
178 } 184 }
179 if (map == null) { 185 if (map == null) {
180 Logger.root.severe("Disconnecting: Unable to decode 'null' message"); 186 Logger.root.severe("Disconnecting: Unable to decode 'null' message");
181 disconnect(reason:"Unable to decode 'null' message"); 187 disconnect(reason:"Connection saw 'null' message");
182 return null; 188 return null;
183 } 189 }
184 return map; 190 return map;
185 } 191 }
186 192
187 void _onBinaryMessage(dynamic data) { 193 void _onBinaryMessage(dynamic data) {
188 _webSocket.nonStringToByteData(data).then((ByteData bytes) { 194 _webSocket.nonStringToByteData(data).then((ByteData bytes) {
189 // See format spec. in VMs Service::SendEvent. 195 // See format spec. in VMs Service::SendEvent.
190 int offset = 0; 196 int offset = 0;
191 // Dart2JS workaround (no getUint64). Limit to 4 GB metadata. 197 // Dart2JS workaround (no getUint64). Limit to 4 GB metadata.
(...skipping 22 matching lines...) Expand all
214 return; 220 return;
215 } 221 }
216 var event = map['event']; 222 var event = map['event'];
217 if (event != null) { 223 if (event != null) {
218 postServiceEvent(event, null); 224 postServiceEvent(event, null);
219 return; 225 return;
220 } 226 }
221 227
222 // Extract serial and result. 228 // Extract serial and result.
223 var serial = map['id']; 229 var serial = map['id'];
224 var result = map['result'];
225 230
226 // Complete request. 231 // Complete request.
227 var request = _pendingRequests.remove(serial); 232 var request = _pendingRequests.remove(serial);
228 if (request == null) { 233 if (request == null) {
229 Logger.root.severe('Received unexpected message: ${map}'); 234 Logger.root.severe('Received unexpected message: ${map}');
230 return; 235 return;
231 } 236 }
232 if (request.method != 'getTagProfile' && 237 if (request.method != 'getTagProfile' &&
233 request.method != 'getIsolateMetric' && 238 request.method != 'getIsolateMetric' &&
234 request.method != 'getVMMetric') { 239 request.method != 'getVMMetric') {
235 Logger.root.info( 240 Logger.root.info(
236 'RESPONSE [${serial}] ${request.method}'); 241 'RESPONSE [${serial}] ${request.method}');
237 } 242 }
238 request.completer.complete(result); 243
244 var result = map['result'];
245 if (result != null) {
246 request.completer.complete(result);
247 } else {
248 var exception = new ServerRpcException.fromMap(map['error']);
249 request.completer.completeError(exception);
250 }
239 } 251 }
240 252
241 // WebSocket message event handler. 253 // WebSocket message event handler.
242 void _onMessage(dynamic data) { 254 void _onMessage(dynamic data) {
243 if (data is! String) { 255 if (data is! String) {
244 _onBinaryMessage(data); 256 _onBinaryMessage(data);
245 } else { 257 } else {
246 _onStringMessage(data); 258 _onStringMessage(data);
247 } 259 }
248 } 260 }
249 261
250 Map _generateNetworkError(String userMessage) {
251 var response = {
252 'type': 'ServiceException',
253 'kind': 'ConnectionClosed',
254 'message': userMessage,
255 };
256 return response;
257 }
258
259 void _cancelRequests(Map<String,_WebSocketRequest> requests, 262 void _cancelRequests(Map<String,_WebSocketRequest> requests,
260 String reason) { 263 String message) {
261 requests.forEach((_, _WebSocketRequest request) { 264 requests.forEach((_, _WebSocketRequest request) {
262 request.completer.complete( 265 var exception = new NetworkRpcException(message);
263 _generateNetworkError(reason)); 266 request.completer.completeError(exception);
264 }); 267 });
265 requests.clear(); 268 requests.clear();
266 } 269 }
267 270
268 /// Cancel all pending and delayed requests by completing them with an error. 271 /// Cancel all pending and delayed requests by completing them with an error.
269 void _cancelAllRequests(String reason) { 272 void _cancelAllRequests(String reason) {
273 String message = 'Canceling request: $reason';
270 if (_pendingRequests.length > 0) { 274 if (_pendingRequests.length > 0) {
271 Logger.root.info('Cancelling all pending requests.'); 275 Logger.root.info('Canceling all pending requests.');
272 _cancelRequests(_pendingRequests, reason); 276 _cancelRequests(_pendingRequests, message);
273 } 277 }
274 if (_delayedRequests.length > 0) { 278 if (_delayedRequests.length > 0) {
275 Logger.root.info('Cancelling all delayed requests.'); 279 Logger.root.info('Canceling all delayed requests.');
276 _cancelRequests(_delayedRequests, reason); 280 _cancelRequests(_delayedRequests, message);
277 } 281 }
278 } 282 }
279 283
280 /// Send all delayed requests. 284 /// Send all delayed requests.
281 void _sendAllDelayedRequests() { 285 void _sendAllDelayedRequests() {
282 assert(_webSocket.isOpen); 286 assert(_webSocket.isOpen);
283 if (_delayedRequests.length == 0) { 287 if (_delayedRequests.length == 0) {
284 return; 288 return;
285 } 289 }
286 Logger.root.info('Sending all delayed requests.'); 290 Logger.root.info('Sending all delayed requests.');
(...skipping 28 matching lines...) Expand all
315 if (request.method != 'getTagProfile' && 319 if (request.method != 'getTagProfile' &&
316 request.method != 'getIsolateMetric' && 320 request.method != 'getIsolateMetric' &&
317 request.method != 'getVMMetric') { 321 request.method != 'getVMMetric') {
318 Logger.root.info( 322 Logger.root.info(
319 'GET [${serial}] ${request.method}(${request.params}) from ${target.ne tworkAddress}'); 323 'GET [${serial}] ${request.method}(${request.params}) from ${target.ne tworkAddress}');
320 } 324 }
321 // Send message. 325 // Send message.
322 _webSocket.send(message); 326 _webSocket.send(message);
323 } 327 }
324 } 328 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698