Beispiel #1
0
        /// <summary>
        /// Generates the PipInfo for a given pip, and then serializes it
        /// </summary>
        /// <param name="pipReference">PipReference to hydrate into a complete Pip</param>
        /// <param name="writer">Writer to write data to</param>
        /// <param name="serializer">Serializer to serialize with</param>
        public void GenerateAndSerializePipInfo(PipReference pipReference, JsonWriter writer, JsonSerializer serializer)
        {
            Pip pip = pipReference.HydratePip();

            // All PipInfos will have metadata
            PipInfo generatedPipInfo = new PipInfo
            {
                PipMetadata = GeneratePipMetadata(pip)
            };

            if (Filters.OnlyMetadata)
            {
                serializer.Serialize(writer, generatedPipInfo);
                return;
            }
            // Fill the data depending on the type of Pip
            switch (pip.PipType)
            {
            case PipType.CopyFile:
                generatedPipInfo.CopyFilePipDetails = GenerateCopyFilePipDetails((CopyFile)pip);
                break;

            case PipType.Process:
                generatedPipInfo.ProcessPipDetails = GenerateProcessPipDetails((Process)pip);
                break;

            case PipType.Ipc:
                generatedPipInfo.IpcPipDetails = GenerateIpcPipDetails((IpcPip)pip);
                break;

            case PipType.Value:
                generatedPipInfo.ValuePipDetails = GenerateValuePipDetails((ValuePip)pip);
                break;

            case PipType.SpecFile:
                generatedPipInfo.SpecFilePipDetails = GenerateSpecFilePipDetails((SpecFilePip)pip);
                break;

            case PipType.Module:
                generatedPipInfo.ModulePipDetails = GenerateModulePipDetails((ModulePip)pip);
                break;

            case PipType.HashSourceFile:
                generatedPipInfo.HashSourceFilePipDetails = GenerateHashSourceFilePipDetails((HashSourceFile)pip);
                break;

            case PipType.SealDirectory:
                generatedPipInfo.SealDirectoryPipDetails = GenerateSealDirectoryPipDetails((SealDirectory)pip);
                break;

            case PipType.WriteFile:
                generatedPipInfo.WriteFilePipDetails = GenerateWriteFilePipDetails((WriteFile)pip);
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
            serializer.Serialize(writer, generatedPipInfo);
        }
Beispiel #2
0
        private async Task HandlePipStepAsync(SinglePipBuildRequest pipBuildRequest, Possible <Unit> reportInputsResult)
        {
            // Do not block the caller.
            await Task.Yield();

            var pipId   = new PipId(pipBuildRequest.PipIdValue);
            var pip     = m_pipTable.HydratePip(pipId, PipQueryContext.LoggingPipFailedOnWorker);
            var pipType = pip.PipType;
            var step    = (PipExecutionStep)pipBuildRequest.Step;

            if (!(pipType == PipType.Process || pipType == PipType.Ipc || step == PipExecutionStep.MaterializeOutputs))
            {
                throw Contract.AssertFailure(I($"Workers can only execute process or IPC pips for steps other than MaterializeOutputs: Step={step}, PipId={pipId}, Pip={pip.GetDescription(m_environment.Context)}"));
            }

            m_pendingBuildRequests[pipId] = pipBuildRequest;
            var pipCompletionData = new ExtendedPipCompletionData(new PipCompletionData()
            {
                PipIdValue = pipId.Value, Step = (int)step
            })
            {
                SemiStableHash = m_pipTable.GetPipSemiStableHash(pipId)
            };

            m_pendingPipCompletions[pipId] = pipCompletionData;

            using (var operationContext = m_operationTracker.StartOperation(PipExecutorCounter.WorkerServiceHandlePipStepDuration, pipId, pipType, m_appLoggingContext))
                using (operationContext.StartOperation(step))
                {
                    var pipInfo = new PipInfo(pip, m_environment.Context);

                    if (!reportInputsResult.Succeeded)
                    {
                        // Could not report inputs due to input mismatch. Fail the pip
                        BuildXL.Scheduler.Tracing.Logger.Log.PipMaterializeDependenciesFailureUnrelatedToCache(
                            m_appLoggingContext,
                            pipInfo.Description,
                            ArtifactMaterializationResult.VerifySourceFilesFailed.ToString(),
                            reportInputsResult.Failure.DescribeIncludingInnerFailures());

                        ReportResult(
                            operationContext,
                            pip,
                            ExecutionResult.GetFailureNotRunResult(m_appLoggingContext),
                            step);

                        return;
                    }

                    if (step == PipExecutionStep.CacheLookup)
                    {
                        // Directory dependencies need to be registered for cache lookup.
                        // For process execution, the input materialization guarantees the registration.
                        m_environment.State.FileContentManager.RegisterDirectoryDependencies(pipInfo.UnderlyingPip);
                    }

                    m_workerPipStateManager.Transition(pipId, WorkerPipState.Queued);
                    m_scheduler.HandlePipRequest(pipId, m_workerRunnablePipObserver, step, pipBuildRequest.Priority);

                    // Track how much time the request spent queued
                    using (var op = operationContext.StartOperation(PipExecutorCounter.WorkerServiceQueuedPipStepDuration))
                    {
                        await pipCompletionData.StepExecutionStarted.Task;
                        pipCompletionData.SerializedData.QueueTicks = op.Duration.Value.Ticks;
                    }

                    ExecutionResult executionResult;

                    // Track how much time the request spent executing
                    using (operationContext.StartOperation(PipExecutorCounter.WorkerServiceExecutePipStepDuration))
                    {
                        executionResult = await pipCompletionData.StepExecutionCompleted.Task;
                    }

                    ReportResult(
                        operationContext,
                        pip,
                        executionResult,
                        step);
                }
        }
Beispiel #3
0
        private string GetRunningPipsMessage(string standardStatus, string perfInfo)
        {
            lock (m_runningPipsLock)
            {
                // First, bail out if the visualizer data isn't available
                if (EngineModel.VisualizationInformation == null ||
                    EngineModel.VisualizationInformation.Scheduler.State != Engine.Visualization.VisualizationValueState.Available ||
                    EngineModel.VisualizationInformation.Context.State != Engine.Visualization.VisualizationValueState.Available ||
                    EngineModel.VisualizationInformation.PipGraph.State != Engine.Visualization.VisualizationValueState.Available)
                {
                    return(null);
                }

                var context     = EngineModel.VisualizationInformation.Context.Value;
                var stringTable = context.StringTable;
                var pathTable   = context.PathTable;
                var symbolTable = context.SymbolTable;

                if (m_runningPips == null)
                {
                    m_runningPips = new Dictionary <PipId, PipInfo>();
                }

                DateTime thisCollection = DateTime.UtcNow;

                // Use the viewer's interface to fetch the info about which pips are currently running.
                foreach (var pip in EngineModel.VisualizationInformation.Scheduler.Value.RetrieveExecutingProcessPips())
                {
                    PipInfo runningInfo;
                    if (!m_runningPips.TryGetValue(pip.PipId, out runningInfo))
                    {
                        // This is a new pip that wasn't running the last time the currently running pips were queried
                        Pip p = pip.HydratePip();

                        runningInfo = new PipInfo()
                        {
                            PipDescription = p.GetShortDescription(context),
                            FirstSeen      = DateTime.UtcNow,
                        };
                        m_runningPips.Add(pip.PipId, runningInfo);
                    }

                    runningInfo.LastSeen = DateTime.UtcNow;
                }

                // Build up a string based on the snapshot of what pips are being running
                using (var pooledWrapper = Pools.StringBuilderPool.GetInstance())
                {
                    StringBuilder sb = pooledWrapper.Instance;
                    sb.Append(TimeSpanToString(TimeDisplay.Seconds, DateTime.UtcNow - BaseTime));
                    sb.Append(' ');
                    sb.Append(standardStatus);
                    if (!string.IsNullOrWhiteSpace(perfInfo))
                    {
                        sb.Append(". " + perfInfo);
                    }

                    // Display the log file location if there have been errors logged. This allows the user to open the
                    // log files while the build is running to see errors that have scrolled off the console
                    var errors = Interlocked.Read(ref m_errorsLogged);
                    if (errors > 0 && m_logsDirectory != null)
                    {
                        sb.AppendLine();
                        sb.AppendFormat(Strings.App_Errors_LogsDirectory, errors, m_logsDirectory);
                    }

                    int pipCount = 0;

                    foreach (var item in m_runningPips.ToArray().OrderBy(kvp => kvp.Value.FirstSeen))
                    {
                        if (item.Value.LastSeen < thisCollection)
                        {
                            // If the pip was last seen before this collection it is no longer running and should be removed
                            m_runningPips.Remove(item.Key);
                        }
                        else
                        {
                            pipCount++;
                            if (pipCount <= m_maxStatusPips)
                            {
                                // Otherwise include it in the string
                                string info = string.Format(CultureInfo.InvariantCulture, "   {0} {1}",
                                                            TimeSpanToString(TimeDisplay.Seconds, item.Value.LastSeen - item.Value.FirstSeen),
                                                            item.Value.PipDescription);

                                // Don't have a trailing newline for the last message;
                                if (sb.Length > 0)
                                {
                                    sb.AppendLine();
                                }

                                sb.Append(info);
                            }
                        }
                    }

                    if (pipCount > m_maxStatusPips)
                    {
                        sb.AppendLine();
                        sb.AppendFormat(Strings.ConsoleListener_AdditionalPips, pipCount - m_maxStatusPips);
                    }

                    return(sb.ToString());
                }
            }
        }