| 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 'package:async/async.dart'; | 9 import 'package:async/async.dart'; |
| 10 | 10 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 | 61 |
| 62 /// The subscription to [phase]'s [Phase.onStatusChange] stream. | 62 /// The subscription to [phase]'s [Phase.onStatusChange] stream. |
| 63 StreamSubscription<NodeStatus> _phaseStatusSubscription; | 63 StreamSubscription<NodeStatus> _phaseStatusSubscription; |
| 64 | 64 |
| 65 /// How far along [this] is in processing its assets. | 65 /// How far along [this] is in processing its assets. |
| 66 NodeStatus get status { | 66 NodeStatus get status { |
| 67 if (_state == _State.APPLIED || _state == _State.DECLARED) { | 67 if (_state == _State.APPLIED || _state == _State.DECLARED) { |
| 68 return NodeStatus.IDLE; | 68 return NodeStatus.IDLE; |
| 69 } | 69 } |
| 70 | 70 |
| 71 if (_declaring && _state != _State.DECLARING && | 71 if (_declaring && |
| 72 _state != _State.DECLARING && |
| 72 _state != _State.NEEDS_DECLARE) { | 73 _state != _State.NEEDS_DECLARE) { |
| 73 return NodeStatus.MATERIALIZING; | 74 return NodeStatus.MATERIALIZING; |
| 74 } else { | 75 } else { |
| 75 return NodeStatus.RUNNING; | 76 return NodeStatus.RUNNING; |
| 76 } | 77 } |
| 77 } | 78 } |
| 78 | 79 |
| 79 /// The [TransformInfo] describing this node. | 80 /// The [TransformInfo] describing this node. |
| 80 /// | 81 /// |
| 81 /// [TransformInfo] is the publicly-visible representation of a transform | 82 /// [TransformInfo] is the publicly-visible representation of a transform |
| 82 /// node. | 83 /// node. |
| 83 TransformInfo get info => new TransformInfo(transformer, | 84 TransformInfo get info => |
| 84 new AssetId(phase.cascade.package, key)); | 85 new TransformInfo(transformer, new AssetId(phase.cascade.package, key)); |
| 85 | 86 |
| 86 /// Whether this is a declaring transform. | 87 /// Whether this is a declaring transform. |
| 87 /// | 88 /// |
| 88 /// This is usually identical to `transformer is | 89 /// This is usually identical to `transformer is |
| 89 /// DeclaringAggregateTransformer`, but if a declaring and non-lazy | 90 /// DeclaringAggregateTransformer`, but if a declaring and non-lazy |
| 90 /// transformer emits an error during `declareOutputs` it's treated as though | 91 /// transformer emits an error during `declareOutputs` it's treated as though |
| 91 /// it wasn't declaring. | 92 /// it wasn't declaring. |
| 92 bool get _declaring => transformer is DeclaringAggregateTransformer && | 93 bool get _declaring => |
| 94 transformer is DeclaringAggregateTransformer && |
| 93 (_state == _State.DECLARING || _declaredOutputs != null); | 95 (_state == _State.DECLARING || _declaredOutputs != null); |
| 94 | 96 |
| 95 /// Whether this transform has been forced since it last finished applying. | 97 /// Whether this transform has been forced since it last finished applying. |
| 96 /// | 98 /// |
| 97 /// A transform being forced means it should run until it generates outputs | 99 /// A transform being forced means it should run until it generates outputs |
| 98 /// and is no longer dirty. This is always true for non-declaring | 100 /// and is no longer dirty. This is always true for non-declaring |
| 99 /// transformers, since they always need to eagerly generate outputs. | 101 /// transformers, since they always need to eagerly generate outputs. |
| 100 bool _forced; | 102 bool _forced; |
| 101 | 103 |
| 102 /// The subscriptions to each secondary input's [AssetNode.onStateChange] | 104 /// The subscriptions to each secondary input's [AssetNode.onStateChange] |
| (...skipping 30 matching lines...) Expand all Loading... |
| 133 /// The current state of [this]. | 135 /// The current state of [this]. |
| 134 var _state = _State.DECLARED; | 136 var _state = _State.DECLARED; |
| 135 | 137 |
| 136 /// Whether [this] has been marked as removed. | 138 /// Whether [this] has been marked as removed. |
| 137 bool get _isRemoved => _streams.onAssetController.isClosed; | 139 bool get _isRemoved => _streams.onAssetController.isClosed; |
| 138 | 140 |
| 139 // If [transformer] is declaring but not lazy and [primary] is available, we | 141 // If [transformer] is declaring but not lazy and [primary] is available, we |
| 140 // can run [apply] even if [force] hasn't been called, since [transformer] | 142 // can run [apply] even if [force] hasn't been called, since [transformer] |
| 141 // should run eagerly if possible. | 143 // should run eagerly if possible. |
| 142 bool get _canRunDeclaringEagerly => | 144 bool get _canRunDeclaringEagerly => |
| 143 _declaring && transformer is! LazyAggregateTransformer && | 145 _declaring && |
| 146 transformer is! LazyAggregateTransformer && |
| 144 _primaries.every((input) => input.state.isAvailable); | 147 _primaries.every((input) => input.state.isAvailable); |
| 145 | 148 |
| 146 /// Which primary inputs the most recent run of this transform has declared | 149 /// Which primary inputs the most recent run of this transform has declared |
| 147 /// that it consumes. | 150 /// that it consumes. |
| 148 /// | 151 /// |
| 149 /// This starts out `null`, indicating that the transform hasn't declared | 152 /// This starts out `null`, indicating that the transform hasn't declared |
| 150 /// anything yet. This is not meaningful unless [_state] is [_State.APPLIED] | 153 /// anything yet. This is not meaningful unless [_state] is [_State.APPLIED] |
| 151 /// or [_State.DECLARED]. | 154 /// or [_State.DECLARED]. |
| 152 Set<AssetId> _consumedPrimaries; | 155 Set<AssetId> _consumedPrimaries; |
| 153 | 156 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 213 }); | 216 }); |
| 214 | 217 |
| 215 _run(); | 218 _run(); |
| 216 } | 219 } |
| 217 | 220 |
| 218 /// Adds [input] as a primary input for this node. | 221 /// Adds [input] as a primary input for this node. |
| 219 void addPrimary(AssetNode input) { | 222 void addPrimary(AssetNode input) { |
| 220 _primaries.add(input); | 223 _primaries.add(input); |
| 221 if (_forced) input.force(); | 224 if (_forced) input.force(); |
| 222 | 225 |
| 223 _primarySubscriptions[input.id] = input.onStateChange | 226 _primarySubscriptions[input.id] = |
| 224 .listen((_) => _onPrimaryStateChange(input)); | 227 input.onStateChange.listen((_) => _onPrimaryStateChange(input)); |
| 225 | 228 |
| 226 if (_state == _State.DECLARING && !_declareController.isDone) { | 229 if (_state == _State.DECLARING && !_declareController.isDone) { |
| 227 // If we're running `declareOutputs` and its id stream isn't closed yet, | 230 // If we're running `declareOutputs` and its id stream isn't closed yet, |
| 228 // pass this in as another id. | 231 // pass this in as another id. |
| 229 _declareController.addId(input.id); | 232 _declareController.addId(input.id); |
| 230 _maybeFinishDeclareController(); | 233 _maybeFinishDeclareController(); |
| 231 } else if (_state == _State.APPLYING) { | 234 } else if (_state == _State.APPLYING) { |
| 232 // If we're running `apply`, we need to wait until [input] is available | 235 // If we're running `apply`, we need to wait until [input] is available |
| 233 // before we pass it into the stream. If it's available now, great; if | 236 // before we pass it into the stream. If it's available now, great; if |
| 234 // not, [_onPrimaryStateChange] will handle it. | 237 // not, [_onPrimaryStateChange] will handle it. |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 285 if (_state == _State.DECLARED) _apply(); | 288 if (_state == _State.DECLARED) _apply(); |
| 286 } | 289 } |
| 287 | 290 |
| 288 /// Marks this transform as dirty. | 291 /// Marks this transform as dirty. |
| 289 /// | 292 /// |
| 290 /// Specifically, this should be called when one of the transform's inputs' | 293 /// Specifically, this should be called when one of the transform's inputs' |
| 291 /// contents change, or when a secondary input is removed. Primary inputs | 294 /// contents change, or when a secondary input is removed. Primary inputs |
| 292 /// being added or removed are handled by [addInput] and | 295 /// being added or removed are handled by [addInput] and |
| 293 /// [_onPrimaryStateChange]. | 296 /// [_onPrimaryStateChange]. |
| 294 void _dirty() { | 297 void _dirty() { |
| 295 if (_state == _State.DECLARING || _state == _State.NEEDS_DECLARE || | 298 if (_state == _State.DECLARING || |
| 299 _state == _State.NEEDS_DECLARE || |
| 296 _state == _State.NEEDS_APPLY) { | 300 _state == _State.NEEDS_APPLY) { |
| 297 // If we already know that [_apply] needs to be run, there's nothing to do | 301 // If we already know that [_apply] needs to be run, there's nothing to do |
| 298 // here. | 302 // here. |
| 299 return; | 303 return; |
| 300 } | 304 } |
| 301 | 305 |
| 302 if (!_forced && !_canRunDeclaringEagerly) { | 306 if (!_forced && !_canRunDeclaringEagerly) { |
| 303 // [forced] should only ever be false for a declaring transformer. | 307 // [forced] should only ever be false for a declaring transformer. |
| 304 assert(_declaring); | 308 assert(_declaring); |
| 305 | 309 |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 370 // pass it to the stream. | 374 // pass it to the stream. |
| 371 _applyController.addInput(input.asset); | 375 _applyController.addInput(input.asset); |
| 372 _maybeFinishApplyController(); | 376 _maybeFinishApplyController(); |
| 373 } | 377 } |
| 374 } else { | 378 } else { |
| 375 if (_forced) input.force(); | 379 if (_forced) input.force(); |
| 376 | 380 |
| 377 var controller = _passThroughControllers[input.id]; | 381 var controller = _passThroughControllers[input.id]; |
| 378 if (controller != null) controller.setDirty(); | 382 if (controller != null) controller.setDirty(); |
| 379 | 383 |
| 380 if (_state == _State.APPLYING && !_applyController.addedId(input.id) && | 384 if (_state == _State.APPLYING && |
| 385 !_applyController.addedId(input.id) && |
| 381 (_forced || !input.isLazy)) { | 386 (_forced || !input.isLazy)) { |
| 382 // If the input hasn't yet been added to the transform's input stream, | 387 // If the input hasn't yet been added to the transform's input stream, |
| 383 // there's no need to consider the transformation dirty. However, if the | 388 // there's no need to consider the transformation dirty. However, if the |
| 384 // input is lazy and we're running eagerly, we need to restart the | 389 // input is lazy and we're running eagerly, we need to restart the |
| 385 // transformation. | 390 // transformation. |
| 386 return; | 391 return; |
| 387 } | 392 } |
| 388 _dirty(); | 393 _dirty(); |
| 389 } | 394 } |
| 390 } | 395 } |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 465 // If `declareOutputs` fails, fall back to treating a declaring | 470 // If `declareOutputs` fails, fall back to treating a declaring |
| 466 // transformer as though it were eager. | 471 // transformer as though it were eager. |
| 467 if (transformer is! LazyAggregateTransformer) _forced = true; | 472 if (transformer is! LazyAggregateTransformer) _forced = true; |
| 468 callback(); | 473 callback(); |
| 469 return; | 474 return; |
| 470 } | 475 } |
| 471 | 476 |
| 472 _consumedPrimaries = controller.consumedPrimaries; | 477 _consumedPrimaries = controller.consumedPrimaries; |
| 473 _declaredOutputs = controller.outputIds; | 478 _declaredOutputs = controller.outputIds; |
| 474 var invalidIds = _declaredOutputs | 479 var invalidIds = _declaredOutputs |
| 475 .where((id) => id.package != phase.cascade.package).toSet(); | 480 .where((id) => id.package != phase.cascade.package) |
| 481 .toSet(); |
| 476 for (var id in invalidIds) { | 482 for (var id in invalidIds) { |
| 477 _declaredOutputs.remove(id); | 483 _declaredOutputs.remove(id); |
| 478 // TODO(nweiz): report this as a warning rather than a failing error. | 484 // TODO(nweiz): report this as a warning rather than a failing error. |
| 479 phase.cascade.reportError(new InvalidOutputException(info, id)); | 485 phase.cascade.reportError(new InvalidOutputException(info, id)); |
| 480 } | 486 } |
| 481 | 487 |
| 482 for (var primary in _primaries) { | 488 for (var primary in _primaries) { |
| 483 if (_declaredOutputs.contains(primary.id)) continue; | 489 if (_declaredOutputs.contains(primary.id)) continue; |
| 484 _passThrough(primary.id); | 490 _passThrough(primary.id); |
| 485 } | 491 } |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 656 return; | 662 return; |
| 657 } | 663 } |
| 658 | 664 |
| 659 var message = new StringBuffer("Not yet complete after " | 665 var message = new StringBuffer("Not yet complete after " |
| 660 "${niceDuration(_timeInTransformer.elapsed)}"); | 666 "${niceDuration(_timeInTransformer.elapsed)}"); |
| 661 if (_pendingSecondaryInputs.isNotEmpty) { | 667 if (_pendingSecondaryInputs.isNotEmpty) { |
| 662 message.write(", waiting on input(s) " | 668 message.write(", waiting on input(s) " |
| 663 "${_pendingSecondaryInputs.keys.join(", ")}"); | 669 "${_pendingSecondaryInputs.keys.join(", ")}"); |
| 664 } | 670 } |
| 665 _streams.onLogController.add(new LogEntry( | 671 _streams.onLogController.add(new LogEntry( |
| 666 info, | 672 info, info.primaryId, LogLevel.FINE, message.toString(), null)); |
| 667 info.primaryId, | |
| 668 LogLevel.FINE, | |
| 669 message.toString(), | |
| 670 null)); | |
| 671 }); | 673 }); |
| 672 | 674 |
| 673 return transformer.apply(controller.transform); | 675 return transformer.apply(controller.transform); |
| 674 }).whenComplete(() { | 676 }).whenComplete(() { |
| 675 transformCounterTimer.cancel(); | 677 transformCounterTimer.cancel(); |
| 676 _timeInTransformer.stop(); | 678 _timeInTransformer.stop(); |
| 677 _timeAwaitingInputs.stop(); | 679 _timeAwaitingInputs.stop(); |
| 678 | 680 |
| 679 // Cancel the controller here even if `apply` wasn't interrupted. Since | 681 // Cancel the controller here even if `apply` wasn't interrupted. Since |
| 680 // the apply is finished, we want to close out the controller's streams. | 682 // the apply is finished, we want to close out the controller's streams. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 695 if (_state == _State.NEEDS_APPLY) return false; | 697 if (_state == _State.NEEDS_APPLY) return false; |
| 696 if (_state == _State.NEEDS_DECLARE) return false; | 698 if (_state == _State.NEEDS_DECLARE) return false; |
| 697 if (controller.loggedError) return true; | 699 if (controller.loggedError) return true; |
| 698 | 700 |
| 699 // If the transformer took long enough, log its duration in fine output. | 701 // If the transformer took long enough, log its duration in fine output. |
| 700 // That way it's not always visible, but users running with "pub serve | 702 // That way it's not always visible, but users running with "pub serve |
| 701 // --verbose" can see it. | 703 // --verbose" can see it. |
| 702 var ranLong = _timeInTransformer.elapsed > new Duration(seconds: 1); | 704 var ranLong = _timeInTransformer.elapsed > new Duration(seconds: 1); |
| 703 var ranLongLocally = | 705 var ranLongLocally = |
| 704 _timeInTransformer.elapsed - _timeAwaitingInputs.elapsed > | 706 _timeInTransformer.elapsed - _timeAwaitingInputs.elapsed > |
| 705 new Duration(milliseconds: 200); | 707 new Duration(milliseconds: 200); |
| 706 | 708 |
| 707 // Report the transformer's timing information if it spent more than 0.2s | 709 // Report the transformer's timing information if it spent more than 0.2s |
| 708 // doing things other than waiting for its secondary inputs or if it spent | 710 // doing things other than waiting for its secondary inputs or if it spent |
| 709 // more than 1s in total. | 711 // more than 1s in total. |
| 710 if (ranLongLocally || ranLong) { | 712 if (ranLongLocally || ranLong) { |
| 711 _streams.onLogController.add(new LogEntry( | 713 _streams.onLogController.add(new LogEntry( |
| 712 info, info.primaryId, LogLevel.FINE, | 714 info, |
| 715 info.primaryId, |
| 716 LogLevel.FINE, |
| 713 "Took ${niceDuration(_timeInTransformer.elapsed)} " | 717 "Took ${niceDuration(_timeInTransformer.elapsed)} " |
| 714 "(${niceDuration(_timeAwaitingInputs.elapsed)} awaiting " | 718 "(${niceDuration(_timeAwaitingInputs.elapsed)} awaiting " |
| 715 "secondary inputs).", | 719 "secondary inputs).", |
| 716 null)); | 720 null)); |
| 717 } | 721 } |
| 718 | 722 |
| 719 _handleApplyResults(controller); | 723 _handleApplyResults(controller); |
| 720 return false; | 724 return false; |
| 721 }).catchError((error, stackTrace) { | 725 }).catchError((error, stackTrace) { |
| 722 // If the transform became dirty while processing, ignore any errors from | 726 // If the transform became dirty while processing, ignore any errors from |
| 723 // it. | 727 // it. |
| 724 if (_state == _State.NEEDS_APPLY || _isRemoved) return false; | 728 if (_state == _State.NEEDS_APPLY || _isRemoved) return false; |
| 725 | 729 |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 916 /// declaring and [APPLYING] otherwise. If a primary input is added or | 920 /// declaring and [APPLYING] otherwise. If a primary input is added or |
| 917 /// removed, this will transition to [DECLARING]. | 921 /// removed, this will transition to [DECLARING]. |
| 918 static const APPLIED = const _State._("applied"); | 922 static const APPLIED = const _State._("applied"); |
| 919 | 923 |
| 920 final String name; | 924 final String name; |
| 921 | 925 |
| 922 const _State._(this.name); | 926 const _State._(this.name); |
| 923 | 927 |
| 924 String toString() => name; | 928 String toString() => name; |
| 925 } | 929 } |
| OLD | NEW |