When invalidate because of the ERROR state, propagate its exception.

I have to move invalidation implementation into CacheEntry, because we need to set the "exception" field value.
Should we also move "setDependedOnResults" and make ResultData a dumb data container?

R=brianwilkerson@google.com
BUG=

Review URL: https://codereview.chromium.org//1126793004

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@45608 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
scheglov@google.com 2015-05-07 19:10:27 +00:00
parent 965ac274f6
commit 11f96844dc
2 changed files with 76 additions and 86 deletions

View file

@ -345,9 +345,7 @@ class CacheEntry {
}
this._exception = exception;
for (ResultDescriptor descriptor in descriptors) {
ResultData data = _getResultData(descriptor);
TargetedResult thisResult = new TargetedResult(_target, descriptor);
data.invalidate(_partition, thisResult, CacheState.ERROR);
_invalidate(descriptor, exception);
}
}
@ -366,8 +364,7 @@ class CacheEntry {
if (state == CacheState.INVALID) {
ResultData data = _resultMap[descriptor];
if (data != null) {
TargetedResult thisResult = new TargetedResult(_target, descriptor);
data.invalidate(_partition, thisResult, CacheState.INVALID);
_invalidate(descriptor, null);
}
} else {
ResultData data = _getResultData(descriptor);
@ -394,9 +391,9 @@ class CacheEntry {
if (_partition != null) {
_partition.resultStored(thisResult, value);
}
_invalidate(descriptor, null);
ResultData data = _getResultData(descriptor);
data.invalidate(_partition, thisResult, CacheState.INVALID);
data.setDependedOnResults(_partition, thisResult, dependedOn);
_setDependedOnResults(data, thisResult, dependedOn);
data.state = CacheState.VALID;
data.value = value == null ? descriptor.defaultValue : value;
data.memento = memento;
@ -422,6 +419,49 @@ class CacheEntry {
return _resultMap.putIfAbsent(descriptor, () => new ResultData(descriptor));
}
/**
* Invalidate the result represented by the given [descriptor].
* Propagate invalidation to other results that depend on it.
*/
void _invalidate(ResultDescriptor descriptor, CaughtException exception) {
ResultData thisData = _getResultData(descriptor);
// Invalidate this result.
if (exception == null) {
thisData.state = CacheState.INVALID;
} else {
thisData.state = CacheState.ERROR;
_exception = exception;
}
thisData.value = descriptor.defaultValue;
// Stop depending on other results.
TargetedResult thisResult = new TargetedResult(_target, descriptor);
List<TargetedResult> dependedOnResults = thisData.dependedOnResults;
thisData.dependedOnResults = <TargetedResult>[];
dependedOnResults.forEach((TargetedResult dependedOnResult) {
ResultData data = _partition._getDataFor(dependedOnResult);
data.dependentResults.remove(thisResult);
});
// Invalidate results that depend on this result.
List<TargetedResult> dependentResults = thisData.dependentResults;
thisData.dependentResults = <TargetedResult>[];
dependentResults.forEach((TargetedResult dependentResult) {
CacheEntry entry = _partition.get(dependentResult.target);
entry._invalidate(dependentResult.result, exception);
});
}
/**
* Set the [dependedOn] on which this result depends.
*/
void _setDependedOnResults(ResultData thisData, TargetedResult thisResult,
List<TargetedResult> dependedOn) {
thisData.dependedOnResults = dependedOn;
thisData.dependedOnResults.forEach((TargetedResult dependentResult) {
ResultData data = _partition._getDataFor(dependentResult);
data.dependentResults.add(thisResult);
});
}
/**
* Set the value of the flag with the given [index] to the given [value].
*/
@ -784,13 +824,6 @@ class ResultData {
value = descriptor.defaultValue;
}
/**
* Add the given [result] to the list of dependent results.
*/
void addDependentResult(TargetedResult result) {
dependentResults.add(result);
}
/**
* Flush this value.
*/
@ -798,54 +831,6 @@ class ResultData {
state = CacheState.FLUSHED;
value = descriptor.defaultValue;
}
/**
* Invalidate this [ResultData] that corresponds to [thisResult] and
* propagate invalidation to the results that depend on this one.
*/
void invalidate(CachePartition partition, TargetedResult thisResult,
CacheState newState) {
// Invalidate this result.
state = newState;
value = descriptor.defaultValue;
// Stop depending on other results.
List<TargetedResult> dependedOnResults = this.dependedOnResults;
this.dependedOnResults = <TargetedResult>[];
dependedOnResults.forEach((TargetedResult dependedOnResult) {
ResultData data = partition._getDataFor(dependedOnResult);
data.removeDependentResult(thisResult);
});
// Invalidate results that depend on this result.
List<TargetedResult> dependentResults = this.dependentResults;
this.dependentResults = <TargetedResult>[];
dependentResults.forEach((TargetedResult dependentResult) {
ResultData data = partition._getDataFor(dependentResult);
data.invalidate(partition, dependentResult, newState);
});
}
/**
* Remove the given [result] from the list of dependent results.
*/
void removeDependentResult(TargetedResult result) {
dependentResults.remove(result);
}
/**
* Set the [dependedOn] on which this result depends.
*/
void setDependedOnResults(CachePartition partition, TargetedResult thisResult,
List<TargetedResult> dependedOn) {
dependedOnResults.forEach((TargetedResult dependedOnResult) {
ResultData data = partition._getDataFor(dependedOnResult);
data.removeDependentResult(thisResult);
});
dependedOnResults = dependedOn;
dependedOnResults.forEach((TargetedResult dependentResult) {
ResultData data = partition._getDataFor(dependentResult);
data.addDependentResult(thisResult);
});
}
}
/**

View file

@ -242,38 +242,43 @@ class CacheEntryTest extends EngineTestCase {
}
test_setErrorState_invalidateDependent() {
AnalysisTarget target = new TestSource();
CacheEntry entry = new CacheEntry();
cache.put(target, entry);
AnalysisTarget target1 = new TestSource('/a.dart');
AnalysisTarget target2 = new TestSource('/b.dart');
CacheEntry entry1 = new CacheEntry();
CacheEntry entry2 = new CacheEntry();
cache.put(target1, entry1);
cache.put(target2, entry2);
ResultDescriptor result1 = new ResultDescriptor('result1', -1);
ResultDescriptor result2 = new ResultDescriptor('result2', -2);
ResultDescriptor result3 = new ResultDescriptor('result3', -3);
ResultDescriptor result4 = new ResultDescriptor('result4', -4);
// set results, all of them are VALID
entry.setValue(result1, 111, TargetedResult.EMPTY_LIST, null);
entry.setValue(result2, 222, [new TargetedResult(target, result1)], null);
entry.setValue(result3, 333, [new TargetedResult(target, result2)], null);
entry.setValue(result4, 444, [], null);
expect(entry.getState(result1), CacheState.VALID);
expect(entry.getState(result2), CacheState.VALID);
expect(entry.getState(result3), CacheState.VALID);
expect(entry.getState(result4), CacheState.VALID);
expect(entry.getValue(result1), 111);
expect(entry.getValue(result2), 222);
expect(entry.getValue(result3), 333);
expect(entry.getValue(result4), 444);
entry1.setValue(result1, 111, TargetedResult.EMPTY_LIST, null);
entry2.setValue(result2, 222, [new TargetedResult(target1, result1)], null);
entry2.setValue(result3, 333, [new TargetedResult(target2, result2)], null);
entry2.setValue(result4, 444, [], null);
expect(entry1.getState(result1), CacheState.VALID);
expect(entry2.getState(result2), CacheState.VALID);
expect(entry2.getState(result3), CacheState.VALID);
expect(entry2.getState(result4), CacheState.VALID);
expect(entry1.getValue(result1), 111);
expect(entry2.getValue(result2), 222);
expect(entry2.getValue(result3), 333);
expect(entry2.getValue(result4), 444);
// set error state
CaughtException exception = new CaughtException(null, null);
entry.setErrorState(exception, <ResultDescriptor>[result1]);
entry1.setErrorState(exception, <ResultDescriptor>[result1]);
// result2 and result3 are invalidated, result4 is intact
expect(entry.getState(result1), CacheState.ERROR);
expect(entry.getState(result2), CacheState.ERROR);
expect(entry.getState(result3), CacheState.ERROR);
expect(entry.getState(result4), CacheState.VALID);
expect(entry.getValue(result1), -1);
expect(entry.getValue(result2), -2);
expect(entry.getValue(result3), -3);
expect(entry.getValue(result4), 444);
expect(entry1.getState(result1), CacheState.ERROR);
expect(entry2.getState(result2), CacheState.ERROR);
expect(entry2.getState(result3), CacheState.ERROR);
expect(entry2.getState(result4), CacheState.VALID);
expect(entry1.getValue(result1), -1);
expect(entry2.getValue(result2), -2);
expect(entry2.getValue(result3), -3);
expect(entry2.getValue(result4), 444);
expect(entry1.exception, exception);
expect(entry2.exception, exception);
}
test_setErrorState_noDescriptors() {