/// <summary> /// Adding an edge to a Btc graph can do the following if the edge already exists: /// 1) not add the new edge, instead upgrade existing edge to type mixed ( == input and output) /// 2) not add the new edge, instead update the existing edge's edge counts if any are zero (means unknown) /// </summary> public override void AddEdge(CdmEdge e) { #region Data Quality Checks CdmEdgeBtc ebNew = e as CdmEdgeBtc; if (ebNew == null) { Msg.LogError("CdmGraphBtc.AddEdge cannot cast edge to CdmEdgeBtc"); return; } // Check edge has been handed to us in correct format, that is Transaction in the source slot CdmNode n = FindNodeAtEndOfEdge(ebNew.NodeTargetId, ebNew.EdgeId); if (n != null) { // Above may seem a bit lax, but we dont know order things will be added to the graph, maybe node is not known yet if (n.NodeType != NodeType.Tx) { Msg.LogError("CdmGraphBtc.AddEdge all edges must have a transaction as their source"); return; } } #endregion CdmEdgeBtc ebExisting = FindEdgeByNodeSourceAndTarget(ebNew.NodeSourceId, ebNew.NodeTargetId) as CdmEdgeBtc; if (ebExisting == null) { // New edge, just add to list _edges.Add(ebNew); } else { // Edge exists in graph already, upgrade it to type mixed if needed MergeExistingEdge(ebNew, ebExisting); } }
/// <summary> /// Add depth values to the graph fragment /// </summary> private void UpdateFragmentAddDepth(CdmRequest r, CdmGraph gFragmentFromPool) { // a) node process: if request.node == node being inspected, and depth = -1, make depth 0. If depth = anything else, leave it alone. // b) edge process: look at the nodes on either end of the edge (call them n1 and n2) and examine their depth values: // n1 n2 // -1 -1 both unknown, should not happen, leave alone // 0 -1 make the -1 = 1 (same case as below, order doesnt matter) // -1 X make the -1 = X + 1 (same case as above, order doesnt matter) // X Y both known, leave alone // a) Node process List <CdmNode> nodes = gFragmentFromPool.GetAllNodes(); foreach (CdmNode n in nodes) { if (r.NodeId == n.NodeId) { if (n.Depth == -1) { // the node we're looking at is the node that was asked for in the request. Now, if previously // we didn't know it's depth we know now that it must be the first requested node for this graph. n.Depth = 0; } break; } } // b) Edge process List <CdmEdge> edges = gFragmentFromPool.GetAllEdges(); foreach (CdmEdge e in edges) { CdmNode n1 = null; CdmNode n2 = null; gFragmentFromPool.GetNodesAtEitherEndofEdge(e.EdgeId, out n1, out n2); if (n1.Depth == -1 && n2.Depth == -1) { // both unknown, shouldn't happen, just leave alone Msg.LogWarning("CdmCore.UpdateFragmentAddDepth() has both nodes unknown depth for edge: " + e.EdgeId); } else if (n1.Depth != -1 || n2.Depth != -1) { // precisely one unknown, so now we know the other if (n1.Depth == -1) { n1.Depth = n2.Depth + 1; } else { n2.Depth = n1.Depth + 1; } } else { // both known, this is fine where we're just refreshing known values, so leave alone } } }
/// <summary> /// If the CdmPool can fulfill the request, return the graph fragment required, return null otherwise /// </summary> /// <param name="r">The request we want to fulfill, which is a node and a range from-to of edge numbers</param> /// <param name="isPerfectMatchRequired">When true, the pool must perfectly match request, when false will return whatever pool has, even if incomplete</param> /// <returns>Graph fragment that fully or partially fulfills request, or null</returns> private CdmGraph CanCdmPoolFulfillRequest(CdmRequest r, bool isPerfectMatchRequired) { if (r == null) { return(null); } CdmNode n = CdmPool.FindNodeById(r.NodeId); if (n == null) { return(null); } int edgesAskedForCount = r.EdgeCountTo - r.EdgeCountFrom + 1; int edgesFoundCount = 0; int endOfEdgeNodesAskedForCount = edgesAskedForCount; int endOfEdgeNodesFoundCount = 0; // Add requested node to graph fragment we will send CdmGraph gFragment = CreateNewGraph(_adaptorSelector.GetChosenAdaptor().GetFamily()); gFragment.AddNode(n); // Get requisite edges for (int i = r.EdgeCountFrom; i <= r.EdgeCountTo; i++) { // This searches both ways around, sender and receiver CdmEdge e = CdmPool.FindEdgeByNodeAndNumber(n.NodeId, i); if (e != null) { // Store the edge edgesFoundCount++; gFragment.AddEdge(e); // Store the node at the end of the edge CdmNode eoen = CdmPool.FindNodeAtEndOfEdge(n.NodeId, e.EdgeId); gFragment.AddNode(eoen); endOfEdgeNodesFoundCount++; } } if (isPerfectMatchRequired) { if (edgesFoundCount >= edgesAskedForCount && endOfEdgeNodesFoundCount >= endOfEdgeNodesAskedForCount) { return(gFragment); } else { return(null); } } else { return(gFragment); } }
public virtual void AddNode(CdmNode n) { // Only add if not already there CdmNode existing = FindNodeById(n.NodeId); if (existing == null) { _nodes.Add(n); } }
public virtual void GetNodesAtEitherEndofEdge(string edgeId, out CdmNode n1, out CdmNode n2) { CdmEdge e = _edges.Find(c => (c.EdgeId == edgeId)); if (e != null) { n1 = FindNodeById(e.NodeTargetId); n2 = FindNodeById(e.NodeSourceId); } else { n1 = null; n2 = null; } }
/// <summary> /// Adding a node to a Btc graph can do the following if the node already exists: /// 1) not add the new node, instead update the existing node's data /// </summary> public override void AddNode(CdmNode n) { #region Data Quality Checks CdmNodeBtc nbNew = n as CdmNodeBtc; if (nbNew == null) { Msg.LogError("CdmGraphBtc.AddNode cannot cast edge to CdmNodeBtc"); return; } #endregion CdmNodeBtc nbExisting = FindNodeById(nbNew.NodeId) as CdmNodeBtc; if (nbExisting == null) { // New node, just add to list _nodes.Add(nbNew); } else { // Node exists in graph already, merge in any previously unknown data MergeExistingNode(nbNew, nbExisting); } }