|
// 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.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace Microsoft.Build.BuildEngine
{
/// <summary>
/// This class is a container for node status
/// </summary>
internal class NodeStatus
{
#region Constructors
/// <summary>
/// Default constructor creating a NodeStatus
/// </summary>
internal NodeStatus
(
int requestId,
bool isActive,
int queueDepth,
long lastTaskActivityTimeStamp,
long lastEngineActivityTimeStamp,
bool isLaunchInProgress
)
{
this.requestId = requestId;
this.isActive = isActive;
this.queueDepth = queueDepth;
this.lastTaskActivityTimeStamp = lastTaskActivityTimeStamp;
this.lastEngineActivityTimeStamp = lastEngineActivityTimeStamp;
this.isLaunchInProgress = isLaunchInProgress;
this.unhandledException = null;
this.statusTimeStamp = DateTime.Now.Ticks;
}
/// <summary>
/// Create a node status describing an unhandled error
/// </summary>
internal NodeStatus
(
Exception unhandledException
)
{
this.requestId = UnrequestedStatus;
this.isActive = true;
this.isLaunchInProgress = false;
this.unhandledException = unhandledException;
this.statusTimeStamp = DateTime.Now.Ticks;
}
/// <summary>
/// Create a node status indicating that breadth first traversal should be used
/// </summary>
internal NodeStatus
(
bool useBreadthFirstTraversal
)
{
this.requestId = UnrequestedStatus;
this.isActive = true;
this.isLaunchInProgress = false;
this.unhandledException = null;
this.traversalType = useBreadthFirstTraversal;
}
/// <summary>
/// Create a node status indicating that node process has exited
/// </summary>
internal NodeStatus
(
int requestId
)
{
this.requestId = requestId;
this.isActive = true;
this.isLaunchInProgress = false;
this.unhandledException = null;
this.hasExited = true;
}
#endregion
#region Properties
/// <summary>
/// The time period for which the node has been idle when the status report was filled out
/// </summary>
internal long TimeSinceLastTaskActivity
{
get
{
return statusTimeStamp - lastTaskActivityTimeStamp;
}
}
/// <summary>
/// The time period for which the node has been idle when the status report was filled out
/// </summary>
internal long TimeSinceLastLoopActivity
{
get
{
return statusTimeStamp - lastEngineActivityTimeStamp;
}
}
/// <summary>
/// The time stamp at which the node was last active
/// </summary>
internal long LastTaskActivity
{
get
{
return lastTaskActivityTimeStamp;
}
}
/// <summary>
/// The time stamp at which there was activity in the node's build loop
/// </summary>
internal long LastLoopActivity
{
get
{
return lastEngineActivityTimeStamp;
}
}
/// <summary>
/// True if the node is active (i.e. has been launched and can accept commands)
/// </summary>
internal bool IsActive
{
get
{
return this.isActive;
}
}
/// <summary>
/// True if the node process is no longer alive
/// </summary>
internal bool HasExited
{
get
{
return this.hasExited;
}
}
/// <summary>
/// The token of the request to which this is a response (-1 if status is unrequested)
/// </summary>
internal int RequestId
{
get
{
return this.requestId;
}
}
/// <summary>
/// The number of requests that need to be processed
/// </summary>
internal int QueueDepth
{
get
{
return this.queueDepth;
}
}
/// <summary>
/// The state of the targets which are in progress on the node
/// </summary>
internal TargetInProgessState[] StateOfInProgressTargets
{
get
{
return this.stateOfInProgressTargets;
}
set
{
this.stateOfInProgressTargets = value;
}
}
/// <summary>
/// True if the node is in the process of being launched, but is not yet active
/// </summary>
internal bool IsLaunchInProgress
{
get
{
return isLaunchInProgress;
}
}
/// <summary>
/// Returns the exception that occurred on the node
/// </summary>
internal Exception UnhandledException
{
get
{
return unhandledException;
}
}
internal bool TraversalType
{
get
{
return traversalType;
}
}
#endregion
#region Data
private long statusTimeStamp; // the timestamp indicating when this status structure was filled out
private int requestId; // the token of the request to which this is a response (-1 if status is unrequested)
private bool isActive; // is the node active
private bool isLaunchInProgress; // is the node in the process of being launched
private int queueDepth; // the number of build request in the node's queue
private long lastTaskActivityTimeStamp; // the time stamp of the last task activity
private long lastEngineActivityTimeStamp; // the time stamp of the last engine activity
private TargetInProgessState[] stateOfInProgressTargets;
private Exception unhandledException; // unhandled exception
private bool traversalType; // if true use breadth first traversal
private bool hasExited; // if true the node process is no longer alive
private static BinaryFormatter formatter = new BinaryFormatter();
internal const int UnrequestedStatus = -1; // used to indicate that the node is generating status without request
#endregion
#region CustomSerializationToStream
internal void WriteToStream(BinaryWriter writer)
{
writer.Write(traversalType);
writer.Write((Int64)statusTimeStamp);
writer.Write((Int32)requestId);
writer.Write(isActive);
writer.Write(isLaunchInProgress);
writer.Write((Int32)queueDepth);
writer.Write((Int64)lastTaskActivityTimeStamp);
writer.Write((Int64)lastEngineActivityTimeStamp);
if (stateOfInProgressTargets == null)
{
writer.Write((byte)0);
}
else
{
writer.Write((byte)1);
writer.Write((Int32)stateOfInProgressTargets.Length);
for (int i = 0; i < stateOfInProgressTargets.Length; i++)
{
if (stateOfInProgressTargets[i] == null)
{
writer.Write((byte)0);
}
else
{
writer.Write((byte)1);
stateOfInProgressTargets[i].WriteToStream(writer);
}
}
}
if (unhandledException == null)
{
writer.Write((byte)0);
}
else
{
writer.Write((byte)1);
formatter.Serialize(writer.BaseStream, unhandledException);
}
}
internal static NodeStatus CreateFromStream(BinaryReader reader)
{
NodeStatus status = new NodeStatus(null);
status.traversalType = reader.ReadBoolean();
status.statusTimeStamp = reader.ReadInt64();
status.requestId = reader.ReadInt32();
status.isActive = reader.ReadBoolean();
status.isLaunchInProgress = reader.ReadBoolean();
status.queueDepth = reader.ReadInt32();
status.lastTaskActivityTimeStamp = reader.ReadInt64();
status.lastEngineActivityTimeStamp = reader.ReadInt64();
if (reader.ReadByte() == 0)
{
status.stateOfInProgressTargets = null;
}
else
{
int numberOfInProgressTargets = reader.ReadInt32();
status.stateOfInProgressTargets = new TargetInProgessState[numberOfInProgressTargets];
for (int i = 0; i < numberOfInProgressTargets; i++)
{
if (reader.ReadByte() == 0)
{
status.stateOfInProgressTargets[i] = null;
}
else
{
TargetInProgessState state = new TargetInProgessState();
state.CreateFromStream(reader);
status.stateOfInProgressTargets[i] = state;
}
}
}
if (reader.ReadByte() == 0)
{
status.unhandledException = null;
}
else
{
status.unhandledException = (Exception)formatter.Deserialize(reader.BaseStream);
}
return status;
}
#endregion
}
}
|