Example #1
0
        /// <summary>
        /// Add a child request to this record. Child requests block the parent.
        /// </summary>
        /// <param name="childRecord"></param>
        internal void AddChildRecord(ScheduleRecord childRecord)
        {
            if (requestIdToChildRecord == null)
            {
                requestIdToChildRecord = new Dictionary <ScheduleRecordKey, ScheduleRecord>();
            }

            requestIdToChildRecord.Add(childRecord.RecordKey, childRecord);
        }
Example #2
0
        /// <summary>
        /// This method is called to update the datastructures to reflect that given request will
        /// be built on a given node.
        /// </summary>
        /// <param name="currentRequest"></param>
        /// <param name="nodeUsed"></param>
        internal void NotifyOfSchedulingDecision(BuildRequest currentRequest, int nodeUsed)
        {
            // Don't update structures on the child node or in single proc mode
            if (childMode || nodes.Length == 1)
            {
                return;
            }

            // Update the count of requests being build on the node
            totalRequestsPerNode[nodeUsed]++;

            // Ignore host requests
            if (currentRequest.HandleId == EngineCallback.invalidEngineHandle)
            {
                return;
            }

            if (Engine.debugMode)
            {
                string targetnames = currentRequest.TargetNames != null?String.Join(";", currentRequest.TargetNames) : "null";

                Console.WriteLine("Sending project " + currentRequest.ProjectFileName + " Target " + targetnames + " to " + nodeUsed);
            }

            // Update the records
            ScheduleRecordKey recordKey = new ScheduleRecordKey(currentRequest.HandleId, currentRequest.RequestId);
            ScheduleRecordKey parentKey = new ScheduleRecordKey(currentRequest.ParentHandleId, currentRequest.ParentRequestId);
            ScheduleRecord    record    = new ScheduleRecord(recordKey, parentKey, nodeUsed, currentRequest.ProjectFileName,
                                                             currentRequest.ToolsetVersion, currentRequest.TargetNames);

            lock (scheduleTableLock)
            {
                ErrorUtilities.VerifyThrow(!handleIdToScheduleRecord.ContainsKey(recordKey),
                                           "Schedule record should not be in the table");

                handleIdToScheduleRecord.Add(recordKey, record);

                // The ParentHandleId is an invalidEngineHandle when the host is the one who created
                // the current request
                if (currentRequest.ParentHandleId != EngineCallback.invalidEngineHandle)
                {
                    ErrorUtilities.VerifyThrow(handleIdToScheduleRecord.ContainsKey(parentKey),
                                               "Parent schedule record should be in the table");
                    ScheduleRecord parentRecord = handleIdToScheduleRecord[parentKey];
                    if (!parentRecord.Blocked)
                    {
                        blockedRequestsPerNode[parentRecord.EvaluationNode]++;
                    }
                    parentRecord.AddChildRecord(record);
                }
            }
        }
Example #3
0
        /// <summary>
        /// Used by the introspector to dump the state when the nodes are being shutdown due to an error.
        /// </summary>
        internal void DumpState()
        {
            for (int i = 0; i < totalRequestsPerNode.Length; i++)
            {
                Console.WriteLine("Node " + i + " Outstanding " + totalRequestsPerNode[i] + " Blocked " + blockedRequestsPerNode[i]);
            }

            foreach (ScheduleRecordKey key in handleIdToScheduleRecord.Keys)
            {
                ScheduleRecord record = handleIdToScheduleRecord[key];
                Console.WriteLine(key.HandleId + ":" + key.RequestId + " " + record.ProjectName + " on node " + record.EvaluationNode);
            }
        }
Example #4
0
        /// <summary>
        /// This method is called when a build request is completed on a particular node. NodeId is never used instead we look up the node from the build request
        /// and the schedule record table
        /// </summary>
        internal void NotifyOfBuildResult(int nodeId, BuildResult buildResult)
        {
            if (!childMode && nodes.Length > 1)
            {
                // Ignore host requests
                if (buildResult.HandleId == EngineCallback.invalidEngineHandle)
                {
                    return;
                }

                ScheduleRecordKey recordKey      = new ScheduleRecordKey(buildResult.HandleId, buildResult.RequestId);
                ScheduleRecord    scheduleRecord = null;
                lock (scheduleTableLock)
                {
                    ErrorUtilities.VerifyThrow(handleIdToScheduleRecord.ContainsKey(recordKey),
                                               "Schedule record should be in the table");

                    scheduleRecord = handleIdToScheduleRecord[recordKey];
                    totalRequestsPerNode[scheduleRecord.EvaluationNode]--;
                    handleIdToScheduleRecord.Remove(recordKey);

                    if (scheduleRecord.ParentKey.HandleId != EngineCallback.invalidEngineHandle)
                    {
                        ErrorUtilities.VerifyThrow(handleIdToScheduleRecord.ContainsKey(scheduleRecord.ParentKey),
                                                   "Parent schedule record should be in the table");
                        ScheduleRecord parentRecord = handleIdToScheduleRecord[scheduleRecord.ParentKey];

                        // As long as there are child requests under the parent request the parent request is considered blocked
                        // Remove this build request from the list of requests the parent request is waiting on. This may unblock the parent request
                        parentRecord.ReportChildCompleted(recordKey);

                        // If completing the child request has unblocked the parent request due to all of the the Child requests being completed
                        // decrement the number of blocked requests.
                        if (!parentRecord.Blocked)
                        {
                            blockedRequestsPerNode[parentRecord.EvaluationNode]--;
                        }
                    }
                }

                // Dump some interesting information to the console if profile build is turned on by an environment variable
                if (parentEngine.ProfileBuild && scheduleRecord != null && buildResult.TaskTime != 0)
                {
                    Console.WriteLine("N " + scheduleRecord.EvaluationNode + " Name " + scheduleRecord.ProjectName + ":" +
                                      scheduleRecord.ParentKey.HandleId + ":" + scheduleRecord.ParentKey.RequestId +
                                      " Total " + buildResult.TotalTime + " Engine " + buildResult.EngineTime + " Task " + buildResult.TaskTime);
                }
            }
        }