|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// THE ASSEMBLY BUILT FROM THIS SOURCE FILE HAS BEEN DEPRECATED FOR YEARS. IT IS BUILT ONLY TO PROVIDE
// BACKWARD COMPATIBILITY FOR API USERS WHO HAVE NOT YET MOVED TO UPDATED APIS. PLEASE DO NOT SEND PULL
// REQUESTS THAT CHANGE THIS FILE WITHOUT FIRST CHECKING WITH THE MAINTAINERS THAT THE FIX IS REQUIRED.
using System;
using System.Collections;
using System.IO;
using Microsoft.Build.BuildEngine.Shared;
namespace Microsoft.Build.BuildEngine
{
/// <summary>
/// This class is a container for build results travelling from the engine to the node
/// </summary>
internal class BuildResult
{
#region Constructions
internal BuildResult()
{
// used for serialization
}
/// <summary>
/// Constructor
/// </summary>
internal BuildResult
(
IDictionary outputsByTarget, Hashtable resultByTarget, bool evaluationResult,
int handleId, int requestId, int projectId, bool useResultCache,
string defaultTargets, string initialTargets,
int totalTime, int engineTime, int taskTime
)
{
this.outputsByTarget = outputsByTarget;
this.resultByTarget = resultByTarget;
this.handleId = handleId;
this.requestId = requestId;
this.projectId = projectId;
this.flags = (byte)((evaluationResult ? 1 : 0) | (useResultCache ? 2 : 0));
this.defaultTargets = defaultTargets;
this.initialTargets = initialTargets;
this.totalTime = totalTime;
this.engineTime = engineTime;
this.taskTime = taskTime;
}
/// <summary>
/// Copy constructor
/// </summary>
internal BuildResult
(BuildResult buildResultToCopy, bool deepCopy)
{
ErrorUtilities.VerifyThrowArgumentNull(buildResultToCopy, "Cannot have a null build result passed in");
this.flags = buildResultToCopy.flags;
this.handleId = buildResultToCopy.handleId;
this.requestId = buildResultToCopy.requestId;
this.projectId = buildResultToCopy.projectId;
this.outputsByTarget = new Hashtable();
this.defaultTargets = buildResultToCopy.defaultTargets;
this.initialTargets = buildResultToCopy.initialTargets;
this.resultByTarget = new Hashtable(buildResultToCopy.resultByTarget, StringComparer.OrdinalIgnoreCase);
if (buildResultToCopy.outputsByTarget == null)
{
return;
}
if (deepCopy)
{
// Copy all the old data
foreach (DictionaryEntry entry in buildResultToCopy.outputsByTarget)
{
// Make deep copies of all the target outputs before
// passing them back
BuildItem[] originalArray = (BuildItem[])entry.Value;
BuildItem[] itemArray = new BuildItem[originalArray.Length];
for (int i = 0; i < originalArray.Length; i++)
{
if (!originalArray[i].IsUninitializedItem)
{
itemArray[i] = originalArray[i].Clone();
itemArray[i].CloneVirtualMetadata();
}
else
{
itemArray[i] = new BuildItem(null, originalArray[i].FinalItemSpecEscaped);
}
}
this.outputsByTarget.Add(entry.Key, itemArray);
}
}
else
{
// Create a new hashtable but point at the same data
foreach (DictionaryEntry entry in buildResultToCopy.outputsByTarget)
{
this.outputsByTarget.Add(entry.Key, entry.Value);
}
}
}
#endregion
#region Properties
internal IDictionary OutputsByTarget
{
get
{
return this.outputsByTarget;
}
}
internal Hashtable ResultByTarget
{
get
{
return this.resultByTarget;
}
}
internal bool EvaluationResult
{
get
{
return (this.flags & 1) == 0 ? false : true;
}
}
internal int HandleId
{
get
{
return this.handleId;
}
set
{
this.handleId = value;
}
}
internal int RequestId
{
get
{
return this.requestId;
}
set
{
this.requestId = value;
}
}
internal int ProjectId
{
get
{
return this.projectId;
}
}
internal bool UseResultCache
{
get
{
return (this.flags & 2) == 0 ? false : true;
}
}
internal string DefaultTargets
{
get
{
return this.defaultTargets;
}
}
internal string InitialTargets
{
get
{
return this.initialTargets;
}
}
/// <summary>
/// Total time spent on the build request measured from the time it is received to the time build
/// result is created. This number will be 0 if the result was in the cache.
/// </summary>
internal int TotalTime
{
get
{
return this.totalTime;
}
}
/// <summary>
/// Total time spent in the engine working on the build request. This number will be 0 if the result
/// was in the cache.
/// </summary>
internal int EngineTime
{
get
{
return this.engineTime;
}
}
/// <summary>
/// Total time spent in the running tasks for the build request. This number will be 0 if the result
/// was in the cache.
/// </summary>
internal int TaskTime
{
get
{
return this.taskTime;
}
}
#endregion
#region Methods
/// <summary>
/// BuildItems are passed around internally, including across the wire. Before passing these
/// to tasks, they need to be converted into TaskItems using this method.
/// </summary>
internal void ConvertToTaskItems()
{
// If outputsByTarget was null then we dont have to re-create anything as nothing was passed over
if (outputsByTarget != null)
{
string[] keys = new string[outputsByTarget.Count];
outputsByTarget.Keys.CopyTo(keys, 0);
for (int key_index = 0; key_index < keys.Length; key_index++)
{
object key = keys[key_index];
BuildItem[] originalArray = (BuildItem[])outputsByTarget[key];
outputsByTarget[key] = BuildItem.ConvertBuildItemArrayToTaskItems(originalArray);
}
}
}
#endregion
#region Data
private IDictionary outputsByTarget;
private Hashtable resultByTarget;
private byte flags;
private int handleId;
private int requestId;
private int projectId;
private string defaultTargets;
private string initialTargets;
// Timing data related to the execution of the request
private int totalTime;
private int engineTime;
private int taskTime;
#endregion
#region CustomSerializationToStream
internal void WriteToStream(BinaryWriter writer)
{
ErrorUtilities.VerifyThrow(resultByTarget != null, "resultsByTarget cannot be null");
#region OutputsByTarget
if (outputsByTarget == null)
{
writer.Write((byte)0);
}
else
{
writer.Write((byte)1);
writer.Write((Int32)outputsByTarget.Count);
foreach (string key in outputsByTarget.Keys)
{
writer.Write(key);
if (outputsByTarget[key] == null)
{
writer.Write((byte)0);
}
else
{
writer.Write((byte)1);
BuildItem[] items = ((BuildItem[])outputsByTarget[key]);
writer.Write((Int32)items.Length);
foreach (BuildItem item in items)
{
if (item == null)
{
writer.Write((byte)0);
}
writer.Write((byte)1);
item.WriteToStream(writer);
}
}
}
}
#endregion
#region ResultByTarget
//Write Number of HashItems
writer.Write((Int32)resultByTarget.Count);
foreach (string key in resultByTarget.Keys)
{
writer.Write(key);
writer.Write((Int32)resultByTarget[key]);
}
#endregion
writer.Write((byte)flags);
writer.Write((Int32)handleId);
writer.Write((Int32)requestId);
writer.Write((Int32)projectId);
#region DefaultTargets
if (defaultTargets == null)
{
writer.Write((byte)0);
}
else
{
writer.Write((byte)1);
writer.Write(defaultTargets);
}
#endregion
#region InitialTargets
if (initialTargets == null)
{
writer.Write((byte)0);
}
else
{
writer.Write((byte)1);
writer.Write(initialTargets);
}
#endregion
#region Timing data
writer.Write((Int32)totalTime);
writer.Write((Int32)engineTime);
writer.Write((Int32)taskTime);
#endregion
}
internal static BuildResult CreateFromStream(BinaryReader reader)
{
BuildResult buildResult = new BuildResult();
#region OutputsByTarget
if (reader.ReadByte() == 0)
{
buildResult.outputsByTarget = null;
}
else
{
int numberOfElements = reader.ReadInt32();
buildResult.outputsByTarget = new Hashtable(numberOfElements, StringComparer.OrdinalIgnoreCase);
for (int i = 0; i < numberOfElements; i++)
{
string key = reader.ReadString();
BuildItem[] value = null;
if (reader.ReadByte() != 0)
{
int sizeOfArray = reader.ReadInt32();
value = new BuildItem[sizeOfArray];
for (int j = 0; j < sizeOfArray; j++)
{
BuildItem itemToAdd = null;
if (reader.ReadByte() != 0)
{
itemToAdd = new BuildItem(null, string.Empty);
itemToAdd.CreateFromStream(reader);
}
value[j] = itemToAdd;
}
}
buildResult.outputsByTarget.Add(key, value);
}
}
#endregion
#region ResultsByTarget
//Write Number of HashItems
int numberOfHashKeyValuePairs = reader.ReadInt32();
buildResult.resultByTarget = new Hashtable(numberOfHashKeyValuePairs, StringComparer.OrdinalIgnoreCase);
for (int i = 0; i < numberOfHashKeyValuePairs; i++)
{
string key = reader.ReadString();
int value = reader.ReadInt32();
buildResult.resultByTarget.Add(key, (Target.BuildState)value);
}
#endregion
buildResult.flags = reader.ReadByte();
buildResult.handleId = reader.ReadInt32();
buildResult.requestId = reader.ReadInt32();
buildResult.projectId = reader.ReadInt32();
#region DefaultTargets
if (reader.ReadByte() == 0)
{
buildResult.defaultTargets = null;
}
else
{
buildResult.defaultTargets = reader.ReadString();
}
#endregion
#region InitialTargets
if (reader.ReadByte() == 0)
{
buildResult.initialTargets = null;
}
else
{
buildResult.initialTargets = reader.ReadString();
}
#endregion
#region Timing data
buildResult.totalTime = reader.ReadInt32();
buildResult.engineTime = reader.ReadInt32();
buildResult.taskTime = reader.ReadInt32();
#endregion
return buildResult;
}
#endregion
}
}
|