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

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: Add test and review fixes. 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() {
Søren Gjesse 2013/06/17 06:37:47 Consider checking nextRunning here and asserting f
Anders Johnsen 2013/06/17 07:27:11 Done.
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 = () {
Søren Gjesse 2013/06/17 06:37:47 Annoying to have to define some local functions li
Anders Johnsen 2013/06/17 07:27:11 Done.
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 assert(result.length % 2 == 0);
273 break; 323 for (int i = 0; i < result.length; i++) {
274 case LIST_LINK: 324 assert(i % 2 == 0);
275 controller.add(new Link(message[RESPONSE_PATH])); 325 switch (result[i++]) {
276 break; 326 case LIST_FILE:
277 case LIST_ERROR: 327 controller.add(new File(result[i]));
278 var errorType = 328 break;
279 message[RESPONSE_ERROR][_ERROR_RESPONSE_ERROR_TYPE]; 329 case LIST_DIRECTORY:
280 if (errorType == _ILLEGAL_ARGUMENT_RESPONSE) { 330 controller.add(new Directory(result[i]));
281 controller.addError(new ArgumentError()); 331 break;
282 } else if (errorType == _OSERROR_RESPONSE) { 332 case LIST_LINK:
283 var responseError = message[RESPONSE_ERROR]; 333 controller.add(new Link(result[i]));
284 var err = new OSError( 334 break;
285 responseError[_OSERROR_RESPONSE_MESSAGE], 335 case LIST_ERROR:
286 responseError[_OSERROR_RESPONSE_ERROR_CODE]); 336 error(result[i]);
287 var errorPath = message[RESPONSE_PATH]; 337 break;
288 if (errorPath == null) errorPath = path; 338 case LIST_DONE:
289 controller.addError( 339 close();
290 new DirectoryException("Directory listing failed", 340 return;
291 errorPath, 341 }
292 err)); 342 }
343 } else {
344 controller.addError(new DirectoryException("Internal error"));
345 }
346 nextRunning = false;
347 if (!controller.isPaused) {
348 next();
349 }
350 });
351 };
352
353 var request = [_Directory.LIST_START_REQUEST, path, recursive, followLinks];
354 _Directory._newServicePort().call(request)
355 .then((response) {
356 if (response is int) {
357 id = response;
358 next();
293 } else { 359 } else {
294 controller.addError(new DirectoryException("Internal error")); 360 error(response);
361 controller.close();
295 } 362 }
296 break; 363 });
297 case LIST_DONE:
298 responsePort.close();
299 controller.close();
300 break;
301 }
302 });
303 364
304 return controller.stream; 365 return controller.stream;
305 } 366 }
306 367
307 List listSync({bool recursive: false, bool followLinks: true}) { 368 List listSync({bool recursive: false, bool followLinks: true}) {
308 if (_path is! String || recursive is! bool) { 369 if (_path is! String || recursive is! bool) {
309 throw new ArgumentError(); 370 throw new ArgumentError();
310 } 371 }
311 return _list(_path, recursive, followLinks); 372 return _list(_path, recursive, followLinks);
312 } 373 }
(...skipping 22 matching lines...) Expand all
335 396
336 void _ensureDirectoryService() { 397 void _ensureDirectoryService() {
337 if (_directoryService == null) { 398 if (_directoryService == null) {
338 _directoryService = _newServicePort(); 399 _directoryService = _newServicePort();
339 } 400 }
340 } 401 }
341 402
342 final String _path; 403 final String _path;
343 SendPort _directoryService; 404 SendPort _directoryService;
344 } 405 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698