Skip to content

Commit 553649b

Browse files
revert changes for "ResultsCache ignores some of the BuildRequest data,.." (dotnet#9718)
1 parent afcd4bc commit 553649b

File tree

5 files changed

+31
-201
lines changed

5 files changed

+31
-201
lines changed

documentation/wiki/ChangeWaves.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ A wave of features is set to "rotate out" (i.e. become standard functionality) t
3232
- [Change Version switch output to finish with a newline](https://github.com/dotnet/msbuild/pull/9485)
3333
- [Load Microsoft.DotNet.MSBuildSdkResolver into default load context (MSBuild.exe only)](https://github.com/dotnet/msbuild/pull/9439)
3434
- [Load NuGet.Frameworks into secondary AppDomain (MSBuild.exe only)](https://github.com/dotnet/msbuild/pull/9446)
35-
- [ResultsCache ignores some of the BuildRequest data, may return incorrect results](https://github.com/dotnet/msbuild/pull/9565)
3635
- [Update Traits when environment has been changed](https://github.com/dotnet/msbuild/pull/9655)
3736

3837

src/Build.UnitTests/BackEnd/ResultsCache_Tests.cs

Lines changed: 0 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -188,127 +188,6 @@ public void TestRetrieveSubsetTargetsFromResult()
188188
Assert.Equal(BuildResultCode.Success, response.Results.OverallResult);
189189
}
190190

191-
[Fact]
192-
public void TestCacheOnDifferentBuildFlagsPerRequest_ProvideProjectStateAfterBuild()
193-
{
194-
string targetName = "testTarget1";
195-
int submissionId = 1;
196-
int nodeRequestId = 0;
197-
int configurationId = 1;
198-
199-
BuildRequest requestWithNoBuildDataFlags = new BuildRequest(
200-
submissionId,
201-
nodeRequestId,
202-
configurationId,
203-
new string[1] { targetName } /* escapedTargets */,
204-
null /* hostServices */,
205-
BuildEventContext.Invalid /* parentBuildEventContext */,
206-
null /* parentRequest */,
207-
BuildRequestDataFlags.None);
208-
209-
BuildRequest requestWithProjectStateFlag = new BuildRequest(
210-
submissionId,
211-
nodeRequestId,
212-
configurationId,
213-
new string[1] { targetName } /* escapedTargets */,
214-
null /* hostServices */,
215-
BuildEventContext.Invalid /* parentBuildEventContext */,
216-
null /* parentRequest */,
217-
BuildRequestDataFlags.ProvideProjectStateAfterBuild);
218-
219-
BuildRequest requestWithNoBuildDataFlags2 = new BuildRequest(
220-
submissionId,
221-
nodeRequestId,
222-
configurationId,
223-
new string[1] { targetName } /* escapedTargets */,
224-
null /* hostServices */,
225-
BuildEventContext.Invalid /* parentBuildEventContext */,
226-
null /* parentRequest */,
227-
BuildRequestDataFlags.None);
228-
229-
BuildResult resultForRequestWithNoBuildDataFlags = new(requestWithNoBuildDataFlags);
230-
resultForRequestWithNoBuildDataFlags.AddResultsForTarget(targetName, BuildResultUtilities.GetEmptySucceedingTargetResult());
231-
ResultsCache cache = new();
232-
cache.AddResult(resultForRequestWithNoBuildDataFlags);
233-
234-
ResultsCacheResponse cacheResponseForRequestWithNoBuildDataFlags = cache.SatisfyRequest(
235-
requestWithNoBuildDataFlags,
236-
new List<string>(),
237-
new List<string>(new string[] { targetName }),
238-
skippedResultsDoNotCauseCacheMiss: false);
239-
240-
ResultsCacheResponse cachedResponseForProjectState = cache.SatisfyRequest(
241-
requestWithProjectStateFlag,
242-
new List<string>(),
243-
new List<string>(new string[] { targetName }),
244-
skippedResultsDoNotCauseCacheMiss: false);
245-
246-
ResultsCacheResponse cacheResponseForNoBuildDataFlags2 = cache.SatisfyRequest(
247-
requestWithNoBuildDataFlags2,
248-
new List<string>(),
249-
new List<string>(new string[] { targetName }),
250-
skippedResultsDoNotCauseCacheMiss: false);
251-
252-
Assert.Equal(ResultsCacheResponseType.Satisfied, cacheResponseForRequestWithNoBuildDataFlags.Type);
253-
254-
// Because ProvideProjectStateAfterBuildFlag was provided as a part of BuildRequest
255-
Assert.Equal(ResultsCacheResponseType.NotSatisfied, cachedResponseForProjectState.Type);
256-
257-
Assert.Equal(ResultsCacheResponseType.Satisfied, cacheResponseForNoBuildDataFlags2.Type);
258-
}
259-
260-
[Fact]
261-
public void TestCacheOnDifferentBuildFlagsPerRequest_ProvideSubsetOfStateAfterBuild()
262-
{
263-
string targetName = "testTarget1";
264-
int submissionId = 1;
265-
int nodeRequestId = 0;
266-
int configurationId = 1;
267-
268-
BuildRequest requestWithSubsetFlag1 = new BuildRequest(
269-
submissionId,
270-
nodeRequestId,
271-
configurationId,
272-
new string[1] { targetName } /* escapedTargets */,
273-
null /* hostServices */,
274-
BuildEventContext.Invalid /* parentBuildEventContext */,
275-
null /* parentRequest */,
276-
BuildRequestDataFlags.ProvideSubsetOfStateAfterBuild);
277-
278-
BuildRequest requestWithSubsetFlag2 = new BuildRequest(
279-
submissionId,
280-
nodeRequestId,
281-
configurationId,
282-
new string[1] { targetName } /* escapedTargets */,
283-
null /* hostServices */,
284-
BuildEventContext.Invalid /* parentBuildEventContext */,
285-
null /* parentRequest */,
286-
BuildRequestDataFlags.ProvideSubsetOfStateAfterBuild);
287-
288-
BuildResult resultForRequestWithSubsetFlag1 = new(requestWithSubsetFlag1);
289-
resultForRequestWithSubsetFlag1.AddResultsForTarget(targetName, BuildResultUtilities.GetEmptySucceedingTargetResult());
290-
ResultsCache cache = new();
291-
cache.AddResult(resultForRequestWithSubsetFlag1);
292-
293-
ResultsCacheResponse cachedResponseWithSubsetFlag1 = cache.SatisfyRequest(
294-
requestWithSubsetFlag1,
295-
new List<string>(),
296-
new List<string>(new string[] { targetName }),
297-
skippedResultsDoNotCauseCacheMiss: false);
298-
299-
ResultsCacheResponse cachedResponseWithSubsetFlag2 = cache.SatisfyRequest(
300-
requestWithSubsetFlag2,
301-
new List<string>(),
302-
new List<string>(new string[] { targetName }),
303-
skippedResultsDoNotCauseCacheMiss: false);
304-
305-
// It was agreed not to return cache results if ProvideSubsetOfStateAfterBuild is passed,
306-
// because RequestedProjectState may have different user filters defined.
307-
// It is more reliable to ignore the cached value.
308-
Assert.Equal(ResultsCacheResponseType.NotSatisfied, cachedResponseWithSubsetFlag1.Type);
309-
Assert.Equal(ResultsCacheResponseType.NotSatisfied, cachedResponseWithSubsetFlag2.Type);
310-
}
311-
312191
[Fact]
313192
public void TestClearResultsCache()
314193
{

src/Build/BackEnd/Components/Caching/ResultsCache.cs

Lines changed: 31 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,6 @@ namespace Microsoft.Build.BackEnd
1818
/// </summary>
1919
internal class ResultsCache : IResultsCache
2020
{
21-
/// <summary>
22-
/// The presence of any of these flags affects build result for the specified request.
23-
/// </summary>
24-
private const BuildRequestDataFlags FlagsAffectingBuildResults =
25-
BuildRequestDataFlags.ProvideProjectStateAfterBuild
26-
| BuildRequestDataFlags.SkipNonexistentTargets
27-
| BuildRequestDataFlags.IgnoreMissingEmptyAndInvalidImports
28-
| BuildRequestDataFlags.FailOnUnresolvedSdk;
29-
3021
/// <summary>
3122
/// The table of all build results. This table is indexed by configuration id and
3223
/// contains BuildResult objects which have all of the target information.
@@ -149,11 +140,10 @@ public BuildResult GetResultsForConfiguration(int configurationId)
149140

150141
/// <summary>
151142
/// Attempts to satisfy the request from the cache. The request can be satisfied only if:
152-
/// 1. The passed BuildRequestDataFlags can not affect the result data.
153-
/// 2. All specified targets in the request have successful results in the cache or if the sequence of target results
143+
/// 1. All specified targets in the request have successful results in the cache or if the sequence of target results
154144
/// includes 0 or more successful targets followed by at least one failed target.
155-
/// 3. All initial targets in the configuration for the request have non-skipped results in the cache.
156-
/// 4. If there are no specified targets, then all default targets in the request must have non-skipped results
145+
/// 2. All initial targets in the configuration for the request have non-skipped results in the cache.
146+
/// 3. If there are no specified targets, then all default targets in the request must have non-skipped results
157147
/// in the cache.
158148
/// </summary>
159149
/// <param name="request">The request whose results we should return.</param>
@@ -173,53 +163,47 @@ public ResultsCacheResponse SatisfyRequest(BuildRequest request, List<string> co
173163
{
174164
if (_resultsByConfiguration.TryGetValue(request.ConfigurationId, out BuildResult allResults))
175165
{
176-
bool buildDataFlagsSatisfied = ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_10)
177-
? CheckBuildDataFlagsResults(request.BuildRequestDataFlags, allResults.BuildRequestDataFlags) : true;
166+
// Check for targets explicitly specified.
167+
bool explicitTargetsSatisfied = CheckResults(allResults, request.Targets, response.ExplicitTargetsToBuild, skippedResultsDoNotCauseCacheMiss);
178168

179-
if (buildDataFlagsSatisfied)
169+
if (explicitTargetsSatisfied)
180170
{
181-
// Check for targets explicitly specified.
182-
bool explicitTargetsSatisfied = CheckResults(allResults, request.Targets, response.ExplicitTargetsToBuild, skippedResultsDoNotCauseCacheMiss);
171+
// All of the explicit targets, if any, have been satisfied
172+
response.Type = ResultsCacheResponseType.Satisfied;
183173

184-
if (explicitTargetsSatisfied)
174+
// Check for the initial targets. If we don't know what the initial targets are, we assume they are not satisfied.
175+
if (configInitialTargets == null || !CheckResults(allResults, configInitialTargets, null, skippedResultsDoNotCauseCacheMiss))
185176
{
186-
// All of the explicit targets, if any, have been satisfied
187-
response.Type = ResultsCacheResponseType.Satisfied;
177+
response.Type = ResultsCacheResponseType.NotSatisfied;
178+
}
188179

189-
// Check for the initial targets. If we don't know what the initial targets are, we assume they are not satisfied.
190-
if (configInitialTargets == null || !CheckResults(allResults, configInitialTargets, null, skippedResultsDoNotCauseCacheMiss))
180+
// We could still be missing implicit targets, so check those...
181+
if (request.Targets.Count == 0)
182+
{
183+
// Check for the default target, if necessary. If we don't know what the default targets are, we
184+
// assume they are not satisfied.
185+
if (configDefaultTargets == null || !CheckResults(allResults, configDefaultTargets, null, skippedResultsDoNotCauseCacheMiss))
191186
{
192187
response.Type = ResultsCacheResponseType.NotSatisfied;
193188
}
189+
}
194190

195-
// We could still be missing implicit targets, so check those...
196-
if (request.Targets.Count == 0)
191+
// Now report those results requested, if they are satisfied.
192+
if (response.Type == ResultsCacheResponseType.Satisfied)
193+
{
194+
List<string> targetsToAddResultsFor = new List<string>(configInitialTargets);
195+
196+
// Now report either the explicit targets or the default targets
197+
if (request.Targets.Count > 0)
197198
{
198-
// Check for the default target, if necessary. If we don't know what the default targets are, we
199-
// assume they are not satisfied.
200-
if (configDefaultTargets == null || !CheckResults(allResults, configDefaultTargets, null, skippedResultsDoNotCauseCacheMiss))
201-
{
202-
response.Type = ResultsCacheResponseType.NotSatisfied;
203-
}
199+
targetsToAddResultsFor.AddRange(request.Targets);
204200
}
205-
206-
// Now report those results requested, if they are satisfied.
207-
if (response.Type == ResultsCacheResponseType.Satisfied)
201+
else
208202
{
209-
List<string> targetsToAddResultsFor = new List<string>(configInitialTargets);
210-
211-
// Now report either the explicit targets or the default targets
212-
if (request.Targets.Count > 0)
213-
{
214-
targetsToAddResultsFor.AddRange(request.Targets);
215-
}
216-
else
217-
{
218-
targetsToAddResultsFor.AddRange(configDefaultTargets);
219-
}
220-
221-
response.Results = new BuildResult(request, allResults, targetsToAddResultsFor.ToArray(), null);
203+
targetsToAddResultsFor.AddRange(configDefaultTargets);
222204
}
205+
206+
response.Results = new BuildResult(request, allResults, targetsToAddResultsFor.ToArray(), null);
223207
}
224208
}
225209
}
@@ -344,20 +328,6 @@ private static bool CheckResults(BuildResult result, List<string> targets, HashS
344328
return returnValue;
345329
}
346330

347-
/// <summary>
348-
/// Checks results for the specified build flags.
349-
/// </summary>
350-
/// <param name="buildRequestDataFlags">The current request build flags.</param>
351-
/// <param name="buildResultDataFlags">The existing build result data flags.</param>
352-
/// <returns>False if there is any difference in the data flags that can cause missed build data, true otherwise.</returns>
353-
private static bool CheckBuildDataFlagsResults(BuildRequestDataFlags buildRequestDataFlags, BuildRequestDataFlags buildResultDataFlags) =>
354-
355-
// Even if both buildRequestDataFlags and buildResultDataFlags have ProvideSubsetOfStateAfterBuild flag,
356-
// the underlying RequestedProjectState may have different user filters defined.
357-
// It is more reliable to ignore the cached value.
358-
!buildRequestDataFlags.HasFlag(BuildRequestDataFlags.ProvideSubsetOfStateAfterBuild)
359-
&& (buildRequestDataFlags & FlagsAffectingBuildResults) == (buildResultDataFlags & FlagsAffectingBuildResults);
360-
361331
public IEnumerator<BuildResult> GetEnumerator()
362332
{
363333
return _resultsByConfiguration.Values.GetEnumerator();

src/Build/BackEnd/Shared/BuildRequest.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,6 @@ private BuildRequest(
119119
_nodeRequestId = nodeRequestId;
120120
_buildRequestDataFlags = buildRequestDataFlags;
121121
_requestedProjectState = requestedProjectState;
122-
123-
if (_requestedProjectState != null)
124-
{
125-
_buildRequestDataFlags |= BuildRequestDataFlags.ProvideSubsetOfStateAfterBuild;
126-
}
127122
}
128123

129124
/// <summary>

src/Build/BackEnd/Shared/BuildResult.cs

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -116,11 +116,6 @@ public class BuildResult : INodePacket, IBuildResults
116116
/// </summary>
117117
private ProjectInstance _projectStateAfterBuild;
118118

119-
/// <summary>
120-
/// The flags provide additional control over the build results and may affect the cached value.
121-
/// </summary>
122-
private BuildRequestDataFlags _buildRequestDataFlags;
123-
124119
private string _schedulerInducedError;
125120

126121
private HashSet<string> _projectTargets;
@@ -209,7 +204,6 @@ internal BuildResult(BuildRequest request, BuildResult existingResults, string[]
209204
_nodeRequestId = request.NodeRequestId;
210205
_circularDependency = false;
211206
_baseOverallResult = true;
212-
_buildRequestDataFlags = request.BuildRequestDataFlags;
213207

214208
if (existingResults == null)
215209
{
@@ -386,12 +380,6 @@ public ProjectInstance ProjectStateAfterBuild
386380
set => _projectStateAfterBuild = value;
387381
}
388382

389-
/// <summary>
390-
/// Gets the flags that were used in the build request to which these results are associated.
391-
/// See <see cref="Execution.BuildRequestDataFlags"/> for examples of the available flags.
392-
/// </summary>
393-
public BuildRequestDataFlags BuildRequestDataFlags => _buildRequestDataFlags;
394-
395383
/// <summary>
396384
/// Returns the node packet type.
397385
/// </summary>
@@ -593,7 +581,6 @@ void ITranslatable.Translate(ITranslator translator)
593581
translator.Translate(ref _savedCurrentDirectory);
594582
translator.Translate(ref _schedulerInducedError);
595583
translator.TranslateDictionary(ref _savedEnvironmentVariables, StringComparer.OrdinalIgnoreCase);
596-
translator.TranslateEnum(ref _buildRequestDataFlags, (int)_buildRequestDataFlags);
597584
}
598585

599586
/// <summary>

0 commit comments

Comments
 (0)