private bool FindCycle(IDependencyVertex root, IDependencyVertex next, ref ArrayList members, ref Stack stack) { if (s_diagnostics_StackCheck) { if (stack.Contains(next)) { string msg = "GraphSequencer has detected a dependency cycle in the initialization sequence of this model.\r\n"; IDependencyVertex thisDv = next; int depct = 1; foreach (IDependencyVertex idv in (object[])stack.ToArray()) { msg += string.Format("{0}.) {1} depends on {2}.\r\n", (depct++), thisDv, idv); thisDv = idv; } throw new ApplicationException(msg); } else { stack.Push(next); } } foreach (IDependencyVertex parent in next.PredecessorList) { if (parent.Equals(root) || FindCycle(root, parent, ref members, ref stack)) { members.Add(next); return(true); } } return(false); }
/// <summary> /// Call this with an IDependencyVertex object to add it to the sequencer /// for consideration next time there is a request for a service sequence list. /// </summary> /// <param name="vertex">An IDependencyVertex object</param> public void AddVertex(IDependencyVertex vertex) { m_serviceSequenceList = null; if (m_vertices.Contains(vertex)) { string msg = string.Format("Dependency sequencer error: Attempt to register a dependency vertex, {0}, that already exists in the list.", vertex); throw new ApplicationException(msg); } m_vertices.Add((IDependencyVertex)vertex); }
/// <summary> /// Recalculates the service sequence. /// </summary> protected void RecalculateServiceSequence() { m_serviceSequenceList = new ArrayList(); // First we create the list of vertex data and a hashtable to find // the vertex from the underlying. ArrayList lstVerts = new ArrayList(); Hashtable htVerts = new Hashtable(); //_Debug.WriteLine("Calculating Service Sequence."); foreach (IDependencyVertex idv in m_vertices) { VertexRecord v = new VertexRecord(idv); if (s_diagnostics) { _Debug.WriteLine("Parents of " + v.Underlying); foreach (IDependencyVertex idv2 in v.Underlying.PredecessorList) { _Debug.WriteLine("\t" + idv2); } } lstVerts.Add(v); htVerts.Add(idv, v); if (s_diagnostics) { _Debug.WriteLine(String.Format("New vertex, {0} with {1} dependents.", idv, idv.PredecessorList.Count)); } } // Each underlying knows who it depends on - we need each vertex to // know, rather, who depends on IT. foreach (VertexRecord v in lstVerts) { v.EstablishChildRelationships(htVerts); } try { bool bResortNeeded = true; int numAffectedLastAdjustment = lstVerts.Count; // We will repeat the following until all nodes have been evaluated. while (lstVerts.Count > 0) { //if ( lstVerts.Count%100 == 0 ) Console.WriteLine("%%%" + lstVerts.Count); // Sort remaining vertices by the provided Comparer. (defaults to // sorting first by nOrder, then by the vertices' provided comparator. // See below for an explanation of the 'bResortNeeded' boolean. if (bResortNeeded) { if (numAffectedLastAdjustment > lstVerts.Count * 0.02) { lstVerts.Sort(GetVertexComparer()); } else { lstVerts = BubbleSort(lstVerts); } } // Dumps the sort order as it progresses... //foreach ( Vertex v in lstVerts ) _Debug.WriteLine(v.Underlying + " : " + v.Order); // Move the least vertex to the ServiceOrder list. VertexRecord next = (VertexRecord)lstVerts[0]; lstVerts.RemoveAt(0); m_serviceSequenceList.Add(next.Underlying); // If the vertex we just removed had no parents, then the sort order // that was valid in the preceding step is still valid. Nobody had // their child-count reduced, so no one's position in the sort will // have had a reason to change. We just move on to the next one... numAffectedLastAdjustment = next.Underlying.PredecessorList.Count; bResortNeeded = (numAffectedLastAdjustment > 0); if (next.Order != 0) { IDependencyVertex root = next.Underlying; ArrayList members = new ArrayList(); members.Add(root); Stack stack = new Stack(); foreach (IDependencyVertex parent in root.PredecessorList) { if (!FindCycle(root, parent, ref members, ref stack)) { break; } } throw new GraphCycleException(members); } // Decrement the Order of all vertices that this one depended on. next.DecrementParentsChildCount(htVerts); } } catch (StackOverflowException soe) { throw new ApplicationException("The GraphSequencer has detected a probable dependency cycle in the initialization sequence of this model. For details, set the GraphSequencer.StackCheck key to true in the modeler's app.config file.", soe); } #region Diagnostics if (s_diagnostics) { _Debug.WriteLine("Dependency Solver determines sequence to be:"); foreach (IDependencyVertex idv in m_serviceSequenceList) { _Debug.WriteLine("\t" + idv); } } #endregion Diagnostics }
public VertexRecord(IDependencyVertex underlying) { m_underlying = underlying; m_order = 0; }