OLD | NEW |
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 part of service; | 5 part of service; |
6 | 6 |
7 // Some value smaller than the object ring, so requesting a large array | 7 // Some value smaller than the object ring, so requesting a large array |
8 // doesn't result in an expired ref because the elements lapped it in the | 8 // doesn't result in an expired ref because the elements lapped it in the |
9 // object ring. | 9 // object ring. |
10 const int kDefaultFieldLimit = 100; | 10 const int kDefaultFieldLimit = 100; |
(...skipping 571 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
582 _controllers.remove(controller); | 582 _controllers.remove(controller); |
583 if (_controllers.isEmpty) { | 583 if (_controllers.isEmpty) { |
584 assert(_listenFuture != null); | 584 assert(_listenFuture != null); |
585 _listenFuture = null; | 585 _listenFuture = null; |
586 _cancelFuture = _vm._streamCancel(streamId); | 586 _cancelFuture = _vm._streamCancel(streamId); |
587 _cancelFuture.then((_) { | 587 _cancelFuture.then((_) { |
588 if (_controllers.isEmpty) { | 588 if (_controllers.isEmpty) { |
589 // No new listeners showed up during cancelation. | 589 // No new listeners showed up during cancelation. |
590 _onDone(); | 590 _onDone(); |
591 } | 591 } |
| 592 }).catchError((e) { |
| 593 /* ignore */ |
592 }); | 594 }); |
593 } | 595 } |
594 // No need to wait for _cancelFuture here. | 596 // No need to wait for _cancelFuture here. |
595 return new Future.value(null); | 597 return new Future.value(null); |
596 } | 598 } |
597 | 599 |
598 Future<Stream> addStream() async { | 600 Future<Stream> addStream() async { |
599 var controller; | 601 var controller; |
600 controller = new StreamController( | 602 controller = new StreamController( |
601 onCancel:() => _cancelController(controller)); | 603 onCancel:() => _cancelController(controller)); |
602 _controllers.add(controller); | 604 _controllers.add(controller); |
603 if (_cancelFuture != null) { | 605 if (_cancelFuture != null) { |
604 await _cancelFuture; | 606 try { |
| 607 await _cancelFuture; |
| 608 } on NetworkRpcException catch (_) { /* ignore */ } |
605 } | 609 } |
606 if (_listenFuture == null) { | 610 if (_listenFuture == null) { |
607 _listenFuture = _vm._streamListen(streamId); | 611 _listenFuture = _vm._streamListen(streamId); |
608 } | 612 } |
609 await _listenFuture; | 613 try { |
| 614 await _listenFuture; |
| 615 } on NetworkRpcException catch (_) { /* ignore */ } |
610 return controller.stream; | 616 return controller.stream; |
611 } | 617 } |
612 | 618 |
613 void addEvent(ServiceEvent event) { | 619 void addEvent(ServiceEvent event) { |
614 for (var controller in _controllers) { | 620 for (var controller in _controllers) { |
615 controller.add(event); | 621 controller.add(event); |
616 } | 622 } |
617 } | 623 } |
618 } | 624 } |
619 | 625 |
620 /// State for a VM being inspected. | 626 /// State for a VM being inspected. |
621 abstract class VM extends ServiceObjectOwner implements M.VM { | 627 abstract class VM extends ServiceObjectOwner implements M.VM { |
622 VM get vm => this; | 628 VM get vm => this; |
623 Isolate get isolate => null; | 629 Isolate get isolate => null; |
624 | 630 |
625 // TODO(turnidge): The connection should not be stored in the VM object. | 631 // TODO(turnidge): The connection should not be stored in the VM object. |
626 bool get isDisconnected; | 632 bool get isDisconnected; |
| 633 bool get isConnected; |
627 | 634 |
628 // Used for verbose logging. | 635 // Used for verbose logging. |
629 bool verbose = false; | 636 bool verbose = false; |
630 | 637 |
631 // TODO(johnmccutchan): Ensure that isolates do not end up in _cache. | 638 // TODO(johnmccutchan): Ensure that isolates do not end up in _cache. |
632 Map<String,ServiceObject> _cache = new Map<String,ServiceObject>(); | 639 Map<String,ServiceObject> _cache = new Map<String,ServiceObject>(); |
633 final Map<String,Isolate> _isolateCache = <String,Isolate>{}; | 640 final Map<String,Isolate> _isolateCache = <String,Isolate>{}; |
634 | 641 |
635 // The list of live isolates, ordered by isolate start time. | 642 // The list of live isolates, ordered by isolate start time. |
636 final List<Isolate> isolates = <Isolate>[]; | 643 final List<Isolate> isolates = <Isolate>[]; |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
806 } | 813 } |
807 | 814 |
808 Future<ServiceObject> invokeRpc(String method, Map params) { | 815 Future<ServiceObject> invokeRpc(String method, Map params) { |
809 return invokeRpcNoUpgrade(method, params).then((Map response) { | 816 return invokeRpcNoUpgrade(method, params).then((Map response) { |
810 var obj = new ServiceObject._fromMap(this, response); | 817 var obj = new ServiceObject._fromMap(this, response); |
811 if ((obj != null) && obj.canCache) { | 818 if ((obj != null) && obj.canCache) { |
812 String objId = obj.id; | 819 String objId = obj.id; |
813 _cache.putIfAbsent(objId, () => obj); | 820 _cache.putIfAbsent(objId, () => obj); |
814 } | 821 } |
815 return obj; | 822 return obj; |
| 823 }).catchError((e) { |
| 824 return new Future.error(e); |
816 }); | 825 }); |
817 } | 826 } |
818 | 827 |
819 void _dispatchEventToIsolate(ServiceEvent event) { | 828 void _dispatchEventToIsolate(ServiceEvent event) { |
820 var isolate = event.isolate; | 829 var isolate = event.isolate; |
821 if (isolate != null) { | 830 if (isolate != null) { |
822 isolate._onEvent(event); | 831 isolate._onEvent(event); |
823 } | 832 } |
824 } | 833 } |
825 | 834 |
826 Future restart() { | 835 Future restart() { |
827 return invokeRpc('_restartVM', {}); | 836 return invokeRpc('_restartVM', {}); |
828 } | 837 } |
829 | 838 |
830 Future<Map> _fetchDirect({int count: kDefaultFieldLimit}) async { | 839 Future<Map> _fetchDirect({int count: kDefaultFieldLimit}) async { |
831 if (!loaded) { | 840 if (!loaded) { |
832 // The vm service relies on these events to keep the VM and | 841 // The vm service relies on these events to keep the VM and |
833 // Isolate types up to date. | 842 // Isolate types up to date. |
834 try { | 843 try { |
835 await listenEventStream(kVMStream, _dispatchEventToIsolate); | 844 await listenEventStream(kVMStream, _dispatchEventToIsolate); |
836 await listenEventStream(kIsolateStream, _dispatchEventToIsolate); | 845 await listenEventStream(kIsolateStream, _dispatchEventToIsolate); |
837 await listenEventStream(kDebugStream, _dispatchEventToIsolate); | 846 await listenEventStream(kDebugStream, _dispatchEventToIsolate); |
838 await listenEventStream(_kGraphStream, _dispatchEventToIsolate); | 847 await listenEventStream(_kGraphStream, _dispatchEventToIsolate); |
839 } on FakeVMRpcException catch (_) { | 848 } on FakeVMRpcException catch (_) { |
840 // ignore FakeVMRpcExceptions here. | 849 // ignore FakeVMRpcExceptions here. |
| 850 } on NetworkRpcException catch (_) { |
| 851 // ignore network errors here. |
841 } | 852 } |
842 } | 853 } |
843 return await invokeRpcNoUpgrade('getVM', {}); | 854 return await invokeRpcNoUpgrade('getVM', {}); |
844 } | 855 } |
845 | 856 |
846 Future setName(String newName) { | 857 Future setName(String newName) { |
847 return invokeRpc('setVMName', { 'name': newName }); | 858 return invokeRpc('setVMName', { 'name': newName }); |
848 } | 859 } |
849 | 860 |
850 Future<ServiceObject> getFlagList() { | 861 Future<ServiceObject> getFlagList() { |
851 return invokeRpc('getFlagList', {}); | 862 return invokeRpc('getFlagList', {}); |
852 } | 863 } |
853 | 864 |
854 Future<ServiceObject> _streamListen(String streamId) { | 865 Future<ServiceObject> _streamListen(String streamId) { |
855 Map params = { | 866 Map params = { |
856 'streamId': streamId, | 867 'streamId': streamId, |
857 }; | 868 }; |
858 return invokeRpc('streamListen', params); | 869 return invokeRpc('streamListen', params).catchError((e) { |
| 870 // Ignore network errors on stream listen. |
| 871 if (e is NetworkRpcException) { |
| 872 return null; |
| 873 } |
| 874 }); |
859 } | 875 } |
860 | 876 |
861 Future<ServiceObject> _streamCancel(String streamId) { | 877 Future<ServiceObject> _streamCancel(String streamId) { |
862 Map params = { | 878 Map params = { |
863 'streamId': streamId, | 879 'streamId': streamId, |
864 }; | 880 }; |
865 return invokeRpc('streamCancel', params); | 881 return invokeRpc('streamCancel', params).catchError((e) { |
| 882 // Ignore network errors on stream cancel. |
| 883 if (e is NetworkRpcException) { |
| 884 return null; |
| 885 } |
| 886 }); |
866 } | 887 } |
867 | 888 |
868 // A map from stream id to event stream state. | 889 // A map from stream id to event stream state. |
869 Map<String,_EventStreamState> _eventStreams = {}; | 890 Map<String,_EventStreamState> _eventStreams = {}; |
870 | 891 |
871 // Well-known stream ids. | 892 // Well-known stream ids. |
872 static const kVMStream = 'VM'; | 893 static const kVMStream = 'VM'; |
873 static const kIsolateStream = 'Isolate'; | 894 static const kIsolateStream = 'Isolate'; |
874 static const kTimelineStream = 'Timeline'; | 895 static const kTimelineStream = 'Timeline'; |
875 static const kDebugStream = 'Debug'; | 896 static const kDebugStream = 'Debug'; |
876 static const kGCStream = 'GC'; | 897 static const kGCStream = 'GC'; |
877 static const kStdoutStream = 'Stdout'; | 898 static const kStdoutStream = 'Stdout'; |
878 static const kStderrStream = 'Stderr'; | 899 static const kStderrStream = 'Stderr'; |
879 static const _kGraphStream = '_Graph'; | 900 static const _kGraphStream = '_Graph'; |
880 | 901 |
881 /// Returns a single-subscription Stream object for a VM event stream. | 902 /// Returns a single-subscription Stream object for a VM event stream. |
882 Future<Stream> getEventStream(String streamId) async { | 903 Future<Stream> getEventStream(String streamId) async { |
883 var eventStream = _eventStreams.putIfAbsent( | 904 var eventStream = _eventStreams.putIfAbsent( |
884 streamId, () => new _EventStreamState( | 905 streamId, () => new _EventStreamState( |
885 this, streamId, () => _eventStreams.remove(streamId))); | 906 this, streamId, () => _eventStreams.remove(streamId))); |
886 return eventStream.addStream(); | 907 Stream stream = await eventStream.addStream(); |
| 908 return stream; |
887 } | 909 } |
888 | 910 |
889 /// Helper function for listening to an event stream. | 911 /// Helper function for listening to an event stream. |
890 Future<StreamSubscription> listenEventStream(String streamId, | 912 Future<StreamSubscription> listenEventStream(String streamId, |
891 Function function) async { | 913 Function function) async { |
892 var stream = await getEventStream(streamId); | 914 var stream = await getEventStream(streamId); |
893 return stream.listen(function); | 915 return stream.listen(function); |
894 } | 916 } |
895 | 917 |
896 /// Force the VM to disconnect. | 918 /// Force the VM to disconnect. |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
980 | 1002 |
981 // Always connected. | 1003 // Always connected. |
982 Future _onConnect; | 1004 Future _onConnect; |
983 Future get onConnect { | 1005 Future get onConnect { |
984 if (_onConnect != null) { | 1006 if (_onConnect != null) { |
985 return _onConnect; | 1007 return _onConnect; |
986 } | 1008 } |
987 _onConnect = new Future.value(this); | 1009 _onConnect = new Future.value(this); |
988 return _onConnect; | 1010 return _onConnect; |
989 } | 1011 } |
| 1012 bool get isConnected => !isDisconnected; |
990 // Only complete when requested. | 1013 // Only complete when requested. |
991 Completer _onDisconnect = new Completer(); | 1014 Completer _onDisconnect = new Completer(); |
992 Future get onDisconnect => _onDisconnect.future; | 1015 Future get onDisconnect => _onDisconnect.future; |
993 bool get isDisconnected => _onDisconnect.isCompleted; | 1016 bool get isDisconnected => _onDisconnect.isCompleted; |
994 | 1017 |
995 Future<Map> invokeRpcRaw(String method, Map params) { | 1018 Future<Map> invokeRpcRaw(String method, Map params) { |
996 if (params.isEmpty) { | 1019 if (params.isEmpty) { |
997 params = null; | 1020 params = null; |
998 } | 1021 } |
999 var key = _canonicalizeUri(new Uri(path: method, queryParameters: params)); | 1022 var key = _canonicalizeUri(new Uri(path: method, queryParameters: params)); |
(...skipping 3361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4361 var v = list[i]; | 4384 var v = list[i]; |
4362 if ((v is Map) && _isServiceMap(v)) { | 4385 if ((v is Map) && _isServiceMap(v)) { |
4363 list[i] = owner.getFromMap(v); | 4386 list[i] = owner.getFromMap(v); |
4364 } else if (v is List) { | 4387 } else if (v is List) { |
4365 _upgradeList(v, owner); | 4388 _upgradeList(v, owner); |
4366 } else if (v is Map) { | 4389 } else if (v is Map) { |
4367 _upgradeMap(v, owner); | 4390 _upgradeMap(v, owner); |
4368 } | 4391 } |
4369 } | 4392 } |
4370 } | 4393 } |
OLD | NEW |