/// <summary> /// Determines if there is change set information for given snapshot /// </summary> /// <param name="snapshotId">Snapshot Id to query</param> /// <returns>True if data exists</returns> public bool ContainsSnapshot(Guid snapshotId) { lock (sync) { Edge <Guid, EdgeData> edge = null; return(BPlusTreeOperations.TryFindEdge(nodes, Constants.SnapshotsNodeId, new EdgeData(EdgeType.ListItem, snapshotId), out edge)); } }
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); } } } }
internal Guid GetInstanceTypeId(Guid referenceId) { Edge <Guid, EdgeData> edge = null; if (BPlusTreeOperations.TryFindEdge(provider, referenceId, new EdgeData(EdgeType.OfType, null), out edge)) { return(edge.ToNodeId); } else { return(Guid.Empty); } }
internal bool TryGetReference(Guid instanceId, object key, out Guid referenceId) { Edge <Guid, EdgeData> edge = null; if (BPlusTreeOperations.TryFindEdge(provider, instanceId, new EdgeData(EdgeType.ListItem, key), out edge)) { referenceId = edge.ToNodeId; return(true); } else { referenceId = Guid.Empty; return(false); } }
internal bool TryGetScalar(Guid instanceId, object key, out object value) { Edge <Guid, EdgeData> edge = null; if (BPlusTreeOperations.TryFindEdge(provider, instanceId, new EdgeData(EdgeType.ListItem, key), out edge)) { value = provider.GetNode(edge.ToNodeId, NodeAccess.Read).Data; return(true); } else { value = null; return(false); } }
/// <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> /// Recursive breadth-first pass through node graph which generates parent information /// </summary> /// <param name="snapshotId">Snapshot to generate</param> /// <param name="nodeId">Visited node</param> /// <param name="visitedNodes">List of visited nodes</param> private void AddParentsRecursive(Guid nodeId, Hashtable visitedNodes, INodeProvider <Guid, object, EdgeData> nodes) { if (nodeId.Equals(Constants.NullReferenceNodeId)) { return; } if (visitedNodes.ContainsKey(nodeId)) { return; } else { visitedNodes.Add(nodeId, null); } // Add the node as parent of all child nodes foreach (var edge in dataNodeProvider.GetNode(nodeId, NodeAccess.Read).Edges.Values) { if (EdgeFilter(edge)) { if (!nodes.Contains(edge.ToNodeId)) { var holderNode = BPlusTreeOperations.CreateRootNode(NodeType.Collection, edge.ToNodeId); nodes.SetNode(edge.ToNodeId, holderNode); } var edgeData = new EdgeData(EdgeType.Contains, nodeId); Edge <Guid, EdgeData> existingEdge = null; if (!BPlusTreeOperations.TryFindEdge(nodes, edge.ToNodeId, edgeData, out existingEdge)) { BPlusTreeOperations.InsertEdge(nodes, edge.ToNodeId, new Edge <Guid, EdgeData>(nodeId, edgeData), ParentsTreeOrder); } } } foreach (var edge in dataNodeProvider.GetNode(nodeId, NodeAccess.Read).Edges.Values) { AddParentsRecursive(edge.ToNodeId, visitedNodes, nodes); } }
public void TestConsistency() { INodeProvider <Guid, object, EdgeData> nodes = new DirectNodeProviderSafe <Guid, object, EdgeData>(new MemoryStorageUnsafe <Guid, object>(), false); Guid rootId = Guid.NewGuid(); Node <Guid, object, EdgeData> node = BPlusTreeOperations.CreateRootNode(NodeType.Collection, rootId); nodes.SetNode(rootId, node); Collection <Guid> references = new Collection <Guid>(); Collection <Guid> referencesAdded = new Collection <Guid>(); for (int i = 0; i < 1000; i++) { references.Add(Guid.NewGuid()); } foreach (var reference in references) { var data = new EdgeData(EdgeType.ListItem, reference); BPlusTreeOperations.InsertEdge(nodes, rootId, new Edge <Guid, EdgeData>(reference, data), TreeOrder); referencesAdded.Add(reference); foreach (var addedReference in referencesAdded) { var dataAdded = new EdgeData(EdgeType.ListItem, addedReference); Edge <Guid, EdgeData> edge; Assert.IsTrue(BPlusTreeOperations.TryFindEdge(nodes, rootId, dataAdded, out edge)); Assert.AreEqual(addedReference, edge.Data.Data); } } foreach (var reference in references) { var data = new EdgeData(EdgeType.ListItem, reference); Edge <Guid, EdgeData> edge; Assert.IsTrue(BPlusTreeOperations.TryFindEdge(nodes, rootId, data, out edge)); Assert.AreEqual(reference, edge.Data.Data); Assert.AreEqual(reference, edge.ToNodeId); } }
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); } } }
internal bool ContainsKey(Guid instanceId, object key) { Edge <Guid, EdgeData> edge = null; return(BPlusTreeOperations.TryFindEdge(provider, instanceId, new EdgeData(EdgeType.ListItem, key), out edge)); }
/// <summary> /// Updates parent information based on change set /// </summary> /// <param name="changeSet">Data change description</param> public void UpdateParents(AppendableChangeSet <Guid, object, EdgeData> changeSet, ICollectedNodesProvider <Guid, object, EdgeData> collectedNodesProvider) { lock (dataSync) { if (changeSet.SourceSnapshotId != lastSnapshotId) { // If the last snapshot is not in the memory, clear and return nodes.Clear(); createdNodes = false; return; } using (var enumerator = collectedNodesProvider.GetEdges(changeSet.SourceSnapshotId)) { if (enumerator != null) { while (enumerator.MoveNext()) { if (nodes.Contains(enumerator.Current.ToNodeId)) { DeleteTree(enumerator.Current.ToNodeId); } // Get the old node var node = dataNodeProvider.GetNode(enumerator.Current.ToNodeId, NodeAccess.Read); // For every edge in old node foreach (var edge in node.Edges.Values) { if (EdgeFilter(edge)) { // Find holder in destination snapshot for referenced node if (nodes.Contains(edge.ToNodeId)) { BPlusTreeOperations.RemoveEdge(nodes, edge.ToNodeId, new EdgeData(EdgeType.Contains, enumerator.Current.ToNodeId), ParentsTreeOrder); } } } } } } // Add new node ids to map foreach (Guid nodeId in changeSet.Nodes.EnumerateNodes()) { var holderNode = BPlusTreeOperations.CreateRootNode(NodeType.Collection, nodeId); nodes.SetNode(nodeId, holderNode); } // Add reused nodes if needed foreach (Guid nodeId in changeSet.ReusedNodes.Keys) { if (!nodes.Contains(nodeId)) { var holderNode = BPlusTreeOperations.CreateRootNode(NodeType.Collection, nodeId); nodes.SetNode(nodeId, holderNode); } } // Add new node edges to map foreach (Guid nodeId in changeSet.Nodes.EnumerateNodes()) { var node = changeSet.Nodes.GetNode(nodeId, NodeAccess.Read); // Add this id into all referenced nodes foreach (var edge in node.Edges.Values) { if (EdgeFilter(edge)) { var edgeData = new EdgeData(EdgeType.Contains, nodeId); Edge <Guid, EdgeData> existingEdge = null; if (!BPlusTreeOperations.TryFindEdge(nodes, edge.ToNodeId, edgeData, out existingEdge)) { BPlusTreeOperations.InsertEdge(nodes, edge.ToNodeId, new Edge <Guid, EdgeData>(nodeId, edgeData), ParentsTreeOrder); } } } } // Set last snapshot as the destination ID lastSnapshotId = changeSet.DestinationSnapshotId; } }