Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 library barback.graph.transform_node; | 5 library barback.graph.transform_node; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 | 8 |
| 9 import '../asset/asset.dart'; | 9 import '../asset/asset.dart'; |
| 10 import '../asset/asset_id.dart'; | 10 import '../asset/asset_id.dart'; |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 159 | 159 |
| 160 /// The controller for the currently-running [AggregateTransformer.apply] | 160 /// The controller for the currently-running [AggregateTransformer.apply] |
| 161 /// call's [AggregateTransform]. | 161 /// call's [AggregateTransform]. |
| 162 /// | 162 /// |
| 163 /// This will be non-`null` when [AggregateTransform.apply] is running, which | 163 /// This will be non-`null` when [AggregateTransform.apply] is running, which |
| 164 /// means that it's always non-`null` when [_state] is [_State.APPLYING] or | 164 /// means that it's always non-`null` when [_state] is [_State.APPLYING] or |
| 165 /// [_State.NEEDS_APPLY], sometimes non-`null` when it's | 165 /// [_State.NEEDS_APPLY], sometimes non-`null` when it's |
| 166 /// [_State.NEEDS_DECLARE], and always `null` otherwise. | 166 /// [_State.NEEDS_DECLARE], and always `null` otherwise. |
| 167 AggregateTransformController _applyController; | 167 AggregateTransformController _applyController; |
| 168 | 168 |
| 169 /// The number of secondary inputs that have been requested but not yet | |
| 170 /// produced. | |
| 171 int _pendingSecondaryInputs = 0; | |
| 172 | |
| 173 /// A stopwatch that tracks the total time spent in a transformer's `apply` | |
| 174 /// function. | |
| 175 final _timeInTransformer = new Stopwatch(); | |
| 176 | |
| 177 /// A stopwatch that tracks the time in a transformer's `apply` function spent | |
| 178 /// waiting for [getInput] calls to complete. | |
| 179 final _timeAwaitingInputs = new Stopwatch(); | |
| 180 | |
| 169 TransformNode(this.classifier, this.transformer, this.key, this._location) { | 181 TransformNode(this.classifier, this.transformer, this.key, this._location) { |
| 170 _forced = transformer is! DeclaringAggregateTransformer; | 182 _forced = transformer is! DeclaringAggregateTransformer; |
| 171 | 183 |
| 172 _phaseAssetSubscription = phase.previous.onAsset.listen((node) { | 184 _phaseAssetSubscription = phase.previous.onAsset.listen((node) { |
| 173 if (!_missingInputs.contains(node.id)) return; | 185 if (!_missingInputs.contains(node.id)) return; |
| 174 if (_forced) node.force(); | 186 if (_forced) node.force(); |
| 175 _dirty(); | 187 _dirty(); |
| 176 }); | 188 }); |
| 177 | 189 |
| 178 _phaseStatusSubscription = phase.previous.onStatusChange.listen((status) { | 190 _phaseStatusSubscription = phase.previous.onStatusChange.listen((status) { |
| (...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 541 | 553 |
| 542 _state = _State.APPLIED; | 554 _state = _State.APPLIED; |
| 543 _streams.changeStatus(NodeStatus.IDLE); | 555 _streams.changeStatus(NodeStatus.IDLE); |
| 544 }); | 556 }); |
| 545 } | 557 } |
| 546 | 558 |
| 547 /// Gets the asset for an input [id]. | 559 /// Gets the asset for an input [id]. |
| 548 /// | 560 /// |
| 549 /// If an input with [id] cannot be found, throws an [AssetNotFoundException]. | 561 /// If an input with [id] cannot be found, throws an [AssetNotFoundException]. |
| 550 Future<Asset> getInput(AssetId id) { | 562 Future<Asset> getInput(AssetId id) { |
| 563 _timeAwaitingInputs.start(); | |
| 564 _pendingSecondaryInputs++; | |
| 551 return phase.previous.getOutput(id).then((node) { | 565 return phase.previous.getOutput(id).then((node) { |
| 552 // Throw if the input isn't found. This ensures the transformer's apply | 566 // Throw if the input isn't found. This ensures the transformer's apply |
| 553 // is exited. We'll then catch this and report it through the proper | 567 // is exited. We'll then catch this and report it through the proper |
| 554 // results stream. | 568 // results stream. |
| 555 if (node == null) { | 569 if (node == null) { |
| 556 _missingInputs.add(id); | 570 _missingInputs.add(id); |
| 557 throw new AssetNotFoundException(id); | 571 throw new AssetNotFoundException(id); |
| 558 } | 572 } |
| 559 | 573 |
| 560 _secondarySubscriptions.putIfAbsent(node.id, () { | 574 _secondarySubscriptions.putIfAbsent(node.id, () { |
| 561 return node.onStateChange.listen((_) => _dirty()); | 575 return node.onStateChange.listen((_) => _dirty()); |
| 562 }); | 576 }); |
| 563 | 577 |
| 564 return node.asset; | 578 return node.asset; |
| 579 }).whenComplete(() { | |
| 580 _pendingSecondaryInputs--; | |
| 581 if (_pendingSecondaryInputs != 0) return; | |
|
Bob Nystrom
2014/07/01 17:08:35
Nit, but I think this is clearer without an early
nweiz
2014/07/01 21:57:09
Done.
| |
| 582 _timeAwaitingInputs.stop(); | |
| 565 }); | 583 }); |
| 566 } | 584 } |
| 567 | 585 |
| 568 /// Run [AggregateTransformer.apply]. | 586 /// Run [AggregateTransformer.apply]. |
| 569 /// | 587 /// |
| 570 /// Returns whether or not an error occurred while running the transformer. | 588 /// Returns whether or not an error occurred while running the transformer. |
| 571 Future<bool> _runApply() { | 589 Future<bool> _runApply() { |
| 572 var controller = new AggregateTransformController(this); | 590 var controller = new AggregateTransformController(this); |
| 573 _applyController = controller; | 591 _applyController = controller; |
| 574 _streams.onLogPool.add(controller.onLog); | 592 _streams.onLogPool.add(controller.onLog); |
| 575 for (var primary in _primaries) { | 593 for (var primary in _primaries) { |
| 576 if (!primary.state.isAvailable) continue; | 594 if (!primary.state.isAvailable) continue; |
| 577 controller.addInput(primary.asset); | 595 controller.addInput(primary.asset); |
| 578 } | 596 } |
| 579 _maybeFinishApplyController(); | 597 _maybeFinishApplyController(); |
| 580 | 598 |
| 581 return syncFuture(() { | 599 return syncFuture(() { |
| 600 _timeInTransformer.reset(); | |
| 601 _timeAwaitingInputs.reset(); | |
| 602 _timeInTransformer.start(); | |
| 582 return transformer.apply(controller.transform); | 603 return transformer.apply(controller.transform); |
| 583 }).whenComplete(() { | 604 }).whenComplete(() { |
| 605 _timeInTransformer.stop(); | |
| 606 _timeAwaitingInputs.stop(); | |
| 607 | |
| 584 // Cancel the controller here even if `apply` wasn't interrupted. Since | 608 // Cancel the controller here even if `apply` wasn't interrupted. Since |
| 585 // the apply is finished, we want to close out the controller's streams. | 609 // the apply is finished, we want to close out the controller's streams. |
| 586 controller.cancel(); | 610 controller.cancel(); |
| 587 _applyController = null; | 611 _applyController = null; |
| 588 }).then((_) { | 612 }).then((_) { |
| 589 assert(_state != _State.DECLARED); | 613 assert(_state != _State.DECLARED); |
| 590 assert(_state != _State.DECLARING); | 614 assert(_state != _State.DECLARING); |
| 591 assert(_state != _State.APPLIED); | 615 assert(_state != _State.APPLIED); |
| 592 | 616 |
| 593 if (!_forced && _primaries.any((node) => !node.state.isAvailable)) { | 617 if (!_forced && _primaries.any((node) => !node.state.isAvailable)) { |
| 594 _state = _State.DECLARED; | 618 _state = _State.DECLARED; |
| 595 _streams.changeStatus(NodeStatus.IDLE); | 619 _streams.changeStatus(NodeStatus.IDLE); |
| 596 return false; | 620 return false; |
| 597 } | 621 } |
| 598 | 622 |
| 599 if (_isRemoved) return false; | 623 if (_isRemoved) return false; |
| 600 if (_state == _State.NEEDS_APPLY) return false; | 624 if (_state == _State.NEEDS_APPLY) return false; |
| 601 if (_state == _State.NEEDS_DECLARE) return false; | 625 if (_state == _State.NEEDS_DECLARE) return false; |
| 602 if (controller.loggedError) return true; | 626 if (controller.loggedError) return true; |
| 627 | |
| 628 // If the transformer took long enough, log its duration in fine output. | |
| 629 // That way it's not always visible, but users running with "pub serve | |
| 630 // --verbose" can see it. | |
|
Bob Nystrom
2014/07/01 17:08:36
Since it's at FINE anyway, how about either always
nweiz
2014/07/01 21:57:09
I added an additional check that compares the tota
| |
| 631 if (_timeInTransformer.elapsed > new Duration(seconds: 1)) { | |
| 632 _streams.onLogController.add(new LogEntry( | |
| 633 info, info.primaryId, LogLevel.FINE, | |
| 634 "Took ${niceDuration(_timeInTransformer.elapsed)} " | |
|
Bob Nystrom
2014/07/01 17:08:36
Maybe clarify that it was apply() that was timed?
nweiz
2014/07/01 21:57:08
I think it's clear that that's what's going on.
| |
| 635 "(${niceDuration(_timeAwaitingInputs.elapsed)} awaiting secondary " | |
|
Bob Nystrom
2014/07/01 17:08:35
Long line.
nweiz
2014/07/01 21:57:08
Done.
| |
| 636 "inputs).", | |
| 637 null)); | |
| 638 } | |
| 639 | |
| 603 _handleApplyResults(controller); | 640 _handleApplyResults(controller); |
| 604 return false; | 641 return false; |
| 605 }).catchError((error, stackTrace) { | 642 }).catchError((error, stackTrace) { |
| 606 // If the transform became dirty while processing, ignore any errors from | 643 // If the transform became dirty while processing, ignore any errors from |
| 607 // it. | 644 // it. |
| 608 if (_state == _State.NEEDS_APPLY || _isRemoved) return false; | 645 if (_state == _State.NEEDS_APPLY || _isRemoved) return false; |
| 609 | 646 |
| 610 // Catch all transformer errors and pipe them to the results stream. This | 647 // Catch all transformer errors and pipe them to the results stream. This |
| 611 // is so a broken transformer doesn't take down the whole graph. | 648 // is so a broken transformer doesn't take down the whole graph. |
| 612 phase.cascade.reportError(_wrapException(error, stackTrace)); | 649 phase.cascade.reportError(_wrapException(error, stackTrace)); |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 796 /// declaring and [APPLYING] otherwise. If a primary input is added or | 833 /// declaring and [APPLYING] otherwise. If a primary input is added or |
| 797 /// removed, this will transition to [DECLARING]. | 834 /// removed, this will transition to [DECLARING]. |
| 798 static const APPLIED = const _State._("applied"); | 835 static const APPLIED = const _State._("applied"); |
| 799 | 836 |
| 800 final String name; | 837 final String name; |
| 801 | 838 |
| 802 const _State._(this.name); | 839 const _State._(this.name); |
| 803 | 840 |
| 804 String toString() => name; | 841 String toString() => name; |
| 805 } | 842 } |
| OLD | NEW |