private void WriteGraphNodeEntry( Pip pip, IPipScheduleTraversal graph, PipExecutionContext context, Dictionary <PipId, ProcessExecutionMonitoringReportedEventData> directoryInputContent, Dictionary <PipId, PipExecutionDirectoryOutputs> directoryOutputContent) { Contract.Requires(pip != null); m_writer.WriteWhitespace(Environment.NewLine); m_writer.WriteStartObject(); { WriteStaticPipDetails(pip, context); { // We get nice space savings by omitting dependsOn when it is empty (think HashSourceFile and WriteFile pips). bool writtenHeader = false; foreach (var dependency in graph.RetrievePipImmediateDependencies(pip)) { if (!writtenHeader) { m_writer.WritePropertyName("dependsOn"); m_writer.WriteStartArray(); writtenHeader = true; } if (IncludePip(dependency.PipType)) { m_writer.WriteValue(dependency.PipId.Value); } } if (writtenHeader) { m_writer.WriteEndArray(); } writtenHeader = false; PipArtifacts.ForEachInput(pip, dependency => { int dependencyId; if (dependency.IsFile) { if (!m_fileIds.TryGetValue(dependency.FileArtifact.Path.ToString(context.PathTable), out dependencyId)) { Contract.Assume(false, "Expected file artifact already written (dependency of pip) " + dependency.Path.ToString(context.PathTable)); throw new InvalidOperationException("Unreachable"); } if (!writtenHeader) { m_writer.WritePropertyName("consumes"); m_writer.WriteStartArray(); writtenHeader = true; } m_writer.WriteValue(dependencyId); } return(true); }, includeLazyInputs: true); // Write reads from shared opaque directories if (directoryInputContent.TryGetValue(pip.PipId, out var pipInput)) { foreach (var input in pipInput.ReportedFileAccesses) { int dependencyId; if (!m_fileIds.TryGetValue(input.ManifestPath.ToString(context.PathTable), out dependencyId)) { // Ignore unrecognized reads (these are usually directories / files that aren't produced, so we don't have their ID) continue; } m_writer.WriteValue(dependencyId); } } if (writtenHeader) { m_writer.WriteEndArray(); } } { m_writer.WritePropertyName("produces"); m_writer.WriteStartArray(); SortedSet <int> writes = new SortedSet <int>(); PipArtifacts.ForEachOutput(pip, dependency => { int dependencyId; if (dependency.IsFile) { if (!m_fileIds.TryGetValue(dependency.FileArtifact.Path.ToString(context.PathTable), out dependencyId)) { Contract.Assume(false, "Expected file artifact already written (output of pip) " + dependency.Path.ToString(context.PathTable)); throw new InvalidOperationException("Unreachable"); } writes.Add(dependencyId); } return(true); }, includeUncacheable: true); // Write outputs into shared opaque directories if (directoryOutputContent.TryGetValue(pip.PipId, out var pipOutput)) { foreach (var output in pipOutput.DirectoryOutputs) { DirectoryArtifact dir = output.directoryArtifact; var content = output.fileArtifactArray; foreach (var file in content) { int dependencyId; if (!m_fileIds.TryGetValue(file.Path.ToString(context.PathTable), out dependencyId)) { Contract.Assume(false, "Expected file artifact not found in fileId table " + file.Path.ToString(context.PathTable)); throw new InvalidOperationException("Unreachable"); } writes.Add(dependencyId); } } } foreach (int dependencyId in writes) { m_writer.WriteValue(dependencyId); } m_writer.WriteEndArray(); } } m_writer.WriteEndObject(); }
private void WriteGraphNodeEntry( Pip pip, IPipScheduleTraversal graph, PipExecutionContext context, Dictionary <DirectoryArtifact, int> directoryIds) { Contract.Requires(pip != null); m_writer.WriteWhitespace(Environment.NewLine); m_writer.WriteStartObject(); { WriteStaticPipDetails(pip, context); { // We get nice space savings by omitting dependsOn when it is empty (think HashSourceFile and WriteFile pips). bool writtenHeader = false; foreach (var dependency in graph.RetrievePipImmediateDependencies(pip)) { if (!writtenHeader) { m_writer.WritePropertyName("dependsOn"); m_writer.WriteStartArray(); writtenHeader = true; } if (IncludePip(dependency.PipType)) { m_writer.WriteValue(dependency.PipId.Value); } } if (writtenHeader) { m_writer.WriteEndArray(); } writtenHeader = false; PipArtifacts.ForEachInput(pip, dependency => { int dependencyId; if (dependency.IsFile) { if (!m_fileIds.TryGetValue(dependency.FileArtifact, out dependencyId)) { Contract.Assume(false, "Expected file artifact already written (dependency of pip) " + dependency.Path.ToString(context.PathTable)); throw new InvalidOperationException("Unreachable"); } } else { if (!directoryIds.TryGetValue(dependency.DirectoryArtifact, out dependencyId)) { Contract.Assume(false, "Expected directory artifact already written (input of pip) " + dependency.Path.ToString(context.PathTable)); throw new InvalidOperationException("Unreachable"); } } if (!writtenHeader) { m_writer.WritePropertyName("consumes"); m_writer.WriteStartArray(); writtenHeader = true; } m_writer.WriteValue(dependencyId); return(true); }, includeLazyInputs: true); if (writtenHeader) { m_writer.WriteEndArray(); } } { m_writer.WritePropertyName("produces"); m_writer.WriteStartArray(); PipArtifacts.ForEachOutput(pip, dependency => { int dependencyId; if (dependency.IsFile) { if (!m_fileIds.TryGetValue(dependency.FileArtifact, out dependencyId)) { Contract.Assume(false, "Expected file artifact already written (output of pip) " + dependency.Path.ToString(context.PathTable)); throw new InvalidOperationException("Unreachable"); } } else { if (!directoryIds.TryGetValue(dependency.DirectoryArtifact, out dependencyId)) { Contract.Assume(false, "Expected directory artifact already written (output of pip) " + dependency.Path.ToString(context.PathTable)); throw new InvalidOperationException("Unreachable"); } } m_writer.WriteValue(dependencyId); return(true); }, includeUncacheable: true); m_writer.WriteEndArray(); } } m_writer.WriteEndObject(); }