Пример #1
0
 public FilteredDirectedGraph(IReadonlyDirectedGraph graph, VisitationTracker nodeFilter)
 {
     m_graph         = graph;
     m_nodeFilter    = nodeFilter;
     m_nodePredicate = node => nodeFilter.WasVisited(node);
     m_edgePredicate = edge => nodeFilter.WasVisited(edge.OtherNode);
     m_nodeHeights   = Lazy.Create(ComputeHeights);
 }
Пример #2
0
        /// <inheritdoc />
        public GraphPatchingStatistics PartiallyReloadGraph(HashSet <AbsolutePath> affectedSpecs)
        {
            Contract.Requires(affectedSpecs != null);

            var startTime = DateTime.UtcNow;
            var mustSkipDueToTransitivity    = new VisitationTracker(m_oldPipGraph);
            var mustPostponeDueToServicePips = new VisitationTracker(m_oldPipGraph);
            var toPostpone = new SortedList <uint, Pip>();

            MultiValueDictionary <int, NodeId> nodesByHeight = m_oldPipGraph.TopSort();
            int numReloadedPips      = 0;
            int numNotReloadablePips = 0;

            m_builder.SealDirectoryTable.StartPatching();

            // go one level at a time:
            //   - process nodes at the same height in parallel
            //   - postpone service-related pips because they must be added in the order of creation
            //     (because, for example, pip builder adds forward edges from service client to service finalization pips)
            for (int height = 0; height < nodesByHeight.Count; height++)
            {
                Parallel.ForEach(
                    nodesByHeight[height],
                    new ParallelOptions {
                    MaxDegreeOfParallelism = m_maxDegreeOfParallelism
                },
                    body: (node) =>
                {
                    var pipId   = node.ToPipId();
                    var pipType = m_oldPipTable.GetPipType(pipId);

                    // skip non-reloadable pips
                    if (!s_reloadablePipTypes.Contains(pipType))
                    {
                        Interlocked.Increment(ref numNotReloadablePips);
                        return;
                    }

                    var pip = HydratePip(pipId);
                    AbsolutePath?producingSpec = GetProducerSpecFile(pip);

                    // check if this node must be skipped due to its spec file being affected
                    if (producingSpec == null || affectedSpecs.Contains(producingSpec.Value))
                    {
                        mustSkipDueToTransitivity.MarkVisited(node);
                        MarkAllDependentsVisited(mustSkipDueToTransitivity, node);
                        return;
                    }

                    // check if this pip is a service-related pip which must be postponed
                    if (ServicePipKindUtil.IsServiceRelatedPip(pip))
                    {
                        SynchronizedAddToSortedList(toPostpone, pip);
                        MarkAllDependentsVisited(mustPostponeDueToServicePips, node);
                        return;
                    }

                    // check if this node must be postponed because it depends on a node that was already postponed
                    if (mustPostponeDueToServicePips.WasVisited(node))
                    {
                        SynchronizedAddToSortedList(toPostpone, pip);
                        MarkAllDependentsVisited(mustPostponeDueToServicePips, node);
                        return;
                    }

                    // check if this node must be skipped due to transitivity
                    ThrowIfVisited(mustSkipDueToTransitivity, pip);

                    // everything passed: reload this node
                    ReloadPip(pip, ref numReloadedPips);
                });
            }

            // add postponed nodes sequentially in the order of creation
            foreach (var pip in toPostpone.Values)
            {
                var serviceKind = ServicePipKindUtil.ServiceKind(pip);
                if (serviceKind != ServicePipKind.ServiceShutdown && serviceKind != ServicePipKind.ServiceFinalization)
                {
                    // 'shutdown' and 'finalization' are exception because of forward edges that are added
                    // during construction from service client pips to service shutdown/finalization pips.
                    ThrowIfVisited(mustSkipDueToTransitivity, pip);
                }

                ReloadPip(pip, ref numReloadedPips);
            }

            m_builder.SealDirectoryTable.FinishPatching();

            return(new GraphPatchingStatistics
            {
                ElapsedMilliseconds = (int)DateTime.UtcNow.Subtract(startTime).TotalMilliseconds,
                NumPipsReloaded = numReloadedPips,
                NumPipsAutomaticallyAdded = m_builder.PipCount - numReloadedPips,
                NumPipsNotReloadable = numNotReloadablePips,
                NumPipsSkipped = mustSkipDueToTransitivity.VisitedCount,
                AffectedSpecs = affectedSpecs,
            });
        }