private void FindTreeAddedElements(Guid nodeId, RecursiveResolutionParameters parameters, out Dictionary <EdgeData, Edge <Guid, EdgeData> > addedElements, out Dictionary <EdgeData, Edge <Guid, EdgeData> > removedElements) { addedElements = new Dictionary <EdgeData, Edge <Guid, EdgeData> >(); removedElements = new Dictionary <EdgeData, Edge <Guid, EdgeData> >(); // TODO (nsabo) Optimize searching by new ID value Guid originalNodeId = Guid.Empty; foreach (var item in parameters.IntermediateChanges) { if (item.Value.Equals(nodeId)) { originalNodeId = item.Key; break; } } if (originalNodeId == Guid.Empty) { originalNodeId = nodeId; } // Go through changed list and see if some item has not been included in the last version using (var enumerator = BPlusTreeOperations.GetEnumerator(parameters.SourceProvider, originalNodeId, EdgeType.ListItem)) { while (enumerator.MoveNext()) { var edge = enumerator.Current; Edge <Guid, EdgeData> foundEdge = null; // Try finding the element in last version if (!BPlusTreeOperations.TryFindEdge(nodes, originalNodeId, edge.Data, out foundEdge)) { addedElements.Add(edge.Data, edge); } } } // Go through last version and see if there are elements which are not found in changed list using (var enumerator = BPlusTreeOperations.GetEnumerator(nodes, originalNodeId, EdgeType.ListItem)) { while (enumerator.MoveNext()) { var edge = enumerator.Current; Edge <Guid, EdgeData> foundEdge = null; // Try finding the element in last version if (!BPlusTreeOperations.TryFindEdge(parameters.SourceProvider, originalNodeId, edge.Data, out foundEdge)) { removedElements.Add(edge.Data, edge); } } } }
/// <summary> /// Provides change set edges for given snapshot /// </summary> /// <param name="snapshotId">Snapshot ID</param> /// <returns>Change set edge enumerator</returns> public IEnumerator <Edge <Guid, EdgeData> > GetChangeSetEdges(Guid snapshotId) { lock (sync) { Edge <Guid, EdgeData> edge = null; if (BPlusTreeOperations.TryFindEdge(nodes, Constants.SnapshotsNodeId, new EdgeData(EdgeType.ListItem, snapshotId), out edge)) { return(BPlusTreeOperations.GetEnumerator(nodes, snapshotId, EdgeType.ListItem)); } else { // Returtn empty enumerator return(new Collection <Edge <Guid, EdgeData> >().GetEnumerator()); } } }
/// <summary> /// Returns list of parents for given node witin a snapshot /// </summary> /// <param name="snapshotId">Snapshot within parents are requested</param> /// <param name="nodeId">Node which parents are returned</param> /// <returns>List of parent node identifiers for each node in dictionary format, or null if there are no parent edges</returns> public IEnumerator <Edge <Guid, EdgeData> > ParentEdges(Guid snapshotId, Guid nodeId) { lock (dataSync) { // Generate parents if they dont exist if (!createdNodes) { createdNodes = true; AddParentsRecursive(snapshotId, new Hashtable(), nodes); lastSnapshotId = snapshotId; } // Do we have the last snapshot in the memory if (snapshotId != lastSnapshotId) { // Try going for fallback provider if (fallbackParentMapProvider != null) { return(fallbackParentMapProvider.ParentEdges(snapshotId, nodeId)); } else { // If not, generate asked snapshot nodes.Clear(); AddParentsRecursive(snapshotId, new Hashtable(), nodes); lastSnapshotId = snapshotId; } } // Find edge leading to holder node for given ID if (nodes.Contains(nodeId)) { return(BPlusTreeOperations.GetEnumerator(nodes, nodeId, EdgeType.Contains)); } else { return(null); } } }
private static void LogCollection(Guid nodeId, Node <Guid, object, EdgeData> node, INodeProvider <Guid, object, EdgeData> nodes, INodeProvider <Guid, object, EdgeData> changes, int tabLevel, Hashtable visited, TypesService typesService) { Edge <Guid, EdgeData> typeEdge = null; BPlusTreeOperations.TryFindEdge(nodes, nodeId, new EdgeData(EdgeType.OfType, null), out typeEdge); var typeId = typeEdge.ToNodeId; var typeName = typesService.GetTypeFromId(typeId).Name; Debug.WriteLine(LogTabs(tabLevel) + nodeId + "(" + typeName + ")"); Debug.WriteLine(LogTabs(tabLevel) + "Previous=" + node.Previous); using (var enumeration = BPlusTreeOperations.GetEnumerator(nodes, nodeId, EdgeType.ListItem)) { while (enumeration.MoveNext()) { Debug.WriteLine(LogTabs(tabLevel) + enumeration.Current.Data + "="); LogNodesRecursive(enumeration.Current.ToNodeId, nodes, changes, tabLevel + 1, visited, typesService); } } }
/// <summary> /// Returns edges to collectable nodes for a snapshot /// </summary> /// <param name="snapshotId">Snapshot identifier</param> /// <returns>Enumerator of edges towards collectable nodes</returns> public IEnumerator <Edge <Guid, EdgeData> > GetEdges(Guid snapshotId) { return(BPlusTreeOperations.GetEnumerator(nodes, snapshotId, EdgeType.ListItem)); }
internal IEnumerator <Edge <Guid, EdgeData> > GetEnumerator(Guid instanceId) { return(BPlusTreeOperations.GetEnumerator(provider, instanceId, EdgeType.ListItem)); }
private void MergeRecursive(Guid nodeId, RecursiveResolutionParameters parameters) { if (parameters.VisitedNodes.ContainsKey(nodeId)) { return; } parameters.VisitedNodes.Add(nodeId, null); // Are we within the last snapshot affected sub tree if (parameters.SubTree.ContainsKey(nodeId)) { // Create node which we will change var node = parameters.DestinationProvider.GetNode(nodeId, NodeAccess.ReadWrite); // Perform the change depending on node type switch (node.NodeType) { case NodeType.Snapshot: foreach (var edge in node.Edges.Values) { MergeRecursive(edge.ToNodeId, parameters); } break; case NodeType.Scalar: throw new NotImplementedException("TODO"); case NodeType.Object: { // Is there a change in the changeset with conflicting change? // TODO (nsabo) Optimize searching by new ID value Guid changeNodeId = (Guid)parameters.SubTree[nodeId]; if (changeNodeId != Guid.Empty) { var changedNode = parameters.ChangeSet.Nodes.GetNode(changeNodeId, NodeAccess.Read); var originalNode = nodes.GetNode(changeNodeId, NodeAccess.Read); nodeMergeExecutor.MergeObjects(nodeId, originalNode, changedNode, node, new MergeRecursiveDelegate(MergeRecursive), new InsertRecursiveDelegate(InsertRecursive), parameters); } else { var changedNode = parameters.ChangeSet.Nodes.GetNode(nodeId, NodeAccess.Read); if (changedNode != null) { nodeMergeExecutor.ChangeObject(nodeId, changedNode, node, new MergeRecursiveDelegate(MergeRecursive), new InsertRecursiveDelegate(InsertRecursive), parameters); } else { // Follow edges foreach (var item in node.Edges.Values) { MergeRecursive(item.ToNodeId, parameters); } } } break; } case NodeType.Collection: case NodeType.Dictionary: { var treeOrder = node.NodeType == NodeType.Collection ? CollectionInstancesService.BPlusTreeOrder : DictionaryInstancesService.BPlusTreeOrder; // Search the changeset for new added elements Dictionary <EdgeData, Edge <Guid, EdgeData> > addedEdges = null; Dictionary <EdgeData, Edge <Guid, EdgeData> > removedEdges = null; FindTreeAddedElements(nodeId, parameters, out addedEdges, out removedEdges); foreach (var addedEdge in addedEdges.Values) { // Add node in the isolated provider InsertRecursive(addedEdge.ToNodeId, parameters); // Create edge from the current collection BPlusTreeOperations.InsertEdge(parameters.DestinationProvider, nodeId, addedEdge, treeOrder); } foreach (var removedEdge in removedEdges.Values) { BPlusTreeOperations.RemoveEdge(parameters.DestinationProvider, nodeId, removedEdge.Data, treeOrder); } // Enumerate through existing elements and look for their changes using (var enumerator = BPlusTreeOperations.GetEnumerator(nodes, nodeId, EdgeType.ListItem)) { while (enumerator.MoveNext()) { if (!addedEdges.ContainsKey(enumerator.Current.Data) && !removedEdges.ContainsKey(enumerator.Current.Data)) { MergeRecursive(enumerator.Current.ToNodeId, parameters); } } } break; } default: throw new ArgumentException("Unexpected node type in tree :" + node.NodeType); } parameters.DestinationProvider.SetNode(nodeId, node); } }