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

Side by Side Diff: sdk/lib/io/directory_impl.dart

Issue 16813006: Make Directory.list pull-based, making it possible to pause, resume and cancel directory listing. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Make the code more Windows-friendly. Created 7 years, 6 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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 dart.io; 5 part of dart.io;
6 6
7 class _Directory implements Directory { 7 class _Directory implements Directory {
8 static const CREATE_REQUEST = 0; 8 static const CREATE_REQUEST = 0;
9 static const DELETE_REQUEST = 1; 9 static const DELETE_REQUEST = 1;
10 static const EXISTS_REQUEST = 2; 10 static const EXISTS_REQUEST = 2;
11 static const CREATE_TEMP_REQUEST = 3; 11 static const CREATE_TEMP_REQUEST = 3;
12 static const LIST_REQUEST = 4; 12 static const LIST_START_REQUEST = 4;
13 static const RENAME_REQUEST = 5; 13 static const LIST_NEXT_REQUEST = 5;
14 static const LIST_STOP_REQUEST = 6;
15 static const RENAME_REQUEST = 7;
14 16
15 _Directory(String this._path); 17 _Directory(String this._path);
16 _Directory.fromPath(Path path) : this(path.toNativePath()); 18 _Directory.fromPath(Path path) : this(path.toNativePath());
17 19
18 external static String _current(); 20 external static String _current();
19 external static _setCurrent(path); 21 external static _setCurrent(path);
20 external static _createTemp(String template); 22 external static _createTemp(String template);
21 external static int _exists(String path); 23 external static int _exists(String path);
22 external static _create(String path); 24 external static _create(String path);
23 external static _delete(String path, bool recursive); 25 external static _delete(String path, bool recursive);
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 const int LIST_DIRECTORY = 1; 246 const int LIST_DIRECTORY = 1;
245 const int LIST_LINK = 2; 247 const int LIST_LINK = 2;
246 const int LIST_ERROR = 3; 248 const int LIST_ERROR = 3;
247 const int LIST_DONE = 4; 249 const int LIST_DONE = 4;
248 250
249 const int RESPONSE_TYPE = 0; 251 const int RESPONSE_TYPE = 0;
250 const int RESPONSE_PATH = 1; 252 const int RESPONSE_PATH = 1;
251 const int RESPONSE_COMPLETE = 1; 253 const int RESPONSE_COMPLETE = 1;
252 const int RESPONSE_ERROR = 2; 254 const int RESPONSE_ERROR = 2;
253 255
254 var controller = new StreamController<FileSystemEntity>(sync: true); 256 int id;
255 257
256 List request = [ _Directory.LIST_REQUEST, path, recursive, followLinks ]; 258 Function next;
257 ReceivePort responsePort = new ReceivePort(); 259 Function close;
258 // Use a separate directory service port for each listing as 260
259 // listing operations on the same directory can run in parallel. 261 void onResume() {
260 _Directory._newServicePort().send(request, responsePort.toSendPort()); 262 if (id != null) next();
261 responsePort.receive((message, replyTo) { 263 }
262 if (message is !List || message[RESPONSE_TYPE] is !int) { 264
263 responsePort.close(); 265 bool nextRunning = false;
264 controller.addError(new DirectoryException("Internal error")); 266 bool canceled = false;
267
268 void onCancel() {
269 canceled = true;
270 // If we are active, but not requesting, close.
271 if (id != null && !nextRunning) {
272 close();
273 }
274 }
275
276 var controller = new StreamController<FileSystemEntity>(sync: true,
277 onResume: onResume,
278 onCancel: onCancel);
279
280 bool closed = false;
281 close = () {
282 if (closed) return;
283 closed = true;
284 _Directory._newServicePort().call([_Directory.LIST_STOP_REQUEST, id])
285 .then((_) {
286 controller.close();
287 });
288 };
289
290 void error(message) {
291 var errorType =
292 message[RESPONSE_ERROR][_ERROR_RESPONSE_ERROR_TYPE];
293 if (errorType == _ILLEGAL_ARGUMENT_RESPONSE) {
294 controller.addError(new ArgumentError());
295 } else if (errorType == _OSERROR_RESPONSE) {
296 var responseError = message[RESPONSE_ERROR];
297 var err = new OSError(
298 responseError[_OSERROR_RESPONSE_MESSAGE],
299 responseError[_OSERROR_RESPONSE_ERROR_CODE]);
300 var errorPath = message[RESPONSE_PATH];
301 if (errorPath == null) errorPath = path;
302 controller.addError(
303 new DirectoryException("Directory listing failed",
304 errorPath,
305 err));
306 } else {
307 controller.addError(
308 new DirectoryException("Internal error"));
309 }
310 }
311
312 next = () {
313 if (canceled) {
314 close();
265 return; 315 return;
266 } 316 }
267 switch (message[RESPONSE_TYPE]) { 317 if (nextRunning) return;
268 case LIST_FILE: 318 nextRunning = true;
269 controller.add(new File(message[RESPONSE_PATH])); 319 _Directory._newServicePort().call([_Directory.LIST_NEXT_REQUEST, id])
270 break; 320 .then((result) {
271 case LIST_DIRECTORY: 321 if (result is List) {
272 controller.add(new Directory(message[RESPONSE_PATH])); 322 for (var message in result) {
273 break; 323 if (message == null) break;
274 case LIST_LINK: 324 switch (message[RESPONSE_TYPE]) {
275 controller.add(new Link(message[RESPONSE_PATH])); 325 case LIST_FILE:
276 break; 326 controller.add(new File(message[RESPONSE_PATH]));
277 case LIST_ERROR: 327 break;
278 var errorType = 328 case LIST_DIRECTORY:
279 message[RESPONSE_ERROR][_ERROR_RESPONSE_ERROR_TYPE]; 329 controller.add(new Directory(message[RESPONSE_PATH]));
280 if (errorType == _ILLEGAL_ARGUMENT_RESPONSE) { 330 break;
281 controller.addError(new ArgumentError()); 331 case LIST_LINK:
282 } else if (errorType == _OSERROR_RESPONSE) { 332 controller.add(new Link(message[RESPONSE_PATH]));
283 var responseError = message[RESPONSE_ERROR]; 333 break;
284 var err = new OSError( 334 case LIST_ERROR:
285 responseError[_OSERROR_RESPONSE_MESSAGE], 335 error(message);
286 responseError[_OSERROR_RESPONSE_ERROR_CODE]); 336 break;
287 var errorPath = message[RESPONSE_PATH]; 337 case LIST_DONE:
288 if (errorPath == null) errorPath = path; 338 close();
289 controller.addError( 339 return;
290 new DirectoryException("Directory listing failed", 340 }
291 errorPath, 341 }
292 err)); 342 } else {
343 controller.addError(new DirectoryException("Internal error"));
344 }
345 nextRunning = false;
346 if (!controller.isPaused) {
347 next();
348 }
349 });
350 };
351
352 var request = [_Directory.LIST_START_REQUEST, path, recursive, followLinks];
353 _Directory._newServicePort().call(request)
354 .then((response) {
355 if (response is int) {
356 id = response;
357 next();
293 } else { 358 } else {
294 controller.addError(new DirectoryException("Internal error")); 359 error(response);
360 controller.close();
295 } 361 }
296 break; 362 });
297 case LIST_DONE:
298 responsePort.close();
299 controller.close();
300 break;
301 }
302 });
303 363
304 return controller.stream; 364 return controller.stream;
305 } 365 }
306 366
307 List listSync({bool recursive: false, bool followLinks: true}) { 367 List listSync({bool recursive: false, bool followLinks: true}) {
308 if (_path is! String || recursive is! bool) { 368 if (_path is! String || recursive is! bool) {
309 throw new ArgumentError(); 369 throw new ArgumentError();
310 } 370 }
311 return _list(_path, recursive, followLinks); 371 return _list(_path, recursive, followLinks);
312 } 372 }
(...skipping 22 matching lines...) Expand all
335 395
336 void _ensureDirectoryService() { 396 void _ensureDirectoryService() {
337 if (_directoryService == null) { 397 if (_directoryService == null) {
338 _directoryService = _newServicePort(); 398 _directoryService = _newServicePort();
339 } 399 }
340 } 400 }
341 401
342 final String _path; 402 final String _path;
343 SendPort _directoryService; 403 SendPort _directoryService;
344 } 404 }
OLDNEW
« runtime/bin/directory_linux.cc ('K') | « runtime/bin/directory_linux.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698