| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | |
| 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. | |
| 4 | |
| 5 part of dart.io; | |
| 6 | |
| 7 abstract class _IOResourceInfo { | |
| 8 final String type; | |
| 9 final int id; | |
| 10 String get name; | |
| 11 static int _count = 0; | |
| 12 | |
| 13 static final Stopwatch _sw = new Stopwatch()..start(); | |
| 14 static final _startTime = new DateTime.now().millisecondsSinceEpoch; | |
| 15 | |
| 16 static double get timestamp => _startTime + _sw.elapsedMicroseconds/1000; | |
| 17 | |
| 18 _IOResourceInfo(this.type) : id = _IOResourceInfo.getNextID(); | |
| 19 | |
| 20 /// Get the full set of values for a specific implementation. This is normally | |
| 21 /// looked up based on an id from a referenceValueMap. | |
| 22 Map<String, String> get fullValueMap; | |
| 23 | |
| 24 /// The reference map, used to return a list of values, e.g., getting | |
| 25 /// all open sockets. The structure of this is shared among all subclasses. | |
| 26 Map<String, String> get referenceValueMap => | |
| 27 { | |
| 28 // The type for a reference object is prefixed with @ in observatory. | |
| 29 'type': '@$type', | |
| 30 'id': id, | |
| 31 'name': name, | |
| 32 }; | |
| 33 | |
| 34 static int getNextID() => _count++; | |
| 35 } | |
| 36 | |
| 37 abstract class _ReadWriteResourceInfo extends _IOResourceInfo { | |
| 38 int totalRead; | |
| 39 int totalWritten; | |
| 40 int readCount; | |
| 41 int writeCount; | |
| 42 double lastRead; | |
| 43 double lastWrite; | |
| 44 | |
| 45 // Not all call sites use this. In some cases, e.g., a socket, a read does | |
| 46 // not always mean that we actually read some bytes (we may do a read to see | |
| 47 // if there are some bytes available). | |
| 48 void addRead(int bytes) { | |
| 49 totalRead += bytes; | |
| 50 readCount++; | |
| 51 lastRead = _IOResourceInfo.timestamp; | |
| 52 } | |
| 53 | |
| 54 // In cases where we read but did not neccesarily get any bytes, use this to | |
| 55 // update the readCount and timestamp. Manually update totalRead if any bytes | |
| 56 // where acutally read. | |
| 57 void didRead() { addRead(0); } | |
| 58 | |
| 59 void addWrite(int bytes) { | |
| 60 totalWritten += bytes; | |
| 61 writeCount++; | |
| 62 lastWrite = _IOResourceInfo.timestamp; | |
| 63 } | |
| 64 | |
| 65 _ReadWriteResourceInfo(String type) : | |
| 66 totalRead = 0, | |
| 67 totalWritten = 0, | |
| 68 readCount = 0, | |
| 69 writeCount = 0, | |
| 70 lastRead = 0.0, | |
| 71 lastWrite = 0.0, | |
| 72 super(type); | |
| 73 | |
| 74 Map<String, String> get fullValueMap => | |
| 75 { | |
| 76 'type': type, | |
| 77 'id': id, | |
| 78 'name': name, | |
| 79 'totalRead': totalRead, | |
| 80 'totalWritten': totalWritten, | |
| 81 'readCount': readCount, | |
| 82 'writeCount': writeCount, | |
| 83 'lastRead': lastRead, | |
| 84 'lastWrite': lastWrite | |
| 85 }; | |
| 86 } | |
| 87 | |
| 88 class _FileResourceInfo extends _ReadWriteResourceInfo { | |
| 89 static const String TYPE = '_file'; | |
| 90 | |
| 91 final file; | |
| 92 | |
| 93 static Map<int, _FileResourceInfo> openFiles = | |
| 94 new Map<int, _FileResourceInfo>(); | |
| 95 | |
| 96 _FileResourceInfo(this.file) : super(TYPE) { | |
| 97 FileOpened(this); | |
| 98 } | |
| 99 | |
| 100 static FileOpened(_FileResourceInfo info) { | |
| 101 assert(!openFiles.containsKey(info.id)); | |
| 102 openFiles[info.id] = info; | |
| 103 } | |
| 104 | |
| 105 static FileClosed(_FileResourceInfo info) { | |
| 106 assert(openFiles.containsKey(info.id)); | |
| 107 openFiles.remove(info.id); | |
| 108 } | |
| 109 | |
| 110 static Iterable<Map<String, String>> getOpenFilesList() { | |
| 111 return new List.from(openFiles.values.map((e) => e.referenceValueMap)); | |
| 112 } | |
| 113 | |
| 114 static Future<ServiceExtensionResponse> getOpenFiles(function, params) { | |
| 115 assert(function == 'ext.dart.io.getOpenFiles'); | |
| 116 var data = {'type': '_openfiles', 'data': getOpenFilesList()}; | |
| 117 var json = JSON.encode(data); | |
| 118 return new Future.value(new ServiceExtensionResponse.result(json)); | |
| 119 } | |
| 120 | |
| 121 Map<String, String> getFileInfoMap() { | |
| 122 var result = fullValueMap; | |
| 123 return result; | |
| 124 } | |
| 125 | |
| 126 static Future<ServiceExtensionResponse> getFileInfoMapByID(function, params) { | |
| 127 assert(params.containsKey('id')); | |
| 128 var id = int.parse(params['id']); | |
| 129 var result = | |
| 130 openFiles.containsKey(id) ? openFiles[id].getFileInfoMap() : {}; | |
| 131 var json = JSON.encode(result); | |
| 132 return new Future.value(new ServiceExtensionResponse.result(json)); | |
| 133 } | |
| 134 | |
| 135 String get name { | |
| 136 return '${file.path}'; | |
| 137 } | |
| 138 } | |
| 139 | |
| 140 class _ProcessResourceInfo extends _IOResourceInfo{ | |
| 141 static const String TYPE = '_process'; | |
| 142 final process; | |
| 143 final double startedAt; | |
| 144 | |
| 145 static Map<int, _ProcessResourceInfo> startedProcesses = | |
| 146 new Map<int, _ProcessResourceInfo>(); | |
| 147 | |
| 148 _ProcessResourceInfo(this.process) : | |
| 149 startedAt = _IOResourceInfo.timestamp, | |
| 150 super(TYPE) { | |
| 151 ProcessStarted(this); | |
| 152 } | |
| 153 | |
| 154 String get name => process._path; | |
| 155 | |
| 156 void stopped() { ProcessStopped(this); } | |
| 157 | |
| 158 Map<String, String> get fullValueMap => | |
| 159 { | |
| 160 'type': type, | |
| 161 'id': id, | |
| 162 'name': name, | |
| 163 'pid': process.pid, | |
| 164 'startedAt': startedAt, | |
| 165 'arguments': process._arguments, | |
| 166 'workingDirectory': | |
| 167 process._workingDirectory == null ? '.' : process._workingDirectory, | |
| 168 }; | |
| 169 | |
| 170 static ProcessStarted(_ProcessResourceInfo info) { | |
| 171 assert(!startedProcesses.containsKey(info.id)); | |
| 172 startedProcesses[info.id] = info; | |
| 173 } | |
| 174 | |
| 175 static ProcessStopped(_ProcessResourceInfo info) { | |
| 176 assert(startedProcesses.containsKey(info.id)); | |
| 177 startedProcesses.remove(info.id); | |
| 178 } | |
| 179 | |
| 180 static Iterable<Map<String, String>> getStartedProcessesList() => | |
| 181 new List.from(startedProcesses.values.map((e) => e.referenceValueMap)); | |
| 182 | |
| 183 static Future<ServiceExtensionResponse> getStartedProcesses( | |
| 184 String function, Map<String, String> params) { | |
| 185 assert(function == 'ext.dart.io.getProcesses'); | |
| 186 var data = {'type': '_startedprocesses', 'data': getStartedProcessesList()}; | |
| 187 var json = JSON.encode(data); | |
| 188 return new Future.value(new ServiceExtensionResponse.result(json)); | |
| 189 } | |
| 190 | |
| 191 static Future<ServiceExtensionResponse> getProcessInfoMapById( | |
| 192 String function, Map<String, String> params) { | |
| 193 var id = int.parse(params['id']); | |
| 194 var result = startedProcesses.containsKey(id) | |
| 195 ? startedProcesses[id].fullValueMap | |
| 196 : {}; | |
| 197 var json = JSON.encode(result); | |
| 198 return new Future.value(new ServiceExtensionResponse.result(json)); | |
| 199 } | |
| 200 } | |
| 201 | |
| 202 class _SocketResourceInfo extends _ReadWriteResourceInfo { | |
| 203 static const String TCP_STRING = 'TCP'; | |
| 204 static const String UDP_STRING = 'UDP'; | |
| 205 static const String TYPE = '_socket'; | |
| 206 | |
| 207 final socket; | |
| 208 | |
| 209 static Map<int, _SocketResourceInfo> openSockets = | |
| 210 new Map<int, _SocketResourceInfo>(); | |
| 211 | |
| 212 _SocketResourceInfo(this.socket) : super(TYPE) { | |
| 213 SocketOpened(this); | |
| 214 } | |
| 215 | |
| 216 String get name { | |
| 217 if (socket.isListening) { | |
| 218 return 'listening:${socket.address.host}:${socket.port}'; | |
| 219 } | |
| 220 var remote = ''; | |
| 221 try { | |
| 222 var remoteHost = socket.remoteAddress.host; | |
| 223 var remotePort = socket.remotePort; | |
| 224 remote = ' -> $remoteHost:$remotePort'; | |
| 225 } catch (e) { } // ignored if we can't get the information | |
| 226 return '${socket.address.host}:${socket.port}$remote'; | |
| 227 } | |
| 228 | |
| 229 static Iterable<Map<String, String>> getOpenSocketsList() { | |
| 230 return new List.from(openSockets.values.map((e) => e.referenceValueMap)); | |
| 231 } | |
| 232 | |
| 233 Map<String, String> getSocketInfoMap() { | |
| 234 var result = fullValueMap; | |
| 235 result['socketType'] = socket.isTcp ? TCP_STRING : UDP_STRING; | |
| 236 result['listening'] = socket.isListening; | |
| 237 result['host'] = socket.address.host; | |
| 238 result['port'] = socket.port; | |
| 239 if (!socket.isListening) { | |
| 240 try { | |
| 241 result['remoteHost'] = socket.remoteAddress.host; | |
| 242 result['remotePort'] = socket.remotePort; | |
| 243 } catch (e) { | |
| 244 // UDP. | |
| 245 result['remotePort'] = 'NA'; | |
| 246 result['remoteHost'] = 'NA'; | |
| 247 } | |
| 248 } else { | |
| 249 result['remotePort'] = 'NA'; | |
| 250 result['remoteHost'] = 'NA'; | |
| 251 } | |
| 252 result['addressType'] = socket.address.type.name; | |
| 253 return result; | |
| 254 } | |
| 255 | |
| 256 static Future<ServiceExtensionResponse> getSocketInfoMapByID( | |
| 257 String function, Map<String, String> params) { | |
| 258 assert(params.containsKey('id')); | |
| 259 var id = int.parse(params['id']); | |
| 260 var result = | |
| 261 openSockets.containsKey(id) ? openSockets[id].getSocketInfoMap() : {}; | |
| 262 var json = JSON.encode(result); | |
| 263 return new Future.value(new ServiceExtensionResponse.result(json)); | |
| 264 } | |
| 265 | |
| 266 static Future<ServiceExtensionResponse> getOpenSockets(function, params) { | |
| 267 assert(function == 'ext.dart.io.getOpenSockets'); | |
| 268 var data = {'type': '_opensockets', 'data': getOpenSocketsList()}; | |
| 269 var json = JSON.encode(data); | |
| 270 return new Future.value(new ServiceExtensionResponse.result(json)); | |
| 271 } | |
| 272 | |
| 273 static SocketOpened(_SocketResourceInfo info) { | |
| 274 assert(!openSockets.containsKey(info.id)); | |
| 275 openSockets[info.id] = info; | |
| 276 } | |
| 277 | |
| 278 static SocketClosed(_SocketResourceInfo info) { | |
| 279 assert(openSockets.containsKey(info.id)); | |
| 280 openSockets.remove(info.id); | |
| 281 } | |
| 282 | |
| 283 } | |
| OLD | NEW |