| Index: runtime/bin/directory_impl.dart
|
| diff --git a/runtime/bin/directory_impl.dart b/runtime/bin/directory_impl.dart
|
| index f455d7477f7beb72cedfd0842b459fe2d9396659..d5a9953b38fb08b9cf9bb3633e1c41d30cfcdd5a 100644
|
| --- a/runtime/bin/directory_impl.dart
|
| +++ b/runtime/bin/directory_impl.dart
|
| @@ -10,167 +10,30 @@ class _OSStatus {
|
| }
|
|
|
|
|
| -class _DirectoryListingIsolate extends Isolate {
|
| -
|
| - _DirectoryListingIsolate() : super.heavy();
|
| -
|
| - void main() {
|
| - port.receive((message, replyTo) {
|
| - bool started = _list(message['dir'],
|
| - message['recursive'],
|
| - message['dirPort'],
|
| - message['filePort'],
|
| - message['donePort'],
|
| - message['errorPort']);
|
| - replyTo.send(started);
|
| - port.close();
|
| - });
|
| - }
|
| -
|
| - bool _list(String dir,
|
| - bool recursive,
|
| - SendPort dirPort,
|
| - SendPort filePort,
|
| - SendPort donePort,
|
| - SendPort errorPort) native "Directory_List";
|
| -}
|
| -
|
| -
|
| -class _DirectoryOperation {
|
| - abstract void execute(ReceivePort port);
|
| -
|
| - void set replyPort(SendPort port) {
|
| - _replyPort = port;
|
| - }
|
| -
|
| - SendPort _replyPort;
|
| -}
|
| -
|
| -
|
| -class _DirExitOperation extends _DirectoryOperation {
|
| - void execute(ReceivePort port) {
|
| - port.close();
|
| - }
|
| -}
|
| -
|
| -
|
| -class _DirExistsOperation extends _DirectoryOperation {
|
| - _DirExistsOperation(String this._path);
|
| -
|
| - void execute(ReceivePort port) {
|
| - _replyPort.send(_Directory._exists(_path), port.toSendPort());
|
| - }
|
| -
|
| - String _path;
|
| -}
|
| -
|
| -
|
| -class _DirCreateOperation extends _DirectoryOperation {
|
| - _DirCreateOperation(String this._path);
|
| -
|
| - void execute(ReceivePort port) {
|
| - _replyPort.send(_Directory._create(_path), port.toSendPort());
|
| - }
|
| -
|
| - String _path;
|
| -}
|
| -
|
| -
|
| -class _DirCreateTempOperation extends _DirectoryOperation {
|
| - _DirCreateTempOperation(String this._path);
|
| -
|
| - void execute(ReceivePort port) {
|
| - var status = new _OSStatus();
|
| - var result = _Directory._createTemp(_path, status);
|
| - if (result == null) {
|
| - _replyPort.send(status, port.toSendPort());
|
| - } else {
|
| - _replyPort.send(result, port.toSendPort());
|
| - }
|
| - }
|
| -
|
| - String _path;
|
| -}
|
| -
|
| -
|
| -class _DirDeleteOperation extends _DirectoryOperation {
|
| - _DirDeleteOperation(String this._path, bool this._recursive);
|
| -
|
| - void execute(ReceivePort port) {
|
| - _replyPort.send(_Directory._delete(_path, _recursive), port.toSendPort());
|
| - }
|
| -
|
| - String _path;
|
| - bool _recursive;
|
| -}
|
| -
|
| -
|
| -class _DirectoryOperationIsolate extends Isolate {
|
| - _DirectoryOperationIsolate() : super.heavy();
|
| -
|
| - void handleOperation(_DirectoryOperation message, SendPort ignored) {
|
| - message.execute(port);
|
| - port.receive(handleOperation);
|
| - }
|
| -
|
| - void main() {
|
| - port.receive(handleOperation);
|
| - }
|
| -}
|
| -
|
| -
|
| -class _DirectoryOperationScheduler {
|
| - _DirectoryOperationScheduler() : _queue = new Queue();
|
| -
|
| - void schedule(SendPort port) {
|
| - assert(_isolate != null);
|
| - if (_queue.isEmpty()) {
|
| - port.send(new _DirExitOperation());
|
| - _isolate = null;
|
| - } else {
|
| - port.send(_queue.removeFirst());
|
| - }
|
| - }
|
| -
|
| - void scheduleWrap(void callback(result, ignored)) {
|
| - return (result, replyTo) {
|
| - callback(result, replyTo);
|
| - schedule(replyTo);
|
| - };
|
| - }
|
| -
|
| - void enqueue(_DirectoryOperation operation, void callback(result, ignored)) {
|
| - ReceivePort replyPort = new ReceivePort.singleShot();
|
| - replyPort.receive(scheduleWrap(callback));
|
| - operation.replyPort = replyPort.toSendPort();
|
| - _queue.addLast(operation);
|
| - if (_isolate == null) {
|
| - _isolate = new _DirectoryOperationIsolate();
|
| - _isolate.spawn().then((port) {
|
| - schedule(port);
|
| - });
|
| - }
|
| - }
|
| -
|
| - Queue<_DirectoryOperation> _queue;
|
| - _DirectoryOperationIsolate _isolate;
|
| -}
|
| -
|
| -
|
| class _Directory implements Directory {
|
| + static final kCreateRequest = 0;
|
| + static final kDeleteRequest = 1;
|
| + static final kExistsRequest = 2;
|
| + static final kCreateTempRequest = 3;
|
| + static final kListRequest = 4;
|
|
|
| - _Directory(String this._path)
|
| - : _scheduler = new _DirectoryOperationScheduler();
|
| + _Directory(String this._path);
|
|
|
| static String _createTemp(String template,
|
| _OSStatus status) native "Directory_CreateTemp";
|
| static int _exists(String path) native "Directory_Exists";
|
| static bool _create(String path) native "Directory_Create";
|
| static bool _delete(String path, bool recursive) native "Directory_Delete";
|
| + static SendPort _newServicePort() native "Directory_NewServicePort";
|
|
|
| void exists() {
|
| - var operation = new _DirExistsOperation(_path);
|
| - _scheduler.enqueue(operation, (result, ignored) {
|
| + if (_directoryService == null) {
|
| + _directoryService = _newServicePort();
|
| + }
|
| + List request = new List(2);
|
| + request[0] = kExistsRequest;
|
| + request[1] = _path;
|
| + _directoryService.call(request).receive((result, replyTo) {
|
| var handler =
|
| (_existsHandler != null) ? _existsHandler : (result) => null;
|
| if (result < 0) {
|
| @@ -192,11 +55,15 @@ class _Directory implements Directory {
|
| }
|
|
|
| void create() {
|
| - var operation = new _DirCreateOperation(_path);
|
| - _scheduler.enqueue(operation, (result, ignored) {
|
| - var handler = (_createHandler != null) ? _createHandler : () => null;
|
| + if (_directoryService == null) {
|
| + _directoryService = _newServicePort();
|
| + }
|
| + List request = new List(2);
|
| + request[0] = kCreateRequest;
|
| + request[1] = _path;
|
| + _directoryService.call(request).receive((result, replyTo) {
|
| if (result) {
|
| - handler();
|
| + if (_createHandler != null) _createHandler();
|
| } else if (_errorHandler != null) {
|
| _errorHandler("Directory creation failed: $_path");
|
| }
|
| @@ -210,16 +77,19 @@ class _Directory implements Directory {
|
| }
|
|
|
| void createTemp() {
|
| - var operation = new _DirCreateTempOperation(_path);
|
| - _scheduler.enqueue(operation, (result, ignored) {
|
| - var handler =
|
| - (_createTempHandler != null) ? _createTempHandler : () => null;
|
| - if (result is !_OSStatus) {
|
| + if (_directoryService == null) {
|
| + _directoryService = _newServicePort();
|
| + }
|
| + List request = new List(2);
|
| + request[0] = kCreateTempRequest;
|
| + request[1] = _path;
|
| + _directoryService.call(request).receive((result, replyTo) {
|
| + if (result is !List) {
|
| _path = result;
|
| - handler();
|
| - } else if (_errorHandler !== null) {
|
| + if (_createTempHandler != null) _createTempHandler();
|
| + } else if (_errorHandler != null) {
|
| _errorHandler("Could not create temporary directory [$_path]: " +
|
| - "${result._errorMessage}");
|
| + "${result[1]}");
|
| }
|
| });
|
| }
|
| @@ -238,11 +108,16 @@ class _Directory implements Directory {
|
| }
|
|
|
| void delete([bool recursive = false]) {
|
| - var operation = new _DirDeleteOperation(_path, recursive);
|
| - _scheduler.enqueue(operation, (result, ignored) {
|
| - var handler = (_deleteHandler != null) ? _deleteHandler : () => null;
|
| + if (_directoryService == null) {
|
| + _directoryService = _newServicePort();
|
| + }
|
| + List request = new List(3);
|
| + request[0] = kDeleteRequest;
|
| + request[1] = _path;
|
| + request[2] = recursive;
|
| + _directoryService.call(request).receive((result, replyTo) {
|
| if (result) {
|
| - handler();
|
| + if (_deleteHandler != null) _deleteHandler();
|
| } else if (_errorHandler != null) {
|
| if (recursive) {
|
| _errorHandler("Recursive directory deletion failed: $_path");
|
| @@ -260,66 +135,40 @@ class _Directory implements Directory {
|
| }
|
|
|
| void list([bool recursive = false]) {
|
| - new _DirectoryListingIsolate().spawn().then((port) {
|
| - // Build a map of parameters to the directory listing isolate.
|
| - Map listingParameters = new Map();
|
| - listingParameters['dir'] = _path;
|
| - listingParameters['recursive'] = recursive;
|
| -
|
| - // Setup ports to receive messages from listing.
|
| - // TODO(ager): Do not explicitly transform to send ports when
|
| - // implicit conversions are implemented.
|
| - ReceivePort dirPort;
|
| - ReceivePort filePort;
|
| - ReceivePort donePort;
|
| - ReceivePort errorPort;
|
| - if (_dirHandler !== null) {
|
| - dirPort = new ReceivePort();
|
| - dirPort.receive((String dir, ignored) {
|
| - _dirHandler(dir);
|
| - });
|
| - listingParameters['dirPort'] = dirPort.toSendPort();
|
| - }
|
| - if (_fileHandler !== null) {
|
| - filePort = new ReceivePort();
|
| - filePort.receive((String file, ignored) {
|
| - _fileHandler(file);
|
| - });
|
| - listingParameters['filePort'] = filePort.toSendPort();
|
| + final int kListDirectory = 0;
|
| + final int kListFile = 1;
|
| + final int kListError = 2;
|
| + final int kListDone = 3;
|
| +
|
| + List request = new List(3);
|
| + request[0] = kListRequest;
|
| + request[1] = _path;
|
| + request[2] = recursive;
|
| + ReceivePort responsePort = new ReceivePort();
|
| + // Use a separate directory service port for each listing as
|
| + // listing operations on the same directory can run in parallel.
|
| + _newServicePort().send(request, responsePort.toSendPort());
|
| + responsePort.receive((message, replyTo) {
|
| + if (message is !List || message[0] is !int) {
|
| + responsePort.close();
|
| + if (_errorHandler != null) _errorHandler("Internal error");
|
| + return;
|
| }
|
| - if (_doneHandler !== null) {
|
| - donePort = new ReceivePort.singleShot();
|
| - donePort.receive((bool completed, ignored) {
|
| - _doneHandler(completed);
|
| - });
|
| - listingParameters['donePort'] = donePort.toSendPort();
|
| + switch (message[0]) {
|
| + case kListDirectory:
|
| + if (_dirHandler != null) _dirHandler(message[1]);
|
| + break;
|
| + case kListFile:
|
| + if (_fileHandler != null) _fileHandler(message[1]);
|
| + break;
|
| + case kListError:
|
| + if (_errorHandler != null) _errorHandler(message[1]);
|
| + break;
|
| + case kListDone:
|
| + responsePort.close();
|
| + if (_doneHandler != null) _doneHandler(message[1]);
|
| + break;
|
| }
|
| - if (_errorHandler !== null) {
|
| - errorPort = new ReceivePort.singleShot();
|
| - errorPort.receive((String error, ignored) {
|
| - _errorHandler(error);
|
| - });
|
| - listingParameters['errorPort'] = errorPort.toSendPort();
|
| - }
|
| -
|
| - // Close ports when listing is done.
|
| - ReceivePort closePortsPort = new ReceivePort();
|
| - closePortsPort.receive((message, replyTo) {
|
| - if (!message) {
|
| - errorPort.toSendPort().send(
|
| - "Failed to list directory: $_path recursive: $recursive");
|
| - donePort.toSendPort().send(false);
|
| - } else {
|
| - _closePort(errorPort);
|
| - _closePort(donePort);
|
| - }
|
| - _closePort(dirPort);
|
| - _closePort(filePort);
|
| - _closePort(closePortsPort);
|
| - });
|
| -
|
| - // Send the listing parameters to the isolate.
|
| - port.send(listingParameters, closePortsPort.toSendPort());
|
| });
|
| }
|
|
|
| @@ -373,5 +222,5 @@ class _Directory implements Directory {
|
| var _errorHandler;
|
|
|
| String _path;
|
| - _DirectoryOperationScheduler _scheduler;
|
| + SendPort _directoryService;
|
| }
|
|
|